summaryrefslogtreecommitdiff
path: root/Master/tlpkg/tlperl
diff options
context:
space:
mode:
authorSiep Kroonenberg <siepo@cybercomm.nl>2011-02-17 17:56:54 +0000
committerSiep Kroonenberg <siepo@cybercomm.nl>2011-02-17 17:56:54 +0000
commit779e71f16ca01a6244b632b95bdb461fec163b34 (patch)
tree610b33e5531d7d432de62a216345c9daf1230d42 /Master/tlpkg/tlperl
parent539135f1864a2356d0eb3666e0f5b335680872a4 (diff)
New tlperl part XIII
git-svn-id: svn://tug.org/texlive/trunk@21435 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/tlpkg/tlperl')
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/API/HOWTO.pod44
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Author.pm236
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Bundle.pm287
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/CacheMgr.pm246
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Complete.pm175
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Debug.pm79
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/DeferredCode.pm16
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Distribution.pm3896
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Distroprefs.pm451
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Distrostatus.pm45
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Exception/RecursiveDependency.pm85
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Exception/blocked_urllist.pm46
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Exception/yaml_not_installed.pm73
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/FTP.pm1074
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/FTP/netrc.pm63
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/FirstTime.pm1800
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/HandleConfig.pm741
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Index.pm619
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/InfoObj.pm224
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Kwalify.pm136
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Kwalify/distroprefs.dd150
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Kwalify/distroprefs.yml92
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/LWP/UserAgent.pm135
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Mirrors.pm260
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Module.pm688
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Nox.pm51
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Prompt.pm29
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Queue.pm198
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Shell.pm1988
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Tarzip.pm451
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/URL.pm31
-rw-r--r--Master/tlpkg/tlperl/lib/CPAN/Version.pm173
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Backend.pm1330
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Backend/RV.pm144
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Config.pm797
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Configure.pm630
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Configure/Setup.pm1653
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Dist.pm688
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Autobundle.pm117
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Base.pm261
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Build.pm836
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Build/Constants.pm69
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Dist/MM.pm1007
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Sample.pm16
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Error.pm201
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/FAQ.pod30
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Hacking.pod135
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Internals.pm516
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Constants.pm375
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Constants/Report.pm407
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Extract.pm243
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Fetch.pm473
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Report.pm645
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Search.pm363
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Source.pm1417
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Source/Memory.pm374
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Source/SQLite.pm326
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Source/SQLite/Tie.pm145
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Utils.pm657
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Utils/Autoflush.pm5
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Module.pm1815
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Module/Author.pm232
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Module/Author/Fake.pm80
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Module/Checksums.pm251
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Module/Fake.pm86
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Module/Signature.pm65
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Selfupdate.pm547
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Shell.pm341
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Classic.pm1236
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default.pm1938
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default/Plugins/CustomSource.pm201
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default/Plugins/HOWTO.pod136
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default/Plugins/Remote.pm186
-rw-r--r--Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default/Plugins/Source.pm107
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/Alias.pm377
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/Byte.pm120
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/CJKConstants.pm66
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/CN.pm74
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/CN/HZ.pm198
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/Changes.e2x7
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/Config.pm170
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/ConfigLocal_PM.e2x13
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/EBCDIC.pm45
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/Encoder.pm253
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/Encoding.pm360
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/GSM0338.pm292
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/Guess.pm355
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/JP.pm95
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/JP/H2Z.pm176
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/JP/JIS7.pm165
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/KR.pm69
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/KR/2022_KR.pm81
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/MIME/Header.pm241
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/MIME/Header/ISO_2022_JP.pm131
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/MIME/Name.pm94
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/Makefile_PL.e2x180
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/PerlIO.pod167
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/README.e2x31
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/Supported.pod901
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/Symbol.pm44
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/TW.pm75
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/Unicode.pm270
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/Unicode/UTF7.pm128
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/_PM.e2x23
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/_T.e2x7
-rw-r--r--Master/tlpkg/tlperl/lib/Encode/encode.h113
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/CBuilder.pm331
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Base.pm307
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Unix.pm40
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/VMS.pm294
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Windows.pm288
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Windows/BCC.pm130
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Windows/GCC.pm151
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Windows/MSVC.pm131
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/aix.pm31
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/cygwin.pm33
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/darwin.pm22
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/dec_osf.pm18
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/os2.pm80
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/Command.pm369
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/Command/MM.pm275
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/Constant.pm565
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/Constant/Base.pm1006
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/Constant/ProxySubs.pm549
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/Constant/Utils.pm131
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/Constant/XS.pm259
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/Embed.pm511
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/Install.pm1365
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/Installed.pm462
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/Liblist.pm286
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/Liblist/Kid.pm546
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MANIFEST.SKIP51
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MM.pm90
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MM_AIX.pm79
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MM_Any.pm2334
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MM_BeOS.pm61
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MM_Cygwin.pm123
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MM_DOS.pm65
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MM_Darwin.pm47
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MM_MacOS.pm40
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MM_NW5.pm269
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MM_OS2.pm152
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MM_QNX.pm57
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MM_UWIN.pm64
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MM_Unix.pm3634
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MM_VMS.pm1994
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MM_VOS.pm50
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MM_Win32.pm585
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MM_Win95.pm124
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MY.pm40
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MakeMaker.pm2807
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MakeMaker/Config.pm39
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MakeMaker/FAQ.pod431
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/MakeMaker/Tutorial.pod180
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/Manifest.pm881
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/Miniperl.pm280
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/Mkbootstrap.pm109
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/Mksymlists.pm312
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/Packlist.pm352
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/ParseXS.pm2111
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/testlib.pm41
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/typemap336
-rw-r--r--Master/tlpkg/tlperl/lib/ExtUtils/xsubpp156
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Compress/Adapter/Bzip2.pm162
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Compress/Adapter/Deflate.pm165
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Compress/Adapter/Identity.pm101
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Compress/Base.pm981
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Compress/Base/Common.pm956
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Compress/Bzip2.pm758
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Compress/Deflate.pm930
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Compress/Gzip.pm1242
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Compress/Gzip/Constants.pm148
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Compress/RawDeflate.pm1017
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Compress/Zip.pm1612
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Compress/Zip/Constants.pm105
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Compress/Zlib/Constants.pm77
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Compress/Zlib/Extra.pm198
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Dir.pm248
-rw-r--r--Master/tlpkg/tlperl/lib/IO/File.pm204
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Handle.pm635
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Pipe.pm257
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Poll.pm209
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Seekable.pm128
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Select.pm381
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Socket.pm540
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Socket/INET.pm464
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Socket/UNIX.pm143
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Uncompress/Adapter/Bunzip2.pm112
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Uncompress/Adapter/Identity.pm105
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Uncompress/Adapter/Inflate.pm158
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Uncompress/AnyInflate.pm987
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Uncompress/AnyUncompress.pm1018
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Uncompress/Base.pm1474
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Uncompress/Bunzip2.pm858
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Uncompress/Gunzip.pm1111
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Uncompress/Inflate.pm982
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Uncompress/RawInflate.pm1110
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Uncompress/Unzip.pm1549
-rw-r--r--Master/tlpkg/tlperl/lib/IO/Zlib.pm652
-rw-r--r--Master/tlpkg/tlperl/lib/Unicode/Collate.pm1877
-rw-r--r--Master/tlpkg/tlperl/lib/Unicode/Collate/allkeys.txt18191
-rw-r--r--Master/tlpkg/tlperl/lib/Unicode/Collate/keys.txt864
-rw-r--r--Master/tlpkg/tlperl/lib/Unicode/Normalize.pm520
-rw-r--r--Master/tlpkg/tlperl/lib/Unicode/UCD.pm1230
204 files changed, 111517 insertions, 0 deletions
diff --git a/Master/tlpkg/tlperl/lib/CPAN/API/HOWTO.pod b/Master/tlpkg/tlperl/lib/CPAN/API/HOWTO.pod
new file mode 100644
index 00000000000..e65a4bc9313
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/API/HOWTO.pod
@@ -0,0 +1,44 @@
+=head1 NAME
+
+CPAN::API::HOWTO - a recipe book for programming with CPAN.pm
+
+=head1 RECIPES
+
+All of these recipes assume that you have put "use CPAN" at the top of
+your program.
+
+=head2 What distribution contains a particular module?
+
+ my $distribution = CPAN::Shell->expand(
+ "Module", "Data::UUID"
+ )->distribution()->pretty_id();
+
+This returns a string of the form "AUTHORID/TARBALL". If you want the
+full path and filename to this distribution on a CPAN mirror, then it is
+C<.../authors/id/A/AU/AUTHORID/TARBALL>.
+
+=head2 What modules does a particular distribution contain?
+
+ CPAN::Index->reload();
+ my @modules = CPAN::Shell->expand(
+ "Distribution", "JHI/Graph-0.83.tar.gz"
+ )->containsmods();
+
+You may also refer to a distribution in the form A/AU/AUTHORID/TARBALL.
+
+=head1 SEE ALSO
+
+the main CPAN.pm documentation
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+See L<http://www.perl.com/perl/misc/Artistic.html>
+
+=head1 AUTHOR
+
+David Cantrell
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Author.pm b/Master/tlpkg/tlperl/lib/CPAN/Author.pm
new file mode 100644
index 00000000000..e9e9226be5d
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Author.pm
@@ -0,0 +1,236 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+# vim: ts=4 sts=4 sw=4:
+package CPAN::Author;
+use strict;
+
+use CPAN::InfoObj;
+@CPAN::Author::ISA = qw(CPAN::InfoObj);
+use vars qw(
+ $VERSION
+);
+$VERSION = "5.5";
+
+package CPAN::Author;
+use strict;
+
+#-> sub CPAN::Author::force
+sub force {
+ my $self = shift;
+ $self->{force}++;
+}
+
+#-> sub CPAN::Author::force
+sub unforce {
+ my $self = shift;
+ delete $self->{force};
+}
+
+#-> sub CPAN::Author::id
+sub id {
+ my $self = shift;
+ my $id = $self->{ID};
+ $CPAN::Frontend->mydie("Illegal author id[$id]") unless $id =~ /^[A-Z]/;
+ $id;
+}
+
+#-> sub CPAN::Author::as_glimpse ;
+sub as_glimpse {
+ my($self) = @_;
+ my(@m);
+ my $class = ref($self);
+ $class =~ s/^CPAN:://;
+ push @m, sprintf(qq{%-15s %s ("%s" <%s>)\n},
+ $class,
+ $self->{ID},
+ $self->fullname,
+ $self->email);
+ join "", @m;
+}
+
+#-> sub CPAN::Author::fullname ;
+sub fullname {
+ shift->ro->{FULLNAME};
+}
+*name = \&fullname;
+
+#-> sub CPAN::Author::email ;
+sub email { shift->ro->{EMAIL}; }
+
+#-> sub CPAN::Author::ls ;
+sub ls {
+ my $self = shift;
+ my $glob = shift || "";
+ my $silent = shift || 0;
+ my $id = $self->id;
+
+ # adapted from CPAN::Distribution::verifyCHECKSUM ;
+ my(@csf); # chksumfile
+ @csf = $self->id =~ /(.)(.)(.*)/;
+ $csf[1] = join "", @csf[0,1];
+ $csf[2] = join "", @csf[1,2]; # ("A","AN","ANDK")
+ my(@dl);
+ @dl = $self->dir_listing([$csf[0],"CHECKSUMS"], 0, 1);
+ unless (grep {$_->[2] eq $csf[1]} @dl) {
+ $CPAN::Frontend->myprint("Directory $csf[1]/ does not exist\n") unless $silent ;
+ return;
+ }
+ @dl = $self->dir_listing([@csf[0,1],"CHECKSUMS"], 0, 1);
+ unless (grep {$_->[2] eq $csf[2]} @dl) {
+ $CPAN::Frontend->myprint("Directory $id/ does not exist\n") unless $silent;
+ return;
+ }
+ @dl = $self->dir_listing([@csf,"CHECKSUMS"], 1, 1);
+ if ($glob) {
+ if ($CPAN::META->has_inst("Text::Glob")) {
+ $glob =~ s|/$|/*|;
+ my $rglob = Text::Glob::glob_to_regex($glob);
+ CPAN->debug("glob[$glob]rglob[$rglob]dl[@dl]") if $CPAN::DEBUG;
+ my @tmpdl = grep { $_->[2] =~ /$rglob/ } @dl;
+ if (1==@tmpdl && $tmpdl[0][0]==0) {
+ $rglob = Text::Glob::glob_to_regex("$glob/*");
+ @dl = grep { $_->[2] =~ /$rglob/ } @dl;
+ } else {
+ @dl = @tmpdl;
+ }
+ CPAN->debug("rglob[$rglob]dl[@dl]") if $CPAN::DEBUG;
+ } else {
+ $CPAN::Frontend->mydie("Text::Glob not installed, cannot proceed");
+ }
+ }
+ unless ($silent >= 2) {
+ $CPAN::Frontend->myprint
+ (
+ join "",
+ map {
+ sprintf
+ (
+ "%8d %10s %s/%s%s\n",
+ $_->[0],
+ $_->[1],
+ $id,
+ $_->[2],
+ 0==$_->[0]?"/":"",
+ )
+ } sort { $a->[2] cmp $b->[2] } @dl
+ );
+ }
+ @dl;
+}
+
+# returns an array of arrays, the latter contain (size,mtime,filename)
+#-> sub CPAN::Author::dir_listing ;
+sub dir_listing {
+ my $self = shift;
+ my $chksumfile = shift;
+ my $recursive = shift;
+ my $may_ftp = shift;
+
+ my $lc_want =
+ File::Spec->catfile($CPAN::Config->{keep_source_where},
+ "authors", "id", @$chksumfile);
+
+ my $fh;
+
+ CPAN->debug("chksumfile[@$chksumfile]recursive[$recursive]may_ftp[$may_ftp]") if $CPAN::DEBUG;
+ # Purge and refetch old (pre-PGP) CHECKSUMS; they are a security
+ # hazard. (Without GPG installed they are not that much better,
+ # though.)
+ $fh = FileHandle->new;
+ if (open($fh, $lc_want)) {
+ my $line = <$fh>; close $fh;
+ unlink($lc_want) unless $line =~ /PGP/;
+ }
+
+ local($") = "/";
+ # connect "force" argument with "index_expire".
+ my $force = $self->{force};
+ if (my @stat = stat $lc_want) {
+ $force ||= $stat[9] + $CPAN::Config->{index_expire}*86400 <= time;
+ }
+ my $lc_file;
+ if ($may_ftp) {
+ $lc_file = eval {
+ CPAN::FTP->localize
+ (
+ "authors/id/@$chksumfile",
+ $lc_want,
+ $force,
+ );
+ };
+ unless ($lc_file) {
+ $CPAN::Frontend->myprint("Trying $lc_want.gz\n");
+ $chksumfile->[-1] .= ".gz";
+ $lc_file = eval {
+ CPAN::FTP->localize
+ ("authors/id/@$chksumfile",
+ "$lc_want.gz",
+ 1,
+ );
+ };
+ if ($lc_file) {
+ $lc_file =~ s{\.gz(?!\n)\Z}{}; #};
+ eval{CPAN::Tarzip->new("$lc_file.gz")->gunzip($lc_file)};
+ } else {
+ return;
+ }
+ }
+ } else {
+ $lc_file = $lc_want;
+ # we *could* second-guess and if the user has a file: URL,
+ # then we could look there. But on the other hand, if they do
+ # have a file: URL, wy did they choose to set
+ # $CPAN::Config->{show_upload_date} to false?
+ }
+
+ # adapted from CPAN::Distribution::CHECKSUM_check_file ;
+ $fh = FileHandle->new;
+ my($cksum);
+ if (open $fh, $lc_file) {
+ local($/);
+ my $eval = <$fh>;
+ $eval =~ s/\015?\012/\n/g;
+ close $fh;
+ my($compmt) = Safe->new();
+ $cksum = $compmt->reval($eval);
+ if ($@) {
+ rename $lc_file, "$lc_file.bad";
+ Carp::confess($@) if $@;
+ }
+ } elsif ($may_ftp) {
+ Carp::carp ("Could not open '$lc_file' for reading.");
+ } else {
+ # Maybe should warn: "You may want to set show_upload_date to a true value"
+ return;
+ }
+ my(@result,$f);
+ for $f (sort keys %$cksum) {
+ if (exists $cksum->{$f}{isdir}) {
+ if ($recursive) {
+ my(@dir) = @$chksumfile;
+ pop @dir;
+ push @dir, $f, "CHECKSUMS";
+ push @result, [ 0, "-", $f ];
+ push @result, map {
+ [$_->[0], $_->[1], "$f/$_->[2]"]
+ } $self->dir_listing(\@dir,1,$may_ftp);
+ } else {
+ push @result, [ 0, "-", $f ];
+ }
+ } else {
+ push @result, [
+ ($cksum->{$f}{"size"}||0),
+ $cksum->{$f}{"mtime"}||"---",
+ $f
+ ];
+ }
+ }
+ @result;
+}
+
+#-> sub CPAN::Author::reports
+sub reports {
+ $CPAN::Frontend->mywarn("reports on authors not implemented.
+Please file a bugreport if you need this.\n");
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Bundle.pm b/Master/tlpkg/tlperl/lib/CPAN/Bundle.pm
new file mode 100644
index 00000000000..e7360f80485
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Bundle.pm
@@ -0,0 +1,287 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+# vim: ts=4 sts=4 sw=4:
+package CPAN::Bundle;
+use strict;
+use CPAN::Module;
+@CPAN::Bundle::ISA = qw(CPAN::Module);
+
+use vars qw(
+ $VERSION
+);
+$VERSION = "5.5";
+
+sub look {
+ my $self = shift;
+ $CPAN::Frontend->myprint($self->as_string);
+}
+
+#-> CPAN::Bundle::undelay
+sub undelay {
+ my $self = shift;
+ delete $self->{later};
+ for my $c ( $self->contains ) {
+ my $obj = CPAN::Shell->expandany($c) or next;
+ $obj->undelay;
+ }
+}
+
+# mark as dirty/clean
+#-> sub CPAN::Bundle::color_cmd_tmps ;
+sub color_cmd_tmps {
+ my($self) = shift;
+ my($depth) = shift || 0;
+ my($color) = shift || 0;
+ my($ancestors) = shift || [];
+ # a module needs to recurse to its cpan_file, a distribution needs
+ # to recurse into its prereq_pms, a bundle needs to recurse into its modules
+
+ return if exists $self->{incommandcolor}
+ && $color==1
+ && $self->{incommandcolor}==$color;
+ if ($depth>=$CPAN::MAX_RECURSION) {
+ die(CPAN::Exception::RecursiveDependency->new($ancestors));
+ }
+ # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1;
+
+ for my $c ( $self->contains ) {
+ my $obj = CPAN::Shell->expandany($c) or next;
+ CPAN->debug("c[$c]obj[$obj]") if $CPAN::DEBUG;
+ $obj->color_cmd_tmps($depth+1,$color,[@$ancestors, $self->id]);
+ }
+ # never reached code?
+ #if ($color==0) {
+ #delete $self->{badtestcnt};
+ #}
+ $self->{incommandcolor} = $color;
+}
+
+#-> sub CPAN::Bundle::as_string ;
+sub as_string {
+ my($self) = @_;
+ $self->contains;
+ # following line must be "=", not "||=" because we have a moving target
+ $self->{INST_VERSION} = $self->inst_version;
+ return $self->SUPER::as_string;
+}
+
+#-> sub CPAN::Bundle::contains ;
+sub contains {
+ my($self) = @_;
+ my($inst_file) = $self->inst_file || "";
+ my($id) = $self->id;
+ $self->debug("inst_file[$inst_file]id[$id]") if $CPAN::DEBUG;
+ if ($inst_file && CPAN::Version->vlt($self->inst_version,$self->cpan_version)) {
+ undef $inst_file;
+ }
+ unless ($inst_file) {
+ # Try to get at it in the cpan directory
+ $self->debug("no inst_file") if $CPAN::DEBUG;
+ my $cpan_file;
+ $CPAN::Frontend->mydie("I don't know a bundle with ID $id\n") unless
+ $cpan_file = $self->cpan_file;
+ if ($cpan_file eq "N/A") {
+ $CPAN::Frontend->mydie("Bundle $id not found on disk and not on CPAN.
+ Maybe stale symlink? Maybe removed during session? Giving up.\n");
+ }
+ my $dist = $CPAN::META->instance('CPAN::Distribution',
+ $self->cpan_file);
+ $self->debug("before get id[$dist->{ID}]") if $CPAN::DEBUG;
+ $dist->get;
+ $self->debug("after get id[$dist->{ID}]") if $CPAN::DEBUG;
+ my($todir) = $CPAN::Config->{'cpan_home'};
+ my(@me,$from,$to,$me);
+ @me = split /::/, $self->id;
+ $me[-1] .= ".pm";
+ $me = File::Spec->catfile(@me);
+ $from = $self->find_bundle_file($dist->{build_dir},join('/',@me));
+ $to = File::Spec->catfile($todir,$me);
+ File::Path::mkpath(File::Basename::dirname($to));
+ File::Copy::copy($from, $to)
+ or Carp::confess("Couldn't copy $from to $to: $!");
+ $inst_file = $to;
+ }
+ my @result;
+ my $fh = FileHandle->new;
+ local $/ = "\n";
+ open($fh,$inst_file) or die "Could not open '$inst_file': $!";
+ my $in_cont = 0;
+ $self->debug("inst_file[$inst_file]") if $CPAN::DEBUG;
+ while (<$fh>) {
+ $in_cont = m/^=(?!head1\s+(?i-xsm:CONTENTS))/ ? 0 :
+ m/^=head1\s+(?i-xsm:CONTENTS)/ ? 1 : $in_cont;
+ next unless $in_cont;
+ next if /^=/;
+ s/\#.*//;
+ next if /^\s+$/;
+ chomp;
+ push @result, (split " ", $_, 2)[0];
+ }
+ close $fh;
+ delete $self->{STATUS};
+ $self->{CONTAINS} = \@result;
+ $self->debug("CONTAINS[@result]") if $CPAN::DEBUG;
+ unless (@result) {
+ $CPAN::Frontend->mywarn(qq{
+The bundle file "$inst_file" may be a broken
+bundlefile. It seems not to contain any bundle definition.
+Please check the file and if it is bogus, please delete it.
+Sorry for the inconvenience.
+});
+ }
+ @result;
+}
+
+#-> sub CPAN::Bundle::find_bundle_file
+# $where is in local format, $what is in unix format
+sub find_bundle_file {
+ my($self,$where,$what) = @_;
+ $self->debug("where[$where]what[$what]") if $CPAN::DEBUG;
+### The following two lines let CPAN.pm become Bundle/CPAN.pm :-(
+### my $bu = File::Spec->catfile($where,$what);
+### return $bu if -f $bu;
+ my $manifest = File::Spec->catfile($where,"MANIFEST");
+ unless (-f $manifest) {
+ require ExtUtils::Manifest;
+ my $cwd = CPAN::anycwd();
+ $self->safe_chdir($where);
+ ExtUtils::Manifest::mkmanifest();
+ $self->safe_chdir($cwd);
+ }
+ my $fh = FileHandle->new($manifest)
+ or Carp::croak("Couldn't open $manifest: $!");
+ local($/) = "\n";
+ my $bundle_filename = $what;
+ $bundle_filename =~ s|Bundle.*/||;
+ my $bundle_unixpath;
+ while (<$fh>) {
+ next if /^\s*\#/;
+ my($file) = /(\S+)/;
+ if ($file =~ m|\Q$what\E$|) {
+ $bundle_unixpath = $file;
+ # return File::Spec->catfile($where,$bundle_unixpath); # bad
+ last;
+ }
+ # retry if she managed to have no Bundle directory
+ $bundle_unixpath = $file if $file =~ m|\Q$bundle_filename\E$|;
+ }
+ return File::Spec->catfile($where, split /\//, $bundle_unixpath)
+ if $bundle_unixpath;
+ Carp::croak("Couldn't find a Bundle file in $where");
+}
+
+# needs to work quite differently from Module::inst_file because of
+# cpan_home/Bundle/ directory and the possibility that we have
+# shadowing effect. As it makes no sense to take the first in @INC for
+# Bundles, we parse them all for $VERSION and take the newest.
+
+#-> sub CPAN::Bundle::inst_file ;
+sub inst_file {
+ my($self) = @_;
+ my($inst_file);
+ my(@me);
+ @me = split /::/, $self->id;
+ $me[-1] .= ".pm";
+ my($incdir,$bestv);
+ foreach $incdir ($CPAN::Config->{'cpan_home'},@INC) {
+ my $parsefile = File::Spec->catfile($incdir, @me);
+ CPAN->debug("parsefile[$parsefile]") if $CPAN::DEBUG;
+ next unless -f $parsefile;
+ my $have = eval { MM->parse_version($parsefile); };
+ if ($@) {
+ $CPAN::Frontend->mywarn("Error while parsing version number in file '$parsefile'\n");
+ }
+ if (!$bestv || CPAN::Version->vgt($have,$bestv)) {
+ $self->{INST_FILE} = $parsefile;
+ $self->{INST_VERSION} = $bestv = $have;
+ }
+ }
+ $self->{INST_FILE};
+}
+
+#-> sub CPAN::Bundle::inst_version ;
+sub inst_version {
+ my($self) = @_;
+ $self->inst_file; # finds INST_VERSION as side effect
+ $self->{INST_VERSION};
+}
+
+#-> sub CPAN::Bundle::rematein ;
+sub rematein {
+ my($self,$meth) = @_;
+ $self->debug("self[$self] meth[$meth]") if $CPAN::DEBUG;
+ my($id) = $self->id;
+ Carp::croak( "Can't $meth $id, don't have an associated bundle file. :-(\n" )
+ unless $self->inst_file || $self->cpan_file;
+ my($s,%fail);
+ for $s ($self->contains) {
+ my($type) = $s =~ m|/| ? 'CPAN::Distribution' :
+ $s =~ m|^Bundle::| ? 'CPAN::Bundle' : 'CPAN::Module';
+ if ($type eq 'CPAN::Distribution') {
+ $CPAN::Frontend->mywarn(qq{
+The Bundle }.$self->id.qq{ contains
+explicitly a file '$s'.
+Going to $meth that.
+});
+ $CPAN::Frontend->mysleep(5);
+ }
+ # possibly noisy action:
+ $self->debug("type[$type] s[$s]") if $CPAN::DEBUG;
+ my $obj = $CPAN::META->instance($type,$s);
+ $obj->{reqtype} = $self->{reqtype};
+ $obj->$meth();
+ }
+}
+
+# If a bundle contains another that contains an xs_file we have here,
+# we just don't bother I suppose
+#-> sub CPAN::Bundle::xs_file
+sub xs_file {
+ return 0;
+}
+
+#-> sub CPAN::Bundle::force ;
+sub fforce { shift->rematein('fforce',@_); }
+#-> sub CPAN::Bundle::force ;
+sub force { shift->rematein('force',@_); }
+#-> sub CPAN::Bundle::notest ;
+sub notest { shift->rematein('notest',@_); }
+#-> sub CPAN::Bundle::get ;
+sub get { shift->rematein('get',@_); }
+#-> sub CPAN::Bundle::make ;
+sub make { shift->rematein('make',@_); }
+#-> sub CPAN::Bundle::test ;
+sub test {
+ my $self = shift;
+ # $self->{badtestcnt} ||= 0;
+ $self->rematein('test',@_);
+}
+#-> sub CPAN::Bundle::install ;
+sub install {
+ my $self = shift;
+ $self->rematein('install',@_);
+}
+#-> sub CPAN::Bundle::clean ;
+sub clean { shift->rematein('clean',@_); }
+
+#-> sub CPAN::Bundle::uptodate ;
+sub uptodate {
+ my($self) = @_;
+ return 0 unless $self->SUPER::uptodate; # we mut have the current Bundle def
+ my $c;
+ foreach $c ($self->contains) {
+ my $obj = CPAN::Shell->expandany($c);
+ return 0 unless $obj->uptodate;
+ }
+ return 1;
+}
+
+#-> sub CPAN::Bundle::readme ;
+sub readme {
+ my($self) = @_;
+ my($file) = $self->cpan_file or $CPAN::Frontend->myprint(qq{
+No File found for bundle } . $self->id . qq{\n}), return;
+ $self->debug("self[$self] file[$file]") if $CPAN::DEBUG;
+ $CPAN::META->instance('CPAN::Distribution',$file)->readme;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/CacheMgr.pm b/Master/tlpkg/tlperl/lib/CPAN/CacheMgr.pm
new file mode 100644
index 00000000000..827baeaefdb
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/CacheMgr.pm
@@ -0,0 +1,246 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+# vim: ts=4 sts=4 sw=4:
+package CPAN::CacheMgr;
+use strict;
+use CPAN::InfoObj;
+@CPAN::CacheMgr::ISA = qw(CPAN::InfoObj CPAN);
+use Cwd qw(chdir);
+use File::Find;
+
+use vars qw(
+ $VERSION
+);
+$VERSION = "5.5";
+
+package CPAN::CacheMgr;
+use strict;
+
+#-> sub CPAN::CacheMgr::as_string ;
+sub as_string {
+ eval { require Data::Dumper };
+ if ($@) {
+ return shift->SUPER::as_string;
+ } else {
+ return Data::Dumper::Dumper(shift);
+ }
+}
+
+#-> sub CPAN::CacheMgr::cachesize ;
+sub cachesize {
+ shift->{DU};
+}
+
+#-> sub CPAN::CacheMgr::tidyup ;
+sub tidyup {
+ my($self) = @_;
+ return unless $CPAN::META->{LOCK};
+ return unless -d $self->{ID};
+ my @toremove = grep { $self->{SIZE}{$_}==0 } @{$self->{FIFO}};
+ for my $current (0..$#toremove) {
+ my $toremove = $toremove[$current];
+ $CPAN::Frontend->myprint(sprintf(
+ "DEL(%d/%d): %s \n",
+ $current+1,
+ scalar @toremove,
+ $toremove,
+ )
+ );
+ return if $CPAN::Signal;
+ $self->_clean_cache($toremove);
+ return if $CPAN::Signal;
+ }
+}
+
+#-> sub CPAN::CacheMgr::dir ;
+sub dir {
+ shift->{ID};
+}
+
+#-> sub CPAN::CacheMgr::entries ;
+sub entries {
+ my($self,$dir) = @_;
+ return unless defined $dir;
+ $self->debug("reading dir[$dir]") if $CPAN::DEBUG;
+ $dir ||= $self->{ID};
+ my($cwd) = CPAN::anycwd();
+ chdir $dir or Carp::croak("Can't chdir to $dir: $!");
+ my $dh = DirHandle->new(File::Spec->curdir)
+ or Carp::croak("Couldn't opendir $dir: $!");
+ my(@entries);
+ for ($dh->read) {
+ next if $_ eq "." || $_ eq "..";
+ if (-f $_) {
+ push @entries, File::Spec->catfile($dir,$_);
+ } elsif (-d _) {
+ push @entries, File::Spec->catdir($dir,$_);
+ } else {
+ $CPAN::Frontend->mywarn("Warning: weird direntry in $dir: $_\n");
+ }
+ }
+ chdir $cwd or Carp::croak("Can't chdir to $cwd: $!");
+ sort { -M $a <=> -M $b} @entries;
+}
+
+#-> sub CPAN::CacheMgr::disk_usage ;
+sub disk_usage {
+ my($self,$dir,$fast) = @_;
+ return if exists $self->{SIZE}{$dir};
+ return if $CPAN::Signal;
+ my($Du) = 0;
+ if (-e $dir) {
+ if (-d $dir) {
+ unless (-x $dir) {
+ unless (chmod 0755, $dir) {
+ $CPAN::Frontend->mywarn("I have neither the -x permission nor the ".
+ "permission to change the permission; cannot ".
+ "estimate disk usage of '$dir'\n");
+ $CPAN::Frontend->mysleep(5);
+ return;
+ }
+ }
+ } elsif (-f $dir) {
+ # nothing to say, no matter what the permissions
+ }
+ } else {
+ $CPAN::Frontend->mywarn("File or directory '$dir' has gone, ignoring\n");
+ return;
+ }
+ if ($fast) {
+ $Du = 0; # placeholder
+ } else {
+ find(
+ sub {
+ $File::Find::prune++ if $CPAN::Signal;
+ return if -l $_;
+ if ($^O eq 'MacOS') {
+ require Mac::Files;
+ my $cat = Mac::Files::FSpGetCatInfo($_);
+ $Du += $cat->ioFlLgLen() + $cat->ioFlRLgLen() if $cat;
+ } else {
+ if (-d _) {
+ unless (-x _) {
+ unless (chmod 0755, $_) {
+ $CPAN::Frontend->mywarn("I have neither the -x permission nor ".
+ "the permission to change the permission; ".
+ "can only partially estimate disk usage ".
+ "of '$_'\n");
+ $CPAN::Frontend->mysleep(5);
+ return;
+ }
+ }
+ } else {
+ $Du += (-s _);
+ }
+ }
+ },
+ $dir
+ );
+ }
+ return if $CPAN::Signal;
+ $self->{SIZE}{$dir} = $Du/1024/1024;
+ unshift @{$self->{FIFO}}, $dir;
+ $self->debug("measured $dir is $Du") if $CPAN::DEBUG;
+ $self->{DU} += $Du/1024/1024;
+ $self->{DU};
+}
+
+#-> sub CPAN::CacheMgr::_clean_cache ;
+sub _clean_cache {
+ my($self,$dir) = @_;
+ return unless -e $dir;
+ unless (File::Spec->canonpath(File::Basename::dirname($dir))
+ eq File::Spec->canonpath($CPAN::Config->{build_dir})) {
+ $CPAN::Frontend->mywarn("Directory '$dir' not below $CPAN::Config->{build_dir}, ".
+ "will not remove\n");
+ $CPAN::Frontend->mysleep(5);
+ return;
+ }
+ $self->debug("have to rmtree $dir, will free $self->{SIZE}{$dir}")
+ if $CPAN::DEBUG;
+ File::Path::rmtree($dir);
+ my $id_deleted = 0;
+ if ($dir !~ /\.yml$/ && -f "$dir.yml") {
+ my $yaml_module = CPAN::_yaml_module();
+ if ($CPAN::META->has_inst($yaml_module)) {
+ my($peek_yaml) = eval { CPAN->_yaml_loadfile("$dir.yml"); };
+ if ($@) {
+ $CPAN::Frontend->mywarn("(parse error on '$dir.yml' removing anyway)");
+ unlink "$dir.yml" or
+ $CPAN::Frontend->mywarn("(Could not unlink '$dir.yml': $!)");
+ return;
+ } elsif (my $id = $peek_yaml->[0]{distribution}{ID}) {
+ $CPAN::META->delete("CPAN::Distribution", $id);
+
+ # XXX we should restore the state NOW, otherise this
+ # distro does not exist until we read an index. BUG ALERT(?)
+
+ # $CPAN::Frontend->mywarn (" +++\n");
+ $id_deleted++;
+ }
+ }
+ unlink "$dir.yml"; # may fail
+ unless ($id_deleted) {
+ CPAN->debug("no distro found associated with '$dir'");
+ }
+ }
+ $self->{DU} -= $self->{SIZE}{$dir};
+ delete $self->{SIZE}{$dir};
+}
+
+#-> sub CPAN::CacheMgr::new ;
+sub new {
+ my $class = shift;
+ my $time = time;
+ my($debug,$t2);
+ $debug = "";
+ my $self = {
+ ID => $CPAN::Config->{build_dir},
+ MAX => $CPAN::Config->{'build_cache'},
+ SCAN => $CPAN::Config->{'scan_cache'} || 'atstart',
+ DU => 0
+ };
+ File::Path::mkpath($self->{ID});
+ my $dh = DirHandle->new($self->{ID});
+ bless $self, $class;
+ $self->scan_cache;
+ $t2 = time;
+ $debug .= "timing of CacheMgr->new: ".($t2 - $time);
+ $time = $t2;
+ CPAN->debug($debug) if $CPAN::DEBUG;
+ $self;
+}
+
+#-> sub CPAN::CacheMgr::scan_cache ;
+sub scan_cache {
+ my $self = shift;
+ return if $self->{SCAN} eq 'never';
+ $CPAN::Frontend->mydie("Unknown scan_cache argument: $self->{SCAN}")
+ unless $self->{SCAN} eq 'atstart';
+ return unless $CPAN::META->{LOCK};
+ $CPAN::Frontend->myprint(
+ sprintf("Scanning cache %s for sizes\n",
+ $self->{ID}));
+ my $e;
+ my @entries = $self->entries($self->{ID});
+ my $i = 0;
+ my $painted = 0;
+ for $e (@entries) {
+ my $symbol = ".";
+ if ($self->{DU} > $self->{MAX}) {
+ $symbol = "-";
+ $self->disk_usage($e,1);
+ } else {
+ $self->disk_usage($e);
+ }
+ $i++;
+ while (($painted/76) < ($i/@entries)) {
+ $CPAN::Frontend->myprint($symbol);
+ $painted++;
+ }
+ return if $CPAN::Signal;
+ }
+ $CPAN::Frontend->myprint("DONE\n");
+ $self->tidyup;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Complete.pm b/Master/tlpkg/tlperl/lib/CPAN/Complete.pm
new file mode 100644
index 00000000000..e1fe896d4a5
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Complete.pm
@@ -0,0 +1,175 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+# vim: ts=4 sts=4 sw=4:
+package CPAN::Complete;
+use strict;
+@CPAN::Complete::ISA = qw(CPAN::Debug);
+# Q: where is the "How do I add a new command" HOWTO?
+# A: svn diff -r 1048:1049 where andk added the report command
+@CPAN::Complete::COMMANDS = sort qw(
+ ? ! a b d h i m o q r u
+ autobundle
+ bye
+ clean
+ cvs_import
+ dump
+ exit
+ failed
+ force
+ fforce
+ hosts
+ install
+ install_tested
+ is_tested
+ look
+ ls
+ make
+ mkmyconfig
+ notest
+ perldoc
+ quit
+ readme
+ recent
+ recompile
+ reload
+ report
+ reports
+ scripts
+ smoke
+ test
+ upgrade
+);
+
+use vars qw(
+ $VERSION
+);
+$VERSION = "5.5";
+
+package CPAN::Complete;
+use strict;
+
+sub gnu_cpl {
+ my($text, $line, $start, $end) = @_;
+ my(@perlret) = cpl($text, $line, $start);
+ # find longest common match. Can anybody show me how to peruse
+ # T::R::Gnu to have this done automatically? Seems expensive.
+ return () unless @perlret;
+ my($newtext) = $text;
+ for (my $i = length($text)+1;;$i++) {
+ last unless length($perlret[0]) && length($perlret[0]) >= $i;
+ my $try = substr($perlret[0],0,$i);
+ my @tries = grep {substr($_,0,$i) eq $try} @perlret;
+ # warn "try[$try]tries[@tries]";
+ if (@tries == @perlret) {
+ $newtext = $try;
+ } else {
+ last;
+ }
+ }
+ ($newtext,@perlret);
+}
+
+#-> sub CPAN::Complete::cpl ;
+sub cpl {
+ my($word,$line,$pos) = @_;
+ $word ||= "";
+ $line ||= "";
+ $pos ||= 0;
+ CPAN->debug("word [$word] line[$line] pos[$pos]") if $CPAN::DEBUG;
+ $line =~ s/^\s*//;
+ if ($line =~ s/^((?:notest|f?force)\s*)//) {
+ $pos -= length($1);
+ }
+ my @return;
+ if ($pos == 0 || $line =~ /^(?:h(?:elp)?|\?)\s/) {
+ @return = grep /^\Q$word\E/, @CPAN::Complete::COMMANDS;
+ } elsif ( $line !~ /^[\!abcdghimorutl]/ ) {
+ @return = ();
+ } elsif ($line =~ /^a\s/) {
+ @return = cplx('CPAN::Author',uc($word));
+ } elsif ($line =~ /^ls\s/) {
+ my($author,$rest) = $word =~ m|([^/]+)/?(.*)|;
+ @return = $rest ? () : map {"$_/"} cplx('CPAN::Author',uc($author||""));
+ if (0 && 1==@return) { # XXX too slow and even wrong when there is a * already
+ @return = grep /^\Q$word\E/, map {"$author/$_->[2]"} CPAN::Shell->expand("Author",$author)->ls("$rest*","2");
+ }
+ } elsif ($line =~ /^b\s/) {
+ CPAN::Shell->local_bundles;
+ @return = cplx('CPAN::Bundle',$word);
+ } elsif ($line =~ /^d\s/) {
+ @return = cplx('CPAN::Distribution',$word);
+ } elsif ($line =~ m/^(
+ [mru]|make|clean|dump|get|test|install|readme|look|cvs_import|perldoc|recent
+ )\s/x ) {
+ if ($word =~ /^Bundle::/) {
+ CPAN::Shell->local_bundles;
+ }
+ @return = (cplx('CPAN::Module',$word),cplx('CPAN::Bundle',$word));
+ } elsif ($line =~ /^i\s/) {
+ @return = cpl_any($word);
+ } elsif ($line =~ /^reload\s/) {
+ @return = cpl_reload($word,$line,$pos);
+ } elsif ($line =~ /^o\s/) {
+ @return = cpl_option($word,$line,$pos);
+ } elsif ($line =~ m/^\S+\s/ ) {
+ # fallback for future commands and what we have forgotten above
+ @return = (cplx('CPAN::Module',$word),cplx('CPAN::Bundle',$word));
+ } else {
+ @return = ();
+ }
+ return @return;
+}
+
+#-> sub CPAN::Complete::cplx ;
+sub cplx {
+ my($class, $word) = @_;
+ if (CPAN::_sqlite_running()) {
+ $CPAN::SQLite->search($class, "^\Q$word\E");
+ }
+ my $method = "id";
+ $method = "pretty_id" if $class eq "CPAN::Distribution";
+ sort grep /^\Q$word\E/, map { $_->$method() } $CPAN::META->all_objects($class);
+}
+
+#-> sub CPAN::Complete::cpl_any ;
+sub cpl_any {
+ my($word) = shift;
+ return (
+ cplx('CPAN::Author',$word),
+ cplx('CPAN::Bundle',$word),
+ cplx('CPAN::Distribution',$word),
+ cplx('CPAN::Module',$word),
+ );
+}
+
+#-> sub CPAN::Complete::cpl_reload ;
+sub cpl_reload {
+ my($word,$line,$pos) = @_;
+ $word ||= "";
+ my(@words) = split " ", $line;
+ CPAN->debug("word[$word] line[$line] pos[$pos]") if $CPAN::DEBUG;
+ my(@ok) = qw(cpan index);
+ return @ok if @words == 1;
+ return grep /^\Q$word\E/, @ok if @words == 2 && $word;
+}
+
+#-> sub CPAN::Complete::cpl_option ;
+sub cpl_option {
+ my($word,$line,$pos) = @_;
+ $word ||= "";
+ my(@words) = split " ", $line;
+ CPAN->debug("word[$word] line[$line] pos[$pos]") if $CPAN::DEBUG;
+ my(@ok) = qw(conf debug);
+ return @ok if @words == 1;
+ return grep /^\Q$word\E/, @ok if @words == 2 && length($word);
+ if (0) {
+ } elsif ($words[1] eq 'index') {
+ return ();
+ } elsif ($words[1] eq 'conf') {
+ return CPAN::HandleConfig::cpl(@_);
+ } elsif ($words[1] eq 'debug') {
+ return sort grep /^\Q$word\E/i,
+ sort keys %CPAN::DEBUG, 'all';
+ }
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Debug.pm b/Master/tlpkg/tlperl/lib/CPAN/Debug.pm
new file mode 100644
index 00000000000..23c4a3685b6
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Debug.pm
@@ -0,0 +1,79 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+package CPAN::Debug;
+use strict;
+use vars qw($VERSION);
+
+$VERSION = "5.5001";
+# module is internal to CPAN.pm
+
+%CPAN::DEBUG = qw[
+ CPAN 1
+ Index 2
+ InfoObj 4
+ Author 8
+ Distribution 16
+ Bundle 32
+ Module 64
+ CacheMgr 128
+ Complete 256
+ FTP 512
+ Shell 1024
+ Eval 2048
+ HandleConfig 4096
+ Tarzip 8192
+ Version 16384
+ Queue 32768
+ FirstTime 65536
+];
+
+$CPAN::DEBUG ||= 0;
+
+#-> sub CPAN::Debug::debug ;
+sub debug {
+ my($self,$arg) = @_;
+
+ my @caller;
+ my $i = 0;
+ while () {
+ my(@c) = (caller($i))[0 .. ($i ? 3 : 2)];
+ last unless defined $c[0];
+ push @caller, \@c;
+ for (0,3) {
+ last if $_ > $#c;
+ $c[$_] =~ s/.*:://;
+ }
+ for (1) {
+ $c[$_] =~ s|.*/||;
+ }
+ last if ++$i>=3;
+ }
+ pop @caller;
+ if ($CPAN::DEBUG{$caller[0][0]} & $CPAN::DEBUG) {
+ if ($arg and ref $arg) {
+ eval { require Data::Dumper };
+ if ($@) {
+ $CPAN::Frontend->myprint("Debug(\n" . $arg->as_string . ")\n");
+ } else {
+ $CPAN::Frontend->myprint("Debug(\n" . Data::Dumper::Dumper($arg) . ")\n");
+ }
+ } else {
+ my $outer = "";
+ local $" = ",";
+ if (@caller>1) {
+ $outer = ",[@{$caller[1]}]";
+ }
+ $CPAN::Frontend->myprint("Debug(@{$caller[0]}$outer): $arg\n");
+ }
+ }
+}
+
+1;
+
+__END__
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/CPAN/DeferredCode.pm b/Master/tlpkg/tlperl/lib/CPAN/DeferredCode.pm
new file mode 100644
index 00000000000..0db37a64853
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/DeferredCode.pm
@@ -0,0 +1,16 @@
+package CPAN::DeferredCode;
+
+use strict;
+use vars qw/$VERSION/;
+
+use overload fallback => 1, map { ($_ => 'run') } qw/
+ bool "" 0+
+/;
+
+$VERSION = "5.50";
+
+sub run {
+ $_[0]->();
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Distribution.pm b/Master/tlpkg/tlperl/lib/CPAN/Distribution.pm
new file mode 100644
index 00000000000..ac8f873a130
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Distribution.pm
@@ -0,0 +1,3896 @@
+package CPAN::Distribution;
+use strict;
+use Cwd qw(chdir);
+use CPAN::Distroprefs;
+use CPAN::InfoObj;
+@CPAN::Distribution::ISA = qw(CPAN::InfoObj);
+use vars qw($VERSION);
+$VERSION = "1.9456_01";
+
+# Accessors
+sub cpan_comment {
+ my $self = shift;
+ my $ro = $self->ro or return;
+ $ro->{CPAN_COMMENT}
+}
+
+#-> CPAN::Distribution::undelay
+sub undelay {
+ my $self = shift;
+ for my $delayer (
+ "configure_requires_later",
+ "configure_requires_later_for",
+ "later",
+ "later_for",
+ ) {
+ delete $self->{$delayer};
+ }
+}
+
+#-> CPAN::Distribution::is_dot_dist
+sub is_dot_dist {
+ my($self) = @_;
+ return substr($self->id,-1,1) eq ".";
+}
+
+# add the A/AN/ stuff
+#-> CPAN::Distribution::normalize
+sub normalize {
+ my($self,$s) = @_;
+ $s = $self->id unless defined $s;
+ if (substr($s,-1,1) eq ".") {
+ # using a global because we are sometimes called as static method
+ if (!$CPAN::META->{LOCK}
+ && !$CPAN::Have_warned->{"$s is unlocked"}++
+ ) {
+ $CPAN::Frontend->mywarn("You are visiting the local directory
+ '$s'
+ without lock, take care that concurrent processes do not do likewise.\n");
+ $CPAN::Frontend->mysleep(1);
+ }
+ if ($s eq ".") {
+ $s = "$CPAN::iCwd/.";
+ } elsif (File::Spec->file_name_is_absolute($s)) {
+ } elsif (File::Spec->can("rel2abs")) {
+ $s = File::Spec->rel2abs($s);
+ } else {
+ $CPAN::Frontend->mydie("Your File::Spec is too old, please upgrade File::Spec");
+ }
+ CPAN->debug("s[$s]") if $CPAN::DEBUG;
+ unless ($CPAN::META->exists("CPAN::Distribution", $s)) {
+ for ($CPAN::META->instance("CPAN::Distribution", $s)) {
+ $_->{build_dir} = $s;
+ $_->{archived} = "local_directory";
+ $_->{unwrapped} = CPAN::Distrostatus->new("YES -- local_directory");
+ }
+ }
+ } elsif (
+ $s =~ tr|/|| == 1
+ or
+ $s !~ m|[A-Z]/[A-Z-]{2}/[A-Z-]{2,}/|
+ ) {
+ return $s if $s =~ m:^N/A|^Contact Author: ;
+ $s =~ s|^(.)(.)([^/]*/)(.+)$|$1/$1$2/$1$2$3$4|;
+ CPAN->debug("s[$s]") if $CPAN::DEBUG;
+ }
+ $s;
+}
+
+#-> sub CPAN::Distribution::author ;
+sub author {
+ my($self) = @_;
+ my($authorid);
+ if (substr($self->id,-1,1) eq ".") {
+ $authorid = "LOCAL";
+ } else {
+ ($authorid) = $self->pretty_id =~ /^([\w\-]+)/;
+ }
+ CPAN::Shell->expand("Author",$authorid);
+}
+
+# tries to get the yaml from CPAN instead of the distro itself:
+# EXPERIMENTAL, UNDOCUMENTED AND UNTESTED, for Tels
+sub fast_yaml {
+ my($self) = @_;
+ my $meta = $self->pretty_id;
+ $meta =~ s/\.(tar.gz|tgz|zip|tar.bz2)/.meta/;
+ my(@ls) = CPAN::Shell->globls($meta);
+ my $norm = $self->normalize($meta);
+
+ my($local_file);
+ my($local_wanted) =
+ File::Spec->catfile(
+ $CPAN::Config->{keep_source_where},
+ "authors",
+ "id",
+ split(/\//,$norm)
+ );
+ $self->debug("Doing localize") if $CPAN::DEBUG;
+ unless ($local_file =
+ CPAN::FTP->localize("authors/id/$norm",
+ $local_wanted)) {
+ $CPAN::Frontend->mydie("Giving up on downloading yaml file '$local_wanted'\n");
+ }
+ my $yaml = CPAN->_yaml_loadfile($local_file)->[0];
+}
+
+#-> sub CPAN::Distribution::cpan_userid
+sub cpan_userid {
+ my $self = shift;
+ if ($self->{ID} =~ m{[A-Z]/[A-Z\-]{2}/([A-Z\-]+)/}) {
+ return $1;
+ }
+ return $self->SUPER::cpan_userid;
+}
+
+#-> sub CPAN::Distribution::pretty_id
+sub pretty_id {
+ my $self = shift;
+ my $id = $self->id;
+ return $id unless $id =~ m|^./../|;
+ substr($id,5);
+}
+
+#-> sub CPAN::Distribution::base_id
+sub base_id {
+ my $self = shift;
+ my $id = $self->pretty_id();
+ my $base_id = File::Basename::basename($id);
+ $base_id =~ s{\.(?:tar\.(bz2|gz|Z)|t(?:gz|bz)|zip)$}{}i;
+ return $base_id;
+}
+
+#-> sub CPAN::Distribution::tested_ok_but_not_installed
+sub tested_ok_but_not_installed {
+ my $self = shift;
+ return (
+ $self->{make_test}
+ && $self->{build_dir}
+ && (UNIVERSAL::can($self->{make_test},"failed") ?
+ ! $self->{make_test}->failed :
+ $self->{make_test} =~ /^YES/
+ )
+ && (
+ !$self->{install}
+ ||
+ $self->{install}->failed
+ )
+ );
+}
+
+
+# mark as dirty/clean for the sake of recursion detection. $color=1
+# means "in use", $color=0 means "not in use anymore". $color=2 means
+# we have determined prereqs now and thus insist on passing this
+# through (at least) once again.
+
+#-> sub CPAN::Distribution::color_cmd_tmps ;
+sub color_cmd_tmps {
+ my($self) = shift;
+ my($depth) = shift || 0;
+ my($color) = shift || 0;
+ my($ancestors) = shift || [];
+ # a distribution needs to recurse into its prereq_pms
+ $self->debug("color_cmd_tmps[$depth,$color,@$ancestors]") if $CPAN::DEBUG;
+
+ return if exists $self->{incommandcolor}
+ && $color==1
+ && $self->{incommandcolor}==$color;
+ if ($depth>=$CPAN::MAX_RECURSION) {
+ die(CPAN::Exception::RecursiveDependency->new($ancestors));
+ }
+ # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1;
+ my $prereq_pm = $self->prereq_pm;
+ if (defined $prereq_pm) {
+ PREREQ: for my $pre (keys %{$prereq_pm->{requires}||{}},
+ keys %{$prereq_pm->{build_requires}||{}}) {
+ next PREREQ if $pre eq "perl";
+ my $premo;
+ unless ($premo = CPAN::Shell->expand("Module",$pre)) {
+ $CPAN::Frontend->mywarn("prerequisite module[$pre] not known\n");
+ $CPAN::Frontend->mysleep(2);
+ next PREREQ;
+ }
+ $premo->color_cmd_tmps($depth+1,$color,[@$ancestors, $self->id]);
+ }
+ }
+ if ($color==0) {
+ delete $self->{sponsored_mods};
+
+ # as we are at the end of a command, we'll give up this
+ # reminder of a broken test. Other commands may test this guy
+ # again. Maybe 'badtestcnt' should be renamed to
+ # 'make_test_failed_within_command'?
+ delete $self->{badtestcnt};
+ }
+ $self->{incommandcolor} = $color;
+}
+
+#-> sub CPAN::Distribution::as_string ;
+sub as_string {
+ my $self = shift;
+ $self->containsmods;
+ $self->upload_date;
+ $self->SUPER::as_string(@_);
+}
+
+#-> sub CPAN::Distribution::containsmods ;
+sub containsmods {
+ my $self = shift;
+ return keys %{$self->{CONTAINSMODS}} if exists $self->{CONTAINSMODS};
+ my $dist_id = $self->{ID};
+ for my $mod ($CPAN::META->all_objects("CPAN::Module")) {
+ my $mod_file = $mod->cpan_file or next;
+ my $mod_id = $mod->{ID} or next;
+ # warn "mod_file[$mod_file] dist_id[$dist_id] mod_id[$mod_id]";
+ # sleep 1;
+ if ($CPAN::Signal) {
+ delete $self->{CONTAINSMODS};
+ return;
+ }
+ $self->{CONTAINSMODS}{$mod_id} = undef if $mod_file eq $dist_id;
+ }
+ keys %{$self->{CONTAINSMODS}||={}};
+}
+
+#-> sub CPAN::Distribution::upload_date ;
+sub upload_date {
+ my $self = shift;
+ return $self->{UPLOAD_DATE} if exists $self->{UPLOAD_DATE};
+ my(@local_wanted) = split(/\//,$self->id);
+ my $filename = pop @local_wanted;
+ push @local_wanted, "CHECKSUMS";
+ my $author = CPAN::Shell->expand("Author",$self->cpan_userid);
+ return unless $author;
+ my @dl = $author->dir_listing(\@local_wanted,0,$CPAN::Config->{show_upload_date});
+ return unless @dl;
+ my($dirent) = grep { $_->[2] eq $filename } @dl;
+ # warn sprintf "dirent[%s]id[%s]", $dirent, $self->id;
+ return unless $dirent->[1];
+ return $self->{UPLOAD_DATE} = $dirent->[1];
+}
+
+#-> sub CPAN::Distribution::uptodate ;
+sub uptodate {
+ my($self) = @_;
+ my $c;
+ foreach $c ($self->containsmods) {
+ my $obj = CPAN::Shell->expandany($c);
+ unless ($obj->uptodate) {
+ my $id = $self->pretty_id;
+ $self->debug("$id not uptodate due to $c") if $CPAN::DEBUG;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+#-> sub CPAN::Distribution::called_for ;
+sub called_for {
+ my($self,$id) = @_;
+ $self->{CALLED_FOR} = $id if defined $id;
+ return $self->{CALLED_FOR};
+}
+
+#-> sub CPAN::Distribution::get ;
+sub get {
+ my($self) = @_;
+ $self->debug("checking goto id[$self->{ID}]") if $CPAN::DEBUG;
+ if (my $goto = $self->prefs->{goto}) {
+ $CPAN::Frontend->mywarn
+ (sprintf(
+ "delegating to '%s' as specified in prefs file '%s' doc %d\n",
+ $goto,
+ $self->{prefs_file},
+ $self->{prefs_file_doc},
+ ));
+ return $self->goto($goto);
+ }
+ local $ENV{PERL5LIB} = defined($ENV{PERL5LIB})
+ ? $ENV{PERL5LIB}
+ : ($ENV{PERLLIB} || "");
+ local $ENV{PERL5OPT} = defined $ENV{PERL5OPT} ? $ENV{PERL5OPT} : "";
+ $CPAN::META->set_perl5lib;
+ local $ENV{MAKEFLAGS}; # protect us from outer make calls
+
+ EXCUSE: {
+ my @e;
+ my $goodbye_message;
+ $self->debug("checking disabled id[$self->{ID}]") if $CPAN::DEBUG;
+ if ($self->prefs->{disabled} && ! $self->{force_update}) {
+ my $why = sprintf(
+ "Disabled via prefs file '%s' doc %d",
+ $self->{prefs_file},
+ $self->{prefs_file_doc},
+ );
+ push @e, $why;
+ $self->{unwrapped} = CPAN::Distrostatus->new("NO $why");
+ $goodbye_message = "[disabled] -- NA $why";
+ # note: not intended to be persistent but at least visible
+ # during this session
+ } else {
+ if (exists $self->{build_dir} && -d $self->{build_dir}
+ && ($self->{modulebuild}||$self->{writemakefile})
+ ) {
+ # this deserves print, not warn:
+ $CPAN::Frontend->myprint(" Has already been unwrapped into directory ".
+ "$self->{build_dir}\n"
+ );
+ return 1;
+ }
+
+ # although we talk about 'force' we shall not test on
+ # force directly. New model of force tries to refrain from
+ # direct checking of force.
+ exists $self->{unwrapped} and (
+ UNIVERSAL::can($self->{unwrapped},"failed") ?
+ $self->{unwrapped}->failed :
+ $self->{unwrapped} =~ /^NO/
+ )
+ and push @e, "Unwrapping had some problem, won't try again without force";
+ }
+ if (@e) {
+ $CPAN::Frontend->mywarn(join "", map {"$_\n"} @e);
+ if ($goodbye_message) {
+ $self->goodbye($goodbye_message);
+ }
+ return;
+ }
+ }
+ my $sub_wd = CPAN::anycwd(); # for cleaning up as good as possible
+
+ my($local_file);
+ unless ($self->{build_dir} && -d $self->{build_dir}) {
+ $self->get_file_onto_local_disk;
+ return if $CPAN::Signal;
+ $self->check_integrity;
+ return if $CPAN::Signal;
+ (my $packagedir,$local_file) = $self->run_preps_on_packagedir;
+ if (exists $self->{writemakefile} && ref $self->{writemakefile}
+ && $self->{writemakefile}->can("failed") &&
+ $self->{writemakefile}->failed) {
+ return;
+ }
+ $packagedir ||= $self->{build_dir};
+ $self->{build_dir} = $packagedir;
+ }
+
+ if ($CPAN::Signal) {
+ $self->safe_chdir($sub_wd);
+ return;
+ }
+ return $self->choose_MM_or_MB($local_file);
+}
+
+#-> CPAN::Distribution::get_file_onto_local_disk
+sub get_file_onto_local_disk {
+ my($self) = @_;
+
+ return if $self->is_dot_dist;
+ my($local_file);
+ my($local_wanted) =
+ File::Spec->catfile(
+ $CPAN::Config->{keep_source_where},
+ "authors",
+ "id",
+ split(/\//,$self->id)
+ );
+
+ $self->debug("Doing localize") if $CPAN::DEBUG;
+ unless ($local_file =
+ CPAN::FTP->localize("authors/id/$self->{ID}",
+ $local_wanted)) {
+ my $note = "";
+ if ($CPAN::Index::DATE_OF_02) {
+ $note = "Note: Current database in memory was generated ".
+ "on $CPAN::Index::DATE_OF_02\n";
+ }
+ $CPAN::Frontend->mydie("Giving up on '$local_wanted'\n$note");
+ }
+
+ $self->debug("local_wanted[$local_wanted]local_file[$local_file]") if $CPAN::DEBUG;
+ $self->{localfile} = $local_file;
+}
+
+
+#-> CPAN::Distribution::check_integrity
+sub check_integrity {
+ my($self) = @_;
+
+ return if $self->is_dot_dist;
+ if ($CPAN::META->has_inst("Digest::SHA")) {
+ $self->debug("Digest::SHA is installed, verifying");
+ $self->verifyCHECKSUM;
+ } else {
+ $self->debug("Digest::SHA is NOT installed");
+ }
+}
+
+#-> CPAN::Distribution::run_preps_on_packagedir
+sub run_preps_on_packagedir {
+ my($self) = @_;
+ return if $self->is_dot_dist;
+
+ $CPAN::META->{cachemgr} ||= CPAN::CacheMgr->new(); # unsafe meta access, ok
+ my $builddir = $CPAN::META->{cachemgr}->dir; # unsafe meta access, ok
+ $self->safe_chdir($builddir);
+ $self->debug("Removing tmp-$$") if $CPAN::DEBUG;
+ File::Path::rmtree("tmp-$$");
+ unless (mkdir "tmp-$$", 0755) {
+ $CPAN::Frontend->unrecoverable_error(<<EOF);
+Couldn't mkdir '$builddir/tmp-$$': $!
+
+Cannot continue: Please find the reason why I cannot make the
+directory
+$builddir/tmp-$$
+and fix the problem, then retry.
+
+EOF
+ }
+ if ($CPAN::Signal) {
+ return;
+ }
+ $self->safe_chdir("tmp-$$");
+
+ #
+ # Unpack the goods
+ #
+ my $local_file = $self->{localfile};
+ my $ct = eval{CPAN::Tarzip->new($local_file)};
+ unless ($ct) {
+ $self->{unwrapped} = CPAN::Distrostatus->new("NO");
+ delete $self->{build_dir};
+ return;
+ }
+ if ($local_file =~ /(\.tar\.(bz2|gz|Z)|\.tgz)(?!\n)\Z/i) {
+ $self->{was_uncompressed}++ unless eval{$ct->gtest()};
+ $self->untar_me($ct);
+ } elsif ( $local_file =~ /\.zip(?!\n)\Z/i ) {
+ $self->unzip_me($ct);
+ } else {
+ $self->{was_uncompressed}++ unless $ct->gtest();
+ $local_file = $self->handle_singlefile($local_file);
+ }
+
+ # we are still in the tmp directory!
+ # Let's check if the package has its own directory.
+ my $dh = DirHandle->new(File::Spec->curdir)
+ or Carp::croak("Couldn't opendir .: $!");
+ my @readdir = grep $_ !~ /^\.\.?(?!\n)\Z/s, $dh->read; ### MAC??
+ if (grep { $_ eq "pax_global_header" } @readdir) {
+ $CPAN::Frontend->mywarn("Your (un)tar seems to have extracted a file named 'pax_global_header'
+from the tarball '$local_file'.
+This is almost certainly an error. Please upgrade your tar.
+I'll ignore this file for now.
+See also http://rt.cpan.org/Ticket/Display.html?id=38932\n");
+ $CPAN::Frontend->mysleep(5);
+ @readdir = grep { $_ ne "pax_global_header" } @readdir;
+ }
+ $dh->close;
+ my ($packagedir);
+ # XXX here we want in each branch File::Temp to protect all build_dir directories
+ if (CPAN->has_usable("File::Temp")) {
+ my $tdir_base;
+ my $from_dir;
+ my @dirents;
+ if (@readdir == 1 && -d $readdir[0]) {
+ $tdir_base = $readdir[0];
+ $from_dir = File::Spec->catdir(File::Spec->curdir,$readdir[0]);
+ my $dh2;
+ unless ($dh2 = DirHandle->new($from_dir)) {
+ my($mode) = (stat $from_dir)[2];
+ my $why = sprintf
+ (
+ "Couldn't opendir '%s', mode '%o': %s",
+ $from_dir,
+ $mode,
+ $!,
+ );
+ $CPAN::Frontend->mywarn("$why\n");
+ $self->{writemakefile} = CPAN::Distrostatus->new("NO -- $why");
+ return;
+ }
+ @dirents = grep $_ !~ /^\.\.?(?!\n)\Z/s, $dh2->read; ### MAC??
+ } else {
+ my $userid = $self->cpan_userid;
+ CPAN->debug("userid[$userid]");
+ if (!$userid or $userid eq "N/A") {
+ $userid = "anon";
+ }
+ $tdir_base = $userid;
+ $from_dir = File::Spec->curdir;
+ @dirents = @readdir;
+ }
+ $packagedir = File::Temp::tempdir(
+ "$tdir_base-XXXXXX",
+ DIR => $builddir,
+ CLEANUP => 0,
+ );
+ chmod 0777 &~ umask, $packagedir; # may fail
+ my $f;
+ for $f (@dirents) { # is already without "." and ".."
+ my $from = File::Spec->catdir($from_dir,$f);
+ my $to = File::Spec->catdir($packagedir,$f);
+ unless (File::Copy::move($from,$to)) {
+ my $err = $!;
+ $from = File::Spec->rel2abs($from);
+ Carp::confess("Couldn't move $from to $to: $err");
+ }
+ }
+ } else { # older code below, still better than nothing when there is no File::Temp
+ my($distdir);
+ if (@readdir == 1 && -d $readdir[0]) {
+ $distdir = $readdir[0];
+ $packagedir = File::Spec->catdir($builddir,$distdir);
+ $self->debug("packagedir[$packagedir]builddir[$builddir]distdir[$distdir]")
+ if $CPAN::DEBUG;
+ -d $packagedir and $CPAN::Frontend->myprint("Removing previously used ".
+ "$packagedir\n");
+ File::Path::rmtree($packagedir);
+ unless (File::Copy::move($distdir,$packagedir)) {
+ $CPAN::Frontend->unrecoverable_error(<<EOF);
+Couldn't move '$distdir' to '$packagedir': $!
+
+Cannot continue: Please find the reason why I cannot move
+$builddir/tmp-$$/$distdir
+to
+$packagedir
+and fix the problem, then retry
+
+EOF
+ }
+ $self->debug(sprintf("moved distdir[%s] to packagedir[%s] -e[%s]-d[%s]",
+ $distdir,
+ $packagedir,
+ -e $packagedir,
+ -d $packagedir,
+ )) if $CPAN::DEBUG;
+ } else {
+ my $userid = $self->cpan_userid;
+ CPAN->debug("userid[$userid]") if $CPAN::DEBUG;
+ if (!$userid or $userid eq "N/A") {
+ $userid = "anon";
+ }
+ my $pragmatic_dir = $userid . '000';
+ $pragmatic_dir =~ s/\W_//g;
+ $pragmatic_dir++ while -d "../$pragmatic_dir";
+ $packagedir = File::Spec->catdir($builddir,$pragmatic_dir);
+ $self->debug("packagedir[$packagedir]") if $CPAN::DEBUG;
+ File::Path::mkpath($packagedir);
+ my($f);
+ for $f (@readdir) { # is already without "." and ".."
+ my $to = File::Spec->catdir($packagedir,$f);
+ File::Copy::move($f,$to) or Carp::confess("Couldn't move $f to $to: $!");
+ }
+ }
+ }
+ $self->{build_dir} = $packagedir;
+ $self->safe_chdir($builddir);
+ File::Path::rmtree("tmp-$$");
+
+ $self->safe_chdir($packagedir);
+ $self->_signature_business();
+ $self->safe_chdir($builddir);
+
+ return($packagedir,$local_file);
+}
+
+#-> sub CPAN::Distribution::parse_meta_yml ;
+sub parse_meta_yml {
+ my($self, $yaml) = @_;
+ $self->debug(sprintf("parse_meta_yml[%s]",$yaml||'undef')) if $CPAN::DEBUG;
+ my $build_dir = $self->{build_dir} or die "PANIC: cannot parse yaml without a build_dir";
+ $yaml ||= File::Spec->catfile($build_dir,"META.yml");
+ $self->debug("meta[$yaml]") if $CPAN::DEBUG;
+ return unless -f $yaml;
+ my $early_yaml;
+ eval {
+ $CPAN::META->has_inst("Parse::CPAN::Meta") or die;
+ # P::C::M returns last document in scalar context
+ $early_yaml = Parse::CPAN::Meta::LoadFile($yaml);
+ };
+ unless ($early_yaml) {
+ eval { $early_yaml = CPAN->_yaml_loadfile($yaml)->[0]; };
+ }
+ $self->debug(sprintf("yaml[%s]", $early_yaml || 'UNDEF')) if $CPAN::DEBUG;
+ $self->debug($early_yaml) if $CPAN::DEBUG && $early_yaml;
+ return $early_yaml || undef;
+}
+
+#-> sub CPAN::Distribution::satisfy_requires ;
+sub satisfy_requires {
+ my ($self) = @_;
+ $self->debug("Entering satisfy_requires") if $CPAN::DEBUG;
+ if (my @prereq = $self->unsat_prereq("later")) {
+ $self->debug("unsatisfied[@prereq]") if $CPAN::DEBUG;
+ $self->debug(@prereq) if $CPAN::DEBUG && @prereq;
+ if ($prereq[0][0] eq "perl") {
+ my $need = "requires perl '$prereq[0][1]'";
+ my $id = $self->pretty_id;
+ $CPAN::Frontend->mywarn("$id $need; you have only $]; giving up\n");
+ $self->{make} = CPAN::Distrostatus->new("NO $need");
+ $self->store_persistent_state;
+ die "[prereq] -- NOT OK\n";
+ } else {
+ my $follow = eval { $self->follow_prereqs("later",@prereq); };
+ if (0) {
+ } elsif ($follow) {
+ # signal success to the queuerunner
+ return 1;
+ } elsif ($@ && ref $@ && $@->isa("CPAN::Exception::RecursiveDependency")) {
+ $CPAN::Frontend->mywarn($@);
+ die "[depend] -- NOT OK\n";
+ }
+ }
+ }
+ return;
+}
+
+#-> sub CPAN::Distribution::satisfy_configure_requires ;
+sub satisfy_configure_requires {
+ my($self) = @_;
+ $self->debug("Entering satisfy_configure_requires") if $CPAN::DEBUG;
+ my $enable_configure_requires = 1;
+ if (!$enable_configure_requires) {
+ return 1;
+ # if we return 1 here, everything is as before we introduced
+ # configure_requires that means, things with
+ # configure_requires simply fail, all others succeed
+ }
+ my @prereq = $self->unsat_prereq("configure_requires_later");
+ $self->debug("configure_requires[@prereq]") if $CPAN::DEBUG;
+ return 1 unless @prereq;
+ $self->debug(\@prereq) if $CPAN::DEBUG;
+ if ($self->{configure_requires_later}) {
+ for my $k (keys %{$self->{configure_requires_later_for}||{}}) {
+ if ($self->{configure_requires_later_for}{$k}>1) {
+ # we must not come here a second time
+ $CPAN::Frontend->mywarn("Panic: Some prerequisites is not available, please investigate...");
+ require YAML::Syck;
+ $CPAN::Frontend->mydie
+ (
+ YAML::Syck::Dump
+ ({self=>$self, prereq=>\@prereq})
+ );
+ }
+ }
+ }
+ if ($prereq[0][0] eq "perl") {
+ my $need = "requires perl '$prereq[0][1]'";
+ my $id = $self->pretty_id;
+ $CPAN::Frontend->mywarn("$id $need; you have only $]; giving up\n");
+ $self->{make} = CPAN::Distrostatus->new("NO $need");
+ $self->store_persistent_state;
+ return $self->goodbye("[prereq] -- NOT OK");
+ } else {
+ my $follow = eval {
+ $self->follow_prereqs("configure_requires_later", @prereq);
+ };
+ if (0) {
+ } elsif ($follow) {
+ return;
+ } elsif ($@ && ref $@ && $@->isa("CPAN::Exception::RecursiveDependency")) {
+ $CPAN::Frontend->mywarn($@);
+ return $self->goodbye("[depend] -- NOT OK");
+ }
+ else {
+ return $self->goodbye("[configure_requires] -- NOT OK");
+ }
+ }
+ die "never reached";
+}
+
+#-> sub CPAN::Distribution::choose_MM_or_MB ;
+sub choose_MM_or_MB {
+ my($self,$local_file) = @_;
+ $self->satisfy_configure_requires() or return;
+ my($mpl) = File::Spec->catfile($self->{build_dir},"Makefile.PL");
+ my($mpl_exists) = -f $mpl;
+ unless ($mpl_exists) {
+ # NFS has been reported to have racing problems after the
+ # renaming of a directory in some environments.
+ # This trick helps.
+ $CPAN::Frontend->mysleep(1);
+ my $mpldh = DirHandle->new($self->{build_dir})
+ or Carp::croak("Couldn't opendir $self->{build_dir}: $!");
+ $mpl_exists = grep /^Makefile\.PL$/, $mpldh->read;
+ $mpldh->close;
+ }
+ my $prefer_installer = "eumm"; # eumm|mb
+ if (-f File::Spec->catfile($self->{build_dir},"Build.PL")) {
+ if ($mpl_exists) { # they *can* choose
+ if ($CPAN::META->has_inst("Module::Build")) {
+ $prefer_installer = CPAN::HandleConfig->prefs_lookup(
+ $self, q{prefer_installer}
+ );
+ # M::B <= 0.35 left a DATA handle open that
+ # causes problems upgrading M::B on Windows
+ close *Module::Build::Version::DATA
+ if fileno *Module::Build::Version::DATA;
+ }
+ } else {
+ $prefer_installer = "mb";
+ }
+ }
+ return unless $self->patch;
+ if (lc($prefer_installer) eq "rand") {
+ $prefer_installer = rand()<.5 ? "eumm" : "mb";
+ }
+ if (lc($prefer_installer) eq "mb") {
+ $self->{modulebuild} = 1;
+ } elsif ($self->{archived} eq "patch") {
+ # not an edge case, nothing to install for sure
+ my $why = "A patch file cannot be installed";
+ $CPAN::Frontend->mywarn("Refusing to handle this file: $why\n");
+ $self->{writemakefile} = CPAN::Distrostatus->new("NO $why");
+ } elsif (! $mpl_exists) {
+ $self->_edge_cases($mpl,$local_file);
+ }
+ if ($self->{build_dir}
+ &&
+ $CPAN::Config->{build_dir_reuse}
+ ) {
+ $self->store_persistent_state;
+ }
+ return $self;
+}
+
+#-> CPAN::Distribution::store_persistent_state
+sub store_persistent_state {
+ my($self) = @_;
+ my $dir = $self->{build_dir};
+ unless (File::Spec->canonpath(File::Basename::dirname($dir))
+ eq File::Spec->canonpath($CPAN::Config->{build_dir})) {
+ $CPAN::Frontend->mywarnonce("Directory '$dir' not below $CPAN::Config->{build_dir}, ".
+ "will not store persistent state\n");
+ return;
+ }
+ my $file = sprintf "%s.yml", $dir;
+ my $yaml_module = CPAN::_yaml_module();
+ if ($CPAN::META->has_inst($yaml_module)) {
+ CPAN->_yaml_dumpfile(
+ $file,
+ {
+ time => time,
+ perl => CPAN::_perl_fingerprint(),
+ distribution => $self,
+ }
+ );
+ } else {
+ $CPAN::Frontend->myprintonce("'$yaml_module' not installed, ".
+ "will not store persistent state\n");
+ }
+}
+
+#-> CPAN::Distribution::try_download
+sub try_download {
+ my($self,$patch) = @_;
+ my $norm = $self->normalize($patch);
+ my($local_wanted) =
+ File::Spec->catfile(
+ $CPAN::Config->{keep_source_where},
+ "authors",
+ "id",
+ split(/\//,$norm),
+ );
+ $self->debug("Doing localize") if $CPAN::DEBUG;
+ return CPAN::FTP->localize("authors/id/$norm",
+ $local_wanted);
+}
+
+{
+ my $stdpatchargs = "";
+ #-> CPAN::Distribution::patch
+ sub patch {
+ my($self) = @_;
+ $self->debug("checking patches id[$self->{ID}]") if $CPAN::DEBUG;
+ my $patches = $self->prefs->{patches};
+ $patches ||= "";
+ $self->debug("patches[$patches]") if $CPAN::DEBUG;
+ if ($patches) {
+ return unless @$patches;
+ $self->safe_chdir($self->{build_dir});
+ CPAN->debug("patches[$patches]") if $CPAN::DEBUG;
+ my $patchbin = $CPAN::Config->{patch};
+ unless ($patchbin && length $patchbin) {
+ $CPAN::Frontend->mydie("No external patch command configured\n\n".
+ "Please run 'o conf init /patch/'\n\n");
+ }
+ unless (MM->maybe_command($patchbin)) {
+ $CPAN::Frontend->mydie("No external patch command available\n\n".
+ "Please run 'o conf init /patch/'\n\n");
+ }
+ $patchbin = CPAN::HandleConfig->safe_quote($patchbin);
+ local $ENV{PATCH_GET} = 0; # formerly known as -g0
+ unless ($stdpatchargs) {
+ my $system = "$patchbin --version |";
+ local *FH;
+ open FH, $system or die "Could not fork '$system': $!";
+ local $/ = "\n";
+ my $pversion;
+ PARSEVERSION: while (<FH>) {
+ if (/^patch\s+([\d\.]+)/) {
+ $pversion = $1;
+ last PARSEVERSION;
+ }
+ }
+ if ($pversion) {
+ $stdpatchargs = "-N --fuzz=3";
+ } else {
+ $stdpatchargs = "-N";
+ }
+ }
+ my $countedpatches = @$patches == 1 ? "1 patch" : (scalar @$patches . " patches");
+ $CPAN::Frontend->myprint("Going to apply $countedpatches:\n");
+ my $patches_dir = $CPAN::Config->{patches_dir};
+ for my $patch (@$patches) {
+ if ($patches_dir && !File::Spec->file_name_is_absolute($patch)) {
+ my $f = File::Spec->catfile($patches_dir, $patch);
+ $patch = $f if -f $f;
+ }
+ unless (-f $patch) {
+ CPAN->debug("not on disk: patch[$patch]") if $CPAN::DEBUG;
+ if (my $trydl = $self->try_download($patch)) {
+ $patch = $trydl;
+ } else {
+ my $fail = "Could not find patch '$patch'";
+ $CPAN::Frontend->mywarn("$fail; cannot continue\n");
+ $self->{unwrapped} = CPAN::Distrostatus->new("NO -- $fail");
+ delete $self->{build_dir};
+ return;
+ }
+ }
+ $CPAN::Frontend->myprint(" $patch\n");
+ my $readfh = CPAN::Tarzip->TIEHANDLE($patch);
+
+ my $pcommand;
+ my $ppp = $self->_patch_p_parameter($readfh);
+ if ($ppp eq "applypatch") {
+ $pcommand = "$CPAN::Config->{applypatch} -verbose";
+ } else {
+ my $thispatchargs = join " ", $stdpatchargs, $ppp;
+ $pcommand = "$patchbin $thispatchargs";
+ }
+
+ $readfh = CPAN::Tarzip->TIEHANDLE($patch); # open again
+ my $writefh = FileHandle->new;
+ $CPAN::Frontend->myprint(" $pcommand\n");
+ unless (open $writefh, "|$pcommand") {
+ my $fail = "Could not fork '$pcommand'";
+ $CPAN::Frontend->mywarn("$fail; cannot continue\n");
+ $self->{unwrapped} = CPAN::Distrostatus->new("NO -- $fail");
+ delete $self->{build_dir};
+ return;
+ }
+ binmode($writefh);
+ while (my $x = $readfh->READLINE) {
+ print $writefh $x;
+ }
+ unless (close $writefh) {
+ my $fail = "Could not apply patch '$patch'";
+ $CPAN::Frontend->mywarn("$fail; cannot continue\n");
+ $self->{unwrapped} = CPAN::Distrostatus->new("NO -- $fail");
+ delete $self->{build_dir};
+ return;
+ }
+ }
+ $self->{patched}++;
+ }
+ return 1;
+ }
+}
+
+sub _patch_p_parameter {
+ my($self,$fh) = @_;
+ my $cnt_files = 0;
+ my $cnt_p0files = 0;
+ local($_);
+ while ($_ = $fh->READLINE) {
+ if (
+ $CPAN::Config->{applypatch}
+ &&
+ /\#\#\#\# ApplyPatch data follows \#\#\#\#/
+ ) {
+ return "applypatch"
+ }
+ next unless /^[\*\+]{3}\s(\S+)/;
+ my $file = $1;
+ $cnt_files++;
+ $cnt_p0files++ if -f $file;
+ CPAN->debug("file[$file]cnt_files[$cnt_files]cnt_p0files[$cnt_p0files]")
+ if $CPAN::DEBUG;
+ }
+ return "-p1" unless $cnt_files;
+ return $cnt_files==$cnt_p0files ? "-p0" : "-p1";
+}
+
+#-> sub CPAN::Distribution::_edge_cases
+# with "configure" or "Makefile" or single file scripts
+sub _edge_cases {
+ my($self,$mpl,$local_file) = @_;
+ $self->debug(sprintf("makefilepl[%s]anycwd[%s]",
+ $mpl,
+ CPAN::anycwd(),
+ )) if $CPAN::DEBUG;
+ my $build_dir = $self->{build_dir};
+ my($configure) = File::Spec->catfile($build_dir,"Configure");
+ if (-f $configure) {
+ # do we have anything to do?
+ $self->{configure} = $configure;
+ } elsif (-f File::Spec->catfile($build_dir,"Makefile")) {
+ $CPAN::Frontend->mywarn(qq{
+Package comes with a Makefile and without a Makefile.PL.
+We\'ll try to build it with that Makefile then.
+});
+ $self->{writemakefile} = CPAN::Distrostatus->new("YES");
+ $CPAN::Frontend->mysleep(2);
+ } else {
+ my $cf = $self->called_for || "unknown";
+ if ($cf =~ m|/|) {
+ $cf =~ s|.*/||;
+ $cf =~ s|\W.*||;
+ }
+ $cf =~ s|[/\\:]||g; # risk of filesystem damage
+ $cf = "unknown" unless length($cf);
+ if (my $crud = $self->_contains_crud($build_dir)) {
+ my $why = qq{Package contains $crud; not recognized as a perl package, giving up};
+ $CPAN::Frontend->mywarn("$why\n");
+ $self->{writemakefile} = CPAN::Distrostatus->new(qq{NO -- $why});
+ return;
+ }
+ $CPAN::Frontend->mywarn(qq{Package seems to come without Makefile.PL.
+ (The test -f "$mpl" returned false.)
+ Writing one on our own (setting NAME to $cf)\a\n});
+ $self->{had_no_makefile_pl}++;
+ $CPAN::Frontend->mysleep(3);
+
+ # Writing our own Makefile.PL
+
+ my $exefile_stanza = "";
+ if ($self->{archived} eq "maybe_pl") {
+ $exefile_stanza = $self->_exefile_stanza($build_dir,$local_file);
+ }
+
+ my $fh = FileHandle->new;
+ $fh->open(">$mpl")
+ or Carp::croak("Could not open >$mpl: $!");
+ $fh->print(
+ qq{# This Makefile.PL has been autogenerated by the module CPAN.pm
+# because there was no Makefile.PL supplied.
+# Autogenerated on: }.scalar localtime().qq{
+
+use ExtUtils::MakeMaker;
+WriteMakefile(
+ NAME => q[$cf],$exefile_stanza
+ );
+});
+ $fh->close;
+ }
+}
+
+#-> CPAN;:Distribution::_contains_crud
+sub _contains_crud {
+ my($self,$dir) = @_;
+ my(@dirs, $dh, @files);
+ opendir $dh, $dir or return;
+ my $dirent;
+ for $dirent (readdir $dh) {
+ next if $dirent =~ /^\.\.?$/;
+ my $path = File::Spec->catdir($dir,$dirent);
+ if (-d $path) {
+ push @dirs, $dirent;
+ } elsif (-f $path) {
+ push @files, $dirent;
+ }
+ }
+ if (@dirs && @files) {
+ return "both files[@files] and directories[@dirs]";
+ } elsif (@files > 2) {
+ return "several files[@files] but no Makefile.PL or Build.PL";
+ }
+ return;
+}
+
+#-> CPAN;:Distribution::_exefile_stanza
+sub _exefile_stanza {
+ my($self,$build_dir,$local_file) = @_;
+
+ my $fh = FileHandle->new;
+ my $script_file = File::Spec->catfile($build_dir,$local_file);
+ $fh->open($script_file)
+ or Carp::croak("Could not open script '$script_file': $!");
+ local $/ = "\n";
+ # name parsen und prereq
+ my($state) = "poddir";
+ my($name, $prereq) = ("", "");
+ while (<$fh>) {
+ if ($state eq "poddir" && /^=head\d\s+(\S+)/) {
+ if ($1 eq 'NAME') {
+ $state = "name";
+ } elsif ($1 eq 'PREREQUISITES') {
+ $state = "prereq";
+ }
+ } elsif ($state =~ m{^(name|prereq)$}) {
+ if (/^=/) {
+ $state = "poddir";
+ } elsif (/^\s*$/) {
+ # nop
+ } elsif ($state eq "name") {
+ if ($name eq "") {
+ ($name) = /^(\S+)/;
+ $state = "poddir";
+ }
+ } elsif ($state eq "prereq") {
+ $prereq .= $_;
+ }
+ } elsif (/^=cut\b/) {
+ last;
+ }
+ }
+ $fh->close;
+
+ for ($name) {
+ s{.*<}{}; # strip X<...>
+ s{>.*}{};
+ }
+ chomp $prereq;
+ $prereq = join " ", split /\s+/, $prereq;
+ my($PREREQ_PM) = join("\n", map {
+ s{.*<}{}; # strip X<...>
+ s{>.*}{};
+ if (/[\s\'\"]/) { # prose?
+ } else {
+ s/[^\w:]$//; # period?
+ " "x28 . "'$_' => 0,";
+ }
+ } split /\s*,\s*/, $prereq);
+
+ if ($name) {
+ my $to_file = File::Spec->catfile($build_dir, $name);
+ rename $script_file, $to_file
+ or die "Can't rename $script_file to $to_file: $!";
+ }
+
+ return "
+ EXE_FILES => ['$name'],
+ PREREQ_PM => {
+$PREREQ_PM
+ },
+";
+}
+
+#-> CPAN::Distribution::_signature_business
+sub _signature_business {
+ my($self) = @_;
+ my $check_sigs = CPAN::HandleConfig->prefs_lookup($self,
+ q{check_sigs});
+ if ($check_sigs) {
+ if ($CPAN::META->has_inst("Module::Signature")) {
+ if (-f "SIGNATURE") {
+ $self->debug("Module::Signature is installed, verifying") if $CPAN::DEBUG;
+ my $rv = Module::Signature::verify();
+ if ($rv != Module::Signature::SIGNATURE_OK() and
+ $rv != Module::Signature::SIGNATURE_MISSING()) {
+ $CPAN::Frontend->mywarn(
+ qq{\nSignature invalid for }.
+ qq{distribution file. }.
+ qq{Please investigate.\n\n}
+ );
+
+ my $wrap =
+ sprintf(qq{I'd recommend removing %s. Some error occurred }.
+ qq{while checking its signature, so it could }.
+ qq{be invalid. Maybe you have configured }.
+ qq{your 'urllist' with a bad URL. Please check this }.
+ qq{array with 'o conf urllist' and retry. Or }.
+ qq{examine the distribution in a subshell. Try
+ look %s
+and run
+ cpansign -v
+},
+ $self->{localfile},
+ $self->pretty_id,
+ );
+ $self->{signature_verify} = CPAN::Distrostatus->new("NO");
+ $CPAN::Frontend->mywarn(Text::Wrap::wrap("","",$wrap));
+ $CPAN::Frontend->mysleep(5) if $CPAN::Frontend->can("mysleep");
+ } else {
+ $self->{signature_verify} = CPAN::Distrostatus->new("YES");
+ $self->debug("Module::Signature has verified") if $CPAN::DEBUG;
+ }
+ } else {
+ $CPAN::Frontend->mywarn(qq{Package came without SIGNATURE\n\n});
+ }
+ } else {
+ $self->debug("Module::Signature is NOT installed") if $CPAN::DEBUG;
+ }
+ }
+}
+
+#-> CPAN::Distribution::untar_me ;
+sub untar_me {
+ my($self,$ct) = @_;
+ $self->{archived} = "tar";
+ my $result = eval { $ct->untar() };
+ if ($result) {
+ $self->{unwrapped} = CPAN::Distrostatus->new("YES");
+ } else {
+ $self->{unwrapped} = CPAN::Distrostatus->new("NO -- untar failed");
+ }
+}
+
+# CPAN::Distribution::unzip_me ;
+sub unzip_me {
+ my($self,$ct) = @_;
+ $self->{archived} = "zip";
+ if ($ct->unzip()) {
+ $self->{unwrapped} = CPAN::Distrostatus->new("YES");
+ } else {
+ $self->{unwrapped} = CPAN::Distrostatus->new("NO -- unzip failed");
+ }
+ return;
+}
+
+sub handle_singlefile {
+ my($self,$local_file) = @_;
+
+ if ( $local_file =~ /\.pm(\.(gz|Z))?(?!\n)\Z/ ) {
+ $self->{archived} = "pm";
+ } elsif ( $local_file =~ /\.patch(\.(gz|bz2))?(?!\n)\Z/ ) {
+ $self->{archived} = "patch";
+ } else {
+ $self->{archived} = "maybe_pl";
+ }
+
+ my $to = File::Basename::basename($local_file);
+ if ($to =~ s/\.(gz|Z)(?!\n)\Z//) {
+ if (eval{CPAN::Tarzip->new($local_file)->gunzip($to)}) {
+ $self->{unwrapped} = CPAN::Distrostatus->new("YES");
+ } else {
+ $self->{unwrapped} = CPAN::Distrostatus->new("NO -- uncompressing failed");
+ }
+ } else {
+ if (File::Copy::cp($local_file,".")) {
+ $self->{unwrapped} = CPAN::Distrostatus->new("YES");
+ } else {
+ $self->{unwrapped} = CPAN::Distrostatus->new("NO -- copying failed");
+ }
+ }
+ return $to;
+}
+
+#-> sub CPAN::Distribution::new ;
+sub new {
+ my($class,%att) = @_;
+
+ # $CPAN::META->{cachemgr} ||= CPAN::CacheMgr->new();
+
+ my $this = { %att };
+ return bless $this, $class;
+}
+
+#-> sub CPAN::Distribution::look ;
+sub look {
+ my($self) = @_;
+
+ if ($^O eq 'MacOS') {
+ $self->Mac::BuildTools::look;
+ return;
+ }
+
+ if ( $CPAN::Config->{'shell'} ) {
+ $CPAN::Frontend->myprint(qq{
+Trying to open a subshell in the build directory...
+});
+ } else {
+ $CPAN::Frontend->myprint(qq{
+Your configuration does not define a value for subshells.
+Please define it with "o conf shell <your shell>"
+});
+ return;
+ }
+ my $dist = $self->id;
+ my $dir;
+ unless ($dir = $self->dir) {
+ $self->get;
+ }
+ unless ($dir ||= $self->dir) {
+ $CPAN::Frontend->mywarn(qq{
+Could not determine which directory to use for looking at $dist.
+});
+ return;
+ }
+ my $pwd = CPAN::anycwd();
+ $self->safe_chdir($dir);
+ $CPAN::Frontend->myprint(qq{Working directory is $dir\n});
+ {
+ local $ENV{CPAN_SHELL_LEVEL} = $ENV{CPAN_SHELL_LEVEL}||0;
+ $ENV{CPAN_SHELL_LEVEL} += 1;
+ my $shell = CPAN::HandleConfig->safe_quote($CPAN::Config->{'shell'});
+
+ local $ENV{PERL5LIB} = defined($ENV{PERL5LIB})
+ ? $ENV{PERL5LIB}
+ : ($ENV{PERLLIB} || "");
+
+ local $ENV{PERL5OPT} = defined $ENV{PERL5OPT} ? $ENV{PERL5OPT} : "";
+ $CPAN::META->set_perl5lib;
+ local $ENV{MAKEFLAGS}; # protect us from outer make calls
+
+ unless (system($shell) == 0) {
+ my $code = $? >> 8;
+ $CPAN::Frontend->mywarn("Subprocess shell exit code $code\n");
+ }
+ }
+ $self->safe_chdir($pwd);
+}
+
+# CPAN::Distribution::cvs_import ;
+sub cvs_import {
+ my($self) = @_;
+ $self->get;
+ my $dir = $self->dir;
+
+ my $package = $self->called_for;
+ my $module = $CPAN::META->instance('CPAN::Module', $package);
+ my $version = $module->cpan_version;
+
+ my $userid = $self->cpan_userid;
+
+ my $cvs_dir = (split /\//, $dir)[-1];
+ $cvs_dir =~ s/-\d+[^-]+(?!\n)\Z//;
+ my $cvs_root =
+ $CPAN::Config->{cvsroot} || $ENV{CVSROOT};
+ my $cvs_site_perl =
+ $CPAN::Config->{cvs_site_perl} || $ENV{CVS_SITE_PERL};
+ if ($cvs_site_perl) {
+ $cvs_dir = "$cvs_site_perl/$cvs_dir";
+ }
+ my $cvs_log = qq{"imported $package $version sources"};
+ $version =~ s/\./_/g;
+ # XXX cvs: undocumented and unclear how it was meant to work
+ my @cmd = ('cvs', '-d', $cvs_root, 'import', '-m', $cvs_log,
+ "$cvs_dir", $userid, "v$version");
+
+ my $pwd = CPAN::anycwd();
+ chdir($dir) or $CPAN::Frontend->mydie(qq{Could not chdir to "$dir": $!});
+
+ $CPAN::Frontend->myprint(qq{Working directory is $dir\n});
+
+ $CPAN::Frontend->myprint(qq{@cmd\n});
+ system(@cmd) == 0 or
+ # XXX cvs
+ $CPAN::Frontend->mydie("cvs import failed");
+ chdir($pwd) or $CPAN::Frontend->mydie(qq{Could not chdir to "$pwd": $!});
+}
+
+#-> sub CPAN::Distribution::readme ;
+sub readme {
+ my($self) = @_;
+ my($dist) = $self->id;
+ my($sans,$suffix) = $dist =~ /(.+)\.(tgz|tar[\._-]gz|tar\.Z|zip)$/;
+ $self->debug("sans[$sans] suffix[$suffix]\n") if $CPAN::DEBUG;
+ my($local_file);
+ my($local_wanted) =
+ File::Spec->catfile(
+ $CPAN::Config->{keep_source_where},
+ "authors",
+ "id",
+ split(/\//,"$sans.readme"),
+ );
+ my $readme = "authors/id/$sans.readme";
+ $self->debug("Doing localize for '$readme'") if $CPAN::DEBUG;
+ $local_file = CPAN::FTP->localize($readme,
+ $local_wanted)
+ or $CPAN::Frontend->mydie(qq{No $sans.readme found});
+
+ if ($^O eq 'MacOS') {
+ Mac::BuildTools::launch_file($local_file);
+ return;
+ }
+
+ my $fh_pager = FileHandle->new;
+ local($SIG{PIPE}) = "IGNORE";
+ my $pager = $CPAN::Config->{'pager'} || "cat";
+ $fh_pager->open("|$pager")
+ or die "Could not open pager $pager\: $!";
+ my $fh_readme = FileHandle->new;
+ $fh_readme->open($local_file)
+ or $CPAN::Frontend->mydie(qq{Could not open "$local_file": $!});
+ $CPAN::Frontend->myprint(qq{
+Displaying file
+ $local_file
+with pager "$pager"
+});
+ $fh_pager->print(<$fh_readme>);
+ $fh_pager->close;
+}
+
+#-> sub CPAN::Distribution::verifyCHECKSUM ;
+sub verifyCHECKSUM {
+ my($self) = @_;
+ EXCUSE: {
+ my @e;
+ $self->{CHECKSUM_STATUS} ||= "";
+ $self->{CHECKSUM_STATUS} eq "OK" and push @e, "Checksum was ok";
+ $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
+ }
+ my($lc_want,$lc_file,@local,$basename);
+ @local = split(/\//,$self->id);
+ pop @local;
+ push @local, "CHECKSUMS";
+ $lc_want =
+ File::Spec->catfile($CPAN::Config->{keep_source_where},
+ "authors", "id", @local);
+ local($") = "/";
+ if (my $size = -s $lc_want) {
+ $self->debug("lc_want[$lc_want]size[$size]") if $CPAN::DEBUG;
+ if ($self->CHECKSUM_check_file($lc_want,1)) {
+ return $self->{CHECKSUM_STATUS} = "OK";
+ }
+ }
+ $lc_file = CPAN::FTP->localize("authors/id/@local",
+ $lc_want,1);
+ unless ($lc_file) {
+ $CPAN::Frontend->myprint("Trying $lc_want.gz\n");
+ $local[-1] .= ".gz";
+ $lc_file = CPAN::FTP->localize("authors/id/@local",
+ "$lc_want.gz",1);
+ if ($lc_file) {
+ $lc_file =~ s/\.gz(?!\n)\Z//;
+ eval{CPAN::Tarzip->new("$lc_file.gz")->gunzip($lc_file)};
+ } else {
+ return;
+ }
+ }
+ if ($self->CHECKSUM_check_file($lc_file)) {
+ return $self->{CHECKSUM_STATUS} = "OK";
+ }
+}
+
+#-> sub CPAN::Distribution::SIG_check_file ;
+sub SIG_check_file {
+ my($self,$chk_file) = @_;
+ my $rv = eval { Module::Signature::_verify($chk_file) };
+
+ if ($rv == Module::Signature::SIGNATURE_OK()) {
+ $CPAN::Frontend->myprint("Signature for $chk_file ok\n");
+ return $self->{SIG_STATUS} = "OK";
+ } else {
+ $CPAN::Frontend->myprint(qq{\nSignature invalid for }.
+ qq{distribution file. }.
+ qq{Please investigate.\n\n}.
+ $self->as_string,
+ $CPAN::META->instance(
+ 'CPAN::Author',
+ $self->cpan_userid
+ )->as_string);
+
+ my $wrap = qq{I\'d recommend removing $chk_file. Its signature
+is invalid. Maybe you have configured your 'urllist' with
+a bad URL. Please check this array with 'o conf urllist', and
+retry.};
+
+ $CPAN::Frontend->mydie(Text::Wrap::wrap("","",$wrap));
+ }
+}
+
+#-> sub CPAN::Distribution::CHECKSUM_check_file ;
+
+# sloppy is 1 when we have an old checksums file that maybe is good
+# enough
+
+sub CHECKSUM_check_file {
+ my($self,$chk_file,$sloppy) = @_;
+ my($cksum,$file,$basename);
+
+ $sloppy ||= 0;
+ $self->debug("chk_file[$chk_file]sloppy[$sloppy]") if $CPAN::DEBUG;
+ my $check_sigs = CPAN::HandleConfig->prefs_lookup($self,
+ q{check_sigs});
+ if ($check_sigs) {
+ if ($CPAN::META->has_inst("Module::Signature")) {
+ $self->debug("Module::Signature is installed, verifying") if $CPAN::DEBUG;
+ $self->SIG_check_file($chk_file);
+ } else {
+ $self->debug("Module::Signature is NOT installed") if $CPAN::DEBUG;
+ }
+ }
+
+ $file = $self->{localfile};
+ $basename = File::Basename::basename($file);
+ my $fh = FileHandle->new;
+ if (open $fh, $chk_file) {
+ local($/);
+ my $eval = <$fh>;
+ $eval =~ s/\015?\012/\n/g;
+ close $fh;
+ my($compmt) = Safe->new();
+ $cksum = $compmt->reval($eval);
+ if ($@) {
+ rename $chk_file, "$chk_file.bad";
+ Carp::confess($@) if $@;
+ }
+ } else {
+ Carp::carp "Could not open $chk_file for reading";
+ }
+
+ if (! ref $cksum or ref $cksum ne "HASH") {
+ $CPAN::Frontend->mywarn(qq{
+Warning: checksum file '$chk_file' broken.
+
+When trying to read that file I expected to get a hash reference
+for further processing, but got garbage instead.
+});
+ my $answer = CPAN::Shell::colorable_makemaker_prompt("Proceed nonetheless?", "no");
+ $answer =~ /^\s*y/i or $CPAN::Frontend->mydie("Aborted.\n");
+ $self->{CHECKSUM_STATUS} = "NIL -- CHECKSUMS file broken";
+ return;
+ } elsif (exists $cksum->{$basename}{sha256}) {
+ $self->debug("Found checksum for $basename:" .
+ "$cksum->{$basename}{sha256}\n") if $CPAN::DEBUG;
+
+ open($fh, $file);
+ binmode $fh;
+ my $eq = $self->eq_CHECKSUM($fh,$cksum->{$basename}{sha256});
+ $fh->close;
+ $fh = CPAN::Tarzip->TIEHANDLE($file);
+
+ unless ($eq) {
+ my $dg = Digest::SHA->new(256);
+ my($data,$ref);
+ $ref = \$data;
+ while ($fh->READ($ref, 4096) > 0) {
+ $dg->add($data);
+ }
+ my $hexdigest = $dg->hexdigest;
+ $eq += $hexdigest eq $cksum->{$basename}{'sha256-ungz'};
+ }
+
+ if ($eq) {
+ $CPAN::Frontend->myprint("Checksum for $file ok\n");
+ return $self->{CHECKSUM_STATUS} = "OK";
+ } else {
+ $CPAN::Frontend->myprint(qq{\nChecksum mismatch for }.
+ qq{distribution file. }.
+ qq{Please investigate.\n\n}.
+ $self->as_string,
+ $CPAN::META->instance(
+ 'CPAN::Author',
+ $self->cpan_userid
+ )->as_string);
+
+ my $wrap = qq{I\'d recommend removing $file. Its
+checksum is incorrect. Maybe you have configured your 'urllist' with
+a bad URL. Please check this array with 'o conf urllist', and
+retry.};
+
+ $CPAN::Frontend->mydie(Text::Wrap::wrap("","",$wrap));
+
+ # former versions just returned here but this seems a
+ # serious threat that deserves a die
+
+ # $CPAN::Frontend->myprint("\n\n");
+ # sleep 3;
+ # return;
+ }
+ # close $fh if fileno($fh);
+ } else {
+ return if $sloppy;
+ unless ($self->{CHECKSUM_STATUS}) {
+ $CPAN::Frontend->mywarn(qq{
+Warning: No checksum for $basename in $chk_file.
+
+The cause for this may be that the file is very new and the checksum
+has not yet been calculated, but it may also be that something is
+going awry right now.
+});
+ my $answer = CPAN::Shell::colorable_makemaker_prompt("Proceed?", "yes");
+ $answer =~ /^\s*y/i or $CPAN::Frontend->mydie("Aborted.\n");
+ }
+ $self->{CHECKSUM_STATUS} = "NIL -- distro not in CHECKSUMS file";
+ return;
+ }
+}
+
+#-> sub CPAN::Distribution::eq_CHECKSUM ;
+sub eq_CHECKSUM {
+ my($self,$fh,$expect) = @_;
+ if ($CPAN::META->has_inst("Digest::SHA")) {
+ my $dg = Digest::SHA->new(256);
+ my($data);
+ while (read($fh, $data, 4096)) {
+ $dg->add($data);
+ }
+ my $hexdigest = $dg->hexdigest;
+ # warn "fh[$fh] hex[$hexdigest] aexp[$expectMD5]";
+ return $hexdigest eq $expect;
+ }
+ return 1;
+}
+
+#-> sub CPAN::Distribution::force ;
+
+# Both CPAN::Modules and CPAN::Distributions know if "force" is in
+# effect by autoinspection, not by inspecting a global variable. One
+# of the reason why this was chosen to work that way was the treatment
+# of dependencies. They should not automatically inherit the force
+# status. But this has the downside that ^C and die() will return to
+# the prompt but will not be able to reset the force_update
+# attributes. We try to correct for it currently in the read_metadata
+# routine, and immediately before we check for a Signal. I hope this
+# works out in one of v1.57_53ff
+
+# "Force get forgets previous error conditions"
+
+#-> sub CPAN::Distribution::fforce ;
+sub fforce {
+ my($self, $method) = @_;
+ $self->force($method,1);
+}
+
+#-> sub CPAN::Distribution::force ;
+sub force {
+ my($self, $method,$fforce) = @_;
+ my %phase_map = (
+ get => [
+ "unwrapped",
+ "build_dir",
+ "archived",
+ "localfile",
+ "CHECKSUM_STATUS",
+ "signature_verify",
+ "prefs",
+ "prefs_file",
+ "prefs_file_doc",
+ ],
+ make => [
+ "writemakefile",
+ "make",
+ "modulebuild",
+ "prereq_pm",
+ ],
+ test => [
+ "badtestcnt",
+ "make_test",
+ ],
+ install => [
+ "install",
+ ],
+ unknown => [
+ "reqtype",
+ "yaml_content",
+ ],
+ );
+ my $methodmatch = 0;
+ my $ldebug = 0;
+ PHASE: for my $phase (qw(unknown get make test install)) { # order matters
+ $methodmatch = 1 if $fforce || $phase eq $method;
+ next unless $methodmatch;
+ ATTRIBUTE: for my $att (@{$phase_map{$phase}}) {
+ if ($phase eq "get") {
+ if (substr($self->id,-1,1) eq "."
+ && $att =~ /(unwrapped|build_dir|archived)/ ) {
+ # cannot be undone for local distros
+ next ATTRIBUTE;
+ }
+ if ($att eq "build_dir"
+ && $self->{build_dir}
+ && $CPAN::META->{is_tested}
+ ) {
+ delete $CPAN::META->{is_tested}{$self->{build_dir}};
+ }
+ } elsif ($phase eq "test") {
+ if ($att eq "make_test"
+ && $self->{make_test}
+ && $self->{make_test}{COMMANDID}
+ && $self->{make_test}{COMMANDID} == $CPAN::CurrentCommandId
+ ) {
+ # endless loop too likely
+ next ATTRIBUTE;
+ }
+ }
+ delete $self->{$att};
+ if ($ldebug || $CPAN::DEBUG) {
+ # local $CPAN::DEBUG = 16; # Distribution
+ CPAN->debug(sprintf "id[%s]phase[%s]att[%s]", $self->id, $phase, $att);
+ }
+ }
+ }
+ if ($method && $method =~ /make|test|install/) {
+ $self->{force_update} = 1; # name should probably have been force_install
+ }
+}
+
+#-> sub CPAN::Distribution::notest ;
+sub notest {
+ my($self, $method) = @_;
+ # $CPAN::Frontend->mywarn("XDEBUG: set notest for $self $method");
+ $self->{"notest"}++; # name should probably have been force_install
+}
+
+#-> sub CPAN::Distribution::unnotest ;
+sub unnotest {
+ my($self) = @_;
+ # warn "XDEBUG: deleting notest";
+ delete $self->{notest};
+}
+
+#-> sub CPAN::Distribution::unforce ;
+sub unforce {
+ my($self) = @_;
+ delete $self->{force_update};
+}
+
+#-> sub CPAN::Distribution::isa_perl ;
+sub isa_perl {
+ my($self) = @_;
+ my $file = File::Basename::basename($self->id);
+ if ($file =~ m{ ^ perl
+ -?
+ (5)
+ ([._-])
+ (
+ \d{3}(_[0-4][0-9])?
+ |
+ \d+\.\d+
+ )
+ \.tar[._-](?:gz|bz2)
+ (?!\n)\Z
+ }xs) {
+ return "$1.$3";
+ } elsif ($self->cpan_comment
+ &&
+ $self->cpan_comment =~ /isa_perl\(.+?\)/) {
+ return $1;
+ }
+}
+
+
+#-> sub CPAN::Distribution::perl ;
+sub perl {
+ my ($self) = @_;
+ if (! $self) {
+ use Carp qw(carp);
+ carp __PACKAGE__ . "::perl was called without parameters.";
+ }
+ return CPAN::HandleConfig->safe_quote($CPAN::Perl);
+}
+
+
+#-> sub CPAN::Distribution::make ;
+sub make {
+ my($self) = @_;
+ if (my $goto = $self->prefs->{goto}) {
+ return $self->goto($goto);
+ }
+ my $make = $self->{modulebuild} ? "Build" : "make";
+ # Emergency brake if they said install Pippi and get newest perl
+ if ($self->isa_perl) {
+ if (
+ $self->called_for ne $self->id &&
+ ! $self->{force_update}
+ ) {
+ # if we die here, we break bundles
+ $CPAN::Frontend
+ ->mywarn(sprintf(
+ qq{The most recent version "%s" of the module "%s"
+is part of the perl-%s distribution. To install that, you need to run
+ force install %s --or--
+ install %s
+},
+ $CPAN::META->instance(
+ 'CPAN::Module',
+ $self->called_for
+ )->cpan_version,
+ $self->called_for,
+ $self->isa_perl,
+ $self->called_for,
+ $self->id,
+ ));
+ $self->{make} = CPAN::Distrostatus->new("NO isa perl");
+ $CPAN::Frontend->mysleep(1);
+ return;
+ }
+ }
+ $CPAN::Frontend->myprint(sprintf "Running %s for %s\n", $make, $self->id);
+ $self->get;
+ return if $self->prefs->{disabled} && ! $self->{force_update};
+ if ($self->{configure_requires_later}) {
+ return;
+ }
+ local $ENV{PERL5LIB} = defined($ENV{PERL5LIB})
+ ? $ENV{PERL5LIB}
+ : ($ENV{PERLLIB} || "");
+ local $ENV{PERL5OPT} = defined $ENV{PERL5OPT} ? $ENV{PERL5OPT} : "";
+ $CPAN::META->set_perl5lib;
+ local $ENV{MAKEFLAGS}; # protect us from outer make calls
+
+ if ($CPAN::Signal) {
+ delete $self->{force_update};
+ return;
+ }
+
+ my $builddir;
+ EXCUSE: {
+ my @e;
+ if (!$self->{archived} || $self->{archived} eq "NO") {
+ push @e, "Is neither a tar nor a zip archive.";
+ }
+
+ if (!$self->{unwrapped}
+ || (
+ UNIVERSAL::can($self->{unwrapped},"failed") ?
+ $self->{unwrapped}->failed :
+ $self->{unwrapped} =~ /^NO/
+ )) {
+ push @e, "Had problems unarchiving. Please build manually";
+ }
+
+ unless ($self->{force_update}) {
+ exists $self->{signature_verify} and
+ (
+ UNIVERSAL::can($self->{signature_verify},"failed") ?
+ $self->{signature_verify}->failed :
+ $self->{signature_verify} =~ /^NO/
+ )
+ and push @e, "Did not pass the signature test.";
+ }
+
+ if (exists $self->{writemakefile} &&
+ (
+ UNIVERSAL::can($self->{writemakefile},"failed") ?
+ $self->{writemakefile}->failed :
+ $self->{writemakefile} =~ /^NO/
+ )) {
+ # XXX maybe a retry would be in order?
+ my $err = UNIVERSAL::can($self->{writemakefile},"text") ?
+ $self->{writemakefile}->text :
+ $self->{writemakefile};
+ $err =~ s/^NO\s*(--\s+)?//;
+ $err ||= "Had some problem writing Makefile";
+ $err .= ", won't make";
+ push @e, $err;
+ }
+
+ if (defined $self->{make}) {
+ if (UNIVERSAL::can($self->{make},"failed") ?
+ $self->{make}->failed :
+ $self->{make} =~ /^NO/) {
+ if ($self->{force_update}) {
+ # Trying an already failed 'make' (unless somebody else blocks)
+ } else {
+ # introduced for turning recursion detection into a distrostatus
+ my $error = length $self->{make}>3
+ ? substr($self->{make},3) : "Unknown error";
+ $CPAN::Frontend->mywarn("Could not make: $error\n");
+ $self->store_persistent_state;
+ return;
+ }
+ } else {
+ push @e, "Has already been made";
+ my $wait_for_prereqs = eval { $self->satisfy_requires };
+ return 1 if $wait_for_prereqs; # tells queuerunner to continue
+ return $self->goodbye($@) if $@; # tells queuerunner to stop
+ }
+ }
+
+ my $later = $self->{later} || $self->{configure_requires_later};
+ if ($later) { # see also undelay
+ if ($later) {
+ push @e, $later;
+ }
+ }
+
+ $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
+ $builddir = $self->dir or
+ $CPAN::Frontend->mydie("PANIC: Cannot determine build directory\n");
+ unless (chdir $builddir) {
+ push @e, "Couldn't chdir to '$builddir': $!";
+ }
+ $CPAN::Frontend->mywarn(join "", map {" $_\n"} @e) and return if @e;
+ }
+ if ($CPAN::Signal) {
+ delete $self->{force_update};
+ return;
+ }
+ $CPAN::Frontend->myprint("\n CPAN.pm: Going to build ".$self->id."\n\n");
+ $self->debug("Changed directory to $builddir") if $CPAN::DEBUG;
+
+ if ($^O eq 'MacOS') {
+ Mac::BuildTools::make($self);
+ return;
+ }
+
+ my %env;
+ while (my($k,$v) = each %ENV) {
+ next unless defined $v;
+ $env{$k} = $v;
+ }
+ local %ENV = %env;
+ if ($CPAN::Config->{prerequisites_policy} eq "follow") {
+ $ENV{PERL_AUTOINSTALL} ||= "--defaultdeps";
+ $ENV{PERL_EXTUTILS_AUTOINSTALL} ||= "--defaultdeps";
+ }
+ my $system;
+ my $pl_commandline;
+ if ($self->prefs->{pl}) {
+ $pl_commandline = $self->prefs->{pl}{commandline};
+ }
+ if ($pl_commandline) {
+ $system = $pl_commandline;
+ $ENV{PERL} = $^X;
+ } elsif ($self->{'configure'}) {
+ $system = $self->{'configure'};
+ } elsif ($self->{modulebuild}) {
+ my($perl) = $self->perl or die "Couldn\'t find executable perl\n";
+ $system = "$perl Build.PL $CPAN::Config->{mbuildpl_arg}";
+ } else {
+ my($perl) = $self->perl or die "Couldn\'t find executable perl\n";
+ my $switch = "";
+# This needs a handler that can be turned on or off:
+# $switch = "-MExtUtils::MakeMaker ".
+# "-Mops=:default,:filesys_read,:filesys_open,require,chdir"
+# if $] > 5.00310;
+ my $makepl_arg = $self->_make_phase_arg("pl");
+ $ENV{PERL5_CPAN_IS_EXECUTING} = File::Spec->catfile($self->{build_dir},
+ "Makefile.PL");
+ $system = sprintf("%s%s Makefile.PL%s",
+ $perl,
+ $switch ? " $switch" : "",
+ $makepl_arg ? " $makepl_arg" : "",
+ );
+ }
+ my $pl_env;
+ if ($self->prefs->{pl}) {
+ $pl_env = $self->prefs->{pl}{env};
+ }
+ if ($pl_env) {
+ for my $e (keys %$pl_env) {
+ $ENV{$e} = $pl_env->{$e};
+ }
+ }
+ if (exists $self->{writemakefile}) {
+ } else {
+ local($SIG{ALRM}) = sub { die "inactivity_timeout reached\n" };
+ my($ret,$pid,$output);
+ $@ = "";
+ my $go_via_alarm;
+ if ($CPAN::Config->{inactivity_timeout}) {
+ require Config;
+ if ($Config::Config{d_alarm}
+ &&
+ $Config::Config{d_alarm} eq "define"
+ ) {
+ $go_via_alarm++
+ } else {
+ $CPAN::Frontend->mywarn("Warning: you have configured the config ".
+ "variable 'inactivity_timeout' to ".
+ "'$CPAN::Config->{inactivity_timeout}'. But ".
+ "on this machine the system call 'alarm' ".
+ "isn't available. This means that we cannot ".
+ "provide the feature of intercepting long ".
+ "waiting code and will turn this feature off.\n"
+ );
+ $CPAN::Config->{inactivity_timeout} = 0;
+ }
+ }
+ if ($go_via_alarm) {
+ if ( $self->_should_report('pl') ) {
+ ($output, $ret) = CPAN::Reporter::record_command(
+ $system,
+ $CPAN::Config->{inactivity_timeout},
+ );
+ CPAN::Reporter::grade_PL( $self, $system, $output, $ret );
+ }
+ else {
+ eval {
+ alarm $CPAN::Config->{inactivity_timeout};
+ local $SIG{CHLD}; # = sub { wait };
+ if (defined($pid = fork)) {
+ if ($pid) { #parent
+ # wait;
+ waitpid $pid, 0;
+ } else { #child
+ # note, this exec isn't necessary if
+ # inactivity_timeout is 0. On the Mac I'd
+ # suggest, we set it always to 0.
+ exec $system;
+ }
+ } else {
+ $CPAN::Frontend->myprint("Cannot fork: $!");
+ return;
+ }
+ };
+ alarm 0;
+ if ($@) {
+ kill 9, $pid;
+ waitpid $pid, 0;
+ my $err = "$@";
+ $CPAN::Frontend->myprint($err);
+ $self->{writemakefile} = CPAN::Distrostatus->new("NO $err");
+ $@ = "";
+ $self->store_persistent_state;
+ return $self->goodbye("$system -- TIMED OUT");
+ }
+ }
+ } else {
+ if (my $expect_model = $self->_prefs_with_expect("pl")) {
+ # XXX probably want to check _should_report here and warn
+ # about not being able to use CPAN::Reporter with expect
+ $ret = $self->_run_via_expect($system,'writemakefile',$expect_model);
+ if (! defined $ret
+ && $self->{writemakefile}
+ && $self->{writemakefile}->failed) {
+ # timeout
+ return;
+ }
+ }
+ elsif ( $self->_should_report('pl') ) {
+ ($output, $ret) = CPAN::Reporter::record_command($system);
+ CPAN::Reporter::grade_PL( $self, $system, $output, $ret );
+ }
+ else {
+ $ret = system($system);
+ }
+ if ($ret != 0) {
+ $self->{writemakefile} = CPAN::Distrostatus
+ ->new("NO '$system' returned status $ret");
+ $CPAN::Frontend->mywarn("Warning: No success on command[$system]\n");
+ $self->store_persistent_state;
+ return $self->goodbye("$system -- NOT OK");
+ }
+ }
+ if (-f "Makefile" || -f "Build") {
+ $self->{writemakefile} = CPAN::Distrostatus->new("YES");
+ delete $self->{make_clean}; # if cleaned before, enable next
+ } else {
+ my $makefile = $self->{modulebuild} ? "Build" : "Makefile";
+ my $why = "No '$makefile' created";
+ $CPAN::Frontend->mywarn($why);
+ $self->{writemakefile} = CPAN::Distrostatus
+ ->new(qq{NO -- $why\n});
+ $self->store_persistent_state;
+ return $self->goodbye("$system -- NOT OK");
+ }
+ }
+ if ($CPAN::Signal) {
+ delete $self->{force_update};
+ return;
+ }
+ my $wait_for_prereqs = eval { $self->satisfy_requires };
+ return 1 if $wait_for_prereqs; # tells queuerunner to continue
+ return $self->goodbye($@) if $@; # tells queuerunner to stop
+ if ($CPAN::Signal) {
+ delete $self->{force_update};
+ return;
+ }
+ my $make_commandline;
+ if ($self->prefs->{make}) {
+ $make_commandline = $self->prefs->{make}{commandline};
+ }
+ if ($make_commandline) {
+ $system = $make_commandline;
+ $ENV{PERL} = CPAN::find_perl();
+ } else {
+ if ($self->{modulebuild}) {
+ unless (-f "Build") {
+ my $cwd = CPAN::anycwd();
+ $CPAN::Frontend->mywarn("Alert: no Build file available for 'make $self->{id}'".
+ " in cwd[$cwd]. Danger, Will Robinson!\n");
+ $CPAN::Frontend->mysleep(5);
+ }
+ $system = join " ", $self->_build_command(), $CPAN::Config->{mbuild_arg};
+ } else {
+ $system = join " ", $self->_make_command(), $CPAN::Config->{make_arg};
+ }
+ $system =~ s/\s+$//;
+ my $make_arg = $self->_make_phase_arg("make");
+ $system = sprintf("%s%s",
+ $system,
+ $make_arg ? " $make_arg" : "",
+ );
+ }
+ my $make_env;
+ if ($self->prefs->{make}) {
+ $make_env = $self->prefs->{make}{env};
+ }
+ if ($make_env) { # overriding the local ENV of PL, not the outer
+ # ENV, but unlikely to be a risk
+ for my $e (keys %$make_env) {
+ $ENV{$e} = $make_env->{$e};
+ }
+ }
+ my $expect_model = $self->_prefs_with_expect("make");
+ my $want_expect = 0;
+ if ( $expect_model && @{$expect_model->{talk}} ) {
+ my $can_expect = $CPAN::META->has_inst("Expect");
+ if ($can_expect) {
+ $want_expect = 1;
+ } else {
+ $CPAN::Frontend->mywarn("Expect not installed, falling back to ".
+ "system()\n");
+ }
+ }
+ my $system_ok;
+ if ($want_expect) {
+ # XXX probably want to check _should_report here and
+ # warn about not being able to use CPAN::Reporter with expect
+ $system_ok = $self->_run_via_expect($system,'make',$expect_model) == 0;
+ }
+ elsif ( $self->_should_report('make') ) {
+ my ($output, $ret) = CPAN::Reporter::record_command($system);
+ CPAN::Reporter::grade_make( $self, $system, $output, $ret );
+ $system_ok = ! $ret;
+ }
+ else {
+ $system_ok = system($system) == 0;
+ }
+ $self->introduce_myself;
+ if ( $system_ok ) {
+ $CPAN::Frontend->myprint(" $system -- OK\n");
+ $self->{make} = CPAN::Distrostatus->new("YES");
+ } else {
+ $self->{writemakefile} ||= CPAN::Distrostatus->new("YES");
+ $self->{make} = CPAN::Distrostatus->new("NO");
+ $CPAN::Frontend->mywarn(" $system -- NOT OK\n");
+ }
+ $self->store_persistent_state;
+}
+
+# CPAN::Distribution::goodbye ;
+sub goodbye {
+ my($self,$goodbye) = @_;
+ my $id = $self->pretty_id;
+ $CPAN::Frontend->mywarn(" $id\n $goodbye\n");
+ return;
+}
+
+# CPAN::Distribution::_run_via_expect ;
+sub _run_via_expect {
+ my($self,$system,$phase,$expect_model) = @_;
+ CPAN->debug("system[$system]expect_model[$expect_model]") if $CPAN::DEBUG;
+ if ($CPAN::META->has_inst("Expect")) {
+ my $expo = Expect->new; # expo Expect object;
+ $expo->spawn($system);
+ $expect_model->{mode} ||= "deterministic";
+ if ($expect_model->{mode} eq "deterministic") {
+ return $self->_run_via_expect_deterministic($expo,$phase,$expect_model);
+ } elsif ($expect_model->{mode} eq "anyorder") {
+ return $self->_run_via_expect_anyorder($expo,$phase,$expect_model);
+ } else {
+ die "Panic: Illegal expect mode: $expect_model->{mode}";
+ }
+ } else {
+ $CPAN::Frontend->mywarn("Expect not installed, falling back to system()\n");
+ return system($system);
+ }
+}
+
+sub _run_via_expect_anyorder {
+ my($self,$expo,$phase,$expect_model) = @_;
+ my $timeout = $expect_model->{timeout} || 5;
+ my $reuse = $expect_model->{reuse};
+ my @expectacopy = @{$expect_model->{talk}}; # we trash it!
+ my $but = "";
+ my $timeout_start = time;
+ EXPECT: while () {
+ my($eof,$ran_into_timeout);
+ # XXX not up to the full power of expect. one could certainly
+ # wrap all of the talk pairs into a single expect call and on
+ # success tweak it and step ahead to the next question. The
+ # current implementation unnecessarily limits itself to a
+ # single match.
+ my @match = $expo->expect(1,
+ [ eof => sub {
+ $eof++;
+ } ],
+ [ timeout => sub {
+ $ran_into_timeout++;
+ } ],
+ -re => eval"qr{.}",
+ );
+ if ($match[2]) {
+ $but .= $match[2];
+ }
+ $but .= $expo->clear_accum;
+ if ($eof) {
+ $expo->soft_close;
+ return $expo->exitstatus();
+ } elsif ($ran_into_timeout) {
+ # warn "DEBUG: they are asking a question, but[$but]";
+ for (my $i = 0; $i <= $#expectacopy; $i+=2) {
+ my($next,$send) = @expectacopy[$i,$i+1];
+ my $regex = eval "qr{$next}";
+ # warn "DEBUG: will compare with regex[$regex].";
+ if ($but =~ /$regex/) {
+ # warn "DEBUG: will send send[$send]";
+ $expo->send($send);
+ # never allow reusing an QA pair unless they told us
+ splice @expectacopy, $i, 2 unless $reuse;
+ $but =~ s/(?s:^.*?)$regex//;
+ $timeout_start = time;
+ next EXPECT;
+ }
+ }
+ my $have_waited = time - $timeout_start;
+ if ($have_waited < $timeout) {
+ # warn "DEBUG: have_waited[$have_waited]timeout[$timeout]";
+ next EXPECT;
+ }
+ my $why = "could not answer a question during the dialog";
+ $CPAN::Frontend->mywarn("Failing: $why\n");
+ $self->{$phase} =
+ CPAN::Distrostatus->new("NO $why");
+ return 0;
+ }
+ }
+}
+
+sub _run_via_expect_deterministic {
+ my($self,$expo,$phase,$expect_model) = @_;
+ my $ran_into_timeout;
+ my $ran_into_eof;
+ my $timeout = $expect_model->{timeout} || 15; # currently unsettable
+ my $expecta = $expect_model->{talk};
+ EXPECT: for (my $i = 0; $i <= $#$expecta; $i+=2) {
+ my($re,$send) = @$expecta[$i,$i+1];
+ CPAN->debug("timeout[$timeout]re[$re]") if $CPAN::DEBUG;
+ my $regex = eval "qr{$re}";
+ $expo->expect($timeout,
+ [ eof => sub {
+ my $but = $expo->clear_accum;
+ $CPAN::Frontend->mywarn("EOF (maybe harmless)
+expected[$regex]\nbut[$but]\n\n");
+ $ran_into_eof++;
+ } ],
+ [ timeout => sub {
+ my $but = $expo->clear_accum;
+ $CPAN::Frontend->mywarn("TIMEOUT
+expected[$regex]\nbut[$but]\n\n");
+ $ran_into_timeout++;
+ } ],
+ -re => $regex);
+ if ($ran_into_timeout) {
+ # note that the caller expects 0 for success
+ $self->{$phase} =
+ CPAN::Distrostatus->new("NO timeout during expect dialog");
+ return 0;
+ } elsif ($ran_into_eof) {
+ last EXPECT;
+ }
+ $expo->send($send);
+ }
+ $expo->soft_close;
+ return $expo->exitstatus();
+}
+
+#-> CPAN::Distribution::_validate_distropref
+sub _validate_distropref {
+ my($self,@args) = @_;
+ if (
+ $CPAN::META->has_inst("CPAN::Kwalify")
+ &&
+ $CPAN::META->has_inst("Kwalify")
+ ) {
+ eval {CPAN::Kwalify::_validate("distroprefs",@args);};
+ if ($@) {
+ $CPAN::Frontend->mywarn($@);
+ }
+ } else {
+ CPAN->debug("not validating '@args'") if $CPAN::DEBUG;
+ }
+}
+
+#-> CPAN::Distribution::_find_prefs
+sub _find_prefs {
+ my($self) = @_;
+ my $distroid = $self->pretty_id;
+ #CPAN->debug("distroid[$distroid]") if $CPAN::DEBUG;
+ my $prefs_dir = $CPAN::Config->{prefs_dir};
+ return if $prefs_dir =~ /^\s*$/;
+ eval { File::Path::mkpath($prefs_dir); };
+ if ($@) {
+ $CPAN::Frontend->mydie("Cannot create directory $prefs_dir");
+ }
+ # shortcut if there are no distroprefs files
+ {
+ my $dh = DirHandle->new($prefs_dir) or $CPAN::Frontend->mydie("Couldn't open '$prefs_dir': $!");
+ my @files = map { /\.(yml|dd|st)\z/i } $dh->read;
+ return unless @files;
+ }
+ my $yaml_module = CPAN::_yaml_module();
+ my $ext_map = {};
+ my @extensions;
+ if ($CPAN::META->has_inst($yaml_module)) {
+ $ext_map->{yml} = 'CPAN';
+ } else {
+ my @fallbacks;
+ if ($CPAN::META->has_inst("Data::Dumper")) {
+ push @fallbacks, $ext_map->{dd} = 'Data::Dumper';
+ }
+ if ($CPAN::META->has_inst("Storable")) {
+ push @fallbacks, $ext_map->{st} = 'Storable';
+ }
+ if (@fallbacks) {
+ local $" = " and ";
+ unless ($self->{have_complained_about_missing_yaml}++) {
+ $CPAN::Frontend->mywarnonce("'$yaml_module' not installed, falling back ".
+ "to @fallbacks to read prefs '$prefs_dir'\n");
+ }
+ } else {
+ unless ($self->{have_complained_about_missing_yaml}++) {
+ $CPAN::Frontend->mywarnonce("'$yaml_module' not installed, cannot ".
+ "read prefs '$prefs_dir'\n");
+ }
+ }
+ }
+ my $finder = CPAN::Distroprefs->find($prefs_dir, $ext_map);
+ DIRENT: while (my $result = $finder->next) {
+ if ($result->is_warning) {
+ $CPAN::Frontend->mywarn($result->as_string);
+ $CPAN::Frontend->mysleep(1);
+ next DIRENT;
+ } elsif ($result->is_fatal) {
+ $CPAN::Frontend->mydie($result->as_string);
+ }
+
+ my @prefs = @{ $result->prefs };
+
+ ELEMENT: for my $y (0..$#prefs) {
+ my $pref = $prefs[$y];
+ $self->_validate_distropref($pref->data, $result->abs, $y);
+
+ # I don't know why we silently skip when there's no match, but
+ # complain if there's an empty match hashref, and there's no
+ # comment explaining why -- hdp, 2008-03-18
+ unless ($pref->has_any_match) {
+ next ELEMENT;
+ }
+
+ unless ($pref->has_valid_subkeys) {
+ $CPAN::Frontend->mydie(sprintf
+ "Nonconforming .%s file '%s': " .
+ "missing match/* subattribute. " .
+ "Please remove, cannot continue.",
+ $result->ext, $result->abs,
+ );
+ }
+
+ my $arg = {
+ env => \%ENV,
+ distribution => $distroid,
+ perl => \&CPAN::find_perl,
+ perlconfig => \%Config::Config,
+ module => sub { [ $self->containsmods ] },
+ };
+
+ if ($pref->matches($arg)) {
+ return {
+ prefs => $pref->data,
+ prefs_file => $result->abs,
+ prefs_file_doc => $y,
+ };
+ }
+
+ }
+ }
+ return;
+}
+
+# CPAN::Distribution::prefs
+sub prefs {
+ my($self) = @_;
+ if (exists $self->{negative_prefs_cache}
+ &&
+ $self->{negative_prefs_cache} != $CPAN::CurrentCommandId
+ ) {
+ delete $self->{negative_prefs_cache};
+ delete $self->{prefs};
+ }
+ if (exists $self->{prefs}) {
+ return $self->{prefs}; # XXX comment out during debugging
+ }
+ if ($CPAN::Config->{prefs_dir}) {
+ CPAN->debug("prefs_dir[$CPAN::Config->{prefs_dir}]") if $CPAN::DEBUG;
+ my $prefs = $self->_find_prefs();
+ $prefs ||= ""; # avoid warning next line
+ CPAN->debug("prefs[$prefs]") if $CPAN::DEBUG;
+ if ($prefs) {
+ for my $x (qw(prefs prefs_file prefs_file_doc)) {
+ $self->{$x} = $prefs->{$x};
+ }
+ my $bs = sprintf(
+ "%s[%s]",
+ File::Basename::basename($self->{prefs_file}),
+ $self->{prefs_file_doc},
+ );
+ my $filler1 = "_" x 22;
+ my $filler2 = int(66 - length($bs))/2;
+ $filler2 = 0 if $filler2 < 0;
+ $filler2 = " " x $filler2;
+ $CPAN::Frontend->myprint("
+$filler1 D i s t r o P r e f s $filler1
+$filler2 $bs $filler2
+");
+ $CPAN::Frontend->mysleep(1);
+ return $self->{prefs};
+ }
+ }
+ $self->{negative_prefs_cache} = $CPAN::CurrentCommandId;
+ return $self->{prefs} = +{};
+}
+
+# CPAN::Distribution::_make_phase_arg
+sub _make_phase_arg {
+ my($self, $phase) = @_;
+ my $_make_phase_arg;
+ my $prefs = $self->prefs;
+ if (
+ $prefs
+ && exists $prefs->{$phase}
+ && exists $prefs->{$phase}{args}
+ && $prefs->{$phase}{args}
+ ) {
+ $_make_phase_arg = join(" ",
+ map {CPAN::HandleConfig
+ ->safe_quote($_)} @{$prefs->{$phase}{args}},
+ );
+ }
+
+# cpan[2]> o conf make[TAB]
+# make make_install_make_command
+# make_arg makepl_arg
+# make_install_arg
+# cpan[2]> o conf mbuild[TAB]
+# mbuild_arg mbuild_install_build_command
+# mbuild_install_arg mbuildpl_arg
+
+ my $mantra; # must switch make/mbuild here
+ if ($self->{modulebuild}) {
+ $mantra = "mbuild";
+ } else {
+ $mantra = "make";
+ }
+ my %map = (
+ pl => "pl_arg",
+ make => "_arg",
+ test => "_test_arg", # does not really exist but maybe
+ # will some day and now protects
+ # us from unini warnings
+ install => "_install_arg",
+ );
+ my $phase_underscore_meshup = $map{$phase};
+ my $what = sprintf "%s%s", $mantra, $phase_underscore_meshup;
+
+ $_make_phase_arg ||= $CPAN::Config->{$what};
+ return $_make_phase_arg;
+}
+
+# CPAN::Distribution::_make_command
+sub _make_command {
+ my ($self) = @_;
+ if ($self) {
+ return
+ CPAN::HandleConfig
+ ->safe_quote(
+ CPAN::HandleConfig->prefs_lookup($self,
+ q{make})
+ || $Config::Config{make}
+ || 'make'
+ );
+ } else {
+ # Old style call, without object. Deprecated
+ Carp::confess("CPAN::_make_command() used as function. Don't Do That.");
+ return
+ safe_quote(undef,
+ CPAN::HandleConfig->prefs_lookup($self,q{make})
+ || $CPAN::Config->{make}
+ || $Config::Config{make}
+ || 'make');
+ }
+}
+
+#-> sub CPAN::Distribution::follow_prereqs ;
+sub follow_prereqs {
+ my($self) = shift;
+ my($slot) = shift;
+ my(@prereq_tuples) = grep {$_->[0] ne "perl"} @_;
+ return unless @prereq_tuples;
+ my(@good_prereq_tuples);
+ for my $p (@prereq_tuples) {
+ # XXX watch out for foul ones
+ push @good_prereq_tuples, $p;
+ }
+ my $pretty_id = $self->pretty_id;
+ my %map = (
+ b => "build_requires",
+ r => "requires",
+ c => "commandline",
+ );
+ my($filler1,$filler2,$filler3,$filler4);
+ my $unsat = "Unsatisfied dependencies detected during";
+ my $w = length($unsat) > length($pretty_id) ? length($unsat) : length($pretty_id);
+ {
+ my $r = int(($w - length($unsat))/2);
+ my $l = $w - length($unsat) - $r;
+ $filler1 = "-"x4 . " "x$l;
+ $filler2 = " "x$r . "-"x4 . "\n";
+ }
+ {
+ my $r = int(($w - length($pretty_id))/2);
+ my $l = $w - length($pretty_id) - $r;
+ $filler3 = "-"x4 . " "x$l;
+ $filler4 = " "x$r . "-"x4 . "\n";
+ }
+ $CPAN::Frontend->
+ myprint("$filler1 $unsat $filler2".
+ "$filler3 $pretty_id $filler4".
+ join("", map {" $_->[0] \[$map{$_->[1]}]\n"} @good_prereq_tuples),
+ );
+ my $follow = 0;
+ if ($CPAN::Config->{prerequisites_policy} eq "follow") {
+ $follow = 1;
+ } elsif ($CPAN::Config->{prerequisites_policy} eq "ask") {
+ my $answer = CPAN::Shell::colorable_makemaker_prompt(
+"Shall I follow them and prepend them to the queue
+of modules we are processing right now?", "yes");
+ $follow = $answer =~ /^\s*y/i;
+ } else {
+ my @prereq = map { $_=>[0] } @good_prereq_tuples;
+ local($") = ", ";
+ $CPAN::Frontend->
+ myprint(" Ignoring dependencies on modules @prereq\n");
+ }
+ if ($follow) {
+ my $id = $self->id;
+ # color them as dirty
+ for my $gp (@good_prereq_tuples) {
+ # warn "calling color_cmd_tmps(0,1)";
+ my $p = $gp->[0];
+ my $any = CPAN::Shell->expandany($p);
+ $self->{$slot . "_for"}{$any->id}++;
+ if ($any) {
+ $any->color_cmd_tmps(0,2);
+ } else {
+ $CPAN::Frontend->mywarn("Warning (maybe a bug): Cannot expand prereq '$p'\n");
+ $CPAN::Frontend->mysleep(2);
+ }
+ }
+ # queue them and re-queue yourself
+ CPAN::Queue->jumpqueue({qmod => $id, reqtype => $self->{reqtype}},
+ map {+{qmod=>$_->[0],reqtype=>$_->[1]}} reverse @good_prereq_tuples);
+ $self->{$slot} = "Delayed until after prerequisites";
+ return 1; # signal success to the queuerunner
+ }
+ return;
+}
+
+sub _feature_depends {
+ my($self) = @_;
+ my $meta_yml = $self->parse_meta_yml();
+ my $optf = $meta_yml->{optional_features} or return;
+ if (!ref $optf or ref $optf ne "HASH"){
+ $CPAN::Frontend->mywarn("The content of optional_features is not a HASH reference. Cannot use it.\n");
+ $optf = {};
+ }
+ my $wantf = $self->prefs->{features} or return;
+ if (!ref $wantf or ref $wantf ne "ARRAY"){
+ $CPAN::Frontend->mywarn("The content of 'features' is not an ARRAY reference. Cannot use it.\n");
+ $wantf = [];
+ }
+ my $dep = +{};
+ for my $wf (@$wantf) {
+ if (my $f = $optf->{$wf}) {
+ $CPAN::Frontend->myprint("Found the demanded feature '$wf' that ".
+ "is accompanied by this description:\n".
+ $f->{description}.
+ "\n\n"
+ );
+ # configure_requires currently not in the spec, unlikely to be useful anyway
+ for my $reqtype (qw(configure_requires build_requires requires)) {
+ my $reqhash = $f->{$reqtype} or next;
+ while (my($k,$v) = each %$reqhash) {
+ $dep->{$reqtype}{$k} = $v;
+ }
+ }
+ } else {
+ $CPAN::Frontend->mywarn("The demanded feature '$wf' was not ".
+ "found in the META.yml file".
+ "\n\n"
+ );
+ }
+ }
+ $dep;
+}
+
+#-> sub CPAN::Distribution::unsat_prereq ;
+# return ([Foo,"r"],[Bar,"b"]) for normal modules
+# return ([perl=>5.008]) if we need a newer perl than we are running under
+# (sorry for the inconsistency, it was an accident)
+sub unsat_prereq {
+ my($self,$slot) = @_;
+ my(%merged,$prereq_pm);
+ my $prefs_depends = $self->prefs->{depends}||{};
+ my $feature_depends = $self->_feature_depends();
+ if ($slot eq "configure_requires_later") {
+ my $meta_yml = $self->parse_meta_yml();
+ if (defined $meta_yml && (! ref $meta_yml || ref $meta_yml ne "HASH")) {
+ $CPAN::Frontend->mywarn("The content of META.yml is defined but not a HASH reference. Cannot use it.\n");
+ $meta_yml = +{};
+ }
+ %merged = (
+ %{$meta_yml->{configure_requires}||{}},
+ %{$prefs_depends->{configure_requires}||{}},
+ %{$feature_depends->{configure_requires}||{}},
+ );
+ if (-f "Build.PL"
+ && ! -f "Makefile.PL"
+ && ! exists $merged{"Module::Build"}
+ && ! $CPAN::META->has_inst("Module::Build")
+ ) {
+ $CPAN::Frontend->mywarn(
+ " Warning: CPAN.pm discovered Module::Build as undeclared prerequisite.\n".
+ " Adding it now as such.\n"
+ );
+ $CPAN::Frontend->mysleep(5);
+ $merged{"Module::Build"} = 0;
+ delete $self->{writemakefile};
+ }
+ $prereq_pm = {}; # configure_requires defined as "b"
+ } elsif ($slot eq "later") {
+ my $prereq_pm_0 = $self->prereq_pm || {};
+ for my $reqtype (qw(requires build_requires)) {
+ $prereq_pm->{$reqtype} = {%{$prereq_pm_0->{$reqtype}||{}}}; # copy to not pollute it
+ for my $dep ($prefs_depends,$feature_depends) {
+ for my $k (keys %{$dep->{$reqtype}||{}}) {
+ $prereq_pm->{$reqtype}{$k} = $dep->{$reqtype}{$k};
+ }
+ }
+ }
+ %merged = (%{$prereq_pm->{requires}||{}},%{$prereq_pm->{build_requires}||{}});
+ } else {
+ die "Panic: illegal slot '$slot'";
+ }
+ my(@need);
+ my @merged = %merged;
+ CPAN->debug("all merged_prereqs[@merged]") if $CPAN::DEBUG;
+ NEED: while (my($need_module, $need_version) = each %merged) {
+ my($available_version,$inst_file,$available_file,$nmo);
+ if ($need_module eq "perl") {
+ $available_version = $];
+ $available_file = CPAN::find_perl();
+ } else {
+ if (CPAN::_sqlite_running()) {
+ CPAN::Index->reload;
+ $CPAN::SQLite->search("CPAN::Module",$need_module);
+ }
+ $nmo = $CPAN::META->instance("CPAN::Module",$need_module);
+ next if $nmo->uptodate;
+ $inst_file = $nmo->inst_file || '';
+ $available_file = $nmo->available_file || '';
+
+ # if they have not specified a version, we accept any installed one
+ if ( $available_file
+ and ( # a few quick shortcurcuits
+ not defined $need_version
+ or $need_version eq '0' # "==" would trigger warning when not numeric
+ or $need_version eq "undef"
+ )) {
+ unless ($nmo->inst_deprecated) {
+ next NEED;
+ }
+
+ }
+
+ $available_version = $nmo->available_version;
+ }
+
+ # We only want to install prereqs if either they're not installed
+ # or if the installed version is too old. We cannot omit this
+ # check, because if 'force' is in effect, nobody else will check.
+ # But we don't want to accept a deprecated module installed as part
+ # of the Perl core, so we continue if the available file is the installed
+ # one and is deprecated
+
+ if ( $available_file ) {
+ if ( $inst_file && $available_file eq $inst_file && $nmo->inst_deprecated ) {
+ # continue installing as a prereq
+ }
+ else {
+ next NEED if $self->_fulfills_all_version_rqs(
+ $need_module,$available_file,$available_version,$need_version
+ );
+ }
+ }
+
+ if ($need_module eq "perl") {
+ return ["perl", $need_version];
+ }
+ $self->{sponsored_mods}{$need_module} ||= 0;
+ CPAN->debug("need_module[$need_module]s/s/n[$self->{sponsored_mods}{$need_module}]") if $CPAN::DEBUG;
+ if (my $sponsoring = $self->{sponsored_mods}{$need_module}++) {
+ # We have already sponsored it and for some reason it's still
+ # not available. So we do ... what??
+
+ # if we push it again, we have a potential infinite loop
+
+ # The following "next" was a very problematic construct.
+ # It helped a lot but broke some day and had to be
+ # replaced.
+
+ # We must be able to deal with modules that come again and
+ # again as a prereq and have themselves prereqs and the
+ # queue becomes long but finally we would find the correct
+ # order. The RecursiveDependency check should trigger a
+ # die when it's becoming too weird. Unfortunately removing
+ # this next breaks many other things.
+
+ # The bug that brought this up is described in Todo under
+ # "5.8.9 cannot install Compress::Zlib"
+
+ # next; # this is the next that had to go away
+
+ # The following "next NEED" are fine and the error message
+ # explains well what is going on. For example when the DBI
+ # fails and consequently DBD::SQLite fails and now we are
+ # processing CPAN::SQLite. Then we must have a "next" for
+ # DBD::SQLite. How can we get it and how can we identify
+ # all other cases we must identify?
+
+ my $do = $nmo->distribution;
+ next NEED unless $do; # not on CPAN
+ if (CPAN::Version->vcmp($need_version, $nmo->ro->{CPAN_VERSION}) > 0){
+ $CPAN::Frontend->mywarn("Warning: Prerequisite ".
+ "'$need_module => $need_version' ".
+ "for '$self->{ID}' seems ".
+ "not available according to the indices\n"
+ );
+ next NEED;
+ }
+ NOSAYER: for my $nosayer (
+ "unwrapped",
+ "writemakefile",
+ "signature_verify",
+ "make",
+ "make_test",
+ "install",
+ "make_clean",
+ ) {
+ if ($do->{$nosayer}) {
+ my $selfid = $self->pretty_id;
+ my $did = $do->pretty_id;
+ if (UNIVERSAL::can($do->{$nosayer},"failed") ?
+ $do->{$nosayer}->failed :
+ $do->{$nosayer} =~ /^NO/) {
+ if ($nosayer eq "make_test"
+ &&
+ $do->{make_test}{COMMANDID} != $CPAN::CurrentCommandId
+ ) {
+ next NOSAYER;
+ }
+ $CPAN::Frontend->mywarn("Warning: Prerequisite ".
+ "'$need_module => $need_version' ".
+ "for '$selfid' failed when ".
+ "processing '$did' with ".
+ "'$nosayer => $do->{$nosayer}'. Continuing, ".
+ "but chances to succeed are limited.\n"
+ );
+ $CPAN::Frontend->mysleep($sponsoring/10);
+ next NEED;
+ } else { # the other guy succeeded
+ if ($nosayer =~ /^(install|make_test)$/) {
+ # we had this with
+ # DMAKI/DateTime-Calendar-Chinese-0.05.tar.gz
+ # in 2007-03 for 'make install'
+ # and 2008-04: #30464 (for 'make test')
+ $CPAN::Frontend->mywarn("Warning: Prerequisite ".
+ "'$need_module => $need_version' ".
+ "for '$selfid' already built ".
+ "but the result looks suspicious. ".
+ "Skipping another build attempt, ".
+ "to prevent looping endlessly.\n"
+ );
+ next NEED;
+ }
+ }
+ }
+ }
+ }
+ my $needed_as = exists $prereq_pm->{requires}{$need_module} ? "r" : "b";
+ push @need, [$need_module,$needed_as];
+ }
+ my @unfolded = map { "[".join(",",@$_)."]" } @need;
+ CPAN->debug("returning from unsat_prereq[@unfolded]") if $CPAN::DEBUG;
+ @need;
+}
+
+sub _fulfills_all_version_rqs {
+ my($self,$need_module,$available_file,$available_version,$need_version) = @_;
+ my(@all_requirements) = split /\s*,\s*/, $need_version;
+ local($^W) = 0;
+ my $ok = 0;
+ RQ: for my $rq (@all_requirements) {
+ if ($rq =~ s|>=\s*||) {
+ } elsif ($rq =~ s|>\s*||) {
+ # 2005-12: one user
+ if (CPAN::Version->vgt($available_version,$rq)) {
+ $ok++;
+ }
+ next RQ;
+ } elsif ($rq =~ s|!=\s*||) {
+ # 2005-12: no user
+ if (CPAN::Version->vcmp($available_version,$rq)) {
+ $ok++;
+ next RQ;
+ } else {
+ $ok=0;
+ last RQ;
+ }
+ } elsif ($rq =~ m|<=?\s*|) {
+ # 2005-12: no user
+ $CPAN::Frontend->mywarn("Downgrading not supported (rq[$rq])\n");
+ $ok++;
+ next RQ;
+ } elsif ($rq =~ s|==\s*||) {
+ # 2009-07: ELLIOTJS/Perl-Critic-1.099_002.tar.gz
+ if (CPAN::Version->vcmp($available_version,$rq)) {
+ $ok=0;
+ last RQ;
+ } else {
+ $ok++;
+ next RQ;
+ }
+ }
+ if (! CPAN::Version->vgt($rq, $available_version)) {
+ $ok++;
+ }
+ CPAN->debug(sprintf("need_module[%s]available_file[%s]".
+ "available_version[%s]rq[%s]ok[%d]",
+ $need_module,
+ $available_file,
+ $available_version,
+ CPAN::Version->readable($rq),
+ $ok,
+ )) if $CPAN::DEBUG;
+ }
+ my $ret = $ok == @all_requirements;
+ CPAN->debug(sprintf("need_module[%s]ok[%s]all_requirements[%d]",$need_module, $ok, scalar @all_requirements)) if $CPAN::DEBUG;
+ return $ret;
+}
+
+#-> sub CPAN::Distribution::read_yaml ;
+sub read_yaml {
+ my($self) = @_;
+ my $build_dir;
+ unless ($build_dir = $self->{build_dir}) {
+ # maybe permission on build_dir was missing
+ $CPAN::Frontend->mywarn("Warning: cannot determine META.yml without a build_dir.\n");
+ return;
+ }
+ # if MYMETA.yml exists, that takes precedence over META.yml
+ my $meta = File::Spec->catfile($build_dir,"META.yml");
+ my $mymeta = File::Spec->catfile($build_dir,"MYMETA.yml");
+ my $meta_file = -f $mymeta ? $mymeta : $meta;
+ $self->debug("meta_file[$meta_file]") if $CPAN::DEBUG;
+ return unless -f $meta_file;
+ my $yaml;
+ eval { $yaml = $self->parse_meta_yml($meta_file) };
+ if ($@ or ! $yaml) {
+ $CPAN::Frontend->mywarnonce("Could not read ".
+ "'$meta_file'. Falling back to other ".
+ "methods to determine prerequisites\n");
+ return undef; # if we die, then we cannot read YAML's own META.yml
+ }
+ # not "authoritative"
+ if (defined $yaml && (! ref $yaml || ref $yaml ne "HASH")) {
+ $CPAN::Frontend->mywarn("META.yml does not seem to be conforming, cannot use it.\n");
+ $yaml = undef;
+ }
+ $self->debug(sprintf "yaml[%s]", $yaml || "UNDEF")
+ if $CPAN::DEBUG;
+ $self->debug($yaml) if $CPAN::DEBUG && $yaml;
+ # MYMETA.yml is static and authoritative by definition
+ if ( $meta_file eq $mymeta ) {
+ return $yaml;
+ }
+ # META.yml is authoritative only if dynamic_config is defined and false
+ if ( defined $yaml->{dynamic_config} && ! $yaml->{dynamic_config} ) {
+ return $yaml;
+ }
+ # otherwise, we can't use what we found
+ return undef;
+}
+
+#-> sub CPAN::Distribution::prereq_pm ;
+sub prereq_pm {
+ my($self) = @_;
+ return unless $self->{writemakefile} # no need to have succeeded
+ # but we must have run it
+ || $self->{modulebuild};
+ unless ($self->{build_dir}) {
+ return;
+ }
+ CPAN->debug(sprintf "writemakefile[%s]modulebuild[%s]",
+ $self->{writemakefile}||"",
+ $self->{modulebuild}||"",
+ ) if $CPAN::DEBUG;
+ my($req,$breq);
+ if (my $yaml = $self->read_yaml) { # often dynamic_config prevents a result here
+ $req = $yaml->{requires} || {};
+ $breq = $yaml->{build_requires} || {};
+ undef $req unless ref $req eq "HASH" && %$req;
+ if ($req) {
+ if ($yaml->{generated_by} &&
+ $yaml->{generated_by} =~ /ExtUtils::MakeMaker version ([\d\._]+)/) {
+ my $eummv = do { local $^W = 0; $1+0; };
+ if ($eummv < 6.2501) {
+ # thanks to Slaven for digging that out: MM before
+ # that could be wrong because it could reflect a
+ # previous release
+ undef $req;
+ }
+ }
+ my $areq;
+ my $do_replace;
+ while (my($k,$v) = each %{$req||{}}) {
+ if ($v =~ /\d/) {
+ $areq->{$k} = $v;
+ } elsif ($k =~ /[A-Za-z]/ &&
+ $v =~ /[A-Za-z]/ &&
+ $CPAN::META->exists("CPAN::Module",$v)
+ ) {
+ $CPAN::Frontend->mywarn("Suspicious key-value pair in META.yml's ".
+ "requires hash: $k => $v; I'll take both ".
+ "key and value as a module name\n");
+ $CPAN::Frontend->mysleep(1);
+ $areq->{$k} = 0;
+ $areq->{$v} = 0;
+ $do_replace++;
+ }
+ }
+ $req = $areq if $do_replace;
+ }
+ }
+ unless ($req || $breq) {
+ my $build_dir;
+ unless ( $build_dir = $self->{build_dir} ) {
+ return;
+ }
+ my $makefile = File::Spec->catfile($build_dir,"Makefile");
+ my $fh;
+ if (-f $makefile
+ and
+ $fh = FileHandle->new("<$makefile\0")) {
+ CPAN->debug("Getting prereq from Makefile") if $CPAN::DEBUG;
+ local($/) = "\n";
+ while (<$fh>) {
+ last if /MakeMaker post_initialize section/;
+ my($p) = m{^[\#]
+ \s+PREREQ_PM\s+=>\s+(.+)
+ }x;
+ next unless $p;
+ # warn "Found prereq expr[$p]";
+
+ # Regexp modified by A.Speer to remember actual version of file
+ # PREREQ_PM hash key wants, then add to
+ while ( $p =~ m/(?:\s)([\w\:]+)=>(q\[.*?\]|undef),?/g ) {
+ my($m,$n) = ($1,$2);
+ # When a prereq is mentioned twice: let the bigger
+ # win; usual culprit is that they declared
+ # build_requires separately from requires; see
+ # rt.cpan.org #47774
+ my($prevn);
+ if ( defined $req->{$m} ) {
+ $prevn = $req->{$m};
+ }
+ if ($n =~ /^q\[(.*?)\]$/) {
+ $n = $1;
+ }
+ if (!$prevn || CPAN::Version->vlt($prevn, $n)){
+ $req->{$m} = $n;
+ }
+ }
+ last;
+ }
+ }
+ }
+ unless ($req || $breq) {
+ my $build_dir = $self->{build_dir} or die "Panic: no build_dir?";
+ my $buildfile = File::Spec->catfile($build_dir,"Build");
+ if (-f $buildfile) {
+ CPAN->debug("Found '$buildfile'") if $CPAN::DEBUG;
+ my $build_prereqs = File::Spec->catfile($build_dir,"_build","prereqs");
+ if (-f $build_prereqs) {
+ CPAN->debug("Getting prerequisites from '$build_prereqs'") if $CPAN::DEBUG;
+ my $content = do { local *FH;
+ open FH, $build_prereqs
+ or $CPAN::Frontend->mydie("Could not open ".
+ "'$build_prereqs': $!");
+ local $/;
+ <FH>;
+ };
+ my $bphash = eval $content;
+ if ($@) {
+ } else {
+ $req = $bphash->{requires} || +{};
+ $breq = $bphash->{build_requires} || +{};
+ }
+ }
+ }
+ }
+ if ($req || $breq) {
+ return $self->{prereq_pm} = { requires => $req, build_requires => $breq };
+ }
+}
+
+#-> sub CPAN::Distribution::test ;
+sub test {
+ my($self) = @_;
+ if (my $goto = $self->prefs->{goto}) {
+ return $self->goto($goto);
+ }
+ $self->make;
+ return if $self->prefs->{disabled} && ! $self->{force_update};
+ if ($CPAN::Signal) {
+ delete $self->{force_update};
+ return;
+ }
+ # warn "XDEBUG: checking for notest: $self->{notest} $self";
+ if ($self->{notest}) {
+ $CPAN::Frontend->myprint("Skipping test because of notest pragma\n");
+ return 1;
+ }
+
+ my $make = $self->{modulebuild} ? "Build" : "make";
+
+ local $ENV{PERL5LIB} = defined($ENV{PERL5LIB})
+ ? $ENV{PERL5LIB}
+ : ($ENV{PERLLIB} || "");
+
+ local $ENV{PERL5OPT} = defined $ENV{PERL5OPT} ? $ENV{PERL5OPT} : "";
+ $CPAN::META->set_perl5lib;
+ local $ENV{MAKEFLAGS}; # protect us from outer make calls
+
+ $CPAN::Frontend->myprint("Running $make test\n");
+
+ EXCUSE: {
+ my @e;
+ if ($self->{make} or $self->{later}) {
+ # go ahead
+ } else {
+ push @e,
+ "Make had some problems, won't test";
+ }
+
+ exists $self->{make} and
+ (
+ UNIVERSAL::can($self->{make},"failed") ?
+ $self->{make}->failed :
+ $self->{make} =~ /^NO/
+ ) and push @e, "Can't test without successful make";
+ $self->{badtestcnt} ||= 0;
+ if ($self->{badtestcnt} > 0) {
+ require Data::Dumper;
+ CPAN->debug(sprintf "NOREPEAT[%s]", Data::Dumper::Dumper($self)) if $CPAN::DEBUG;
+ push @e, "Won't repeat unsuccessful test during this command";
+ }
+
+ push @e, $self->{later} if $self->{later};
+ push @e, $self->{configure_requires_later} if $self->{configure_requires_later};
+
+ if (exists $self->{build_dir}) {
+ if (exists $self->{make_test}) {
+ if (
+ UNIVERSAL::can($self->{make_test},"failed") ?
+ $self->{make_test}->failed :
+ $self->{make_test} =~ /^NO/
+ ) {
+ if (
+ UNIVERSAL::can($self->{make_test},"commandid")
+ &&
+ $self->{make_test}->commandid == $CPAN::CurrentCommandId
+ ) {
+ push @e, "Has already been tested within this command";
+ }
+ } else {
+ push @e, "Has already been tested successfully";
+ # if global "is_tested" has been cleared, we need to mark this to
+ # be added to PERL5LIB if not already installed
+ if ($self->tested_ok_but_not_installed) {
+ $CPAN::META->is_tested($self->{build_dir},$self->{make_test}{TIME});
+ }
+ }
+ }
+ } elsif (!@e) {
+ push @e, "Has no own directory";
+ }
+ $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
+ unless (chdir $self->{build_dir}) {
+ push @e, "Couldn't chdir to '$self->{build_dir}': $!";
+ }
+ $CPAN::Frontend->mywarn(join "", map {" $_\n"} @e) and return if @e;
+ }
+ $self->debug("Changed directory to $self->{build_dir}")
+ if $CPAN::DEBUG;
+
+ if ($^O eq 'MacOS') {
+ Mac::BuildTools::make_test($self);
+ return;
+ }
+
+ if ($self->{modulebuild}) {
+ my $thm = CPAN::Shell->expand("Module","Test::Harness");
+ my $v = $thm->inst_version;
+ if (CPAN::Version->vlt($v,2.62)) {
+ # XXX Eric Wilhelm reported this as a bug: klapperl:
+ # Test::Harness 3.0 self-tests, so that should be 'unless
+ # installing Test::Harness'
+ unless ($self->id eq $thm->distribution->id) {
+ $CPAN::Frontend->mywarn(qq{The version of your Test::Harness is only
+ '$v', you need at least '2.62'. Please upgrade your Test::Harness.\n});
+ $self->{make_test} = CPAN::Distrostatus->new("NO Test::Harness too old");
+ return;
+ }
+ }
+ }
+
+ if ( ! $self->{force_update} ) {
+ # bypass actual tests if "trust_test_report_history" and have a report
+ my $have_tested_fcn;
+ if ( $CPAN::Config->{trust_test_report_history}
+ && $CPAN::META->has_inst("CPAN::Reporter::History")
+ && ( $have_tested_fcn = CPAN::Reporter::History->can("have_tested" ))) {
+ if ( my @reports = $have_tested_fcn->( dist => $self->base_id ) ) {
+ # Do nothing if grade was DISCARD
+ if ( $reports[-1]->{grade} =~ /^(?:PASS|UNKNOWN)$/ ) {
+ $self->{make_test} = CPAN::Distrostatus->new("YES");
+ # if global "is_tested" has been cleared, we need to mark this to
+ # be added to PERL5LIB if not already installed
+ if ($self->tested_ok_but_not_installed) {
+ $CPAN::META->is_tested($self->{build_dir},$self->{make_test}{TIME});
+ }
+ $CPAN::Frontend->myprint("Found prior test report -- OK\n");
+ return;
+ }
+ elsif ( $reports[-1]->{grade} =~ /^(?:FAIL|NA)$/ ) {
+ $self->{make_test} = CPAN::Distrostatus->new("NO");
+ $self->{badtestcnt}++;
+ $CPAN::Frontend->mywarn("Found prior test report -- NOT OK\n");
+ return;
+ }
+ }
+ }
+ }
+
+ my $system;
+ my $prefs_test = $self->prefs->{test};
+ if (my $commandline
+ = exists $prefs_test->{commandline} ? $prefs_test->{commandline} : "") {
+ $system = $commandline;
+ $ENV{PERL} = CPAN::find_perl();
+ } elsif ($self->{modulebuild}) {
+ $system = sprintf "%s test", $self->_build_command();
+ unless (-e "Build") {
+ my $id = $self->pretty_id;
+ $CPAN::Frontend->mywarn("Alert: no 'Build' file found while trying to test '$id'");
+ }
+ } else {
+ $system = join " ", $self->_make_command(), "test";
+ }
+ my $make_test_arg = $self->_make_phase_arg("test");
+ $system = sprintf("%s%s",
+ $system,
+ $make_test_arg ? " $make_test_arg" : "",
+ );
+ my($tests_ok);
+ my %env;
+ while (my($k,$v) = each %ENV) {
+ next unless defined $v;
+ $env{$k} = $v;
+ }
+ local %ENV = %env;
+ my $test_env;
+ if ($self->prefs->{test}) {
+ $test_env = $self->prefs->{test}{env};
+ }
+ if ($test_env) {
+ for my $e (keys %$test_env) {
+ $ENV{$e} = $test_env->{$e};
+ }
+ }
+ my $expect_model = $self->_prefs_with_expect("test");
+ my $want_expect = 0;
+ if ( $expect_model && @{$expect_model->{talk}} ) {
+ my $can_expect = $CPAN::META->has_inst("Expect");
+ if ($can_expect) {
+ $want_expect = 1;
+ } else {
+ $CPAN::Frontend->mywarn("Expect not installed, falling back to ".
+ "testing without\n");
+ }
+ }
+ if ($want_expect) {
+ if ($self->_should_report('test')) {
+ $CPAN::Frontend->mywarn("Reporting via CPAN::Reporter is currently ".
+ "not supported when distroprefs specify ".
+ "an interactive test\n");
+ }
+ $tests_ok = $self->_run_via_expect($system,'test',$expect_model) == 0;
+ } elsif ( $self->_should_report('test') ) {
+ $tests_ok = CPAN::Reporter::test($self, $system);
+ } else {
+ $tests_ok = system($system) == 0;
+ }
+ $self->introduce_myself;
+ if ( $tests_ok ) {
+ {
+ my @prereq;
+
+ # local $CPAN::DEBUG = 16; # Distribution
+ for my $m (keys %{$self->{sponsored_mods}}) {
+ next unless $self->{sponsored_mods}{$m} > 0;
+ my $m_obj = CPAN::Shell->expand("Module",$m) or next;
+ # XXX we need available_version which reflects
+ # $ENV{PERL5LIB} so that already tested but not yet
+ # installed modules are counted.
+ my $available_version = $m_obj->available_version;
+ my $available_file = $m_obj->available_file;
+ if ($available_version &&
+ !CPAN::Version->vlt($available_version,$self->{prereq_pm}{$m})
+ ) {
+ CPAN->debug("m[$m] good enough available_version[$available_version]")
+ if $CPAN::DEBUG;
+ } elsif ($available_file
+ && (
+ !$self->{prereq_pm}{$m}
+ ||
+ $self->{prereq_pm}{$m} == 0
+ )
+ ) {
+ # lex Class::Accessor::Chained::Fast which has no $VERSION
+ CPAN->debug("m[$m] have available_file[$available_file]")
+ if $CPAN::DEBUG;
+ } else {
+ push @prereq, $m;
+ }
+ }
+ if (@prereq) {
+ my $cnt = @prereq;
+ my $which = join ",", @prereq;
+ my $but = $cnt == 1 ? "one dependency not OK ($which)" :
+ "$cnt dependencies missing ($which)";
+ $CPAN::Frontend->mywarn("Tests succeeded but $but\n");
+ $self->{make_test} = CPAN::Distrostatus->new("NO $but");
+ $self->store_persistent_state;
+ return $self->goodbye("[dependencies] -- NA");
+ }
+ }
+
+ $CPAN::Frontend->myprint(" $system -- OK\n");
+ $self->{make_test} = CPAN::Distrostatus->new("YES");
+ $CPAN::META->is_tested($self->{build_dir},$self->{make_test}{TIME});
+ # probably impossible to need the next line because badtestcnt
+ # has a lifespan of one command
+ delete $self->{badtestcnt};
+ } else {
+ $self->{make_test} = CPAN::Distrostatus->new("NO");
+ $self->{badtestcnt}++;
+ $CPAN::Frontend->mywarn(" $system -- NOT OK\n");
+ CPAN::Shell->optprint
+ ("hint",
+ sprintf
+ ("//hint// to see the cpan-testers results for installing this module, try:
+ reports %s\n",
+ $self->pretty_id));
+ }
+ $self->store_persistent_state;
+}
+
+sub _prefs_with_expect {
+ my($self,$where) = @_;
+ return unless my $prefs = $self->prefs;
+ return unless my $where_prefs = $prefs->{$where};
+ if ($where_prefs->{expect}) {
+ return {
+ mode => "deterministic",
+ timeout => 15,
+ talk => $where_prefs->{expect},
+ };
+ } elsif ($where_prefs->{"eexpect"}) {
+ return $where_prefs->{"eexpect"};
+ }
+ return;
+}
+
+#-> sub CPAN::Distribution::clean ;
+sub clean {
+ my($self) = @_;
+ my $make = $self->{modulebuild} ? "Build" : "make";
+ $CPAN::Frontend->myprint("Running $make clean\n");
+ unless (exists $self->{archived}) {
+ $CPAN::Frontend->mywarn("Distribution seems to have never been unzipped".
+ "/untarred, nothing done\n");
+ return 1;
+ }
+ unless (exists $self->{build_dir}) {
+ $CPAN::Frontend->mywarn("Distribution has no own directory, nothing to do.\n");
+ return 1;
+ }
+ if (exists $self->{writemakefile}
+ and $self->{writemakefile}->failed
+ ) {
+ $CPAN::Frontend->mywarn("No Makefile, don't know how to 'make clean'\n");
+ return 1;
+ }
+ EXCUSE: {
+ my @e;
+ exists $self->{make_clean} and $self->{make_clean} eq "YES" and
+ push @e, "make clean already called once";
+ $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
+ }
+ chdir $self->{build_dir} or
+ Carp::confess("Couldn't chdir to $self->{build_dir}: $!");
+ $self->debug("Changed directory to $self->{build_dir}") if $CPAN::DEBUG;
+
+ if ($^O eq 'MacOS') {
+ Mac::BuildTools::make_clean($self);
+ return;
+ }
+
+ my $system;
+ if ($self->{modulebuild}) {
+ unless (-f "Build") {
+ my $cwd = CPAN::anycwd();
+ $CPAN::Frontend->mywarn("Alert: no Build file available for 'clean $self->{id}".
+ " in cwd[$cwd]. Danger, Will Robinson!");
+ $CPAN::Frontend->mysleep(5);
+ }
+ $system = sprintf "%s clean", $self->_build_command();
+ } else {
+ $system = join " ", $self->_make_command(), "clean";
+ }
+ my $system_ok = system($system) == 0;
+ $self->introduce_myself;
+ if ( $system_ok ) {
+ $CPAN::Frontend->myprint(" $system -- OK\n");
+
+ # $self->force;
+
+ # Jost Krieger pointed out that this "force" was wrong because
+ # it has the effect that the next "install" on this distribution
+ # will untar everything again. Instead we should bring the
+ # object's state back to where it is after untarring.
+
+ for my $k (qw(
+ force_update
+ install
+ writemakefile
+ make
+ make_test
+ )) {
+ delete $self->{$k};
+ }
+ $self->{make_clean} = CPAN::Distrostatus->new("YES");
+
+ } else {
+ # Hmmm, what to do if make clean failed?
+
+ $self->{make_clean} = CPAN::Distrostatus->new("NO");
+ $CPAN::Frontend->mywarn(qq{ $system -- NOT OK\n});
+
+ # 2006-02-27: seems silly to me to force a make now
+ # $self->force("make"); # so that this directory won't be used again
+
+ }
+ $self->store_persistent_state;
+}
+
+#-> sub CPAN::Distribution::goto ;
+sub goto {
+ my($self,$goto) = @_;
+ $goto = $self->normalize($goto);
+ my $why = sprintf(
+ "Goto '$goto' via prefs file '%s' doc %d",
+ $self->{prefs_file},
+ $self->{prefs_file_doc},
+ );
+ $self->{unwrapped} = CPAN::Distrostatus->new("NO $why");
+ # 2007-07-16 akoenig : Better than NA would be if we could inherit
+ # the status of the $goto distro but given the exceptional nature
+ # of 'goto' I feel reluctant to implement it
+ my $goodbye_message = "[goto] -- NA $why";
+ $self->goodbye($goodbye_message);
+
+ # inject into the queue
+
+ CPAN::Queue->delete($self->id);
+ CPAN::Queue->jumpqueue({qmod => $goto, reqtype => $self->{reqtype}});
+
+ # and run where we left off
+
+ my($method) = (caller(1))[3];
+ CPAN->instance("CPAN::Distribution",$goto)->$method();
+ CPAN::Queue->delete_first($goto);
+}
+
+#-> sub CPAN::Distribution::install ;
+sub install {
+ my($self) = @_;
+ if (my $goto = $self->prefs->{goto}) {
+ return $self->goto($goto);
+ }
+ unless ($self->{badtestcnt}) {
+ $self->test;
+ }
+ if ($CPAN::Signal) {
+ delete $self->{force_update};
+ return;
+ }
+ my $make = $self->{modulebuild} ? "Build" : "make";
+ $CPAN::Frontend->myprint("Running $make install\n");
+ EXCUSE: {
+ my @e;
+ if ($self->{make} or $self->{later}) {
+ # go ahead
+ } else {
+ push @e,
+ "Make had some problems, won't install";
+ }
+
+ exists $self->{make} and
+ (
+ UNIVERSAL::can($self->{make},"failed") ?
+ $self->{make}->failed :
+ $self->{make} =~ /^NO/
+ ) and
+ push @e, "Make had returned bad status, install seems impossible";
+
+ if (exists $self->{build_dir}) {
+ } elsif (!@e) {
+ push @e, "Has no own directory";
+ }
+
+ if (exists $self->{make_test} and
+ (
+ UNIVERSAL::can($self->{make_test},"failed") ?
+ $self->{make_test}->failed :
+ $self->{make_test} =~ /^NO/
+ )) {
+ if ($self->{force_update}) {
+ $self->{make_test}->text("FAILED but failure ignored because ".
+ "'force' in effect");
+ } else {
+ push @e, "make test had returned bad status, ".
+ "won't install without force"
+ }
+ }
+ if (exists $self->{install}) {
+ if (UNIVERSAL::can($self->{install},"text") ?
+ $self->{install}->text eq "YES" :
+ $self->{install} =~ /^YES/
+ ) {
+ $CPAN::Frontend->myprint(" Already done\n");
+ $CPAN::META->is_installed($self->{build_dir});
+ return 1;
+ } else {
+ # comment in Todo on 2006-02-11; maybe retry?
+ push @e, "Already tried without success";
+ }
+ }
+
+ push @e, $self->{later} if $self->{later};
+ push @e, $self->{configure_requires_later} if $self->{configure_requires_later};
+
+ $CPAN::Frontend->myprint(join "", map {" $_\n"} @e) and return if @e;
+ unless (chdir $self->{build_dir}) {
+ push @e, "Couldn't chdir to '$self->{build_dir}': $!";
+ }
+ $CPAN::Frontend->mywarn(join "", map {" $_\n"} @e) and return if @e;
+ }
+ $self->debug("Changed directory to $self->{build_dir}")
+ if $CPAN::DEBUG;
+
+ if ($^O eq 'MacOS') {
+ Mac::BuildTools::make_install($self);
+ return;
+ }
+
+ my $system;
+ if (my $commandline = $self->prefs->{install}{commandline}) {
+ $system = $commandline;
+ $ENV{PERL} = CPAN::find_perl();
+ } elsif ($self->{modulebuild}) {
+ my($mbuild_install_build_command) =
+ exists $CPAN::HandleConfig::keys{mbuild_install_build_command} &&
+ $CPAN::Config->{mbuild_install_build_command} ?
+ $CPAN::Config->{mbuild_install_build_command} :
+ $self->_build_command();
+ $system = sprintf("%s install %s",
+ $mbuild_install_build_command,
+ $CPAN::Config->{mbuild_install_arg},
+ );
+ } else {
+ my($make_install_make_command) =
+ CPAN::HandleConfig->prefs_lookup($self,
+ q{make_install_make_command})
+ || $self->_make_command();
+ $system = sprintf("%s install %s",
+ $make_install_make_command,
+ $CPAN::Config->{make_install_arg},
+ );
+ }
+
+ my($stderr) = $^O eq "MSWin32" ? "" : " 2>&1 ";
+ my $brip = CPAN::HandleConfig->prefs_lookup($self,
+ q{build_requires_install_policy});
+ $brip ||="ask/yes";
+ my $id = $self->id;
+ my $reqtype = $self->{reqtype} ||= "c"; # in doubt it was a command
+ my $want_install = "yes";
+ if ($reqtype eq "b") {
+ if ($brip eq "no") {
+ $want_install = "no";
+ } elsif ($brip =~ m|^ask/(.+)|) {
+ my $default = $1;
+ $default = "yes" unless $default =~ /^(y|n)/i;
+ $want_install =
+ CPAN::Shell::colorable_makemaker_prompt
+ ("$id is just needed temporarily during building or testing. ".
+ "Do you want to install it permanently?",
+ $default);
+ }
+ }
+ unless ($want_install =~ /^y/i) {
+ my $is_only = "is only 'build_requires'";
+ $CPAN::Frontend->mywarn("Not installing because $is_only\n");
+ $self->{install} = CPAN::Distrostatus->new("NO -- $is_only");
+ delete $self->{force_update};
+ return;
+ }
+ local $ENV{PERL5LIB} = defined($ENV{PERL5LIB})
+ ? $ENV{PERL5LIB}
+ : ($ENV{PERLLIB} || "");
+
+ local $ENV{PERL5OPT} = defined $ENV{PERL5OPT} ? $ENV{PERL5OPT} : "";
+ $CPAN::META->set_perl5lib;
+ my($pipe) = FileHandle->new("$system $stderr |") || Carp::croak
+("Can't execute $system: $!");
+ my($makeout) = "";
+ while (<$pipe>) {
+ print $_; # intentionally NOT use Frontend->myprint because it
+ # looks irritating when we markup in color what we
+ # just pass through from an external program
+ $makeout .= $_;
+ }
+ $pipe->close;
+ my $close_ok = $? == 0;
+ $self->introduce_myself;
+ if ( $close_ok ) {
+ $CPAN::Frontend->myprint(" $system -- OK\n");
+ $CPAN::META->is_installed($self->{build_dir});
+ $self->{install} = CPAN::Distrostatus->new("YES");
+ } else {
+ $self->{install} = CPAN::Distrostatus->new("NO");
+ $CPAN::Frontend->mywarn(" $system -- NOT OK\n");
+ my $mimc =
+ CPAN::HandleConfig->prefs_lookup($self,
+ q{make_install_make_command});
+ if (
+ $makeout =~ /permission/s
+ && $> > 0
+ && (
+ ! $mimc
+ || $mimc eq (CPAN::HandleConfig->prefs_lookup($self,
+ q{make}))
+ )
+ ) {
+ $CPAN::Frontend->myprint(
+ qq{----\n}.
+ qq{ You may have to su }.
+ qq{to root to install the package\n}.
+ qq{ (Or you may want to run something like\n}.
+ qq{ o conf make_install_make_command 'sudo make'\n}.
+ qq{ to raise your permissions.}
+ );
+ }
+ }
+ delete $self->{force_update};
+ $self->store_persistent_state;
+}
+
+sub introduce_myself {
+ my($self) = @_;
+ $CPAN::Frontend->myprint(sprintf(" %s\n",$self->pretty_id));
+}
+
+#-> sub CPAN::Distribution::dir ;
+sub dir {
+ shift->{build_dir};
+}
+
+#-> sub CPAN::Distribution::perldoc ;
+sub perldoc {
+ my($self) = @_;
+
+ my($dist) = $self->id;
+ my $package = $self->called_for;
+
+ if ($CPAN::META->has_inst("Pod::Perldocs")) {
+ my($perl) = $self->perl
+ or $CPAN::Frontend->mydie("Couldn't find executable perl\n");
+ my @args = ($perl, q{-MPod::Perldocs}, q{-e},
+ q{Pod::Perldocs->run()}, $package);
+ my($wstatus);
+ unless ( ($wstatus = system(@args)) == 0 ) {
+ my $estatus = $wstatus >> 8;
+ $CPAN::Frontend->myprint(qq{
+ Function system("@args")
+ returned status $estatus (wstat $wstatus)
+ });
+ }
+ }
+ else {
+ $self->_display_url( $CPAN::Defaultdocs . $package );
+ }
+}
+
+#-> sub CPAN::Distribution::_check_binary ;
+sub _check_binary {
+ my ($dist,$shell,$binary) = @_;
+ my ($pid,$out);
+
+ $CPAN::Frontend->myprint(qq{ + _check_binary($binary)\n})
+ if $CPAN::DEBUG;
+
+ if ($CPAN::META->has_inst("File::Which")) {
+ return File::Which::which($binary);
+ } else {
+ local *README;
+ $pid = open README, "which $binary|"
+ or $CPAN::Frontend->mywarn(qq{Could not fork 'which $binary': $!\n});
+ return unless $pid;
+ while (<README>) {
+ $out .= $_;
+ }
+ close README
+ or $CPAN::Frontend->mywarn("Could not run 'which $binary': $!\n")
+ and return;
+ }
+
+ $CPAN::Frontend->myprint(qq{ + $out \n})
+ if $CPAN::DEBUG && $out;
+
+ return $out;
+}
+
+#-> sub CPAN::Distribution::_display_url ;
+sub _display_url {
+ my($self,$url) = @_;
+ my($res,$saved_file,$pid,$out);
+
+ $CPAN::Frontend->myprint(qq{ + _display_url($url)\n})
+ if $CPAN::DEBUG;
+
+ # should we define it in the config instead?
+ my $html_converter = "html2text.pl";
+
+ my $web_browser = $CPAN::Config->{'lynx'} || undef;
+ my $web_browser_out = $web_browser
+ ? CPAN::Distribution->_check_binary($self,$web_browser)
+ : undef;
+
+ if ($web_browser_out) {
+ # web browser found, run the action
+ my $browser = CPAN::HandleConfig->safe_quote($CPAN::Config->{'lynx'});
+ $CPAN::Frontend->myprint(qq{system[$browser $url]})
+ if $CPAN::DEBUG;
+ $CPAN::Frontend->myprint(qq{
+Displaying URL
+ $url
+with browser $browser
+});
+ $CPAN::Frontend->mysleep(1);
+ system("$browser $url");
+ if ($saved_file) { 1 while unlink($saved_file) }
+ } else {
+ # web browser not found, let's try text only
+ my $html_converter_out =
+ CPAN::Distribution->_check_binary($self,$html_converter);
+ $html_converter_out = CPAN::HandleConfig->safe_quote($html_converter_out);
+
+ if ($html_converter_out ) {
+ # html2text found, run it
+ $saved_file = CPAN::Distribution->_getsave_url( $self, $url );
+ $CPAN::Frontend->mydie(qq{ERROR: problems while getting $url\n})
+ unless defined($saved_file);
+
+ local *README;
+ $pid = open README, "$html_converter $saved_file |"
+ or $CPAN::Frontend->mydie(qq{
+Could not fork '$html_converter $saved_file': $!});
+ my($fh,$filename);
+ if ($CPAN::META->has_usable("File::Temp")) {
+ $fh = File::Temp->new(
+ dir => File::Spec->tmpdir,
+ template => 'cpan_htmlconvert_XXXX',
+ suffix => '.txt',
+ unlink => 0,
+ );
+ $filename = $fh->filename;
+ } else {
+ $filename = "cpan_htmlconvert_$$.txt";
+ $fh = FileHandle->new();
+ open $fh, ">$filename" or die;
+ }
+ while (<README>) {
+ $fh->print($_);
+ }
+ close README or
+ $CPAN::Frontend->mydie(qq{Could not run '$html_converter $saved_file': $!});
+ my $tmpin = $fh->filename;
+ $CPAN::Frontend->myprint(sprintf(qq{
+Run '%s %s' and
+saved output to %s\n},
+ $html_converter,
+ $saved_file,
+ $tmpin,
+ )) if $CPAN::DEBUG;
+ close $fh;
+ local *FH;
+ open FH, $tmpin
+ or $CPAN::Frontend->mydie(qq{Could not open "$tmpin": $!});
+ my $fh_pager = FileHandle->new;
+ local($SIG{PIPE}) = "IGNORE";
+ my $pager = $CPAN::Config->{'pager'} || "cat";
+ $fh_pager->open("|$pager")
+ or $CPAN::Frontend->mydie(qq{
+Could not open pager '$pager': $!});
+ $CPAN::Frontend->myprint(qq{
+Displaying URL
+ $url
+with pager "$pager"
+});
+ $CPAN::Frontend->mysleep(1);
+ $fh_pager->print(<FH>);
+ $fh_pager->close;
+ } else {
+ # coldn't find the web browser or html converter
+ $CPAN::Frontend->myprint(qq{
+You need to install lynx or $html_converter to use this feature.});
+ }
+ }
+}
+
+#-> sub CPAN::Distribution::_getsave_url ;
+sub _getsave_url {
+ my($dist, $shell, $url) = @_;
+
+ $CPAN::Frontend->myprint(qq{ + _getsave_url($url)\n})
+ if $CPAN::DEBUG;
+
+ my($fh,$filename);
+ if ($CPAN::META->has_usable("File::Temp")) {
+ $fh = File::Temp->new(
+ dir => File::Spec->tmpdir,
+ template => "cpan_getsave_url_XXXX",
+ suffix => ".html",
+ unlink => 0,
+ );
+ $filename = $fh->filename;
+ } else {
+ $fh = FileHandle->new;
+ $filename = "cpan_getsave_url_$$.html";
+ }
+ my $tmpin = $filename;
+ if ($CPAN::META->has_usable('LWP')) {
+ $CPAN::Frontend->myprint("Fetching with LWP:
+ $url
+");
+ my $Ua;
+ CPAN::LWP::UserAgent->config;
+ eval { $Ua = CPAN::LWP::UserAgent->new; };
+ if ($@) {
+ $CPAN::Frontend->mywarn("ERROR: CPAN::LWP::UserAgent->new dies with $@\n");
+ return;
+ } else {
+ my($var);
+ $Ua->proxy('http', $var)
+ if $var = $CPAN::Config->{http_proxy} || $ENV{http_proxy};
+ $Ua->no_proxy($var)
+ if $var = $CPAN::Config->{no_proxy} || $ENV{no_proxy};
+ }
+
+ my $req = HTTP::Request->new(GET => $url);
+ $req->header('Accept' => 'text/html');
+ my $res = $Ua->request($req);
+ if ($res->is_success) {
+ $CPAN::Frontend->myprint(" + request successful.\n")
+ if $CPAN::DEBUG;
+ print $fh $res->content;
+ close $fh;
+ $CPAN::Frontend->myprint(qq{ + saved content to $tmpin \n})
+ if $CPAN::DEBUG;
+ return $tmpin;
+ } else {
+ $CPAN::Frontend->myprint(sprintf(
+ "LWP failed with code[%s], message[%s]\n",
+ $res->code,
+ $res->message,
+ ));
+ return;
+ }
+ } else {
+ $CPAN::Frontend->mywarn(" LWP not available\n");
+ return;
+ }
+}
+
+#-> sub CPAN::Distribution::_build_command
+sub _build_command {
+ my($self) = @_;
+ if ($^O eq "MSWin32") { # special code needed at least up to
+ # Module::Build 0.2611 and 0.2706; a fix
+ # in M:B has been promised 2006-01-30
+ my($perl) = $self->perl or $CPAN::Frontend->mydie("Couldn't find executable perl\n");
+ return "$perl ./Build";
+ }
+ return "./Build";
+}
+
+#-> sub CPAN::Distribution::_should_report
+sub _should_report {
+ my($self, $phase) = @_;
+ die "_should_report() requires a 'phase' argument"
+ if ! defined $phase;
+
+ # configured
+ my $test_report = CPAN::HandleConfig->prefs_lookup($self,
+ q{test_report});
+ return unless $test_report;
+
+ # don't repeat if we cached a result
+ return $self->{should_report}
+ if exists $self->{should_report};
+
+ # don't report if we generated a Makefile.PL
+ if ( $self->{had_no_makefile_pl} ) {
+ $CPAN::Frontend->mywarn(
+ "Will not send CPAN Testers report with generated Makefile.PL.\n"
+ );
+ return $self->{should_report} = 0;
+ }
+
+ # available
+ if ( ! $CPAN::META->has_inst("CPAN::Reporter")) {
+ $CPAN::Frontend->mywarnonce(
+ "CPAN::Reporter not installed. No reports will be sent.\n"
+ );
+ return $self->{should_report} = 0;
+ }
+
+ # capable
+ my $crv = CPAN::Reporter->VERSION;
+ if ( CPAN::Version->vlt( $crv, 0.99 ) ) {
+ # don't cache $self->{should_report} -- need to check each phase
+ if ( $phase eq 'test' ) {
+ return 1;
+ }
+ else {
+ $CPAN::Frontend->mywarn(
+ "Reporting on the '$phase' phase requires CPAN::Reporter 0.99, but \n" .
+ "you only have version $crv\. Only 'test' phase reports will be sent.\n"
+ );
+ return;
+ }
+ }
+
+ # appropriate
+ if ($self->is_dot_dist) {
+ $CPAN::Frontend->mywarn("Reporting via CPAN::Reporter is disabled ".
+ "for local directories\n");
+ return $self->{should_report} = 0;
+ }
+ if ($self->prefs->{patches}
+ &&
+ @{$self->prefs->{patches}}
+ &&
+ $self->{patched}
+ ) {
+ $CPAN::Frontend->mywarn("Reporting via CPAN::Reporter is disabled ".
+ "when the source has been patched\n");
+ return $self->{should_report} = 0;
+ }
+
+ # proceed and cache success
+ return $self->{should_report} = 1;
+}
+
+#-> sub CPAN::Distribution::reports
+sub reports {
+ my($self) = @_;
+ my $pathname = $self->id;
+ $CPAN::Frontend->myprint("Distribution: $pathname\n");
+
+ unless ($CPAN::META->has_inst("CPAN::DistnameInfo")) {
+ $CPAN::Frontend->mydie("CPAN::DistnameInfo not installed; cannot continue");
+ }
+ unless ($CPAN::META->has_usable("LWP")) {
+ $CPAN::Frontend->mydie("LWP not installed; cannot continue");
+ }
+ unless ($CPAN::META->has_usable("File::Temp")) {
+ $CPAN::Frontend->mydie("File::Temp not installed; cannot continue");
+ }
+
+ my $d = CPAN::DistnameInfo->new($pathname);
+
+ my $dist = $d->dist; # "CPAN-DistnameInfo"
+ my $version = $d->version; # "0.02"
+ my $maturity = $d->maturity; # "released"
+ my $filename = $d->filename; # "CPAN-DistnameInfo-0.02.tar.gz"
+ my $cpanid = $d->cpanid; # "GBARR"
+ my $distvname = $d->distvname; # "CPAN-DistnameInfo-0.02"
+
+ my $url = sprintf "http://www.cpantesters.org/show/%s.yaml", $dist;
+
+ CPAN::LWP::UserAgent->config;
+ my $Ua;
+ eval { $Ua = CPAN::LWP::UserAgent->new; };
+ if ($@) {
+ $CPAN::Frontend->mydie("CPAN::LWP::UserAgent->new dies with $@\n");
+ }
+ $CPAN::Frontend->myprint("Fetching '$url'...");
+ my $resp = $Ua->get($url);
+ unless ($resp->is_success) {
+ $CPAN::Frontend->mydie(sprintf "Could not download '%s': %s\n", $url, $resp->code);
+ }
+ $CPAN::Frontend->myprint("DONE\n\n");
+ my $yaml = $resp->content;
+ # was fuer ein Umweg!
+ my $fh = File::Temp->new(
+ dir => File::Spec->tmpdir,
+ template => 'cpan_reports_XXXX',
+ suffix => '.yaml',
+ unlink => 0,
+ );
+ my $tfilename = $fh->filename;
+ print $fh $yaml;
+ close $fh or $CPAN::Frontend->mydie("Could not close '$tfilename': $!");
+ my $unserialized = CPAN->_yaml_loadfile($tfilename)->[0];
+ unlink $tfilename or $CPAN::Frontend->mydie("Could not unlink '$tfilename': $!");
+ my %other_versions;
+ my $this_version_seen;
+ for my $rep (@$unserialized) {
+ my $rversion = $rep->{version};
+ if ($rversion eq $version) {
+ unless ($this_version_seen++) {
+ $CPAN::Frontend->myprint ("$rep->{version}:\n");
+ }
+ my $arch = $rep->{archname} || $rep->{platform} || '????';
+ my $grade = $rep->{action} || $rep->{status} || '????';
+ my $ostext = $rep->{ostext} || ucfirst($rep->{osname}) || '????';
+ $CPAN::Frontend->myprint
+ (sprintf("%1s%1s%-4s %s on %s %s (%s)\n",
+ $arch eq $Config::Config{archname}?"*":"",
+ $grade eq "PASS"?"+":$grade eq"FAIL"?"-":"",
+ $grade,
+ $rep->{perl},
+ $ostext,
+ $rep->{osvers},
+ $arch,
+ ));
+ } else {
+ $other_versions{$rep->{version}}++;
+ }
+ }
+ unless ($this_version_seen) {
+ $CPAN::Frontend->myprint("No reports found for version '$version'
+Reports for other versions:\n");
+ for my $v (sort keys %other_versions) {
+ $CPAN::Frontend->myprint(" $v\: $other_versions{$v}\n");
+ }
+ }
+ $url =~ s/\.yaml/.html/;
+ $CPAN::Frontend->myprint("See $url for details\n");
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Distroprefs.pm b/Master/tlpkg/tlperl/lib/CPAN/Distroprefs.pm
new file mode 100644
index 00000000000..e1be9cdf749
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Distroprefs.pm
@@ -0,0 +1,451 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+# vim: ts=4 sts=4 sw=4:
+
+use strict;
+package CPAN::Distroprefs;
+
+use vars qw($VERSION);
+$VERSION = '6';
+
+package CPAN::Distroprefs::Result;
+
+use File::Spec;
+
+sub new { bless $_[1] || {} => $_[0] }
+
+sub abs { File::Spec->catfile($_[0]->dir, $_[0]->file) }
+
+sub __cloner {
+ my ($class, $name, $newclass) = @_;
+ $newclass = 'CPAN::Distroprefs::Result::' . $newclass;
+ no strict 'refs';
+ *{$class . '::' . $name} = sub {
+ $newclass->new({
+ %{ $_[0] },
+ %{ $_[1] },
+ });
+ };
+}
+BEGIN { __PACKAGE__->__cloner(as_warning => 'Warning') }
+BEGIN { __PACKAGE__->__cloner(as_fatal => 'Fatal') }
+BEGIN { __PACKAGE__->__cloner(as_success => 'Success') }
+
+sub __accessor {
+ my ($class, $key) = @_;
+ no strict 'refs';
+ *{$class . '::' . $key} = sub { $_[0]->{$key} };
+}
+BEGIN { __PACKAGE__->__accessor($_) for qw(type file ext dir) }
+
+sub is_warning { 0 }
+sub is_fatal { 0 }
+sub is_success { 0 }
+
+package CPAN::Distroprefs::Result::Error;
+use vars qw(@ISA);
+BEGIN { @ISA = 'CPAN::Distroprefs::Result' } ## no critic
+BEGIN { __PACKAGE__->__accessor($_) for qw(msg) }
+
+sub as_string {
+ my ($self) = @_;
+ if ($self->msg) {
+ return sprintf $self->fmt_reason, $self->file, $self->msg;
+ } else {
+ return sprintf $self->fmt_unknown, $self->file;
+ }
+}
+
+package CPAN::Distroprefs::Result::Warning;
+use vars qw(@ISA);
+BEGIN { @ISA = 'CPAN::Distroprefs::Result::Error' } ## no critic
+sub is_warning { 1 }
+sub fmt_reason { "Error reading distroprefs file %s, skipping: %s" }
+sub fmt_unknown { "Unknown error reading distroprefs file %s, skipping." }
+
+package CPAN::Distroprefs::Result::Fatal;
+use vars qw(@ISA);
+BEGIN { @ISA = 'CPAN::Distroprefs::Result::Error' } ## no critic
+sub is_fatal { 1 }
+sub fmt_reason { "Error reading distroprefs file %s: %s" }
+sub fmt_unknown { "Unknown error reading distroprefs file %s." }
+
+package CPAN::Distroprefs::Result::Success;
+use vars qw(@ISA);
+BEGIN { @ISA = 'CPAN::Distroprefs::Result' } ## no critic
+BEGIN { __PACKAGE__->__accessor($_) for qw(prefs extension) }
+sub is_success { 1 }
+
+package CPAN::Distroprefs::Iterator;
+
+sub new { bless $_[1] => $_[0] }
+
+sub next { $_[0]->() }
+
+package CPAN::Distroprefs;
+
+use Carp ();
+use DirHandle;
+
+sub _load_method {
+ my ($self, $loader, $result) = @_;
+ return '_load_yaml' if $loader eq 'CPAN' or $loader =~ /^YAML(::|$)/;
+ return '_load_' . $result->ext;
+}
+
+sub _load_yaml {
+ my ($self, $loader, $result) = @_;
+ my $data = eval {
+ $loader eq 'CPAN'
+ ? $loader->_yaml_loadfile($result->abs)
+ : [ $loader->can('LoadFile')->($result->abs) ]
+ };
+ if (my $err = $@) {
+ die $result->as_warning({
+ msg => $err,
+ });
+ } elsif (!$data) {
+ die $result->as_warning;
+ } else {
+ return @$data;
+ }
+}
+
+sub _load_dd {
+ my ($self, $loader, $result) = @_;
+ my @data;
+ {
+ package CPAN::Eval;
+ # this caused a die in CPAN.pm, and I am leaving it 'fatal', though I'm
+ # not sure why we wouldn't just skip the file as we do for all other
+ # errors. -- hdp
+ my $abs = $result->abs;
+ open FH, "<$abs" or die $result->as_fatal(msg => "$!");
+ local $/;
+ my $eval = <FH>;
+ close FH;
+ no strict;
+ eval $eval;
+ if (my $err = $@) {
+ die $result->as_warning({ msg => $err });
+ }
+ my $i = 1;
+ while (${"VAR$i"}) {
+ push @data, ${"VAR$i"};
+ $i++;
+ }
+ }
+ return @data;
+}
+
+sub _load_st {
+ my ($self, $loader, $result) = @_;
+ # eval because Storable is never forward compatible
+ my @data = eval { @{scalar $loader->can('retrieve')->($result->abs) } };
+ if (my $err = $@) {
+ die $result->as_warning({ msg => $err });
+ }
+ return @data;
+}
+
+sub find {
+ my ($self, $dir, $ext_map) = @_;
+
+ my $dh = DirHandle->new($dir) or Carp::croak("Couldn't open '$dir': $!");
+ my @files = sort $dh->read;
+
+ # label the block so that we can use redo in the middle
+ return CPAN::Distroprefs::Iterator->new(sub { LOOP: {
+ return unless %$ext_map;
+
+ local $_ = shift @files;
+ return unless defined;
+ redo if $_ eq '.' || $_ eq '..';
+
+ my $possible_ext = join "|", map { quotemeta } keys %$ext_map;
+ my ($ext) = /\.($possible_ext)$/ or redo;
+ my $loader = $ext_map->{$ext};
+
+ my $result = CPAN::Distroprefs::Result->new({
+ file => $_, ext => $ext, dir => $dir
+ });
+ # copied from CPAN.pm; is this ever actually possible?
+ redo unless -f $result->abs;
+
+ my $load_method = $self->_load_method($loader, $result);
+ my @prefs = eval { $self->$load_method($loader, $result) };
+ if (my $err = $@) {
+ if (ref($err) && eval { $err->isa('CPAN::Distroprefs::Result') }) {
+ return $err;
+ }
+ # rethrow any exceptions that we did not generate
+ die $err;
+ } elsif (!@prefs) {
+ # the loader should have handled this, but just in case:
+ return $result->as_warning;
+ }
+ return $result->as_success({
+ prefs => [
+ map { CPAN::Distroprefs::Pref->new({ data => $_ }) } @prefs
+ ],
+ });
+ } });
+}
+
+package CPAN::Distroprefs::Pref;
+
+use Carp ();
+
+sub new { bless $_[1] => $_[0] }
+
+sub data { shift->{data} }
+
+sub has_any_match { $_[0]->data->{match} ? 1 : 0 }
+
+sub has_match {
+ my $match = $_[0]->data->{match} || return 0;
+ exists $match->{$_[1]} || exists $match->{"not_$_[1]"}
+}
+
+sub has_valid_subkeys {
+ grep { exists $_[0]->data->{match}{$_} }
+ map { $_, "not_$_" }
+ $_[0]->match_attributes
+}
+
+sub _pattern {
+ my $re = shift;
+ my $p = eval sprintf 'qr{%s}', $re;
+ if ($@) {
+ $@ =~ s/\n$//;
+ die "Error in Distroprefs pattern qr{$re}\n$@";
+ }
+ return $p;
+}
+
+sub _match_scalar {
+ my ($match, $data) = @_;
+ my $qr = _pattern($match);
+ return $data =~ /$qr/;
+}
+
+sub _match_hash {
+ my ($match, $data) = @_;
+ for my $mkey (keys %$match) {
+ (my $dkey = $mkey) =~ s/^not_//;
+ my $val = defined $data->{$dkey} ? $data->{$dkey} : '';
+ if (_match_scalar($match->{$mkey}, $val)) {
+ return 0 if $mkey =~ /^not_/;
+ }
+ else {
+ return 0 if $mkey !~ /^not_/;
+ }
+ }
+ return 1;
+}
+
+sub _match {
+ my ($self, $key, $data, $matcher) = @_;
+ my $m = $self->data->{match};
+ if (exists $m->{$key}) {
+ return 0 unless $matcher->($m->{$key}, $data);
+ }
+ if (exists $m->{"not_$key"}) {
+ return 0 if $matcher->($m->{"not_$key"}, $data);
+ }
+ return 1;
+}
+
+sub _scalar_match {
+ my ($self, $key, $data) = @_;
+ return $self->_match($key, $data, \&_match_scalar);
+}
+
+sub _hash_match {
+ my ($self, $key, $data) = @_;
+ return $self->_match($key, $data, \&_match_hash);
+}
+
+# do not take the order of C<keys %$match> because "module" is by far the
+# slowest
+sub match_attributes { qw(env distribution perl perlconfig module) }
+
+sub match_module {
+ my ($self, $modules) = @_;
+ return $self->_match("module", $modules, sub {
+ my($match, $data) = @_;
+ my $qr = _pattern($match);
+ for my $module (@$data) {
+ return 1 if $module =~ /$qr/;
+ }
+ return 0;
+ });
+}
+
+sub match_distribution { shift->_scalar_match(distribution => @_) }
+sub match_perl { shift->_scalar_match(perl => @_) }
+
+sub match_perlconfig { shift->_hash_match(perlconfig => @_) }
+sub match_env { shift->_hash_match(env => @_) }
+
+sub matches {
+ my ($self, $arg) = @_;
+
+ my $default_match = 0;
+ for my $key (grep { $self->has_match($_) } $self->match_attributes) {
+ unless (exists $arg->{$key}) {
+ Carp::croak "Can't match pref: missing argument key $key";
+ }
+ $default_match = 1;
+ my $val = $arg->{$key};
+ # make it possible to avoid computing things until we have to
+ if (ref($val) eq 'CODE') { $val = $val->() }
+ my $meth = "match_$key";
+ return 0 unless $self->$meth($val);
+ }
+
+ return $default_match;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+CPAN::Distroprefs -- read and match distroprefs
+
+=head1 SYNOPSIS
+
+ use CPAN::Distroprefs;
+
+ my %info = (... distribution/environment info ...);
+
+ my $finder = CPAN::Distroprefs->find($prefs_dir, \%ext_map);
+
+ while (my $result = $finder->next) {
+
+ die $result->as_string if $result->is_fatal;
+
+ warn($result->as_string), next if $result->is_warning;
+
+ for my $pref (@{ $result->prefs }) {
+ if ($pref->matches(\%info)) {
+ return $pref;
+ }
+ }
+ }
+
+
+=head1 DESCRIPTION
+
+This module encapsulates reading L<Distroprefs|CPAN> and matching them against CPAN distributions.
+
+=head1 INTERFACE
+
+ my $finder = CPAN::Distroprefs->find($dir, \%ext_map);
+
+ while (my $result = $finder->next) { ... }
+
+Build an iterator which finds distroprefs files in the given directory.
+
+C<%ext_map> is a hashref whose keys are file extensions and whose values are
+modules used to load matching files:
+
+ {
+ 'yml' => 'YAML::Syck',
+ 'dd' => 'Data::Dumper',
+ ...
+ }
+
+Each time C<< $finder->next >> is called, the iterator returns one of two
+possible values:
+
+=over
+
+=item * a CPAN::Distroprefs::Result object
+
+=item * C<undef>, indicating that no prefs files remain to be found
+
+=back
+
+=head1 RESULTS
+
+L<C<find()>|/INTERFACE> returns CPAN::Distroprefs::Result objects to
+indicate success or failure when reading a prefs file.
+
+=head2 Common
+
+All results share some common attributes:
+
+=head3 type
+
+C<success>, C<warning>, or C<fatal>
+
+=head3 file
+
+the file from which these prefs were read, or to which this error refers (relative filename)
+
+=head3 ext
+
+the file's extension, which determines how to load it
+
+=head3 dir
+
+the directory the file was read from
+
+=head3 abs
+
+the absolute path to the file
+
+=head2 Errors
+
+Error results (warning and fatal) contain:
+
+=head3 msg
+
+the error message (usually either C<$!> or a YAML error)
+
+=head2 Successes
+
+Success results contain:
+
+=head3 prefs
+
+an arrayref of CPAN::Distroprefs::Pref objects
+
+=head1 PREFS
+
+CPAN::Distroprefs::Pref objects represent individual distroprefs documents.
+They are constructed automatically as part of C<success> results from C<find()>.
+
+=head3 data
+
+the pref information as a hashref, suitable for e.g. passing to Kwalify
+
+=head3 match_attributes
+
+returns a list of the valid match attributes (see the Distroprefs section in L<CPAN>)
+
+currently: C<env perl perlconfig distribution module>
+
+=head3 has_any_match
+
+true if this pref has a 'match' attribute at all
+
+=head3 has_valid_subkeys
+
+true if this pref has a 'match' attribute and at least one valid match attribute
+
+=head3 matches
+
+ if ($pref->matches(\%arg)) { ... }
+
+true if this pref matches the passed-in hashref, which must have a value for
+each of the C<match_attributes> (above)
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or modify it under
+the same terms as Perl itself.
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Distrostatus.pm b/Master/tlpkg/tlperl/lib/CPAN/Distrostatus.pm
new file mode 100644
index 00000000000..0cc6cc9a793
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Distrostatus.pm
@@ -0,0 +1,45 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+# vim: ts=4 sts=4 sw=4:
+package CPAN::Distrostatus;
+use overload '""' => "as_string",
+ fallback => 1;
+use vars qw($something_has_failed_at);
+use vars qw(
+ $VERSION
+);
+$VERSION = "5.5";
+
+
+sub new {
+ my($class,$arg) = @_;
+ my $failed = substr($arg,0,2) eq "NO";
+ if ($failed) {
+ $something_has_failed_at = $CPAN::CurrentCommandId;
+ }
+ bless {
+ TEXT => $arg,
+ FAILED => $failed,
+ COMMANDID => $CPAN::CurrentCommandId,
+ TIME => time,
+ }, $class;
+}
+sub something_has_just_failed () {
+ defined $something_has_failed_at &&
+ $something_has_failed_at == $CPAN::CurrentCommandId;
+}
+sub commandid { shift->{COMMANDID} }
+sub failed { shift->{FAILED} }
+sub text {
+ my($self,$set) = @_;
+ if (defined $set) {
+ $self->{TEXT} = $set;
+ }
+ $self->{TEXT};
+}
+sub as_string {
+ my($self) = @_;
+ $self->text;
+}
+
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Exception/RecursiveDependency.pm b/Master/tlpkg/tlperl/lib/CPAN/Exception/RecursiveDependency.pm
new file mode 100644
index 00000000000..b928ad74e31
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Exception/RecursiveDependency.pm
@@ -0,0 +1,85 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+# vim: ts=4 sts=4 sw=4:
+package CPAN::Exception::RecursiveDependency;
+use strict;
+use overload '""' => "as_string";
+
+use vars qw(
+ $VERSION
+);
+$VERSION = "5.5";
+
+# a module sees its distribution (no version)
+# a distribution sees its prereqs (which are module names) (usually with versions)
+# a bundle sees its module names and/or its distributions (no version)
+
+sub new {
+ my($class) = shift;
+ my($deps_arg) = shift;
+ my (@deps,%seen,$loop_starts_with);
+ DCHAIN: for my $dep (@$deps_arg) {
+ push @deps, {name => $dep, display_as => $dep};
+ if ($seen{$dep}++) {
+ $loop_starts_with = $dep;
+ last DCHAIN;
+ }
+ }
+ my $in_loop = 0;
+ for my $i (0..$#deps) {
+ my $x = $deps[$i]{name};
+ $in_loop ||= $loop_starts_with && $x eq $loop_starts_with;
+ my $xo = CPAN::Shell->expandany($x) or next;
+ if ($xo->isa("CPAN::Module")) {
+ my $have = $xo->inst_version || "N/A";
+ my($want,$d,$want_type);
+ if ($i>0 and $d = $deps[$i-1]{name}) {
+ my $do = CPAN::Shell->expandany($d);
+ $want = $do->{prereq_pm}{requires}{$x};
+ if (defined $want) {
+ $want_type = "requires: ";
+ } else {
+ $want = $do->{prereq_pm}{build_requires}{$x};
+ if (defined $want) {
+ $want_type = "build_requires: ";
+ } else {
+ $want_type = "unknown status";
+ $want = "???";
+ }
+ }
+ } else {
+ $want = $xo->cpan_version;
+ $want_type = "want: ";
+ }
+ $deps[$i]{have} = $have;
+ $deps[$i]{want_type} = $want_type;
+ $deps[$i]{want} = $want;
+ $deps[$i]{display_as} = "$x (have: $have; $want_type$want)";
+ } elsif ($xo->isa("CPAN::Distribution")) {
+ $deps[$i]{display_as} = $xo->pretty_id;
+ if ($in_loop) {
+ $xo->{make} = CPAN::Distrostatus->new("NO cannot resolve circular dependency");
+ } else {
+ $xo->{make} = CPAN::Distrostatus->new("NO one dependency ($loop_starts_with) is a circular dependency");
+ }
+ $xo->store_persistent_state; # otherwise I will not reach
+ # all involved parties for
+ # the next session
+ }
+ }
+ bless { deps => \@deps, loop_starts_with => $loop_starts_with }, $class;
+}
+
+sub as_string {
+ my($self) = shift;
+ my $deps = $self->{deps};
+ my $loop_starts_with = $self->{loop_starts_with};
+ unless ($loop_starts_with) {
+ return "--not a recursive/circular dependency--";
+ }
+ my $ret = "\nRecursive dependency detected:\n ";
+ $ret .= join("\n => ", map {$_->{display_as}} @$deps);
+ $ret .= ".\nCannot resolve.\n";
+ $ret;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Exception/blocked_urllist.pm b/Master/tlpkg/tlperl/lib/CPAN/Exception/blocked_urllist.pm
new file mode 100644
index 00000000000..102c194e612
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Exception/blocked_urllist.pm
@@ -0,0 +1,46 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+# vim: ts=4 sts=4 sw=4:
+package CPAN::Exception::blocked_urllist;
+use strict;
+use overload '""' => "as_string";
+
+use vars qw(
+ $VERSION
+);
+$VERSION = "1.0";
+
+
+sub new {
+ my($class) = @_;
+ bless {}, $class;
+}
+
+sub as_string {
+ my($self) = shift;
+ if ($CPAN::Config->{connect_to_internet_ok}) {
+ return qq{
+
+You have not configured a urllist for CPAN mirrors. Configure it with
+
+ o conf init urllist
+
+};
+ } else {
+ return qq{
+
+You have not configured a urllist and do not allow connections to the
+internet to get a list of mirrors. If you wish to get a list of CPAN
+mirrors to pick from, use this command
+
+ o conf init connect_to_internet_ok urllist
+
+If you do not wish to get a list of mirrors and would prefer to set
+your urllist manually, use just this command instead
+
+ o conf init urllist
+
+};
+ }
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Exception/yaml_not_installed.pm b/Master/tlpkg/tlperl/lib/CPAN/Exception/yaml_not_installed.pm
new file mode 100644
index 00000000000..e1259e5397d
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Exception/yaml_not_installed.pm
@@ -0,0 +1,73 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+# vim: ts=4 sts=4 sw=4:
+package CPAN::Exception::yaml_not_installed;
+use strict;
+use overload '""' => "as_string";
+
+use vars qw(
+ $VERSION
+);
+$VERSION = "5.5";
+
+
+sub new {
+ my($class,$module,$file,$during) = @_;
+ bless { module => $module, file => $file, during => $during }, $class;
+}
+
+sub as_string {
+ my($self) = shift;
+ "'$self->{module}' not installed, cannot $self->{during} '$self->{file}'\n";
+}
+
+package CPAN::Exception::yaml_process_error;
+use strict;
+use overload '""' => "as_string";
+
+use vars qw(
+ $VERSION
+);
+$VERSION = "5.5";
+
+
+sub new {
+ my($class,$module,$file,$during,$error) = @_;
+ # my $at = Carp::longmess(""); # XXX find something more beautiful
+ bless { module => $module,
+ file => $file,
+ during => $during,
+ error => $error,
+ # at => $at,
+ }, $class;
+}
+
+sub as_string {
+ my($self) = shift;
+ if ($self->{during}) {
+ if ($self->{file}) {
+ if ($self->{module}) {
+ if ($self->{error}) {
+ return "Alert: While trying to '$self->{during}' YAML file\n".
+ " '$self->{file}'\n".
+ "with '$self->{module}' the following error was encountered:\n".
+ " $self->{error}\n";
+ } else {
+ return "Alert: While trying to '$self->{during}' YAML file\n".
+ " '$self->{file}'\n".
+ "with '$self->{module}' some unknown error was encountered\n";
+ }
+ } else {
+ return "Alert: While trying to '$self->{during}' YAML file\n".
+ " '$self->{file}'\n".
+ "some unknown error was encountered\n";
+ }
+ } else {
+ return "Alert: While trying to '$self->{during}' some YAML file\n".
+ "some unknown error was encountered\n";
+ }
+ } else {
+ return "Alert: unknown error encountered\n";
+ }
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/FTP.pm b/Master/tlpkg/tlperl/lib/CPAN/FTP.pm
new file mode 100644
index 00000000000..268ca284678
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/FTP.pm
@@ -0,0 +1,1074 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+# vim: ts=4 sts=4 sw=4:
+package CPAN::FTP;
+use strict;
+
+use Fcntl qw(:flock);
+use File::Basename qw(dirname);
+use File::Path qw(mkpath);
+use CPAN::FTP::netrc;
+use vars qw($connect_to_internet_ok $Ua $Thesite $ThesiteURL $Themethod);
+
+@CPAN::FTP::ISA = qw(CPAN::Debug);
+
+use vars qw(
+ $VERSION
+);
+$VERSION = "5.5004";
+
+#-> sub CPAN::FTP::ftp_statistics
+# if they want to rewrite, they need to pass in a filehandle
+sub _ftp_statistics {
+ my($self,$fh) = @_;
+ my $locktype = $fh ? LOCK_EX : LOCK_SH;
+ $fh ||= FileHandle->new;
+ my $file = File::Spec->catfile($CPAN::Config->{cpan_home},"FTPstats.yml");
+ mkpath dirname $file;
+ open $fh, "+>>$file" or $CPAN::Frontend->mydie("Could not open '$file': $!");
+ my $sleep = 1;
+ my $waitstart;
+ while (!CPAN::_flock($fh, $locktype|LOCK_NB)) {
+ $waitstart ||= localtime();
+ if ($sleep>3) {
+ $CPAN::Frontend->mywarn("Waiting for a read lock on '$file' (since $waitstart)\n");
+ }
+ $CPAN::Frontend->mysleep($sleep);
+ if ($sleep <= 3) {
+ $sleep+=0.33;
+ } elsif ($sleep <=6) {
+ $sleep+=0.11;
+ }
+ }
+ my $stats = eval { CPAN->_yaml_loadfile($file); };
+ if ($@) {
+ if (ref $@) {
+ if (ref $@ eq "CPAN::Exception::yaml_not_installed") {
+ $CPAN::Frontend->myprint("Warning (usually harmless): $@\n");
+ return;
+ } elsif (ref $@ eq "CPAN::Exception::yaml_process_error") {
+ $CPAN::Frontend->mydie($@);
+ }
+ } else {
+ $CPAN::Frontend->mydie($@);
+ }
+ }
+ return $stats->[0];
+}
+
+#-> sub CPAN::FTP::_mytime
+sub _mytime () {
+ if (CPAN->has_inst("Time::HiRes")) {
+ return Time::HiRes::time();
+ } else {
+ return time;
+ }
+}
+
+#-> sub CPAN::FTP::_new_stats
+sub _new_stats {
+ my($self,$file) = @_;
+ my $ret = {
+ file => $file,
+ attempts => [],
+ start => _mytime,
+ };
+ $ret;
+}
+
+#-> sub CPAN::FTP::_add_to_statistics
+sub _add_to_statistics {
+ my($self,$stats) = @_;
+ my $yaml_module = CPAN::_yaml_module();
+ $self->debug("yaml_module[$yaml_module]") if $CPAN::DEBUG;
+ if ($CPAN::META->has_inst($yaml_module)) {
+ $stats->{thesiteurl} = $ThesiteURL;
+ $stats->{end} = CPAN::FTP::_mytime();
+ my $fh = FileHandle->new;
+ my $time = time;
+ my $sdebug = 0;
+ my @debug;
+ @debug = $time if $sdebug;
+ my $fullstats = $self->_ftp_statistics($fh);
+ close $fh;
+ $fullstats->{history} ||= [];
+ push @debug, scalar @{$fullstats->{history}} if $sdebug;
+ push @debug, time if $sdebug;
+ push @{$fullstats->{history}}, $stats;
+ # YAML.pm 0.62 is unacceptably slow with 999;
+ # YAML::Syck 0.82 has no noticable performance problem with 999;
+ my $ftpstats_size = $CPAN::Config->{ftpstats_size} || 99;
+ my $ftpstats_period = $CPAN::Config->{ftpstats_period} || 14;
+ while (
+ @{$fullstats->{history}} > $ftpstats_size
+ || $time - $fullstats->{history}[0]{start} > 86400*$ftpstats_period
+ ) {
+ shift @{$fullstats->{history}}
+ }
+ push @debug, scalar @{$fullstats->{history}} if $sdebug;
+ push @debug, time if $sdebug;
+ push @debug, scalar localtime($fullstats->{history}[0]{start}) if $sdebug;
+ # need no eval because if this fails, it is serious
+ my $sfile = File::Spec->catfile($CPAN::Config->{cpan_home},"FTPstats.yml");
+ CPAN->_yaml_dumpfile("$sfile.$$",$fullstats);
+ if ( $sdebug ) {
+ local $CPAN::DEBUG = 512; # FTP
+ push @debug, time;
+ CPAN->debug(sprintf("DEBUG history: before_read[%d]before[%d]at[%d]".
+ "after[%d]at[%d]oldest[%s]dumped backat[%d]",
+ @debug,
+ ));
+ }
+ # Win32 cannot rename a file to an existing filename
+ unlink($sfile) if ($^O eq 'MSWin32' or $^O eq 'os2');
+ _copy_stat($sfile, "$sfile.$$") if -e $sfile;
+ rename "$sfile.$$", $sfile
+ or $CPAN::Frontend->mydie("Could not rename '$sfile.$$' to '$sfile': $!\n");
+ }
+}
+
+# Copy some stat information (owner, group, mode and) from one file to
+# another.
+# This is a utility function which might be moved to a utility repository.
+#-> sub CPAN::FTP::_copy_stat
+sub _copy_stat {
+ my($src, $dest) = @_;
+ my @stat = stat($src);
+ if (!@stat) {
+ $CPAN::Frontend->mywarn("Can't stat '$src': $!\n");
+ return;
+ }
+
+ eval {
+ chmod $stat[2], $dest
+ or $CPAN::Frontend->mywarn("Can't chmod '$dest' to " . sprintf("0%o", $stat[2]) . ": $!\n");
+ };
+ warn $@ if $@;
+ eval {
+ chown $stat[4], $stat[5], $dest
+ or do {
+ my $save_err = $!; # otherwise it's lost in the get... calls
+ $CPAN::Frontend->mywarn("Can't chown '$dest' to " .
+ (getpwuid($stat[4]))[0] . "/" .
+ (getgrgid($stat[5]))[0] . ": $save_err\n"
+ );
+ };
+ };
+ warn $@ if $@;
+}
+
+# if file is CHECKSUMS, suggest the place where we got the file to be
+# checked from, maybe only for young files?
+#-> sub CPAN::FTP::_recommend_url_for
+sub _recommend_url_for {
+ my($self, $file, $urllist) = @_;
+ if ($file =~ s|/CHECKSUMS(.gz)?$||) {
+ my $fullstats = $self->_ftp_statistics();
+ my $history = $fullstats->{history} || [];
+ while (my $last = pop @$history) {
+ last if $last->{end} - time > 3600; # only young results are interesting
+ next unless $last->{file}; # dirname of nothing dies!
+ next unless $file eq dirname($last->{file});
+ return $last->{thesiteurl};
+ }
+ }
+ if ($CPAN::Config->{randomize_urllist}
+ &&
+ rand(1) < $CPAN::Config->{randomize_urllist}
+ ) {
+ $urllist->[int rand scalar @$urllist];
+ } else {
+ return ();
+ }
+}
+
+#-> sub CPAN::FTP::_get_urllist
+sub _get_urllist {
+ my($self, $with_defaults) = @_;
+ $with_defaults ||= 0;
+ CPAN->debug("with_defaults[$with_defaults]") if $CPAN::DEBUG;
+
+ $CPAN::Config->{urllist} ||= [];
+ unless (ref $CPAN::Config->{urllist} eq 'ARRAY') {
+ $CPAN::Frontend->mywarn("Malformed urllist; ignoring. Configuration file corrupt?\n");
+ $CPAN::Config->{urllist} = [];
+ }
+ my @urllist = grep { defined $_ and length $_ } @{$CPAN::Config->{urllist}};
+ push @urllist, @CPAN::Defaultsites if $with_defaults;
+ for my $u (@urllist) {
+ CPAN->debug("u[$u]") if $CPAN::DEBUG;
+ if (UNIVERSAL::can($u,"text")) {
+ $u->{TEXT} .= "/" unless substr($u->{TEXT},-1) eq "/";
+ } else {
+ $u .= "/" unless substr($u,-1) eq "/";
+ $u = CPAN::URL->new(TEXT => $u, FROM => "USER");
+ }
+ }
+ \@urllist;
+}
+
+#-> sub CPAN::FTP::ftp_get ;
+sub ftp_get {
+ my($class,$host,$dir,$file,$target) = @_;
+ $class->debug(
+ qq[Going to fetch file [$file] from dir [$dir]
+ on host [$host] as local [$target]\n]
+ ) if $CPAN::DEBUG;
+ my $ftp = Net::FTP->new($host);
+ unless ($ftp) {
+ $CPAN::Frontend->mywarn(" Could not connect to host '$host' with Net::FTP\n");
+ return;
+ }
+ return 0 unless defined $ftp;
+ $ftp->debug(1) if $CPAN::DEBUG{'FTP'} & $CPAN::DEBUG;
+ $class->debug(qq[Going to login("anonymous","$Config::Config{cf_email}")]);
+ unless ( $ftp->login("anonymous",$Config::Config{'cf_email'}) ) {
+ my $msg = $ftp->message;
+ $CPAN::Frontend->mywarn(" Couldn't login on $host: $msg\n");
+ return;
+ }
+ unless ( $ftp->cwd($dir) ) {
+ my $msg = $ftp->message;
+ $CPAN::Frontend->mywarn(" Couldn't cwd $dir: $msg\n");
+ return;
+ }
+ $ftp->binary;
+ $class->debug(qq[Going to ->get("$file","$target")\n]) if $CPAN::DEBUG;
+ unless ( $ftp->get($file,$target) ) {
+ my $msg = $ftp->message;
+ $CPAN::Frontend->mywarn(" Couldn't fetch $file from $host: $msg\n");
+ return;
+ }
+ $ftp->quit; # it's ok if this fails
+ return 1;
+}
+
+# If more accuracy is wanted/needed, Chris Leach sent me this patch...
+
+ # > *** /install/perl/live/lib/CPAN.pm- Wed Sep 24 13:08:48 1997
+ # > --- /tmp/cp Wed Sep 24 13:26:40 1997
+ # > ***************
+ # > *** 1562,1567 ****
+ # > --- 1562,1580 ----
+ # > return 1 if substr($url,0,4) eq "file";
+ # > return 1 unless $url =~ m|://([^/]+)|;
+ # > my $host = $1;
+ # > + my $proxy = $CPAN::Config->{'http_proxy'} || $ENV{'http_proxy'};
+ # > + if ($proxy) {
+ # > + $proxy =~ m|://([^/:]+)|;
+ # > + $proxy = $1;
+ # > + my $noproxy = $CPAN::Config->{'no_proxy'} || $ENV{'no_proxy'};
+ # > + if ($noproxy) {
+ # > + if ($host !~ /$noproxy$/) {
+ # > + $host = $proxy;
+ # > + }
+ # > + } else {
+ # > + $host = $proxy;
+ # > + }
+ # > + }
+ # > require Net::Ping;
+ # > return 1 unless $Net::Ping::VERSION >= 2;
+ # > my $p;
+
+
+#-> sub CPAN::FTP::localize ;
+sub localize {
+ my($self,$file,$aslocal,$force,$with_defaults) = @_;
+ $force ||= 0;
+ Carp::croak( "Usage: ->localize(cpan_file,as_local_file[,\$force])" )
+ unless defined $aslocal;
+ if ($CPAN::DEBUG){
+ require Carp;
+ my $longmess = Carp::longmess();
+ $self->debug("file[$file] aslocal[$aslocal] force[$force] carplongmess[$longmess]");
+ }
+ if ($^O eq 'MacOS') {
+ # Comment by AK on 2000-09-03: Uniq short filenames would be
+ # available in CHECKSUMS file
+ my($name, $path) = File::Basename::fileparse($aslocal, '');
+ if (length($name) > 31) {
+ $name =~ s/(
+ \.(
+ readme(\.(gz|Z))? |
+ (tar\.)?(gz|Z) |
+ tgz |
+ zip |
+ pm\.(gz|Z)
+ )
+ )$//x;
+ my $suf = $1;
+ my $size = 31 - length($suf);
+ while (length($name) > $size) {
+ chop $name;
+ }
+ $name .= $suf;
+ $aslocal = File::Spec->catfile($path, $name);
+ }
+ }
+
+ if (-f $aslocal && -r _ && !($force & 1)) {
+ my $size;
+ if ($size = -s $aslocal) {
+ $self->debug("aslocal[$aslocal]size[$size]") if $CPAN::DEBUG;
+ return $aslocal;
+ } else {
+ # empty file from a previous unsuccessful attempt to download it
+ unlink $aslocal or
+ $CPAN::Frontend->mydie("Found a zero-length '$aslocal' that I ".
+ "could not remove.");
+ }
+ }
+ my($maybe_restore) = 0;
+ if (-f $aslocal) {
+ rename $aslocal, "$aslocal.bak$$";
+ $maybe_restore++;
+ }
+
+ my($aslocal_dir) = dirname($aslocal);
+ # Inheritance is not easier to manage than a few if/else branches
+ if ($CPAN::META->has_usable('LWP::UserAgent')) {
+ unless ($Ua) {
+ CPAN::LWP::UserAgent->config;
+ eval {$Ua = CPAN::LWP::UserAgent->new;}; # Why is has_usable still not fit enough?
+ if ($@) {
+ $CPAN::Frontend->mywarn("CPAN::LWP::UserAgent->new dies with $@\n")
+ if $CPAN::DEBUG;
+ } else {
+ my($var);
+ $Ua->proxy('ftp', $var)
+ if $var = $CPAN::Config->{ftp_proxy} || $ENV{ftp_proxy};
+ $Ua->proxy('http', $var)
+ if $var = $CPAN::Config->{http_proxy} || $ENV{http_proxy};
+ $Ua->no_proxy($var)
+ if $var = $CPAN::Config->{no_proxy} || $ENV{no_proxy};
+ }
+ }
+ }
+ for my $prx (qw(ftp_proxy http_proxy no_proxy)) {
+ $ENV{$prx} = $CPAN::Config->{$prx} if $CPAN::Config->{$prx};
+ }
+
+ # Try the list of urls for each single object. We keep a record
+ # where we did get a file from
+ my(@reordered,$last);
+ my $ccurllist = $self->_get_urllist($with_defaults);
+ $last = $#$ccurllist;
+ if ($force & 2) { # local cpans probably out of date, don't reorder
+ @reordered = (0..$last);
+ } else {
+ @reordered =
+ sort {
+ (substr($ccurllist->[$b],0,4) eq "file")
+ <=>
+ (substr($ccurllist->[$a],0,4) eq "file")
+ or
+ defined($ThesiteURL)
+ and
+ ($ccurllist->[$b] eq $ThesiteURL)
+ <=>
+ ($ccurllist->[$a] eq $ThesiteURL)
+ } 0..$last;
+ }
+ my(@levels);
+ $Themethod ||= "";
+ $self->debug("Themethod[$Themethod]reordered[@reordered]") if $CPAN::DEBUG;
+ my @all_levels = (
+ ["dleasy", "file"],
+ ["dleasy"],
+ ["dlhard"],
+ ["dlhardest"],
+ ["dleasy", "http","defaultsites"],
+ ["dlhard", "http","defaultsites"],
+ ["dleasy", "ftp", "defaultsites"],
+ ["dlhard", "ftp", "defaultsites"],
+ ["dlhardest","", "defaultsites"],
+ );
+ if ($Themethod) {
+ @levels = grep {$_->[0] eq $Themethod} @all_levels;
+ push @levels, grep {$_->[0] ne $Themethod} @all_levels;
+ } else {
+ @levels = @all_levels;
+ }
+ @levels = qw/dleasy/ if $^O eq 'MacOS';
+ my($levelno);
+ local $ENV{FTP_PASSIVE} =
+ exists $CPAN::Config->{ftp_passive} ?
+ $CPAN::Config->{ftp_passive} : 1;
+ my $ret;
+ my $stats = $self->_new_stats($file);
+ for ($CPAN::Config->{connect_to_internet_ok}) {
+ $connect_to_internet_ok = $_ if not defined $connect_to_internet_ok and defined $_;
+ }
+ LEVEL: for $levelno (0..$#levels) {
+ my $level_tuple = $levels[$levelno];
+ my($level,$scheme,$sitetag) = @$level_tuple;
+ $self->mymkpath($aslocal_dir) unless $scheme && "file" eq $scheme;
+ my $defaultsites = $sitetag && $sitetag eq "defaultsites" && !@$ccurllist;
+ my @urllist;
+ if ($defaultsites) {
+ unless (defined $connect_to_internet_ok) {
+ $CPAN::Frontend->myprint(sprintf qq{
+I would like to connect to one of the following sites to get '%s':
+
+%s
+},
+ $file,
+ join("",map { " ".$_->text."\n" } @CPAN::Defaultsites),
+ );
+ my $answer = CPAN::Shell::colorable_makemaker_prompt("Is it OK to try to connect to the Internet?", "yes");
+ if ($answer =~ /^y/i) {
+ $connect_to_internet_ok = 1;
+ } else {
+ $connect_to_internet_ok = 0;
+ }
+ }
+ if ($connect_to_internet_ok) {
+ @urllist = @CPAN::Defaultsites;
+ } else {
+ my $sleep = 2;
+ # the tricky thing about dying here is that everybody
+ # believes that calls to exists() or all_objects() are
+ # safe.
+ require CPAN::Exception::blocked_urllist;
+ die CPAN::Exception::blocked_urllist->new;
+ }
+ } else { # ! $defaultsites
+ my @host_seq = $level =~ /dleasy/ ?
+ @reordered : 0..$last; # reordered has file and $Thesiteurl first
+ @urllist = map { $ccurllist->[$_] } @host_seq;
+ }
+ $self->debug("synth. urllist[@urllist]") if $CPAN::DEBUG;
+ my $aslocal_tempfile = $aslocal . ".tmp" . $$;
+ if (my $recommend = $self->_recommend_url_for($file,\@urllist)) {
+ @urllist = grep { $_ ne $recommend } @urllist;
+ unshift @urllist, $recommend;
+ }
+ $self->debug("synth. urllist[@urllist]") if $CPAN::DEBUG;
+ $ret = $self->hostdlxxx($level,$scheme,\@urllist,$file,$aslocal_tempfile,$stats);
+ if ($ret) {
+ CPAN->debug("ret[$ret]aslocal[$aslocal]") if $CPAN::DEBUG;
+ if ($ret eq $aslocal_tempfile) {
+ # if we got it exactly as we asked for, only then we
+ # want to rename
+ rename $aslocal_tempfile, $aslocal
+ or $CPAN::Frontend->mydie("Error while trying to rename ".
+ "'$ret' to '$aslocal': $!");
+ $ret = $aslocal;
+ }
+ elsif (-f $ret && $scheme eq 'file' ) {
+ # it's a local file, so there's nothing left to do, we
+ # let them read from where it is
+ }
+ $Themethod = $level;
+ my $now = time;
+ # utime $now, $now, $aslocal; # too bad, if we do that, we
+ # might alter a local mirror
+ $self->debug("level[$level]") if $CPAN::DEBUG;
+ last LEVEL;
+ } else {
+ unlink $aslocal_tempfile;
+ last if $CPAN::Signal; # need to cleanup
+ }
+ }
+ if ($ret) {
+ $stats->{filesize} = -s $ret;
+ }
+ $self->debug("before _add_to_statistics") if $CPAN::DEBUG;
+ $self->_add_to_statistics($stats);
+ $self->debug("after _add_to_statistics") if $CPAN::DEBUG;
+ if ($ret) {
+ unlink "$aslocal.bak$$";
+ return $ret;
+ }
+ unless ($CPAN::Signal) {
+ my(@mess);
+ local $" = " ";
+ if (@{$CPAN::Config->{urllist}}) {
+ push @mess,
+ qq{Please check, if the URLs I found in your configuration file \(}.
+ join(", ", @{$CPAN::Config->{urllist}}).
+ qq{\) are valid.};
+ } else {
+ push @mess, qq{Your urllist is empty!};
+ }
+ push @mess, qq{The urllist can be edited.},
+ qq{E.g. with 'o conf urllist push ftp://myurl/'};
+ $CPAN::Frontend->mywarn(Text::Wrap::wrap("","","@mess"). "\n\n");
+ $CPAN::Frontend->mydie("Could not fetch $file\n");
+ }
+ if ($maybe_restore) {
+ rename "$aslocal.bak$$", $aslocal;
+ $CPAN::Frontend->myprint("Trying to get away with old file:\n" .
+ $self->ls($aslocal) . "\n");
+ return $aslocal;
+ }
+ return;
+}
+
+sub mymkpath {
+ my($self, $aslocal_dir) = @_;
+ mkpath($aslocal_dir);
+ $CPAN::Frontend->mywarn(qq{Warning: You are not allowed to write into }.
+ qq{directory "$aslocal_dir".
+ I\'ll continue, but if you encounter problems, they may be due
+ to insufficient permissions.\n}) unless -w $aslocal_dir;
+}
+
+sub hostdlxxx {
+ my $self = shift;
+ my $level = shift;
+ my $scheme = shift;
+ my $h = shift;
+ $h = [ grep /^\Q$scheme\E:/, @$h ] if $scheme;
+ my $method = "host$level";
+ $self->$method($h, @_);
+}
+
+sub _set_attempt {
+ my($self,$stats,$method,$url) = @_;
+ push @{$stats->{attempts}}, {
+ method => $method,
+ start => _mytime,
+ url => $url,
+ };
+}
+
+# package CPAN::FTP;
+sub hostdleasy { #called from hostdlxxx
+ my($self,$host_seq,$file,$aslocal,$stats) = @_;
+ my($ro_url);
+ HOSTEASY: for $ro_url (@$host_seq) {
+ $self->_set_attempt($stats,"dleasy",$ro_url);
+ my $url .= "$ro_url$file";
+ $self->debug("localizing perlish[$url]") if $CPAN::DEBUG;
+ if ($url =~ /^file:/) {
+ my $l;
+ if ($CPAN::META->has_inst('URI::URL')) {
+ my $u = URI::URL->new($url);
+ $l = $u->file;
+ } else { # works only on Unix, is poorly constructed, but
+ # hopefully better than nothing.
+ # RFC 1738 says fileurl BNF is
+ # fileurl = "file://" [ host | "localhost" ] "/" fpath
+ # Thanks to "Mark D. Baushke" <mdb@cisco.com> for
+ # the code
+ ($l = $url) =~ s|^file://[^/]*/|/|; # discard the host part
+ $l =~ s|^file:||; # assume they
+ # meant
+ # file://localhost
+ $l =~ s|^/||s
+ if ! -f $l && $l =~ m|^/\w:|; # e.g. /P:
+ }
+ $self->debug("local file[$l]") if $CPAN::DEBUG;
+ if ( -f $l && -r _) {
+ $ThesiteURL = $ro_url;
+ return $l;
+ }
+ # If request is for a compressed file and we can find the
+ # uncompressed file also, return the path of the uncompressed file
+ # otherwise, decompress it and return the resulting path
+ if ($l =~ /(.+)\.gz$/) {
+ my $ungz = $1;
+ if ( -f $ungz && -r _) {
+ $ThesiteURL = $ro_url;
+ return $ungz;
+ }
+ else {
+ eval { CPAN::Tarzip->new($l)->gunzip($aslocal) };
+ if ( -f $aslocal) {
+ $ThesiteURL = $ro_url;
+ return $aslocal;
+ }
+ else {
+ $CPAN::Frontend->mywarn("Error decompressing '$l': $@\n")
+ if $@;
+ return;
+ }
+ }
+ }
+ # Otherwise, return the local file path if it exists
+ elsif ( -f $l && -r _) {
+ $ThesiteURL = $ro_url;
+ return $l;
+ }
+ # If we can't find it, but there is a compressed version
+ # of it, then decompress it
+ elsif (-f "$l.gz") {
+ $self->debug("found compressed $l.gz") if $CPAN::DEBUG;
+ eval { CPAN::Tarzip->new("$l.gz")->gunzip($aslocal) };
+ if ( -f $aslocal) {
+ $ThesiteURL = $ro_url;
+ return $aslocal;
+ }
+ else {
+ $CPAN::Frontend->mywarn("Error decompressing '$l': $@\n")
+ if $@;
+ return;
+ }
+ }
+ $CPAN::Frontend->mywarn("Could not find '$l'\n");
+ }
+ $self->debug("it was not a file URL") if $CPAN::DEBUG;
+ if ($CPAN::META->has_usable('LWP')) {
+ $CPAN::Frontend->myprint("Fetching with LWP:\n$url\n");
+ unless ($Ua) {
+ CPAN::LWP::UserAgent->config;
+ eval { $Ua = CPAN::LWP::UserAgent->new; };
+ if ($@) {
+ $CPAN::Frontend->mywarn("CPAN::LWP::UserAgent->new dies with $@\n");
+ }
+ }
+ my $res = $Ua->mirror($url, $aslocal);
+ if ($res->is_success) {
+ $ThesiteURL = $ro_url;
+ my $now = time;
+ utime $now, $now, $aslocal; # download time is more
+ # important than upload
+ # time
+ return $aslocal;
+ } elsif ($url !~ /\.gz(?!\n)\Z/) {
+ my $gzurl = "$url.gz";
+ $CPAN::Frontend->myprint("Fetching with LWP:\n$gzurl\n");
+ $res = $Ua->mirror($gzurl, "$aslocal.gz");
+ if ($res->is_success) {
+ if (eval {CPAN::Tarzip->new("$aslocal.gz")->gunzip($aslocal)}) {
+ $ThesiteURL = $ro_url;
+ return $aslocal;
+ }
+ }
+ } else {
+ $CPAN::Frontend->myprint(sprintf(
+ "LWP failed with code[%s] message[%s]\n",
+ $res->code,
+ $res->message,
+ ));
+ # Alan Burlison informed me that in firewall environments
+ # Net::FTP can still succeed where LWP fails. So we do not
+ # skip Net::FTP anymore when LWP is available.
+ }
+ } else {
+ $CPAN::Frontend->mywarn(" LWP not available\n");
+ }
+ return if $CPAN::Signal;
+ if ($url =~ m|^ftp://(.*?)/(.*)/(.*)|) {
+ # that's the nice and easy way thanks to Graham
+ $self->debug("recognized ftp") if $CPAN::DEBUG;
+ my($host,$dir,$getfile) = ($1,$2,$3);
+ if ($CPAN::META->has_usable('Net::FTP')) {
+ $dir =~ s|/+|/|g;
+ $CPAN::Frontend->myprint("Fetching with Net::FTP:\n$url\n");
+ $self->debug("getfile[$getfile]dir[$dir]host[$host]" .
+ "aslocal[$aslocal]") if $CPAN::DEBUG;
+ if (CPAN::FTP->ftp_get($host,$dir,$getfile,$aslocal)) {
+ $ThesiteURL = $ro_url;
+ return $aslocal;
+ }
+ if ($aslocal !~ /\.gz(?!\n)\Z/) {
+ my $gz = "$aslocal.gz";
+ $CPAN::Frontend->myprint("Fetching with Net::FTP\n$url.gz\n");
+ if (CPAN::FTP->ftp_get($host,
+ $dir,
+ "$getfile.gz",
+ $gz) &&
+ eval{CPAN::Tarzip->new($gz)->gunzip($aslocal)}
+ ) {
+ $ThesiteURL = $ro_url;
+ return $aslocal;
+ }
+ }
+ # next HOSTEASY;
+ } else {
+ CPAN->debug("Net::FTP does not count as usable atm") if $CPAN::DEBUG;
+ }
+ }
+ if (
+ UNIVERSAL::can($ro_url,"text")
+ and
+ $ro_url->{FROM} eq "USER"
+ ) {
+ ##address #17973: default URLs should not try to override
+ ##user-defined URLs just because LWP is not available
+ my $ret = $self->hostdlhard([$ro_url],$file,$aslocal,$stats);
+ return $ret if $ret;
+ }
+ return if $CPAN::Signal;
+ }
+}
+
+# package CPAN::FTP;
+sub hostdlhard {
+ my($self,$host_seq,$file,$aslocal,$stats) = @_;
+
+ # Came back if Net::FTP couldn't establish connection (or
+ # failed otherwise) Maybe they are behind a firewall, but they
+ # gave us a socksified (or other) ftp program...
+
+ my($ro_url);
+ my($devnull) = $CPAN::Config->{devnull} || "";
+ # < /dev/null ";
+ my($aslocal_dir) = dirname($aslocal);
+ mkpath($aslocal_dir);
+ my $some_dl_success = 0;
+ my $any_attempt = 0;
+ HOSTHARD: for $ro_url (@$host_seq) {
+ $self->_set_attempt($stats,"dlhard",$ro_url);
+ my $url = "$ro_url$file";
+ my($proto,$host,$dir,$getfile);
+
+ # Courtesy Mark Conty mark_conty@cargill.com change from
+ # if ($url =~ m|^ftp://(.*?)/(.*)/(.*)|) {
+ # to
+ if ($url =~ m|^([^:]+)://(.*?)/(.*)/(.*)|) {
+ # proto not yet used
+ ($proto,$host,$dir,$getfile) = ($1,$2,$3,$4);
+ } else {
+ next HOSTHARD; # who said, we could ftp anything except ftp?
+ }
+ next HOSTHARD if $proto eq "file"; # file URLs would have had
+ # success above. Likely a bogus URL
+
+ # making at least one attempt against a host
+ $any_attempt++;
+
+ $self->debug("localizing funkyftpwise[$url]") if $CPAN::DEBUG;
+
+ # Try the most capable first and leave ncftp* for last as it only
+ # does FTP.
+ my $proxy_vars = $self->_proxy_vars($ro_url);
+ DLPRG: for my $f (qw(curl wget lynx ncftpget ncftp)) {
+ my $funkyftp = CPAN::HandleConfig->safe_quote($CPAN::Config->{$f});
+ next DLPRG unless defined $funkyftp;
+ next DLPRG if $funkyftp =~ /^\s*$/;
+
+ my($src_switch) = "";
+ my($chdir) = "";
+ my($stdout_redir) = " > \"$aslocal\"";
+ if ($f eq "lynx") {
+ $src_switch = " -source";
+ } elsif ($f eq "ncftp") {
+ next DLPRG unless $url =~ m{\Aftp://};
+ $src_switch = " -c";
+ } elsif ($f eq "wget") {
+ $src_switch = " -O \"$aslocal\"";
+ $stdout_redir = "";
+ } elsif ($f eq 'curl') {
+ $src_switch = ' -L -f -s -S --netrc-optional';
+ if ($proxy_vars->{http_proxy}) {
+ $src_switch .= qq{ -U "$proxy_vars->{proxy_user}:$proxy_vars->{proxy_pass}" -x "$proxy_vars->{http_proxy}"};
+ }
+ } elsif ($f eq "ncftpget") {
+ next DLPRG unless $url =~ m{\Aftp://};
+ $chdir = "cd $aslocal_dir && ";
+ $stdout_redir = "";
+ }
+ $CPAN::Frontend->myprint(
+ qq[
+Trying with
+ $funkyftp$src_switch
+to get
+ $url
+]);
+ my($system) =
+ "$chdir$funkyftp$src_switch \"$url\" $devnull$stdout_redir";
+ $self->debug("system[$system]") if $CPAN::DEBUG;
+ my($wstatus) = system($system);
+ if ($f eq "lynx") {
+ # lynx returns 0 when it fails somewhere
+ if (-s $aslocal) {
+ my $content = do { local *FH;
+ open FH, $aslocal or die;
+ local $/;
+ <FH> };
+ if ($content =~ /^<.*(<title>[45]|Error [45])/si) {
+ $CPAN::Frontend->mywarn(qq{
+No success, the file that lynx has downloaded looks like an error message:
+$content
+});
+ $CPAN::Frontend->mysleep(1);
+ next DLPRG;
+ }
+ $some_dl_success++;
+ } else {
+ $CPAN::Frontend->myprint(qq{
+No success, the file that lynx has downloaded is an empty file.
+});
+ next DLPRG;
+ }
+ }
+ if ($wstatus == 0) {
+ if (-s $aslocal) {
+ # Looks good
+ $some_dl_success++;
+ }
+ $ThesiteURL = $ro_url;
+ return $aslocal;
+ } else {
+ my $estatus = $wstatus >> 8;
+ my $size = -f $aslocal ?
+ ", left\n$aslocal with size ".-s _ :
+ "\nWarning: expected file [$aslocal] doesn't exist";
+ $CPAN::Frontend->myprint(qq{
+ Function system("$system")
+ returned status $estatus (wstat $wstatus)$size
+ });
+ }
+ return if $CPAN::Signal;
+ } # download/transfer programs (DLPRG)
+ } # host
+ return unless $any_attempt;
+ if ($some_dl_success) {
+ $CPAN::Frontend->mywarn("Warning: doesn't seem we had substantial success downloading '$aslocal'. Don't know how to proceed.\n");
+ } else {
+ $CPAN::Frontend->mywarn("Warning: no success downloading '$aslocal'. Giving up on it.\n");
+ }
+ return;
+}
+
+#-> CPAN::FTP::_proxy_vars
+sub _proxy_vars {
+ my($self,$url) = @_;
+ my $ret = +{};
+ my $http_proxy = $CPAN::Config->{'http_proxy'} || $ENV{'http_proxy'};
+ if ($http_proxy) {
+ my($host) = $url =~ m|://([^/:]+)|;
+ my $want_proxy = 1;
+ my $noproxy = $CPAN::Config->{'no_proxy'} || $ENV{'no_proxy'} || "";
+ my @noproxy = split /\s*,\s*/, $noproxy;
+ if ($host) {
+ DOMAIN: for my $domain (@noproxy) {
+ if ($host =~ /\Q$domain\E$/) { # cf. LWP::UserAgent
+ $want_proxy = 0;
+ last DOMAIN;
+ }
+ }
+ } else {
+ $CPAN::Frontend->mywarn(" Could not determine host from http_proxy '$http_proxy'\n");
+ }
+ if ($want_proxy) {
+ my($user, $pass) =
+ &CPAN::LWP::UserAgent::get_proxy_credentials();
+ $ret = {
+ proxy_user => $user,
+ proxy_pass => $pass,
+ http_proxy => $http_proxy
+ };
+ }
+ }
+ return $ret;
+}
+
+# package CPAN::FTP;
+sub hostdlhardest {
+ my($self,$host_seq,$file,$aslocal,$stats) = @_;
+
+ return unless @$host_seq;
+ my($ro_url);
+ my($aslocal_dir) = dirname($aslocal);
+ mkpath($aslocal_dir);
+ my $ftpbin = $CPAN::Config->{ftp};
+ unless ($ftpbin && length $ftpbin && MM->maybe_command($ftpbin)) {
+ $CPAN::Frontend->myprint("No external ftp command available\n\n");
+ return;
+ }
+ $CPAN::Frontend->mywarn(qq{
+As a last resort we now switch to the external ftp command '$ftpbin'
+to get '$aslocal'.
+
+Doing so often leads to problems that are hard to diagnose.
+
+If you're the victim of such problems, please consider unsetting the
+ftp config variable with
+
+ o conf ftp ""
+ o conf commit
+
+});
+ $CPAN::Frontend->mysleep(2);
+ HOSTHARDEST: for $ro_url (@$host_seq) {
+ $self->_set_attempt($stats,"dlhardest",$ro_url);
+ my $url = "$ro_url$file";
+ $self->debug("localizing ftpwise[$url]") if $CPAN::DEBUG;
+ unless ($url =~ m|^ftp://(.*?)/(.*)/(.*)|) {
+ next;
+ }
+ my($host,$dir,$getfile) = ($1,$2,$3);
+ my $timestamp = 0;
+ my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,
+ $ctime,$blksize,$blocks) = stat($aslocal);
+ $timestamp = $mtime ||= 0;
+ my($netrc) = CPAN::FTP::netrc->new;
+ my($netrcfile) = $netrc->netrc;
+ my($verbose) = $CPAN::DEBUG{'FTP'} & $CPAN::DEBUG ? " -v" : "";
+ my $targetfile = File::Basename::basename($aslocal);
+ my(@dialog);
+ push(
+ @dialog,
+ "lcd $aslocal_dir",
+ "cd /",
+ map("cd $_", split /\//, $dir), # RFC 1738
+ "bin",
+ "passive",
+ "get $getfile $targetfile",
+ "quit"
+ );
+ if (! $netrcfile) {
+ CPAN->debug("No ~/.netrc file found") if $CPAN::DEBUG;
+ } elsif ($netrc->hasdefault || $netrc->contains($host)) {
+ CPAN->debug(sprintf("hasdef[%d]cont($host)[%d]",
+ $netrc->hasdefault,
+ $netrc->contains($host))) if $CPAN::DEBUG;
+ if ($netrc->protected) {
+ my $dialog = join "", map { " $_\n" } @dialog;
+ my $netrc_explain;
+ if ($netrc->contains($host)) {
+ $netrc_explain = "Relying that your .netrc entry for '$host' ".
+ "manages the login";
+ } else {
+ $netrc_explain = "Relying that your default .netrc entry ".
+ "manages the login";
+ }
+ $CPAN::Frontend->myprint(qq{
+ Trying with external ftp to get
+ '$url'
+ $netrc_explain
+ Going to send the dialog
+$dialog
+}
+ );
+ $self->talk_ftp("$ftpbin$verbose $host",
+ @dialog);
+ ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
+ $atime,$mtime,$ctime,$blksize,$blocks) = stat($aslocal);
+ $mtime ||= 0;
+ if ($mtime > $timestamp) {
+ $CPAN::Frontend->myprint("GOT $aslocal\n");
+ $ThesiteURL = $ro_url;
+ return $aslocal;
+ } else {
+ $CPAN::Frontend->myprint("Hmm... Still failed!\n");
+ }
+ return if $CPAN::Signal;
+ } else {
+ $CPAN::Frontend->mywarn(qq{Your $netrcfile is not }.
+ qq{correctly protected.\n});
+ }
+ } else {
+ $CPAN::Frontend->mywarn("Your ~/.netrc neither contains $host
+ nor does it have a default entry\n");
+ }
+
+ # OK, they don't have a valid ~/.netrc. Use 'ftp -n'
+ # then and login manually to host, using e-mail as
+ # password.
+ $CPAN::Frontend->myprint(qq{Issuing "$ftpbin$verbose -n"\n});
+ unshift(
+ @dialog,
+ "open $host",
+ "user anonymous $Config::Config{'cf_email'}"
+ );
+ my $dialog = join "", map { " $_\n" } @dialog;
+ $CPAN::Frontend->myprint(qq{
+ Trying with external ftp to get
+ $url
+ Going to send the dialog
+$dialog
+}
+ );
+ $self->talk_ftp("$ftpbin$verbose -n", @dialog);
+ ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
+ $atime,$mtime,$ctime,$blksize,$blocks) = stat($aslocal);
+ $mtime ||= 0;
+ if ($mtime > $timestamp) {
+ $CPAN::Frontend->myprint("GOT $aslocal\n");
+ $ThesiteURL = $ro_url;
+ return $aslocal;
+ } else {
+ $CPAN::Frontend->myprint("Bad luck... Still failed!\n");
+ }
+ return if $CPAN::Signal;
+ $CPAN::Frontend->mywarn("Can't access URL $url.\n\n");
+ $CPAN::Frontend->mysleep(2);
+ } # host
+}
+
+# package CPAN::FTP;
+sub talk_ftp {
+ my($self,$command,@dialog) = @_;
+ my $fh = FileHandle->new;
+ $fh->open("|$command") or die "Couldn't open ftp: $!";
+ foreach (@dialog) { $fh->print("$_\n") }
+ $fh->close; # Wait for process to complete
+ my $wstatus = $?;
+ my $estatus = $wstatus >> 8;
+ $CPAN::Frontend->myprint(qq{
+Subprocess "|$command"
+ returned status $estatus (wstat $wstatus)
+}) if $wstatus;
+}
+
+# find2perl needs modularization, too, all the following is stolen
+# from there
+# CPAN::FTP::ls
+sub ls {
+ my($self,$name) = @_;
+ my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$sizemm,
+ $atime,$mtime,$ctime,$blksize,$blocks) = lstat($name);
+
+ my($perms,%user,%group);
+ my $pname = $name;
+
+ if ($blocks) {
+ $blocks = int(($blocks + 1) / 2);
+ }
+ else {
+ $blocks = int(($sizemm + 1023) / 1024);
+ }
+
+ if (-f _) { $perms = '-'; }
+ elsif (-d _) { $perms = 'd'; }
+ elsif (-c _) { $perms = 'c'; $sizemm = &sizemm; }
+ elsif (-b _) { $perms = 'b'; $sizemm = &sizemm; }
+ elsif (-p _) { $perms = 'p'; }
+ elsif (-S _) { $perms = 's'; }
+ else { $perms = 'l'; $pname .= ' -> ' . readlink($_); }
+
+ my(@rwx) = ('---','--x','-w-','-wx','r--','r-x','rw-','rwx');
+ my(@moname) = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
+ my $tmpmode = $mode;
+ my $tmp = $rwx[$tmpmode & 7];
+ $tmpmode >>= 3;
+ $tmp = $rwx[$tmpmode & 7] . $tmp;
+ $tmpmode >>= 3;
+ $tmp = $rwx[$tmpmode & 7] . $tmp;
+ substr($tmp,2,1) =~ tr/-x/Ss/ if -u _;
+ substr($tmp,5,1) =~ tr/-x/Ss/ if -g _;
+ substr($tmp,8,1) =~ tr/-x/Tt/ if -k _;
+ $perms .= $tmp;
+
+ my $user = $user{$uid} || $uid; # too lazy to implement lookup
+ my $group = $group{$gid} || $gid;
+
+ my($sec,$min,$hour,$mday,$mon,$year) = localtime($mtime);
+ my($timeyear);
+ my($moname) = $moname[$mon];
+ if (-M _ > 365.25 / 2) {
+ $timeyear = $year + 1900;
+ }
+ else {
+ $timeyear = sprintf("%02d:%02d", $hour, $min);
+ }
+
+ sprintf "%5lu %4ld %-10s %2d %-8s %-8s %8s %s %2d %5s %s\n",
+ $ino,
+ $blocks,
+ $perms,
+ $nlink,
+ $user,
+ $group,
+ $sizemm,
+ $moname,
+ $mday,
+ $timeyear,
+ $pname;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/FTP/netrc.pm b/Master/tlpkg/tlperl/lib/CPAN/FTP/netrc.pm
new file mode 100644
index 00000000000..c05405e7ef6
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/FTP/netrc.pm
@@ -0,0 +1,63 @@
+package CPAN::FTP::netrc;
+use strict;
+
+$CPAN::FTP::netrc::VERSION = $CPAN::FTP::netrc::VERSION = "1.00";
+
+# package CPAN::FTP::netrc;
+sub new {
+ my($class) = @_;
+ my $home = CPAN::HandleConfig::home();
+ my $file = File::Spec->catfile($home,".netrc");
+
+ my($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
+ $atime,$mtime,$ctime,$blksize,$blocks)
+ = stat($file);
+ $mode ||= 0;
+ my $protected = 0;
+
+ my($fh,@machines,$hasdefault);
+ $hasdefault = 0;
+ $fh = FileHandle->new or die "Could not create a filehandle";
+
+ if($fh->open($file)) {
+ $protected = ($mode & 077) == 0;
+ local($/) = "";
+ NETRC: while (<$fh>) {
+ my(@tokens) = split " ", $_;
+ TOKEN: while (@tokens) {
+ my($t) = shift @tokens;
+ if ($t eq "default") {
+ $hasdefault++;
+ last NETRC;
+ }
+ last TOKEN if $t eq "macdef";
+ if ($t eq "machine") {
+ push @machines, shift @tokens;
+ }
+ }
+ }
+ } else {
+ $file = $hasdefault = $protected = "";
+ }
+
+ bless {
+ 'mach' => [@machines],
+ 'netrc' => $file,
+ 'hasdefault' => $hasdefault,
+ 'protected' => $protected,
+ }, $class;
+}
+
+# CPAN::FTP::netrc::hasdefault;
+sub hasdefault { shift->{'hasdefault'} }
+sub netrc { shift->{'netrc'} }
+sub protected { shift->{'protected'} }
+sub contains {
+ my($self,$mach) = @_;
+ for ( @{$self->{'mach'}} ) {
+ return 1 if $_ eq $mach;
+ }
+ return 0;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/FirstTime.pm b/Master/tlpkg/tlperl/lib/CPAN/FirstTime.pm
new file mode 100644
index 00000000000..53ffbf1ef04
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/FirstTime.pm
@@ -0,0 +1,1800 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+package CPAN::FirstTime;
+use strict;
+
+use ExtUtils::MakeMaker ();
+use FileHandle ();
+use File::Basename ();
+use File::Path ();
+use File::Spec ();
+use CPAN::Mirrors ();
+use vars qw($VERSION $silent);
+$VERSION = "5.5301";
+
+=head1 NAME
+
+CPAN::FirstTime - Utility for CPAN::Config file Initialization
+
+=head1 SYNOPSIS
+
+CPAN::FirstTime::init()
+
+=head1 DESCRIPTION
+
+The init routine asks a few questions and writes a CPAN/Config.pm or
+CPAN/MyConfig.pm file (depending on what it is currently using).
+
+In the following all questions and explanations regarding config
+variables are collected.
+
+=cut
+
+# down until the next =back the manpage must be parsed by the program
+# because the text is used in the init dialogues.
+
+my @podpara = split /\n\n/, <<'=back';
+
+=over 2
+
+=item auto_commit
+
+Normally CPAN.pm keeps config variables in memory and changes need to
+be saved in a separate 'o conf commit' command to make them permanent
+between sessions. If you set the 'auto_commit' option to true, changes
+to a config variable are always automatically committed to disk.
+
+Always commit changes to config variables to disk?
+
+=item build_cache
+
+CPAN.pm can limit the size of the disk area for keeping the build
+directories with all the intermediate files.
+
+Cache size for build directory (in MB)?
+
+=item build_dir
+
+Directory where the build process takes place?
+
+=item build_dir_reuse
+
+Until version 1.88 CPAN.pm never trusted the contents of the build_dir
+directory between sessions. Since 1.88_58 CPAN.pm has a YAML-based
+mechanism that makes it possible to share the contents of the
+build_dir/ directory between different sessions with the same version
+of perl. People who prefer to test things several days before
+installing will like this feature because it safes a lot of time.
+
+If you say yes to the following question, CPAN will try to store
+enough information about the build process so that it can pick up in
+future sessions at the same state of affairs as it left a previous
+session.
+
+Store and re-use state information about distributions between
+CPAN.pm sessions?
+
+=item build_requires_install_policy
+
+When a module declares another one as a 'build_requires' prerequisite
+this means that the other module is only needed for building or
+testing the module but need not be installed permanently. In this case
+you may wish to install that other module nonetheless or just keep it
+in the 'build_dir' directory to have it available only temporarily.
+Installing saves time on future installations but makes the perl
+installation bigger.
+
+You can choose if you want to always install (yes), never install (no)
+or be always asked. In the latter case you can set the default answer
+for the question to yes (ask/yes) or no (ask/no).
+
+Policy on installing 'build_requires' modules (yes, no, ask/yes,
+ask/no)?
+
+=item cache_metadata
+
+To considerably speed up the initial CPAN shell startup, it is
+possible to use Storable to create a cache of metadata. If Storable is
+not available, the normal index mechanism will be used.
+
+Note: this mechanism is not used when use_sqlite is on and SQLLite is
+running.
+
+Cache metadata (yes/no)?
+
+=item check_sigs
+
+CPAN packages can be digitally signed by authors and thus verified
+with the security provided by strong cryptography. The exact mechanism
+is defined in the Module::Signature module. While this is generally
+considered a good thing, it is not always convenient to the end user
+to install modules that are signed incorrectly or where the key of the
+author is not available or where some prerequisite for
+Module::Signature has a bug and so on.
+
+With the check_sigs parameter you can turn signature checking on and
+off. The default is off for now because the whole tool chain for the
+functionality is not yet considered mature by some. The author of
+CPAN.pm would recommend setting it to true most of the time and
+turning it off only if it turns out to be annoying.
+
+Note that if you do not have Module::Signature installed, no signature
+checks will be performed at all.
+
+Always try to check and verify signatures if a SIGNATURE file is in
+the package and Module::Signature is installed (yes/no)?
+
+=item colorize_output
+
+When you have Term::ANSIColor installed, you can turn on colorized
+output to have some visual differences between normal CPAN.pm output,
+warnings, debugging output, and the output of the modules being
+installed. Set your favorite colors after some experimenting with the
+Term::ANSIColor module.
+
+Do you want to turn on colored output?
+
+=item colorize_print
+
+Color for normal output?
+
+=item colorize_warn
+
+Color for warnings?
+
+=item colorize_debug
+
+Color for debugging messages?
+
+=item commandnumber_in_prompt
+
+The prompt of the cpan shell can contain the current command number
+for easier tracking of the session or be a plain string.
+
+Do you want the command number in the prompt (yes/no)?
+
+=item connect_to_internet_ok
+
+If you have never defined your own C<urllist> in your configuration
+then C<CPAN.pm> will be hesitant to use the built in default sites for
+downloading. It will ask you once per session if a connection to the
+internet is OK and only if you say yes, it will try to connect. But to
+avoid this question, you can choose your favorite download sites once
+and get away with it. Or, if you have no favorite download sites
+answer yes to the following question.
+
+If no urllist has been chosen yet, would you prefer CPAN.pm to connect
+to the built-in default sites without asking? (yes/no)?
+
+=item ftp_passive
+
+Shall we always set the FTP_PASSIVE environment variable when dealing
+with ftp download (yes/no)?
+
+=item ftpstats_period
+
+Statistics about downloads are truncated by size and period
+simultaneously.
+
+How many days shall we keep statistics about downloads?
+
+=item ftpstats_size
+
+Statistics about downloads are truncated by size and period
+simultaneously.
+
+How many items shall we keep in the statistics about downloads?
+
+=item getcwd
+
+CPAN.pm changes the current working directory often and needs to
+determine its own current working directory. Per default it uses
+Cwd::cwd but if this doesn't work on your system for some reason,
+alternatives can be configured according to the following table:
+
+ cwd Cwd::cwd
+ getcwd Cwd::getcwd
+ fastcwd Cwd::fastcwd
+ backtickcwd external command cwd
+
+Preferred method for determining the current working directory?
+
+=item halt_on_failure
+
+Normaly, CPAN.pm continues processing the full list of targets and
+dependencies, even if one of them fails. However, you can specify
+that CPAN should halt after the first failure.
+
+Do you want to halt on failure (yes/no)?
+
+=item histfile
+
+If you have one of the readline packages (Term::ReadLine::Perl,
+Term::ReadLine::Gnu, possibly others) installed, the interactive CPAN
+shell will have history support. The next two questions deal with the
+filename of the history file and with its size. If you do not want to
+set this variable, please hit SPACE RETURN to the following question.
+
+File to save your history?
+
+=item histsize
+
+Number of lines to save?
+
+=item inactivity_timeout
+
+Sometimes you may wish to leave the processes run by CPAN alone
+without caring about them. Because the Makefile.PL or the Build.PL
+sometimes contains question you're expected to answer, you can set a
+timer that will kill a 'perl Makefile.PL' process after the specified
+time in seconds.
+
+If you set this value to 0, these processes will wait forever. This is
+the default and recommended setting.
+
+Timeout for inactivity during {Makefile,Build}.PL?
+
+=item index_expire
+
+The CPAN indexes are usually rebuilt once or twice per hour, but the
+typical CPAN mirror mirrors only once or twice per day. Depending on
+the quality of your mirror and your desire to be on the bleeding edge,
+you may want to set the following value to more or less than one day
+(which is the default). It determines after how many days CPAN.pm
+downloads new indexes.
+
+Let the index expire after how many days?
+
+=item inhibit_startup_message
+
+When the CPAN shell is started it normally displays a greeting message
+that contains the running version and the status of readline support.
+
+Do you want to turn this message off?
+
+=item keep_source_where
+
+Unless you are accessing the CPAN on your filesystem via a file: URL,
+CPAN.pm needs to keep the source files it downloads somewhere. Please
+supply a directory where the downloaded files are to be kept.
+
+Download target directory?
+
+=item load_module_verbosity
+
+When CPAN.pm loads a module it needs for some optional feature, it
+usually reports about module name and version. Choose 'v' to get this
+message, 'none' to suppress it.
+
+Verbosity level for loading modules (none or v)?
+
+=item makepl_arg
+
+Every Makefile.PL is run by perl in a separate process. Likewise we
+run 'make' and 'make install' in separate processes. If you have
+any parameters (e.g. PREFIX, UNINST or the like) you want to
+pass to the calls, please specify them here.
+
+If you don't understand this question, just press ENTER.
+
+Typical frequently used settings:
+
+ PREFIX=~/perl # non-root users (please see manual for more hints)
+
+Parameters for the 'perl Makefile.PL' command?
+
+=item make_arg
+
+Parameters for the 'make' command? Typical frequently used setting:
+
+ -j3 # dual processor system (on GNU make)
+
+Your choice:
+
+=item make_install_arg
+
+Parameters for the 'make install' command?
+Typical frequently used setting:
+
+ UNINST=1 # to always uninstall potentially conflicting files
+
+Your choice:
+
+=item make_install_make_command
+
+Do you want to use a different make command for 'make install'?
+Cautious people will probably prefer:
+
+ su root -c make
+ or
+ sudo make
+ or
+ /path1/to/sudo -u admin_account /path2/to/make
+
+or some such. Your choice:
+
+=item mbuildpl_arg
+
+A Build.PL is run by perl in a separate process. Likewise we run
+'./Build' and './Build install' in separate processes. If you have any
+parameters you want to pass to the calls, please specify them here.
+
+Typical frequently used settings:
+
+ --install_base /home/xxx # different installation directory
+
+Parameters for the 'perl Build.PL' command?
+
+=item mbuild_arg
+
+Parameters for the './Build' command? Setting might be:
+
+ --extra_linker_flags -L/usr/foo/lib # non-standard library location
+
+Your choice:
+
+=item mbuild_install_arg
+
+Parameters for the './Build install' command? Typical frequently used
+setting:
+
+ --uninst 1 # uninstall conflicting files
+
+Your choice:
+
+=item mbuild_install_build_command
+
+Do you want to use a different command for './Build install'? Sudo
+users will probably prefer:
+
+ su root -c ./Build
+ or
+ sudo ./Build
+ or
+ /path1/to/sudo -u admin_account ./Build
+
+or some such. Your choice:
+
+=item pager
+
+What is your favorite pager program?
+
+=item prefer_installer
+
+When you have Module::Build installed and a module comes with both a
+Makefile.PL and a Build.PL, which shall have precedence?
+
+The main two standard installer modules are the old and well
+established ExtUtils::MakeMaker (for short: EUMM) which uses the
+Makefile.PL. And the next generation installer Module::Build (MB)
+which works with the Build.PL (and often comes with a Makefile.PL
+too). If a module comes only with one of the two we will use that one
+but if both are supplied then a decision must be made between EUMM and
+MB. See also http://rt.cpan.org/Ticket/Display.html?id=29235 for a
+discussion about the right default.
+
+Or, as a third option you can choose RAND which will make a random
+decision (something regular CPAN testers will enjoy).
+
+In case you can choose between running a Makefile.PL or a Build.PL,
+which installer would you prefer (EUMM or MB or RAND)?
+
+=item prefs_dir
+
+CPAN.pm can store customized build environments based on regular
+expressions for distribution names. These are YAML files where the
+default options for CPAN.pm and the environment can be overridden and
+dialog sequences can be stored that can later be executed by an
+Expect.pm object. The CPAN.pm distribution comes with some prefab YAML
+files that cover sample distributions that can be used as blueprints
+to store one own prefs. Please check out the distroprefs/ directory of
+the CPAN.pm distribution to get a quick start into the prefs system.
+
+Directory where to store default options/environment/dialogs for
+building modules that need some customization?
+
+=item prerequisites_policy
+
+The CPAN module can detect when a module which you are trying to build
+depends on prerequisites. If this happens, it can build the
+prerequisites for you automatically ('follow'), ask you for
+confirmation ('ask'), or just ignore them ('ignore'). Choosing
+'follow' also sets PERL_AUTOINSTALL and PERL_EXTUTILS_AUTOINSTALL for
+"--defaultdeps" if not already set.
+
+Please set your policy to one of the three values.
+
+Policy on building prerequisites (follow, ask or ignore)?
+
+=item randomize_urllist
+
+CPAN.pm can introduce some randomness when using hosts for download
+that are configured in the urllist parameter. Enter a numeric value
+between 0 and 1 to indicate how often you want to let CPAN.pm try a
+random host from the urllist. A value of one specifies to always use a
+random host as the first try. A value of zero means no randomness at
+all. Anything in between specifies how often, on average, a random
+host should be tried first.
+
+Randomize parameter
+
+=item scan_cache
+
+By default, each time the CPAN module is started, cache scanning is
+performed to keep the cache size in sync. To prevent this, answer
+'never'.
+
+Perform cache scanning (atstart or never)?
+
+=item shell
+
+What is your favorite shell?
+
+=item show_unparsable_versions
+
+During the 'r' command CPAN.pm finds modules without version number.
+When the command finishes, it prints a report about this. If you
+want this report to be very verbose, say yes to the following
+variable.
+
+Show all individual modules that have no $VERSION?
+
+=item show_upload_date
+
+The 'd' and the 'm' command normally only show you information they
+have in their in-memory database and thus will never connect to the
+internet. If you set the 'show_upload_date' variable to true, 'm' and
+'d' will additionally show you the upload date of the module or
+distribution. Per default this feature is off because it may require a
+net connection to get at the upload date.
+
+Always try to show upload date with 'd' and 'm' command (yes/no)?
+
+=item show_zero_versions
+
+During the 'r' command CPAN.pm finds modules with a version number of
+zero. When the command finishes, it prints a report about this. If you
+want this report to be very verbose, say yes to the following
+variable.
+
+Show all individual modules that have a $VERSION of zero?
+
+=item tar_verbosity
+
+When CPAN.pm uses the tar command, which switch for the verbosity
+shall be used? Choose 'none' for quiet operation, 'v' for file
+name listing, 'vv' for full listing.
+
+Tar command verbosity level (none or v or vv)?
+
+=item term_is_latin
+
+The next option deals with the charset (aka character set) your
+terminal supports. In general, CPAN is English speaking territory, so
+the charset does not matter much but some CPAN have names that are
+outside the ASCII range. If your terminal supports UTF-8, you should
+say no to the next question. If it expects ISO-8859-1 (also known as
+LATIN1) then you should say yes. If it supports neither, your answer
+does not matter because you will not be able to read the names of some
+authors anyway. If you answer no, names will be output in UTF-8.
+
+Your terminal expects ISO-8859-1 (yes/no)?
+
+=item term_ornaments
+
+When using Term::ReadLine, you can turn ornaments on so that your
+input stands out against the output from CPAN.pm.
+
+Do you want to turn ornaments on?
+
+=item test_report
+
+The goal of the CPAN Testers project (http://testers.cpan.org/) is to
+test as many CPAN packages as possible on as many platforms as
+possible. This provides valuable feedback to module authors and
+potential users to identify bugs or platform compatibility issues and
+improves the overall quality and value of CPAN.
+
+One way you can contribute is to send test results for each module
+that you install. If you install the CPAN::Reporter module, you have
+the option to automatically generate and email test reports to CPAN
+Testers whenever you run tests on a CPAN package.
+
+See the CPAN::Reporter documentation for additional details and
+configuration settings. If your firewall blocks outgoing email,
+you will need to configure CPAN::Reporter before sending reports.
+
+Email test reports if CPAN::Reporter is installed (yes/no)?
+
+=item perl5lib_verbosity
+
+When CPAN.pm extends @INC via PERL5LIB, it prints a list of
+directories added (or a summary of how many directories are
+added). Choose 'v' to get this message, 'none' to suppress it.
+
+Verbosity level for PERL5LIB changes (none or v)?
+
+=item trust_test_report_history
+
+When a distribution has already been tested by CPAN::Reporter on
+this machine, CPAN can skip the test phase and just rely on the
+test report history instead.
+
+Note that this will not apply to distributions that failed tests
+because of missing dependencies. Also, tests can be run
+regardless of the history using "force".
+
+Do you want to rely on the test report history (yes/no)?
+
+=item use_sqlite
+
+CPAN::SQLite is a layer between the index files that are downloaded
+from the CPAN and CPAN.pm that speeds up metadata queries and reduces
+memory consumption of CPAN.pm considerably.
+
+Use CPAN::SQLite if available? (yes/no)?
+
+=item version_timeout
+
+This timeout prevents CPAN from hanging when trying to parse a
+pathologically coded $VERSION from a module.
+
+The default is 15 seconds. If you set this value to 0, no timeout
+will occur, but this is not recommended.
+
+Timeout for parsing module versions?
+
+=item yaml_load_code
+
+Both YAML.pm and YAML::Syck are capable of deserialising code. As this
+requires a string eval, which might be a security risk, you can use
+this option to enable or disable the deserialisation of code via
+CPAN::DeferredCode. (Note: This does not work under perl 5.6)
+
+Do you want to enable code deserialisation (yes/no)?
+
+=item yaml_module
+
+At the time of this writing (2009-03) there are three YAML
+implementations working: YAML, YAML::Syck, and YAML::XS. The latter
+two are faster but need a C compiler installed on your system. There
+may be more alternative YAML conforming modules. When I tried two
+other players, YAML::Tiny and YAML::Perl, they seemed not powerful
+enough to work with CPAN.pm. This may have changed in the meantime.
+
+Which YAML implementation would you prefer?
+
+=back
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=cut
+
+use vars qw( %prompts );
+
+{
+
+ my @prompts = (
+
+manual_config => qq[
+CPAN is the world-wide archive of perl resources. It consists of about
+300 sites that all replicate the same contents around the globe. Many
+countries have at least one CPAN site already. The resources found on
+CPAN are easily accessible with the CPAN.pm module. If you want to use
+CPAN.pm, lots of things have to be configured. Fortunately, most of
+them can be determined automatically. If you prefer the automatic
+configuration, answer 'yes' below.
+
+If you prefer to enter a dialog instead, you can answer 'no' to this
+question and I'll let you configure in small steps one thing after the
+other. (Note: you can revisit this dialog anytime later by typing 'o
+conf init' at the cpan prompt.)
+
+],
+
+auto_pick => qq{
+Would you like me to automatically choose the best CPAN mirror
+sites for you? (This means connecting to the Internet and could
+take a couple minutes)},
+
+config_intro => qq{
+
+The following questions are intended to help you with the
+configuration. The CPAN module needs a directory of its own to cache
+important index files and maybe keep a temporary mirror of CPAN files.
+This may be a site-wide or a personal directory.
+
+},
+
+# cpan_home => qq{ },
+
+cpan_home_where => qq{
+
+First of all, I'd like to create this directory. Where?
+
+},
+
+external_progs => qq{
+
+The CPAN module will need a few external programs to work properly.
+Please correct me, if I guess the wrong path for a program. Don't
+panic if you do not have some of them, just press ENTER for those. To
+disable the use of a program, you can type a space followed by ENTER.
+
+},
+
+proxy_intro => qq{
+
+If you're accessing the net via proxies, you can specify them in the
+CPAN configuration or via environment variables. The variable in
+the \$CPAN::Config takes precedence.
+
+},
+
+proxy_user => qq{
+
+If your proxy is an authenticating proxy, you can store your username
+permanently. If you do not want that, just press RETURN. You will then
+be asked for your username in every future session.
+
+},
+
+proxy_pass => qq{
+
+Your password for the authenticating proxy can also be stored
+permanently on disk. If this violates your security policy, just press
+RETURN. You will then be asked for the password in every future
+session.
+
+},
+
+urls_intro => qq{
+Now you need to choose your CPAN mirror sites. You can let me
+pick mirrors for you, you can select them from a list or you
+can enter them by hand.
+},
+
+urls_picker_intro => qq{First, pick a nearby continent and country by typing in the number(s)
+in front of the item(s) you want to select. You can pick several of
+each, separated by spaces. Then, you will be presented with a list of
+URLs of CPAN mirrors in the countries you selected, along with
+previously selected URLs. Select some of those URLs, or just keep the
+old list. Finally, you will be prompted for any extra URLs -- file:,
+ftp:, or http: -- that host a CPAN mirror.
+
+You should select more than one (just in case the first isn't available).
+
+},
+
+password_warn => qq{
+
+Warning: Term::ReadKey seems not to be available, your password will
+be echoed to the terminal!
+
+},
+
+ );
+
+ die "Coding error in \@prompts declaration. Odd number of elements, above"
+ if (@prompts % 2);
+
+ %prompts = @prompts;
+
+ if (scalar(keys %prompts) != scalar(@prompts)/2) {
+ my %already;
+ for my $item (0..$#prompts) {
+ next if $item % 2;
+ die "$prompts[$item] is duplicated\n" if $already{$prompts[$item]}++;
+ }
+ }
+
+ shift @podpara;
+ while (@podpara) {
+ warn "Alert: cannot parse my own manpage for init dialog" unless $podpara[0] =~ s/^=item\s+//;
+ my $name = shift @podpara;
+ my @para;
+ while (@podpara && $podpara[0] !~ /^=item/) {
+ push @para, shift @podpara;
+ }
+ $prompts{$name} = pop @para;
+ if (@para) {
+ $prompts{$name . "_intro"} = join "", map { "$_\n\n" } @para;
+ }
+ }
+
+}
+
+sub init {
+ my($configpm, %args) = @_;
+ use Config;
+ # extra args after 'o conf init'
+ my $matcher = $args{args} && @{$args{args}} ? $args{args}[0] : '';
+ if ($matcher =~ /^\/(.*)\/$/) {
+ # case /regex/ => take the first, ignore the rest
+ $matcher = $1;
+ shift @{$args{args}};
+ if (@{$args{args}}) {
+ local $" = " ";
+ $CPAN::Frontend->mywarn("Ignoring excessive arguments '@{$args{args}}'");
+ $CPAN::Frontend->mysleep(2);
+ }
+ } elsif (0 == length $matcher) {
+ } elsif (0 && $matcher eq "~") { # extremely buggy, but a nice idea
+ my @unconfigured = grep { not exists $CPAN::Config->{$_}
+ or not defined $CPAN::Config->{$_}
+ or not length $CPAN::Config->{$_}
+ } keys %$CPAN::Config;
+ $matcher = "\\b(".join("|", @unconfigured).")\\b";
+ $CPAN::Frontend->mywarn("matcher[$matcher]");
+ } else {
+ # case WORD... => all arguments must be valid
+ for my $arg (@{$args{args}}) {
+ unless (exists $CPAN::HandleConfig::keys{$arg}) {
+ $CPAN::Frontend->mywarn("'$arg' is not a valid configuration variable\n");
+ return;
+ }
+ }
+ $matcher = "\\b(".join("|",@{$args{args}}).")\\b";
+ }
+ CPAN->debug("matcher[$matcher]") if $CPAN::DEBUG;
+
+ unless ($CPAN::VERSION) {
+ require CPAN::Nox;
+ }
+ require CPAN::HandleConfig;
+ CPAN::HandleConfig::require_myconfig_or_config();
+ $CPAN::Config ||= {};
+ local($/) = "\n";
+ local($\) = "";
+ local($|) = 1;
+
+ my($ans,$default); # why so half global?
+
+ #
+ #= Files, directories
+ #
+
+ unless ($matcher) {
+ $CPAN::Frontend->myprint($prompts{manual_config});
+ }
+
+ my $manual_conf;
+
+ local *_real_prompt;
+ if ( $args{autoconfig} ) {
+ $manual_conf = "no";
+ } elsif ($matcher) {
+ $manual_conf = "yes";
+ } else {
+ my $_conf = prompt("Would you like me to configure as much as possible ".
+ "automatically?", "yes");
+ $manual_conf = ($_conf and $_conf =~ /^y/i) ? "no" : "yes";
+ }
+ CPAN->debug("manual_conf[$manual_conf]") if $CPAN::DEBUG;
+ my $fastread;
+ {
+ if ($manual_conf =~ /^y/i) {
+ $fastread = 0;
+ } else {
+ $fastread = 1;
+ $silent = 1;
+ $CPAN::Config->{urllist} ||= [];
+ $CPAN::Config->{connect_to_internet_ok} ||= 1;
+
+ local $^W = 0;
+ # prototype should match that of &MakeMaker::prompt
+ my $current_second = time;
+ my $current_second_count = 0;
+ my $i_am_mad = 0;
+ # silent prompting -- just quietly use default
+ *_real_prompt = sub { return $_[1] };
+ }
+ }
+
+ if (!$matcher or q{
+ build_dir
+ build_dir_reuse
+ cpan_home
+ keep_source_where
+ prefs_dir
+ } =~ /$matcher/) {
+ $CPAN::Frontend->myprint($prompts{config_intro}) unless $silent;
+
+ init_cpan_home($matcher);
+
+ my_dflt_prompt("keep_source_where",
+ File::Spec->catdir($CPAN::Config->{cpan_home},"sources"),
+ $matcher,
+ );
+ my_dflt_prompt("build_dir",
+ File::Spec->catdir($CPAN::Config->{cpan_home},"build"),
+ $matcher
+ );
+ my_yn_prompt(build_dir_reuse => 0, $matcher);
+ my_dflt_prompt("prefs_dir",
+ File::Spec->catdir($CPAN::Config->{cpan_home},"prefs"),
+ $matcher
+ );
+ }
+
+ #
+ #= Config: auto_commit
+ #
+
+ my_yn_prompt(auto_commit => 0, $matcher);
+
+ #
+ #= Cache size, Index expire
+ #
+ my_dflt_prompt(build_cache => 100, $matcher);
+
+ my_dflt_prompt(index_expire => 1, $matcher);
+ my_prompt_loop(scan_cache => 'atstart', $matcher, 'atstart|never');
+
+ #
+ #= cache_metadata
+ #
+
+ my_yn_prompt(cache_metadata => 1, $matcher);
+ my_yn_prompt(use_sqlite => 0, $matcher);
+
+ #
+ #= Do we follow PREREQ_PM?
+ #
+
+ my_prompt_loop(prerequisites_policy => 'follow', $matcher,
+ 'follow|ask|ignore');
+ my_prompt_loop(build_requires_install_policy => 'yes', $matcher,
+ 'yes|no|ask/yes|ask/no');
+
+ #
+ #= Module::Signature
+ #
+ my_yn_prompt(check_sigs => 0, $matcher);
+
+ #
+ #= CPAN::Reporter
+ #
+ if (!$matcher or 'test_report' =~ /$matcher/) {
+ my_yn_prompt(test_report => 0, $matcher);
+ if (
+ $CPAN::Config->{test_report} &&
+ $CPAN::META->has_inst("CPAN::Reporter") &&
+ CPAN::Reporter->can('configure')
+ ) {
+ local *_real_prompt;
+ *_real_prompt = \&CPAN::Shell::colorable_makemaker_prompt;
+ my $_conf = prompt("Would you like me configure CPAN::Reporter now?", $silent ? "no" : "yes");
+ if ($_conf =~ /^y/i) {
+ $CPAN::Frontend->myprint("\nProceeding to configure CPAN::Reporter.\n");
+ CPAN::Reporter::configure();
+ $CPAN::Frontend->myprint("\nReturning to CPAN configuration.\n");
+ }
+ }
+ }
+
+ my_yn_prompt(trust_test_report_history => 0, $matcher);
+
+ #
+ #= YAML vs. YAML::Syck
+ #
+ if (!$matcher or "yaml_module" =~ /$matcher/) {
+ my_dflt_prompt(yaml_module => "YAML", $matcher);
+ my $old_v = $CPAN::Config->{load_module_verbosity};
+ $CPAN::Config->{load_module_verbosity} = q[none];
+ if (!$silent && !$CPAN::META->has_inst($CPAN::Config->{yaml_module})) {
+ $CPAN::Frontend->mywarn
+ ("Warning (maybe harmless): '$CPAN::Config->{yaml_module}' not installed.\n");
+ $CPAN::Frontend->mysleep(3);
+ }
+ $CPAN::Config->{load_module_verbosity} = $old_v;
+ }
+
+ #
+ #= YAML code deserialisation
+ #
+ my_yn_prompt(yaml_load_code => 0, $matcher);
+
+ #
+ #= External programs
+ #
+ my(@path) = split /$Config{'path_sep'}/, $ENV{'PATH'};
+ _init_external_progs($matcher,\@path);
+
+ {
+ my $path = $CPAN::Config->{'pager'} ||
+ $ENV{PAGER} || find_exe("less",\@path) ||
+ find_exe("more",\@path) || ($^O eq 'MacOS' ? $ENV{EDITOR} : 0 )
+ || "more";
+ my_dflt_prompt(pager => $path, $matcher);
+ }
+
+ {
+ my $path = $CPAN::Config->{'shell'};
+ if ($path && File::Spec->file_name_is_absolute($path)) {
+ $CPAN::Frontend->mywarn("Warning: configured $path does not exist\n")
+ unless -e $path;
+ $path = "";
+ }
+ $path ||= $ENV{SHELL};
+ $path ||= $ENV{COMSPEC} if $^O eq "MSWin32";
+ if ($^O eq 'MacOS') {
+ $CPAN::Config->{'shell'} = 'not_here';
+ } else {
+ $path ||= 'sh', $path =~ s,\\,/,g if $^O eq 'os2'; # Cosmetic only
+ my_dflt_prompt(shell => $path, $matcher);
+ }
+ }
+
+ #
+ # verbosity
+ #
+
+ my_prompt_loop(tar_verbosity => 'none', $matcher,
+ 'none|v|vv');
+ my_prompt_loop(load_module_verbosity => 'none', $matcher,
+ 'none|v');
+ my_prompt_loop(perl5lib_verbosity => 'none', $matcher,
+ 'none|v');
+ my_yn_prompt(inhibit_startup_message => 0, $matcher);
+
+ #
+ #= Installer, arguments to make etc.
+ #
+
+ my_prompt_loop(prefer_installer => 'MB', $matcher, 'MB|EUMM|RAND');
+
+ if (!$matcher or 'makepl_arg make_arg' =~ /$matcher/) {
+ my_dflt_prompt(makepl_arg => "", $matcher);
+ my_dflt_prompt(make_arg => "", $matcher);
+ if ( $CPAN::Config->{makepl_arg} =~ /LIBS=|INC=/ ) {
+ $CPAN::Frontend->mywarn(
+ "Warning: Using LIBS or INC in makepl_arg will likely break distributions\n" .
+ "that specify their own LIBS or INC options in Makefile.PL.\n"
+ );
+ }
+
+ }
+
+ require CPAN::HandleConfig;
+ if (exists $CPAN::HandleConfig::keys{make_install_make_command}) {
+ # as long as Windows needs $self->_build_command, we cannot
+ # support sudo on windows :-)
+ my_dflt_prompt(make_install_make_command => $CPAN::Config->{make} || "",
+ $matcher);
+ }
+
+ my_dflt_prompt(make_install_arg => $CPAN::Config->{make_arg} || "",
+ $matcher);
+
+ my_dflt_prompt(mbuildpl_arg => "", $matcher);
+ my_dflt_prompt(mbuild_arg => "", $matcher);
+
+ if (exists $CPAN::HandleConfig::keys{mbuild_install_build_command}
+ and $^O ne "MSWin32") {
+ # as long as Windows needs $self->_build_command, we cannot
+ # support sudo on windows :-)
+ my_dflt_prompt(mbuild_install_build_command => "./Build", $matcher);
+ }
+
+ my_dflt_prompt(mbuild_install_arg => "", $matcher);
+
+ #
+ #= Alarm period
+ #
+
+ my_dflt_prompt(inactivity_timeout => 0, $matcher);
+ my_dflt_prompt(version_timeout => 15, $matcher);
+
+ #
+ #== halt_on_failure
+ #
+ my_yn_prompt(halt_on_failure => 0, $matcher);
+
+ #
+ #= Proxies
+ #
+
+ my @proxy_vars = qw/ftp_proxy http_proxy no_proxy/;
+ my @proxy_user_vars = qw/proxy_user proxy_pass/;
+ if (!$matcher or "@proxy_vars @proxy_user_vars" =~ /$matcher/) {
+ $CPAN::Frontend->myprint($prompts{proxy_intro}) unless $silent;
+
+ for (@proxy_vars) {
+ $prompts{$_} = "Your $_?";
+ my_dflt_prompt($_ => $ENV{$_}||"", $matcher);
+ }
+
+ if ($CPAN::Config->{ftp_proxy} ||
+ $CPAN::Config->{http_proxy}) {
+
+ $default = $CPAN::Config->{proxy_user} || $CPAN::LWP::UserAgent::USER || "";
+
+ $CPAN::Frontend->myprint($prompts{proxy_user}) unless $silent;
+
+ if ($CPAN::Config->{proxy_user} = prompt("Your proxy user id?",$default)) {
+ $CPAN::Frontend->myprint($prompts{proxy_pass}) unless $silent;
+
+ if ($CPAN::META->has_inst("Term::ReadKey")) {
+ Term::ReadKey::ReadMode("noecho");
+ } else {
+ $CPAN::Frontend->myprint($prompts{password_warn}) unless $silent;
+ }
+ $CPAN::Config->{proxy_pass} = prompt_no_strip("Your proxy password?");
+ if ($CPAN::META->has_inst("Term::ReadKey")) {
+ Term::ReadKey::ReadMode("restore");
+ }
+ $CPAN::Frontend->myprint("\n\n") unless $silent;
+ }
+ }
+ }
+
+ #
+ #= how FTP works
+ #
+
+ my_yn_prompt(ftp_passive => 1, $matcher);
+
+ #
+ #= how cwd works
+ #
+
+ my_prompt_loop(getcwd => 'cwd', $matcher,
+ 'cwd|getcwd|fastcwd|backtickcwd');
+
+ #
+ #= the CPAN shell itself (prompt, color)
+ #
+
+ my_yn_prompt(commandnumber_in_prompt => 1, $matcher);
+ my_yn_prompt(term_ornaments => 1, $matcher);
+ if ("colorize_output colorize_print colorize_warn colorize_debug" =~ $matcher) {
+ my_yn_prompt(colorize_output => 0, $matcher);
+ if ($CPAN::Config->{colorize_output}) {
+ if ($CPAN::META->has_inst("Term::ANSIColor")) {
+ my $T="gYw";
+ $CPAN::Frontend->myprint( " on_ on_y ".
+ " on_ma on_\n") unless $silent;
+ $CPAN::Frontend->myprint( " on_black on_red green ellow ".
+ "on_blue genta on_cyan white\n") unless $silent;
+
+ for my $FG ("", "bold",
+ map {$_,"bold $_"} "black","red","green",
+ "yellow","blue",
+ "magenta",
+ "cyan","white") {
+ $CPAN::Frontend->myprint(sprintf( "%12s ", $FG)) unless $silent;
+ for my $BG ("",map {"on_$_"} qw(black red green yellow
+ blue magenta cyan white)) {
+ $CPAN::Frontend->myprint( $FG||$BG ?
+ Term::ANSIColor::colored(" $T ","$FG $BG") : " $T ") unless $silent;
+ }
+ $CPAN::Frontend->myprint( "\n" ) unless $silent;
+ }
+ $CPAN::Frontend->myprint( "\n" ) unless $silent;
+ }
+ for my $tuple (
+ ["colorize_print", "bold blue on_white"],
+ ["colorize_warn", "bold red on_white"],
+ ["colorize_debug", "black on_cyan"],
+ ) {
+ my_dflt_prompt($tuple->[0] => $tuple->[1], $matcher);
+ if ($CPAN::META->has_inst("Term::ANSIColor")) {
+ eval { Term::ANSIColor::color($CPAN::Config->{$tuple->[0]})};
+ if ($@) {
+ $CPAN::Config->{$tuple->[0]} = $tuple->[1];
+ $CPAN::Frontend->mywarn($@."setting to default '$tuple->[1]'\n");
+ }
+ }
+ }
+ }
+ }
+
+ #
+ #== term_is_latin
+ #
+
+ my_yn_prompt(term_is_latin => 1, $matcher);
+
+ #
+ #== save history in file 'histfile'
+ #
+
+ if (!$matcher or 'histfile histsize' =~ /$matcher/) {
+ $CPAN::Frontend->myprint($prompts{histfile_intro}) unless $silent;
+ defined($default = $CPAN::Config->{histfile}) or
+ $default = File::Spec->catfile($CPAN::Config->{cpan_home},"histfile");
+ my_dflt_prompt(histfile => $default, $matcher);
+
+ if ($CPAN::Config->{histfile}) {
+ defined($default = $CPAN::Config->{histsize}) or $default = 100;
+ my_dflt_prompt(histsize => $default, $matcher);
+ }
+ }
+
+ #
+ #== do an ls on the m or the d command
+ #
+ my_yn_prompt(show_upload_date => 0, $matcher);
+
+ #
+ #== verbosity at the end of the r command
+ #
+ if (!$matcher
+ or 'show_unparsable_versions' =~ /$matcher/
+ or 'show_zero_versions' =~ /$matcher/
+ ) {
+ $CPAN::Frontend->myprint($prompts{show_unparsable_or_zero_versions_intro});
+ my_yn_prompt(show_unparsable_versions => 0, $matcher);
+ my_yn_prompt(show_zero_versions => 0, $matcher);
+ }
+
+ #
+ #= MIRRORED.BY and conf_sites()
+ #
+
+ # remember, this is only triggered if no urllist is given, so 0 is
+ # fair and protects the default site from being overloaded and
+ # gives the user more chances to select his own urllist.
+ my_yn_prompt("connect_to_internet_ok" => $fastread ? 1 : 0, $matcher);
+ $CPAN::Config->{urllist} ||= [];
+ if ($matcher) {
+ if ("urllist" =~ $matcher) {
+ $CPAN::Frontend->myprint($prompts{urls_intro});
+
+ # conf_sites would go into endless loop with the smash prompt
+ local *_real_prompt;
+ *_real_prompt = \&CPAN::Shell::colorable_makemaker_prompt;
+ my $_conf = prompt($prompts{auto_pick}, "yes");
+
+ if ( $_conf =~ /^y/i ) {
+ conf_sites( auto_pick => 1 ) or bring_your_own();
+ }
+ else {
+ my $_conf = prompt(
+ "Would you like to pick from the CPAN mirror list?", "yes"
+ );
+
+ if ( $_conf =~ /^y/i ) {
+ conf_sites();
+ }
+ bring_your_own();
+ }
+ _print_urllist();
+ }
+ if ("randomize_urllist" =~ $matcher) {
+ my_dflt_prompt(randomize_urllist => 0, $matcher);
+ }
+ if ("ftpstats_size" =~ $matcher) {
+ my_dflt_prompt(ftpstats_size => 99, $matcher);
+ }
+ if ("ftpstats_period" =~ $matcher) {
+ my_dflt_prompt(ftpstats_period => 14, $matcher);
+ }
+ } elsif ($fastread) {
+ $silent = 0;
+ local *_real_prompt;
+ *_real_prompt = \&CPAN::Shell::colorable_makemaker_prompt;
+ if ( @{ $CPAN::Config->{urllist} } ) {
+ $CPAN::Frontend->myprint(
+ "\nYour 'urllist' is already configured. Type 'o conf init urllist' to change it.\n"
+ );
+ }
+ else {
+ $CPAN::Frontend->myprint(
+ "Autoconfigured everything but 'urllist'.\n"
+ );
+
+ $CPAN::Frontend->myprint($prompts{urls_intro});
+
+ my $_conf = prompt($prompts{auto_pick}, "yes");
+
+ if ( $_conf =~ /^y/i ) {
+ conf_sites( auto_pick => 1 ) or bring_your_own();
+ }
+ else {
+ my $_conf = prompt(
+ "Would you like to pick from the CPAN mirror list?", "yes"
+ );
+
+ if ( $_conf =~ /^y/i ) {
+ conf_sites();
+ }
+ bring_your_own();
+ }
+ _print_urllist();
+ }
+ $CPAN::Frontend->myprint(
+ "\nAutoconfiguration complete.\n"
+ );
+ }
+
+ $silent = 0; # reset
+
+ $CPAN::Frontend->myprint("\n");
+ if ($matcher && !$CPAN::Config->{auto_commit}) {
+ $CPAN::Frontend->myprint("Please remember to call 'o conf commit' to ".
+ "make the config permanent!\n");
+ } else {
+ CPAN::HandleConfig->commit($configpm);
+ }
+}
+
+sub _init_external_progs {
+ my($matcher,$PATH) = @_;
+ my @external_progs = qw/bzip2 gzip tar unzip
+
+ make
+
+ curl lynx wget ncftpget ncftp ftp
+
+ gpg
+
+ patch applypatch
+ /;
+ if (!$matcher or "@external_progs" =~ /$matcher/) {
+ $CPAN::Frontend->myprint($prompts{external_progs}) unless $silent;
+
+ my $old_warn = $^W;
+ local $^W if $^O eq 'MacOS';
+ local $^W = $old_warn;
+ my $progname;
+ for $progname (@external_progs) {
+ next if $matcher && $progname !~ /$matcher/;
+ if ($^O eq 'MacOS') {
+ $CPAN::Config->{$progname} = 'not_here';
+ next;
+ }
+
+ my $progcall = $progname;
+ unless ($matcher) {
+ # we really don't need ncftp if we have ncftpget, but
+ # if they chose this dialog via matcher, they shall have it
+ next if $progname eq "ncftp" && $CPAN::Config->{ncftpget} gt " ";
+ }
+ my $path = $CPAN::Config->{$progname}
+ || $Config::Config{$progname}
+ || "";
+ if (File::Spec->file_name_is_absolute($path)) {
+ # testing existence is not good enough, some have these exe
+ # extensions
+
+ # warn "Warning: configured $path does not exist\n" unless -e $path;
+ # $path = "";
+ } elsif ($path =~ /^\s+$/) {
+ # preserve disabled programs
+ } else {
+ $path = '';
+ }
+ unless ($path) {
+ # e.g. make -> nmake
+ $progcall = $Config::Config{$progname} if $Config::Config{$progname};
+ }
+
+ $path ||= find_exe($progcall,$PATH);
+ unless ($path) { # not -e $path, because find_exe already checked that
+ local $"=";";
+ $CPAN::Frontend->mywarn("Warning: $progcall not found in PATH[@$PATH]\n") unless $silent;
+ if ($progname eq "make") {
+ $CPAN::Frontend->mywarn("ALERT: 'make' is an essential tool for ".
+ "building perl Modules. Please make sure you ".
+ "have 'make' (or some equivalent) ".
+ "working.\n"
+ );
+ if ($^O eq "MSWin32") {
+ $CPAN::Frontend->mywarn("
+Windows users may want to follow this procedure when back in the CPAN shell:
+
+ look YVES/scripts/alien_nmake.pl
+ perl alien_nmake.pl
+
+This will install nmake on your system which can be used as a 'make'
+substitute. You can then revisit this dialog with
+
+ o conf init make
+
+");
+ }
+ }
+ }
+ $prompts{$progname} = "Where is your $progname program?";
+ my_dflt_prompt($progname,$path,$matcher);
+ }
+ }
+}
+
+sub init_cpan_home {
+ my($matcher) = @_;
+ if (!$matcher or 'cpan_home' =~ /$matcher/) {
+ my $cpan_home = $CPAN::Config->{cpan_home}
+ || File::Spec->catdir(CPAN::HandleConfig::home(), ".cpan");
+
+ if (-d $cpan_home) {
+ $CPAN::Frontend->myprint(qq{
+
+I see you already have a directory
+ $cpan_home
+Shall we use it as the general CPAN build and cache directory?
+
+}) unless $silent;
+ } else {
+ # no cpan-home, must prompt and get one
+ $CPAN::Frontend->myprint($prompts{cpan_home_where}) unless $silent;
+ }
+
+ my $default = $cpan_home;
+ my $loop = 0;
+ my($last_ans,$ans);
+ $CPAN::Frontend->myprint(" <cpan_home>\n") unless $silent;
+ PROMPT: while ($ans = prompt("CPAN build and cache directory?",$default)) {
+ if (File::Spec->file_name_is_absolute($ans)) {
+ my @cpan_home = split /[\/\\]/, $ans;
+ DIR: for my $dir (@cpan_home) {
+ if ($dir =~ /^~/ and (!$last_ans or $ans ne $last_ans)) {
+ $CPAN::Frontend
+ ->mywarn("Warning: a tilde in the path will be ".
+ "taken as a literal tilde. Please ".
+ "confirm again if you want to keep it\n");
+ $last_ans = $default = $ans;
+ next PROMPT;
+ }
+ }
+ } else {
+ require Cwd;
+ my $cwd = Cwd::cwd();
+ my $absans = File::Spec->catdir($cwd,$ans);
+ $CPAN::Frontend->mywarn("The path '$ans' is not an ".
+ "absolute path. Please specify ".
+ "an absolute path\n");
+ $default = $absans;
+ next PROMPT;
+ }
+ eval { File::Path::mkpath($ans); }; # dies if it can't
+ if ($@) {
+ $CPAN::Frontend->mywarn("Couldn't create directory $ans.\n".
+ "Please retry.\n");
+ next PROMPT;
+ }
+ if (-d $ans && -w _) {
+ last PROMPT;
+ } else {
+ $CPAN::Frontend->mywarn("Couldn't find directory $ans\n".
+ "or directory is not writable. Please retry.\n");
+ if (++$loop > 5) {
+ $CPAN::Frontend->mydie("Giving up");
+ }
+ }
+ }
+ $CPAN::Config->{cpan_home} = $ans;
+ }
+}
+
+sub my_dflt_prompt {
+ my ($item, $dflt, $m) = @_;
+ my $default = $CPAN::Config->{$item} || $dflt;
+
+ if (!$silent && (!$m || $item =~ /$m/)) {
+ if (my $intro = $prompts{$item . "_intro"}) {
+ $CPAN::Frontend->myprint($intro);
+ }
+ $CPAN::Frontend->myprint(" <$item>\n");
+ $CPAN::Config->{$item} = prompt($prompts{$item}, $default);
+ } else {
+ $CPAN::Config->{$item} = $default;
+ }
+}
+
+sub my_yn_prompt {
+ my ($item, $dflt, $m) = @_;
+ my $default;
+ defined($default = $CPAN::Config->{$item}) or $default = $dflt;
+
+ # $DB::single = 1;
+ if (!$silent && (!$m || $item =~ /$m/)) {
+ if (my $intro = $prompts{$item . "_intro"}) {
+ $CPAN::Frontend->myprint($intro);
+ }
+ $CPAN::Frontend->myprint(" <$item>\n");
+ my $ans = prompt($prompts{$item}, $default ? 'yes' : 'no');
+ $CPAN::Config->{$item} = ($ans =~ /^[y1]/i ? 1 : 0);
+ } else {
+ $CPAN::Config->{$item} = $default;
+ }
+}
+
+sub my_prompt_loop {
+ my ($item, $dflt, $m, $ok) = @_;
+ my $default = $CPAN::Config->{$item} || $dflt;
+ my $ans;
+
+ if (!$silent && (!$m || $item =~ /$m/)) {
+ $CPAN::Frontend->myprint($prompts{$item . "_intro"});
+ $CPAN::Frontend->myprint(" <$item>\n");
+ do { $ans = prompt($prompts{$item}, $default);
+ } until $ans =~ /$ok/;
+ $CPAN::Config->{$item} = $ans;
+ } else {
+ $CPAN::Config->{$item} = $default;
+ }
+}
+
+
+# Here's the logic about the MIRRORED.BY file. There are a number of scenarios:
+# (1) We have a cached MIRRORED.BY file
+# (1a) We're auto-picking
+# - Refresh it automatically if it's old
+# (1b) Otherwise, ask if using cached is ok. If old, default to no.
+# - If cached is not ok, get it from the Internet. If it succeeds we use
+# the new file. Otherwise, we use the old file.
+# (2) We don't have a copy at all
+# (2a) If we are allowed to connect, we try to get a new copy. If it succeeds,
+# we use it, otherwise, we warn about failure
+# (2b) If we aren't allowed to connect,
+
+sub conf_sites {
+ my %args = @_;
+ # auto pick implies using the internet
+ $CPAN::Config->{connect_to_internet_ok} = 1 if $args{auto_pick};
+
+ my $m = 'MIRRORED.BY';
+ my $mby = File::Spec->catfile($CPAN::Config->{keep_source_where},$m);
+ File::Path::mkpath(File::Basename::dirname($mby));
+ # Why are we using MIRRORED.BY from the current directory?
+ # Is this for testing? -- dagolden, 2009-11-05
+ if (-f $mby && -f $m && -M $m < -M $mby) {
+ require File::Copy;
+ File::Copy::copy($m,$mby) or die "Could not update $mby: $!";
+ }
+ local $^T = time;
+ # if we have a cached copy is not older than 60 days, we either
+ # use it or refresh it or fall back to it if the refresh failed.
+ if ($mby && -f $mby && -s _ > 0 ) {
+ my $very_old = (-M $mby > 60);
+ my $mtime = localtime((stat _)[9]);
+ # if auto_pick, refresh anything old automatically
+ if ( $args{auto_pick} ) {
+ if ( $very_old ) {
+ $CPAN::Frontend->myprint(qq{Trying to refresh your mirror list\n});
+ eval { CPAN::FTP->localize($m,$mby,3,1) }
+ or $CPAN::Frontend->myprint(qq{Refresh failed. Using the old cached copy instead.\n});
+ $CPAN::Frontend->myprint("\n");
+ }
+ }
+ else {
+ my $prompt = qq{Found a cached mirror list as of $mtime
+
+If you'd like to just use the cached copy, answer 'yes', below.
+If you'd like an updated copy of the mirror list, answer 'no' and
+I'll get a fresh one from the Internet.
+
+Shall I use the cached mirror list?};
+ my $ans = prompt($prompt, $very_old ? "no" : "yes");
+ if ($ans =~ /^n/i) {
+ $CPAN::Frontend->myprint(qq{Trying to refresh your mirror list\n});
+ # you asked for it from the Internet
+ $CPAN::Config->{connect_to_internet_ok} = 1;
+ eval { CPAN::FTP->localize($m,$mby,3,1) }
+ or $CPAN::Frontend->myprint(qq{Refresh failed. Using the old cached copy instead.\n});
+ $CPAN::Frontend->myprint("\n");
+ }
+ }
+ }
+ # else there is no cached copy and we must fetch or fail
+ else {
+ # If they haven't agree to connect to the internet, ask again
+ if ( ! $CPAN::Config->{connect_to_internet_ok} ) {
+ my $prompt = q{You are missing a copy of the CPAN mirror list.
+
+May I connect to the Internet to get it?};
+ my $ans = prompt($prompt, "yes");
+ if ($ans =~ /^y/i) {
+ $CPAN::Config->{connect_to_internet_ok} = 1;
+ }
+ }
+
+ # Now get it from the Internet or complain
+ if ( $CPAN::Config->{connect_to_internet_ok} ) {
+ $CPAN::Frontend->myprint(qq{Trying to fetch a mirror list from the Internet\n});
+ eval { CPAN::FTP->localize($m,$mby,3,1) }
+ or $CPAN::Frontend->mywarn(<<'HERE');
+We failed to get a copy of the mirror list from the Internet.
+You will need to provide CPAN mirror URLs yourself.
+HERE
+ $CPAN::Frontend->myprint("\n");
+ }
+ else {
+ $CPAN::Frontend->mywarn(<<'HERE');
+You will need to provide CPAN mirror URLs yourself or set
+'o conf connect_to_internet_ok 1' and try again.
+HERE
+ }
+ }
+
+ # if we finally have a good local MIRRORED.BY, get on with picking
+ if (-f $mby && -s _ > 0){
+ $CPAN::Config->{urllist} =
+ $args{auto_pick} ? auto_mirrored_by($mby) : choose_mirrored_by($mby);
+ return 1;
+ }
+
+ return;
+}
+
+sub find_exe {
+ my($exe,$path) = @_;
+ my($dir);
+ #warn "in find_exe exe[$exe] path[@$path]";
+ for $dir (@$path) {
+ my $abs = File::Spec->catfile($dir,$exe);
+ if (($abs = MM->maybe_command($abs))) {
+ return $abs;
+ }
+ }
+}
+
+sub picklist {
+ my($items,$prompt,$default,$require_nonempty,$empty_warning)=@_;
+ CPAN->debug("picklist('$items','$prompt','$default','$require_nonempty',".
+ "'$empty_warning')") if $CPAN::DEBUG;
+ $default ||= '';
+
+ my $pos = 0;
+
+ my @nums;
+ SELECTION: while (1) {
+
+ # display, at most, 15 items at a time
+ my $limit = $#{ $items } - $pos;
+ $limit = 15 if $limit > 15;
+
+ # show the next $limit items, get the new position
+ $pos = display_some($items, $limit, $pos, $default);
+ $pos = 0 if $pos >= @$items;
+
+ my $num = prompt($prompt,$default);
+
+ @nums = split (' ', $num);
+ {
+ my %seen;
+ @nums = grep { !$seen{$_}++ } @nums;
+ }
+ my $i = scalar @$items;
+ unrangify(\@nums);
+ if (0 == @nums) {
+ # cannot allow nothing because nothing means paging!
+ # return;
+ } elsif (grep (/\D/ || $_ < 1 || $_ > $i, @nums)) {
+ $CPAN::Frontend->mywarn("invalid items entered, try again\n");
+ if ("@nums" =~ /\D/) {
+ $CPAN::Frontend->mywarn("(we are expecting only numbers between 1 and $i)\n");
+ }
+ next SELECTION;
+ }
+ if ($require_nonempty && !@nums) {
+ $CPAN::Frontend->mywarn("$empty_warning\n");
+ }
+
+ # a blank line continues...
+ unless (@nums){
+ $CPAN::Frontend->mysleep(0.1); # prevent hot spinning process on the next bug
+ next SELECTION;
+ }
+ last;
+ }
+ for (@nums) { $_-- }
+ @{$items}[@nums];
+}
+
+sub unrangify ($) {
+ my($nums) = $_[0];
+ my @nums2 = ();
+ while (@{$nums||[]}) {
+ my $n = shift @$nums;
+ if ($n =~ /^(\d+)-(\d+)$/) {
+ my @range = $1 .. $2;
+ # warn "range[@range]";
+ push @nums2, @range;
+ } else {
+ push @nums2, $n;
+ }
+ }
+ push @$nums, @nums2;
+}
+
+sub display_some {
+ my ($items, $limit, $pos, $default) = @_;
+ $pos ||= 0;
+
+ my @displayable = @$items[$pos .. ($pos + $limit)];
+ for my $item (@displayable) {
+ $CPAN::Frontend->myprint(sprintf "(%d) %s\n", ++$pos, $item);
+ }
+ my $hit_what = $default ? "SPACE RETURN" : "RETURN";
+ $CPAN::Frontend->myprint(sprintf("%d more items, hit %s to show them\n",
+ (@$items - $pos),
+ $hit_what,
+ ))
+ if $pos < @$items;
+ return $pos;
+}
+
+sub auto_mirrored_by {
+ my $local = shift or return;
+ local $|=1;
+ $CPAN::Frontend->myprint("Searching for the best CPAN mirrors (please be patient) ...");
+ my $mirrors = CPAN::Mirrors->new($local);
+ my $cnt = 0;
+ my @best = $mirrors->best_mirrors(
+ how_many => 5,
+ callback => sub { $CPAN::Frontend->myprint(".") },
+ );
+ my $urllist = [ map { $_->ftp } @best ];
+ push @$urllist, grep { /^file:/ } @{$CPAN::Config->{urllist}};
+ $CPAN::Frontend->myprint(" done!\n\n");
+ return $urllist;
+}
+
+sub choose_mirrored_by {
+ my $local = shift or return;
+ my ($default);
+ my $mirrors = CPAN::Mirrors->new($local);
+ my @previous_urls = @{$CPAN::Config->{urllist}};
+
+ $CPAN::Frontend->myprint($prompts{urls_picker_intro});
+
+ my (@cont, $cont, %cont, @countries, @urls, %seen);
+ my $no_previous_warn =
+ "Sorry! since you don't have any existing picks, you must make a\n" .
+ "geographic selection.";
+ my $offer_cont = [sort $mirrors->continents];
+ if (@previous_urls) {
+ push @$offer_cont, "(edit previous picks)";
+ $default = @$offer_cont;
+ } else {
+ # cannot allow nothing because nothing means paging!
+ # push @$offer_cont, "(none of the above)";
+ }
+ @cont = picklist($offer_cont,
+ "Select your continent (or several nearby continents)",
+ $default,
+ ! @previous_urls,
+ $no_previous_warn);
+ # cannot allow nothing because nothing means paging!
+ # return unless @cont;
+
+ foreach $cont (@cont) {
+ my @c = sort $mirrors->countries($cont);
+ @cont{@c} = map ($cont, 0..$#c);
+ @c = map ("$_ ($cont)", @c) if @cont > 1;
+ push (@countries, @c);
+ }
+ if (@previous_urls && @countries) {
+ push @countries, "(edit previous picks)";
+ $default = @countries;
+ }
+
+ if (@countries) {
+ @countries = picklist (\@countries,
+ "Select your country (or several nearby countries)",
+ $default,
+ ! @previous_urls,
+ $no_previous_warn);
+ %seen = map (($_ => 1), @previous_urls);
+ # hmmm, should take list of defaults from CPAN::Config->{'urllist'}...
+ foreach my $country (@countries) {
+ next if $country =~ /edit previous picks/;
+ (my $bare_country = $country) =~ s/ \(.*\)//;
+ my @u;
+ for my $m ( $mirrors->mirrors($bare_country) ) {
+ push @u, $m->ftp if $m->ftp;
+ push @u, $m->http if $m->http;
+ }
+ @u = grep (! $seen{$_}, @u);
+ @u = map ("$_ ($bare_country)", @u)
+ if @countries > 1;
+ push (@urls, sort @u);
+ }
+ }
+ push (@urls, map ("$_ (previous pick)", @previous_urls));
+ my $prompt = "Select as many URLs as you like (by number),
+put them on one line, separated by blanks, hyphenated ranges allowed
+ e.g. '1 4 5' or '7 1-4 8'";
+ if (@previous_urls) {
+ $default = join (' ', ((scalar @urls) - (scalar @previous_urls) + 1) ..
+ (scalar @urls));
+ $prompt .= "\n(or just hit RETURN to keep your previous picks)";
+ }
+
+ @urls = picklist (\@urls, $prompt, $default);
+ foreach (@urls) { s/ \(.*\)//; }
+ return [ @urls ];
+}
+
+sub bring_your_own {
+ my $urllist = [ @{$CPAN::Config->{urllist}} ];
+ my %seen = map (($_ => 1), @$urllist);
+ my($ans,@urls);
+ my $eacnt = 0; # empty answers
+ $CPAN::Frontend->myprint(<<'HERE');
+
+Now you can enter your own CPAN URLs by hand. A local CPAN mirror can be
+listed using a 'file:' URL like 'file:///path/to/cpan/'
+
+HERE
+ do {
+ my $prompt = "Enter another URL or RETURN to quit:";
+ unless (%seen) {
+ $prompt = qq{CPAN.pm needs at least one URL where it can fetch CPAN files from.
+
+Please enter your CPAN site:};
+ }
+ $ans = prompt ($prompt, "");
+
+ if ($ans) {
+ $ans =~ s|/?\z|/|; # has to end with one slash
+ # XXX This manipulation is odd. Shouldn't we check that $ans is
+ # a directory before converting to file:///? And we need /// below,
+ # too, don't we? -- dagolden, 2009-11-05
+ $ans = "file:$ans" unless $ans =~ /:/; # without a scheme is a file:
+ if ($ans =~ /^\w+:\/./) {
+ push @urls, $ans unless $seen{$ans}++;
+ } else {
+ $CPAN::Frontend->
+ myprint(sprintf(qq{"%s" doesn\'t look like an URL at first sight.
+I\'ll ignore it for now.
+You can add it to your %s
+later if you\'re sure it\'s right.\n},
+ $ans,
+ $INC{'CPAN/MyConfig.pm'}
+ || $INC{'CPAN/Config.pm'}
+ || "configuration file",
+ ));
+ }
+ } else {
+ if (++$eacnt >= 5) {
+ $CPAN::Frontend->
+ mywarn("Giving up.\n");
+ $CPAN::Frontend->mysleep(5);
+ return;
+ }
+ }
+ } while $ans || !%seen;
+
+ @$urllist = CPAN::_uniq(@$urllist, @urls);
+ $CPAN::Config->{urllist} = $urllist;
+}
+
+sub _print_urllist {
+ $CPAN::Frontend->myprint("New urllist\n");
+ for ( @{$CPAN::Config->{urllist} || []} ) {
+ $CPAN::Frontend->myprint(" $_\n")
+ };
+}
+
+sub _strip_spaces {
+ $_[0] =~ s/^\s+//; # no leading spaces
+ $_[0] =~ s/\s+\z//; # no trailing spaces
+}
+
+sub prompt ($;$) {
+ unless (defined &_real_prompt) {
+ *_real_prompt = \&CPAN::Shell::colorable_makemaker_prompt;
+ }
+ my $ans = _real_prompt(@_);
+
+ _strip_spaces($ans);
+ $CPAN::Frontend->myprint("\n");
+
+ return $ans;
+}
+
+
+sub prompt_no_strip ($;$) {
+ return _real_prompt(@_);
+}
+
+
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/HandleConfig.pm b/Master/tlpkg/tlperl/lib/CPAN/HandleConfig.pm
new file mode 100644
index 00000000000..76cd81eee8b
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/HandleConfig.pm
@@ -0,0 +1,741 @@
+package CPAN::HandleConfig;
+use strict;
+use vars qw(%can %keys $loading $VERSION);
+
+$VERSION = "5.5001"; # see also CPAN::Config::VERSION at end of file
+
+%can = (
+ commit => "Commit changes to disk",
+ defaults => "Reload defaults from disk",
+ help => "Short help about 'o conf' usage",
+ init => "Interactive setting of all options",
+);
+
+# Q: where is the "How do I add a new config option" HOWTO?
+# A1: svn diff -r 757:758 # where dagolden added test_report
+# A2: svn diff -r 985:986 # where andk added yaml_module
+# A3: 1. add new config option to %keys below
+# 2. add a Pod description in CPAN::FirstTime; it should include a
+# prompt line; see others for examples
+# 3. add a "matcher" section in CPAN::FirstTime::init that includes
+# a prompt function; see others for examples
+# 4. add config option to documentation section in CPAN.pm
+
+%keys = map { $_ => undef }
+ (
+ "applypatch",
+ "auto_commit",
+ "build_cache",
+ "build_dir",
+ "build_dir_reuse",
+ "build_requires_install_policy",
+ "bzip2",
+ "cache_metadata",
+ "check_sigs",
+ "colorize_debug",
+ "colorize_output",
+ "colorize_print",
+ "colorize_warn",
+ "commandnumber_in_prompt",
+ "commands_quote",
+ "connect_to_internet_ok",
+ "cpan_home",
+ "curl",
+ "dontload_hash", # deprecated after 1.83_68 (rev. 581)
+ "dontload_list",
+ "ftp",
+ "ftp_passive",
+ "ftp_proxy",
+ "ftpstats_size",
+ "ftpstats_period",
+ "getcwd",
+ "gpg",
+ "gzip",
+ "halt_on_failure",
+ "histfile",
+ "histsize",
+ "http_proxy",
+ "inactivity_timeout",
+ "index_expire",
+ "inhibit_startup_message",
+ "keep_source_where",
+ "load_module_verbosity",
+ "lynx",
+ "make",
+ "make_arg",
+ "make_install_arg",
+ "make_install_make_command",
+ "makepl_arg",
+ "mbuild_arg",
+ "mbuild_install_arg",
+ "mbuild_install_build_command",
+ "mbuildpl_arg",
+ "ncftp",
+ "ncftpget",
+ "no_proxy",
+ "pager",
+ "password",
+ "patch",
+ "patches_dir",
+ "perl5lib_verbosity",
+ "prefer_installer",
+ "prefs_dir",
+ "prerequisites_policy",
+ "proxy_pass",
+ "proxy_user",
+ "randomize_urllist",
+ "scan_cache",
+ "shell",
+ "show_unparsable_versions",
+ "show_upload_date",
+ "show_zero_versions",
+ "tar",
+ "tar_verbosity",
+ "term_is_latin",
+ "term_ornaments",
+ "test_report",
+ "trust_test_report_history",
+ "unzip",
+ "urllist",
+ "use_sqlite",
+ "username",
+ "version_timeout",
+ "wait_list",
+ "wget",
+ "yaml_load_code",
+ "yaml_module",
+ );
+
+my %prefssupport = map { $_ => 1 }
+ (
+ "build_requires_install_policy",
+ "check_sigs",
+ "make",
+ "make_install_make_command",
+ "prefer_installer",
+ "test_report",
+ );
+
+# returns true on successful action
+sub edit {
+ my($self,@args) = @_;
+ return unless @args;
+ CPAN->debug("self[$self]args[".join(" | ",@args)."]");
+ my($o,$str,$func,$args,$key_exists);
+ $o = shift @args;
+ if($can{$o}) {
+ my $success = $self->$o(args => \@args); # o conf init => sub init => sub load
+ unless ($success) {
+ die "Panic: could not configure CPAN.pm for args [@args]. Giving up.";
+ }
+ } else {
+ CPAN->debug("o[$o]") if $CPAN::DEBUG;
+ unless (exists $keys{$o}) {
+ $CPAN::Frontend->mywarn("Warning: unknown configuration variable '$o'\n");
+ }
+ my $changed;
+
+
+ # one day I used randomize_urllist for a boolean, so we must
+ # list them explicitly --ak
+ if (0) {
+ } elsif ($o =~ /^(wait_list|urllist|dontload_list)$/) {
+
+ #
+ # ARRAYS
+ #
+
+ $func = shift @args;
+ $func ||= "";
+ CPAN->debug("func[$func]args[@args]") if $CPAN::DEBUG;
+ # Let's avoid eval, it's easier to comprehend without.
+ if ($func eq "push") {
+ push @{$CPAN::Config->{$o}}, @args;
+ $changed = 1;
+ } elsif ($func eq "pop") {
+ pop @{$CPAN::Config->{$o}};
+ $changed = 1;
+ } elsif ($func eq "shift") {
+ shift @{$CPAN::Config->{$o}};
+ $changed = 1;
+ } elsif ($func eq "unshift") {
+ unshift @{$CPAN::Config->{$o}}, @args;
+ $changed = 1;
+ } elsif ($func eq "splice") {
+ my $offset = shift @args || 0;
+ my $length = shift @args || 0;
+ splice @{$CPAN::Config->{$o}}, $offset, $length, @args; # may warn
+ $changed = 1;
+ } elsif ($func) {
+ $CPAN::Config->{$o} = [$func, @args];
+ $changed = 1;
+ } else {
+ $self->prettyprint($o);
+ }
+ if ($changed) {
+ if ($o eq "urllist") {
+ # reset the cached values
+ undef $CPAN::FTP::Thesite;
+ undef $CPAN::FTP::Themethod;
+ $CPAN::Index::LAST_TIME = 0;
+ } elsif ($o eq "dontload_list") {
+ # empty it, it will be built up again
+ $CPAN::META->{dontload_hash} = {};
+ }
+ }
+ } elsif ($o =~ /_hash$/) {
+
+ #
+ # HASHES
+ #
+
+ if (@args==1 && $args[0] eq "") {
+ @args = ();
+ } elsif (@args % 2) {
+ push @args, "";
+ }
+ $CPAN::Config->{$o} = { @args };
+ $changed = 1;
+ } else {
+
+ #
+ # SCALARS
+ #
+
+ if (defined $args[0]) {
+ $CPAN::CONFIG_DIRTY = 1;
+ $CPAN::Config->{$o} = $args[0];
+ $changed = 1;
+ }
+ $self->prettyprint($o)
+ if exists $keys{$o} or defined $CPAN::Config->{$o};
+ }
+ if ($changed) {
+ if ($CPAN::Config->{auto_commit}) {
+ $self->commit;
+ } else {
+ $CPAN::CONFIG_DIRTY = 1;
+ $CPAN::Frontend->myprint("Please use 'o conf commit' to ".
+ "make the config permanent!\n\n");
+ }
+ }
+ }
+}
+
+sub prettyprint {
+ my($self,$k) = @_;
+ my $v = $CPAN::Config->{$k};
+ if (ref $v) {
+ my(@report);
+ if (ref $v eq "ARRAY") {
+ @report = map {"\t$_ \[$v->[$_]]\n"} 0..$#$v;
+ } else {
+ @report = map
+ {
+ sprintf "\t%-18s => %s\n",
+ "[$_]",
+ defined $v->{$_} ? "[$v->{$_}]" : "undef"
+ } keys %$v;
+ }
+ $CPAN::Frontend->myprint(
+ join(
+ "",
+ sprintf(
+ " %-18s\n",
+ $k
+ ),
+ @report
+ )
+ );
+ } elsif (defined $v) {
+ $CPAN::Frontend->myprint(sprintf " %-18s [%s]\n", $k, $v);
+ } else {
+ $CPAN::Frontend->myprint(sprintf " %-18s undef\n", $k);
+ }
+}
+
+sub commit {
+ my($self,@args) = @_;
+ CPAN->debug("args[@args]") if $CPAN::DEBUG;
+ if ($CPAN::RUN_DEGRADED) {
+ $CPAN::Frontend->mydie(
+ "'o conf commit' disabled in ".
+ "degraded mode. Maybe try\n".
+ " !undef \$CPAN::RUN_DEGRADED\n"
+ );
+ }
+ my $configpm;
+ if (@args) {
+ if ($args[0] eq "args") {
+ # we have not signed that contract
+ } else {
+ $configpm = $args[0];
+ }
+ }
+ unless (defined $configpm) {
+ $configpm ||= $INC{"CPAN/MyConfig.pm"};
+ $configpm ||= $INC{"CPAN/Config.pm"};
+ $configpm || Carp::confess(q{
+CPAN::Config::commit called without an argument.
+Please specify a filename where to save the configuration or try
+"o conf init" to have an interactive course through configing.
+});
+ }
+ my($mode);
+ if (-f $configpm) {
+ $mode = (stat $configpm)[2];
+ if ($mode && ! -w _) {
+ Carp::confess("$configpm is not writable");
+ }
+ }
+
+ my $msg;
+ my $home = home();
+ $msg = <<EOF unless $configpm =~ /MyConfig/;
+
+# This is CPAN.pm's systemwide configuration file. This file provides
+# defaults for users, and the values can be changed in a per-user
+# configuration file. The user-config file is being looked for as
+# $home/.cpan/CPAN/MyConfig.pm.
+
+EOF
+ $msg ||= "\n";
+ my($fh) = FileHandle->new;
+ rename $configpm, "$configpm~" if -f $configpm;
+ open $fh, ">$configpm" or
+ $CPAN::Frontend->mydie("Couldn't open >$configpm: $!");
+ $fh->print(qq[$msg\$CPAN::Config = \{\n]);
+ foreach (sort keys %$CPAN::Config) {
+ unless (exists $keys{$_}) {
+ # do not drop them: forward compatibility!
+ $CPAN::Frontend->mywarn("Unknown config variable '$_'\n");
+ next;
+ }
+ $fh->print(
+ " '$_' => ",
+ $self->neatvalue($CPAN::Config->{$_}),
+ ",\n"
+ );
+ }
+
+ $fh->print("};\n1;\n__END__\n");
+ close $fh;
+
+ #$mode = 0444 | ( $mode & 0111 ? 0111 : 0 );
+ #chmod $mode, $configpm;
+###why was that so? $self->defaults;
+ $CPAN::Frontend->myprint("commit: wrote '$configpm'\n");
+ $CPAN::CONFIG_DIRTY = 0;
+ 1;
+}
+
+# stolen from MakeMaker; not taking the original because it is buggy;
+# bugreport will have to say: keys of hashes remain unquoted and can
+# produce syntax errors
+sub neatvalue {
+ my($self, $v) = @_;
+ return "undef" unless defined $v;
+ my($t) = ref $v;
+ unless ($t) {
+ $v =~ s/\\/\\\\/g;
+ return "q[$v]";
+ }
+ if ($t eq 'ARRAY') {
+ my(@m, @neat);
+ push @m, "[";
+ foreach my $elem (@$v) {
+ push @neat, "q[$elem]";
+ }
+ push @m, join ", ", @neat;
+ push @m, "]";
+ return join "", @m;
+ }
+ return "$v" unless $t eq 'HASH';
+ my(@m, $key, $val);
+ while (($key,$val) = each %$v) {
+ last unless defined $key; # cautious programming in case (undef,undef) is true
+ push(@m,"q[$key]=>".$self->neatvalue($val)) ;
+ }
+ return "{ ".join(', ',@m)." }";
+}
+
+sub defaults {
+ my($self) = @_;
+ if ($CPAN::RUN_DEGRADED) {
+ $CPAN::Frontend->mydie(
+ "'o conf defaults' disabled in ".
+ "degraded mode. Maybe try\n".
+ " !undef \$CPAN::RUN_DEGRADED\n"
+ );
+ }
+ my $done;
+ for my $config (qw(CPAN/MyConfig.pm CPAN/Config.pm)) {
+ if ($INC{$config}) {
+ CPAN->debug("INC{'$config'}[$INC{$config}]") if $CPAN::DEBUG;
+ CPAN::Shell->_reload_this($config,{reloforce => 1});
+ $CPAN::Frontend->myprint("'$INC{$config}' reread\n");
+ last;
+ }
+ }
+ $CPAN::CONFIG_DIRTY = 0;
+ 1;
+}
+
+=head2 C<< CLASS->safe_quote ITEM >>
+
+Quotes an item to become safe against spaces
+in shell interpolation. An item is enclosed
+in double quotes if:
+
+ - the item contains spaces in the middle
+ - the item does not start with a quote
+
+This happens to avoid shell interpolation
+problems when whitespace is present in
+directory names.
+
+This method uses C<commands_quote> to determine
+the correct quote. If C<commands_quote> is
+a space, no quoting will take place.
+
+
+if it starts and ends with the same quote character: leave it as it is
+
+if it contains no whitespace: leave it as it is
+
+if it contains whitespace, then
+
+if it contains quotes: better leave it as it is
+
+else: quote it with the correct quote type for the box we're on
+
+=cut
+
+{
+ # Instead of patching the guess, set commands_quote
+ # to the right value
+ my ($quotes,$use_quote)
+ = $^O eq 'MSWin32'
+ ? ('"', '"')
+ : (q{"'}, "'")
+ ;
+
+ sub safe_quote {
+ my ($self, $command) = @_;
+ # Set up quote/default quote
+ my $quote = $CPAN::Config->{commands_quote} || $quotes;
+
+ if ($quote ne ' '
+ and defined($command )
+ and $command =~ /\s/
+ and $command !~ /[$quote]/) {
+ return qq<$use_quote$command$use_quote>
+ }
+ return $command;
+ }
+}
+
+sub init {
+ my($self,@args) = @_;
+ CPAN->debug("self[$self]args[".join(",",@args)."]");
+ $self->load(doit => 1, @args);
+ 1;
+}
+
+# This is a piece of repeated code that is abstracted here for
+# maintainability. RMB
+#
+sub _configpmtest {
+ my($configpmdir, $configpmtest) = @_;
+ if (-w $configpmtest) {
+ return $configpmtest;
+ } elsif (-w $configpmdir) {
+ #_#_# following code dumped core on me with 5.003_11, a.k.
+ my $configpm_bak = "$configpmtest.bak";
+ unlink $configpm_bak if -f $configpm_bak;
+ if( -f $configpmtest ) {
+ if( rename $configpmtest, $configpm_bak ) {
+ $CPAN::Frontend->mywarn(<<END);
+Old configuration file $configpmtest
+ moved to $configpm_bak
+END
+ }
+ }
+ my $fh = FileHandle->new;
+ if ($fh->open(">$configpmtest")) {
+ $fh->print("1;\n");
+ return $configpmtest;
+ } else {
+ # Should never happen
+ Carp::confess("Cannot open >$configpmtest");
+ }
+ } else { return }
+}
+
+sub require_myconfig_or_config () {
+ return if $INC{"CPAN/MyConfig.pm"};
+ local @INC = @INC;
+ my $home = home();
+ unshift @INC, File::Spec->catdir($home,'.cpan');
+ eval { require CPAN::MyConfig };
+ my $err_myconfig = $@;
+ if ($err_myconfig and $err_myconfig !~ m#locate CPAN/MyConfig\.pm#) {
+ die "Error while requiring CPAN::MyConfig:\n$err_myconfig";
+ }
+ unless ($INC{"CPAN/MyConfig.pm"}) { # this guy has settled his needs already
+ eval {require CPAN::Config;}; # not everybody has one
+ my $err_config = $@;
+ if ($err_config and $err_config !~ m#locate CPAN/Config\.pm#) {
+ die "Error while requiring CPAN::Config:\n$err_config";
+ }
+ }
+}
+
+sub home () {
+ my $home;
+ # Suppress load messages until we load the config and know whether
+ # load messages are desired. Otherwise, it's unexpected and odd
+ # why one load message pops up even when verbosity is turned off.
+ # This means File::HomeDir load messages are never seen, but I
+ # think that's probably OK -- DAGOLDEN
+
+ # 5.6.2 seemed to segfault localizing a value in a hashref
+ # so do it manually instead
+ my $old_v = $CPAN::Config->{load_module_verbosity};
+ $CPAN::Config->{load_module_verbosity} = q[none];
+ if ($CPAN::META->has_usable("File::HomeDir")) {
+ if ($^O eq 'darwin') {
+ $home = File::HomeDir->my_home; # my_data is ~/Library/Application Support on darwin,
+ # which causes issues in the toolchain.
+ }
+ else {
+ $home = File::HomeDir->my_data || File::HomeDir->my_home;
+ }
+ }
+ unless (defined $home) {
+ $home = $ENV{HOME};
+ }
+ $CPAN::Config->{load_module_verbosity} = $old_v;
+ $home;
+}
+
+sub load {
+ my($self, %args) = @_;
+ $CPAN::Be_Silent++ if $args{be_silent};
+ my $doit;
+ $doit = delete $args{doit} || 0;
+ $loading = 0 unless defined $loading;
+
+ use Carp;
+ require_myconfig_or_config;
+ my @miss = $self->missing_config_data;
+ CPAN->debug("doit[$doit]loading[$loading]miss[@miss]") if $CPAN::DEBUG;
+ return unless $doit || @miss;
+ return if $loading;
+ local $loading = ($loading||0) + 1;
+
+ require CPAN::FirstTime;
+ my($redo,$configpm,$fh);
+ if (defined $INC{"CPAN/Config.pm"} && -w $INC{"CPAN/Config.pm"}) {
+ $configpm = $INC{"CPAN/Config.pm"};
+ $redo++;
+ } elsif (defined $INC{"CPAN/MyConfig.pm"} && -w $INC{"CPAN/MyConfig.pm"}) {
+ $configpm = $INC{"CPAN/MyConfig.pm"};
+ $redo++;
+ } else {
+ my($path_to_cpan) = File::Basename::dirname($INC{"CPAN.pm"});
+ my($configpmdir) = File::Spec->catdir($path_to_cpan,"CPAN");
+ my($configpmtest) = File::Spec->catfile($configpmdir,"Config.pm");
+ my $inc_key;
+ if (-d $configpmdir or File::Path::mkpath($configpmdir)) {
+ $configpm = _configpmtest($configpmdir,$configpmtest);
+ $inc_key = "CPAN/Config.pm";
+ }
+ unless ($configpm) {
+ $configpmdir = File::Spec->catdir(home,".cpan","CPAN");
+ File::Path::mkpath($configpmdir);
+ $configpmtest = File::Spec->catfile($configpmdir,"MyConfig.pm");
+ $configpm = _configpmtest($configpmdir,$configpmtest);
+ $inc_key = "CPAN/MyConfig.pm";
+ }
+ if ($configpm) {
+ $INC{$inc_key} = $configpm;
+ } else {
+ my $myconfigpm = File::Spec->catfile(home,".cpan","CPAN","MyConfig.pm");
+ $CPAN::Frontend->mydie(<<"END");
+WARNING: CPAN.pm is unable to write a configuration file. You need write
+access to your default perl library directories or you must be able to
+create and write to '$myconfigpm'.
+
+Aborting configuration.
+END
+ }
+
+ }
+ local($") = ", ";
+ if ($redo && !$doit) {
+ $CPAN::Frontend->myprint(<<END);
+Sorry, we have to rerun the configuration dialog for CPAN.pm due to
+some missing parameters... Will write to
+ <<$configpm>>
+
+END
+ $args{args} = \@miss;
+ }
+ my $initialized = CPAN::FirstTime::init($configpm, %args);
+ return $initialized;
+}
+
+
+# returns mandatory but missing entries in the Config
+sub missing_config_data {
+ my(@miss);
+ for (
+ "auto_commit",
+ "build_cache",
+ "build_dir",
+ "cache_metadata",
+ "cpan_home",
+ "ftp_proxy",
+ #"gzip",
+ "http_proxy",
+ "index_expire",
+ #"inhibit_startup_message",
+ "keep_source_where",
+ #"make",
+ "make_arg",
+ "make_install_arg",
+ "makepl_arg",
+ "mbuild_arg",
+ "mbuild_install_arg",
+ ($^O eq "MSWin32" ? "" : "mbuild_install_build_command"),
+ "mbuildpl_arg",
+ "no_proxy",
+ #"pager",
+ "prerequisites_policy",
+ "scan_cache",
+ #"tar",
+ #"unzip",
+ "urllist",
+ ) {
+ next unless exists $keys{$_};
+ push @miss, $_ unless defined $CPAN::Config->{$_};
+ }
+ return @miss;
+}
+
+sub help {
+ $CPAN::Frontend->myprint(q[
+Known options:
+ commit commit session changes to disk
+ defaults reload default config values from disk
+ help this help
+ init enter a dialog to set all or a set of parameters
+
+Edit key values as in the following (the "o" is a literal letter o):
+ o conf build_cache 15
+ o conf build_dir "/foo/bar"
+ o conf urllist shift
+ o conf urllist unshift ftp://ftp.foo.bar/
+ o conf inhibit_startup_message 1
+
+]);
+ 1; #don't reprint CPAN::Config
+}
+
+sub cpl {
+ my($word,$line,$pos) = @_;
+ $word ||= "";
+ CPAN->debug("word[$word] line[$line] pos[$pos]") if $CPAN::DEBUG;
+ my(@words) = split " ", substr($line,0,$pos+1);
+ if (
+ defined($words[2])
+ and
+ $words[2] =~ /list$/
+ and
+ (
+ @words == 3
+ ||
+ @words == 4 && length($word)
+ )
+ ) {
+ return grep /^\Q$word\E/, qw(splice shift unshift pop push);
+ } elsif (defined($words[2])
+ and
+ $words[2] eq "init"
+ and
+ (
+ @words == 3
+ ||
+ @words >= 4 && length($word)
+ )) {
+ return sort grep /^\Q$word\E/, keys %keys;
+ } elsif (@words >= 4) {
+ return ();
+ }
+ my %seen;
+ my(@o_conf) = sort grep { !$seen{$_}++ }
+ keys %can,
+ keys %$CPAN::Config,
+ keys %keys;
+ return grep /^\Q$word\E/, @o_conf;
+}
+
+sub prefs_lookup {
+ my($self,$distro,$what) = @_;
+
+ if ($prefssupport{$what}) {
+ return $CPAN::Config->{$what} unless
+ $distro
+ and $distro->prefs
+ and $distro->prefs->{cpanconfig}
+ and defined $distro->prefs->{cpanconfig}{$what};
+ return $distro->prefs->{cpanconfig}{$what};
+ } else {
+ $CPAN::Frontend->mywarn("Warning: $what not yet officially ".
+ "supported for distroprefs, doing a normal lookup");
+ return $CPAN::Config->{$what};
+ }
+}
+
+
+{
+ package
+ CPAN::Config; ####::###### #hide from indexer
+ # note: J. Nick Koston wrote me that they are using
+ # CPAN::Config->commit although undocumented. I suggested
+ # CPAN::Shell->o("conf","commit") even when ugly it is at least
+ # documented
+
+ # that's why I added the CPAN::Config class with autoload and
+ # deprecated warning
+
+ use strict;
+ use vars qw($AUTOLOAD $VERSION);
+ $VERSION = "5.5001";
+
+ # formerly CPAN::HandleConfig was known as CPAN::Config
+ sub AUTOLOAD { ## no critic
+ my $class = shift; # e.g. in dh-make-perl: CPAN::Config
+ my($l) = $AUTOLOAD;
+ $CPAN::Frontend->mywarn("Dispatching deprecated method '$l' to CPAN::HandleConfig\n");
+ $l =~ s/.*:://;
+ CPAN::HandleConfig->$l(@_);
+ }
+}
+
+1;
+
+__END__
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=cut
+
+# Local Variables:
+# mode: cperl
+# cperl-indent-level: 4
+# End:
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Index.pm b/Master/tlpkg/tlperl/lib/CPAN/Index.pm
new file mode 100644
index 00000000000..9df757de706
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Index.pm
@@ -0,0 +1,619 @@
+package CPAN::Index;
+use strict;
+use vars qw($LAST_TIME $DATE_OF_02 $DATE_OF_03 $HAVE_REANIMATED $VERSION);
+$VERSION = "1.94";
+@CPAN::Index::ISA = qw(CPAN::Debug);
+$LAST_TIME ||= 0;
+$DATE_OF_03 ||= 0;
+# use constant PROTOCOL => "2.0"; # outcommented to avoid warning on upgrade from 1.57
+sub PROTOCOL { 2.0 }
+
+#-> sub CPAN::Index::force_reload ;
+sub force_reload {
+ my($class) = @_;
+ $CPAN::Index::LAST_TIME = 0;
+ $class->reload(1);
+}
+
+my @indexbundle =
+ (
+ {
+ reader => "rd_authindex",
+ dir => "authors",
+ remotefile => '01mailrc.txt.gz',
+ shortlocalfile => '01mailrc.gz',
+ },
+ {
+ reader => "rd_modpacks",
+ dir => "modules",
+ remotefile => '02packages.details.txt.gz',
+ shortlocalfile => '02packag.gz',
+ },
+ {
+ reader => "rd_modlist",
+ dir => "modules",
+ remotefile => '03modlist.data.gz',
+ shortlocalfile => '03mlist.gz',
+ },
+ );
+
+#-> sub CPAN::Index::reload ;
+sub reload {
+ my($self,$force) = @_;
+ my $time = time;
+
+ # XXX check if a newer one is available. (We currently read it
+ # from time to time)
+ for ($CPAN::Config->{index_expire}) {
+ $_ = 0.001 unless $_ && $_ > 0.001;
+ }
+ unless (1 || $CPAN::Have_warned->{readmetadatacache}++) {
+ # debug here when CPAN doesn't seem to read the Metadata
+ require Carp;
+ Carp::cluck("META-PROTOCOL[$CPAN::META->{PROTOCOL}]");
+ }
+ unless ($CPAN::META->{PROTOCOL}) {
+ $self->read_metadata_cache;
+ $CPAN::META->{PROTOCOL} ||= "1.0";
+ }
+ if ( $CPAN::META->{PROTOCOL} < PROTOCOL ) {
+ # warn "Setting last_time to 0";
+ $LAST_TIME = 0; # No warning necessary
+ }
+ if ($LAST_TIME + $CPAN::Config->{index_expire}*86400 > $time
+ and ! $force) {
+ # called too often
+ # CPAN->debug("LAST_TIME[$LAST_TIME]index_expire[$CPAN::Config->{index_expire}]time[$time]");
+ } elsif (0) {
+ # IFF we are developing, it helps to wipe out the memory
+ # between reloads, otherwise it is not what a user expects.
+ undef $CPAN::META; # Neue Gruendlichkeit since v1.52(r1.274)
+ $CPAN::META = CPAN->new;
+ } else {
+ my($debug,$t2);
+ local $LAST_TIME = $time;
+ local $CPAN::META->{PROTOCOL} = PROTOCOL;
+
+ my $needshort = $^O eq "dos";
+
+ INX: for my $indexbundle (@indexbundle) {
+ my $reader = $indexbundle->{reader};
+ my $localfile = $needshort ? $indexbundle->{shortlocalfile} : $indexbundle->{remotefile};
+ my $localpath = File::Spec->catfile($indexbundle->{dir}, $localfile);
+ my $remote = join "/", $indexbundle->{dir}, $indexbundle->{remotefile};
+ my $localized = $self->reload_x($remote, $localpath, $force);
+ $self->$reader($localized); # may die but we let the shell catch it
+ if ($CPAN::DEBUG){
+ $t2 = time;
+ $debug = "timing reading 01[".($t2 - $time)."]";
+ $time = $t2;
+ }
+ return if $CPAN::Signal; # this is sometimes lengthy
+ }
+ $self->write_metadata_cache;
+ if ($CPAN::DEBUG){
+ $t2 = time;
+ $debug .= "03[".($t2 - $time)."]";
+ $time = $t2;
+ }
+ CPAN->debug($debug) if $CPAN::DEBUG;
+ }
+ if ($CPAN::Config->{build_dir_reuse}) {
+ $self->reanimate_build_dir;
+ }
+ if (CPAN::_sqlite_running()) {
+ $CPAN::SQLite->reload(time => $time, force => $force)
+ if not $LAST_TIME;
+ }
+ $LAST_TIME = $time;
+ $CPAN::META->{PROTOCOL} = PROTOCOL;
+}
+
+#-> sub CPAN::Index::reanimate_build_dir ;
+sub reanimate_build_dir {
+ my($self) = @_;
+ unless ($CPAN::META->has_inst($CPAN::Config->{yaml_module}||"YAML")) {
+ return;
+ }
+ return if $HAVE_REANIMATED++;
+ my $d = $CPAN::Config->{build_dir};
+ my $dh = DirHandle->new;
+ opendir $dh, $d or return; # does not exist
+ my $dirent;
+ my $i = 0;
+ my $painted = 0;
+ my $restored = 0;
+ my @candidates = map { $_->[0] }
+ sort { $b->[1] <=> $a->[1] }
+ map { [ $_, -M File::Spec->catfile($d,$_) ] }
+ grep {/\.yml$/} readdir $dh;
+ unless (@candidates) {
+ $CPAN::Frontend->myprint("Build_dir empty, nothing to restore\n");
+ return;
+ }
+ $CPAN::Frontend->myprint
+ (sprintf("Going to read %d yaml file%s from %s/\n",
+ scalar @candidates,
+ @candidates==1 ? "" : "s",
+ $CPAN::Config->{build_dir}
+ ));
+ my $start = CPAN::FTP::_mytime();
+ DISTRO: for $i (0..$#candidates) {
+ my $dirent = $candidates[$i];
+ my $y = eval {CPAN->_yaml_loadfile(File::Spec->catfile($d,$dirent))};
+ if ($@) {
+ warn "Error while parsing file '$dirent'; error: '$@'";
+ next DISTRO;
+ }
+ my $c = $y->[0];
+ if ($c && $c->{perl} && $c->{distribution} && CPAN->_perl_fingerprint($c->{perl})) {
+ my $key = $c->{distribution}{ID};
+ for my $k (keys %{$c->{distribution}}) {
+ if ($c->{distribution}{$k}
+ && ref $c->{distribution}{$k}
+ && UNIVERSAL::isa($c->{distribution}{$k},"CPAN::Distrostatus")) {
+ $c->{distribution}{$k}{COMMANDID} = $i - @candidates;
+ }
+ }
+
+ #we tried to restore only if element already
+ #exists; but then we do not work with metadata
+ #turned off.
+ my $do
+ = $CPAN::META->{readwrite}{'CPAN::Distribution'}{$key}
+ = $c->{distribution};
+ for my $skipper (qw(
+ badtestcnt
+ configure_requires_later
+ configure_requires_later_for
+ force_update
+ later
+ later_for
+ notest
+ should_report
+ sponsored_mods
+ prefs
+ negative_prefs_cache
+ )) {
+ delete $do->{$skipper};
+ }
+ if ($do->can("tested_ok_but_not_installed")) {
+ if ($do->tested_ok_but_not_installed) {
+ $CPAN::META->is_tested($do->{build_dir},$do->{make_test}{TIME});
+ } else {
+ next DISTRO;
+ }
+ }
+ $restored++;
+ }
+ $i++;
+ while (($painted/76) < ($i/@candidates)) {
+ $CPAN::Frontend->myprint(".");
+ $painted++;
+ }
+ }
+ my $took = CPAN::FTP::_mytime() - $start;
+ $CPAN::Frontend->myprint(sprintf(
+ "DONE\nRestored the state of %s (in %.4f secs)\n",
+ $restored || "none",
+ $took,
+ ));
+}
+
+
+#-> sub CPAN::Index::reload_x ;
+sub reload_x {
+ my($cl,$wanted,$localname,$force) = @_;
+ $force |= 2; # means we're dealing with an index here
+ CPAN::HandleConfig->load; # we should guarantee loading wherever
+ # we rely on Config XXX
+ $localname ||= $wanted;
+ my $abs_wanted = File::Spec->catfile($CPAN::Config->{'keep_source_where'},
+ $localname);
+ if (
+ -f $abs_wanted &&
+ -M $abs_wanted < $CPAN::Config->{'index_expire'} &&
+ !($force & 1)
+ ) {
+ my $s = $CPAN::Config->{'index_expire'} == 1 ? "" : "s";
+ $cl->debug(qq{$abs_wanted younger than $CPAN::Config->{'index_expire'} }.
+ qq{day$s. I\'ll use that.});
+ return $abs_wanted;
+ } else {
+ $force |= 1; # means we're quite serious about it.
+ }
+ return CPAN::FTP->localize($wanted,$abs_wanted,$force);
+}
+
+#-> sub CPAN::Index::rd_authindex ;
+sub rd_authindex {
+ my($cl, $index_target) = @_;
+ return unless defined $index_target;
+ return if CPAN::_sqlite_running();
+ my @lines;
+ $CPAN::Frontend->myprint("Going to read '$index_target'\n");
+ local(*FH);
+ tie *FH, 'CPAN::Tarzip', $index_target;
+ local($/) = "\n";
+ local($_);
+ push @lines, split /\012/ while <FH>;
+ my $i = 0;
+ my $painted = 0;
+ foreach (@lines) {
+ my($userid,$fullname,$email) =
+ m/alias\s+(\S+)\s+\"([^\"\<]*)\s+\<(.*)\>\"/;
+ $fullname ||= $email;
+ if ($userid && $fullname && $email) {
+ my $userobj = $CPAN::META->instance('CPAN::Author',$userid);
+ $userobj->set('FULLNAME' => $fullname, 'EMAIL' => $email);
+ } else {
+ CPAN->debug(sprintf "line[%s]", $_) if $CPAN::DEBUG;
+ }
+ $i++;
+ while (($painted/76) < ($i/@lines)) {
+ $CPAN::Frontend->myprint(".");
+ $painted++;
+ }
+ return if $CPAN::Signal;
+ }
+ $CPAN::Frontend->myprint("DONE\n");
+}
+
+sub userid {
+ my($self,$dist) = @_;
+ $dist = $self->{'id'} unless defined $dist;
+ my($ret) = $dist =~ m|(?:\w/\w\w/)?([^/]+)/|;
+ $ret;
+}
+
+#-> sub CPAN::Index::rd_modpacks ;
+sub rd_modpacks {
+ my($self, $index_target) = @_;
+ return unless defined $index_target;
+ return if CPAN::_sqlite_running();
+ $CPAN::Frontend->myprint("Going to read '$index_target'\n");
+ my $fh = CPAN::Tarzip->TIEHANDLE($index_target);
+ local $_;
+ CPAN->debug(sprintf "start[%d]", time) if $CPAN::DEBUG;
+ my $slurp = "";
+ my $chunk;
+ while (my $bytes = $fh->READ(\$chunk,8192)) {
+ $slurp.=$chunk;
+ }
+ my @lines = split /\012/, $slurp;
+ CPAN->debug(sprintf "end[%d]", time) if $CPAN::DEBUG;
+ undef $fh;
+ # read header
+ my($line_count,$last_updated);
+ while (@lines) {
+ my $shift = shift(@lines);
+ last if $shift =~ /^\s*$/;
+ $shift =~ /^Line-Count:\s+(\d+)/ and $line_count = $1;
+ $shift =~ /^Last-Updated:\s+(.+)/ and $last_updated = $1;
+ }
+ CPAN->debug("line_count[$line_count]last_updated[$last_updated]") if $CPAN::DEBUG;
+ if (not defined $line_count) {
+
+ $CPAN::Frontend->mywarn(qq{Warning: Your $index_target does not contain a Line-Count header.
+Please check the validity of the index file by comparing it to more
+than one CPAN mirror. I'll continue but problems seem likely to
+happen.\a
+});
+
+ $CPAN::Frontend->mysleep(5);
+ } elsif ($line_count != scalar @lines) {
+
+ $CPAN::Frontend->mywarn(sprintf qq{Warning: Your %s
+contains a Line-Count header of %d but I see %d lines there. Please
+check the validity of the index file by comparing it to more than one
+CPAN mirror. I'll continue but problems seem likely to happen.\a\n},
+$index_target, $line_count, scalar(@lines));
+
+ }
+ if (not defined $last_updated) {
+
+ $CPAN::Frontend->mywarn(qq{Warning: Your $index_target does not contain a Last-Updated header.
+Please check the validity of the index file by comparing it to more
+than one CPAN mirror. I'll continue but problems seem likely to
+happen.\a
+});
+
+ $CPAN::Frontend->mysleep(5);
+ } else {
+
+ $CPAN::Frontend
+ ->myprint(sprintf qq{ Database was generated on %s\n},
+ $last_updated);
+ $DATE_OF_02 = $last_updated;
+
+ my $age = time;
+ if ($CPAN::META->has_inst('HTTP::Date')) {
+ require HTTP::Date;
+ $age -= HTTP::Date::str2time($last_updated);
+ } else {
+ $CPAN::Frontend->mywarn(" HTTP::Date not available\n");
+ require Time::Local;
+ my(@d) = $last_updated =~ / (\d+) (\w+) (\d+) (\d+):(\d+):(\d+) /;
+ $d[1] = index("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec", $d[1])/4;
+ $age -= $d[1]>=0 ? Time::Local::timegm(@d[5,4,3,0,1,2]) : 0;
+ }
+ $age /= 3600*24;
+ if ($age > 30) {
+
+ $CPAN::Frontend
+ ->mywarn(sprintf
+ qq{Warning: This index file is %d days old.
+ Please check the host you chose as your CPAN mirror for staleness.
+ I'll continue but problems seem likely to happen.\a\n},
+ $age);
+
+ } elsif ($age < -1) {
+
+ $CPAN::Frontend
+ ->mywarn(sprintf
+ qq{Warning: Your system date is %d days behind this index file!
+ System time: %s
+ Timestamp index file: %s
+ Please fix your system time, problems with the make command expected.\n},
+ -$age,
+ scalar gmtime,
+ $DATE_OF_02,
+ );
+
+ }
+ }
+
+
+ # A necessity since we have metadata_cache: delete what isn't
+ # there anymore
+ my $secondtime = $CPAN::META->exists("CPAN::Module","CPAN");
+ CPAN->debug("secondtime[$secondtime]") if $CPAN::DEBUG;
+ my(%exists);
+ my $i = 0;
+ my $painted = 0;
+ foreach (@lines) {
+ # before 1.56 we split into 3 and discarded the rest. From
+ # 1.57 we assign remaining text to $comment thus allowing to
+ # influence isa_perl
+ my($mod,$version,$dist,$comment) = split " ", $_, 4;
+ unless ($mod && defined $version && $dist) {
+ $CPAN::Frontend->mywarn("Could not split line[$_]\n");
+ next;
+ }
+ my($bundle,$id,$userid);
+
+ if ($mod eq 'CPAN' &&
+ ! (
+ CPAN::Queue->exists('Bundle::CPAN') ||
+ CPAN::Queue->exists('CPAN')
+ )
+ ) {
+ local($^W)= 0;
+ if ($version > $CPAN::VERSION) {
+ $CPAN::Frontend->mywarn(qq{
+ New CPAN.pm version (v$version) available.
+ [Currently running version is v$CPAN::VERSION]
+ You might want to try
+ install CPAN
+ reload cpan
+ to both upgrade CPAN.pm and run the new version without leaving
+ the current session.
+
+}); #});
+ $CPAN::Frontend->mysleep(2);
+ $CPAN::Frontend->myprint(qq{\n});
+ }
+ last if $CPAN::Signal;
+ } elsif ($mod =~ /^Bundle::(.*)/) {
+ $bundle = $1;
+ }
+
+ if ($bundle) {
+ $id = $CPAN::META->instance('CPAN::Bundle',$mod);
+ # Let's make it a module too, because bundles have so much
+ # in common with modules.
+
+ # Changed in 1.57_63: seems like memory bloat now without
+ # any value, so commented out
+
+ # $CPAN::META->instance('CPAN::Module',$mod);
+
+ } else {
+
+ # instantiate a module object
+ $id = $CPAN::META->instance('CPAN::Module',$mod);
+
+ }
+
+ # Although CPAN prohibits same name with different version the
+ # indexer may have changed the version for the same distro
+ # since the last time ("Force Reindexing" feature)
+ if ($id->cpan_file ne $dist
+ ||
+ $id->cpan_version ne $version
+ ) {
+ $userid = $id->userid || $self->userid($dist);
+ $id->set(
+ 'CPAN_USERID' => $userid,
+ 'CPAN_VERSION' => $version,
+ 'CPAN_FILE' => $dist,
+ );
+ }
+
+ # instantiate a distribution object
+ if ($CPAN::META->exists('CPAN::Distribution',$dist)) {
+ # we do not need CONTAINSMODS unless we do something with
+ # this dist, so we better produce it on demand.
+
+ ## my $obj = $CPAN::META->instance(
+ ## 'CPAN::Distribution' => $dist
+ ## );
+ ## $obj->{CONTAINSMODS}{$mod} = undef; # experimental
+ } else {
+ $CPAN::META->instance(
+ 'CPAN::Distribution' => $dist
+ )->set(
+ 'CPAN_USERID' => $userid,
+ 'CPAN_COMMENT' => $comment,
+ );
+ }
+ if ($secondtime) {
+ for my $name ($mod,$dist) {
+ # $self->debug("exists name[$name]") if $CPAN::DEBUG;
+ $exists{$name} = undef;
+ }
+ }
+ $i++;
+ while (($painted/76) < ($i/@lines)) {
+ $CPAN::Frontend->myprint(".");
+ $painted++;
+ }
+ return if $CPAN::Signal;
+ }
+ $CPAN::Frontend->myprint("DONE\n");
+ if ($secondtime) {
+ for my $class (qw(CPAN::Module CPAN::Bundle CPAN::Distribution)) {
+ for my $o ($CPAN::META->all_objects($class)) {
+ next if exists $exists{$o->{ID}};
+ $CPAN::META->delete($class,$o->{ID});
+ # CPAN->debug("deleting ID[$o->{ID}] in class[$class]")
+ # if $CPAN::DEBUG;
+ }
+ }
+ }
+}
+
+#-> sub CPAN::Index::rd_modlist ;
+sub rd_modlist {
+ my($cl,$index_target) = @_;
+ return unless defined $index_target;
+ return if CPAN::_sqlite_running();
+ $CPAN::Frontend->myprint("Going to read '$index_target'\n");
+ my $fh = CPAN::Tarzip->TIEHANDLE($index_target);
+ local $_;
+ my $slurp = "";
+ my $chunk;
+ while (my $bytes = $fh->READ(\$chunk,8192)) {
+ $slurp.=$chunk;
+ }
+ my @eval2 = split /\012/, $slurp;
+
+ while (@eval2) {
+ my $shift = shift(@eval2);
+ if ($shift =~ /^Date:\s+(.*)/) {
+ if ($DATE_OF_03 eq $1) {
+ $CPAN::Frontend->myprint("Unchanged.\n");
+ return;
+ }
+ ($DATE_OF_03) = $1;
+ }
+ last if $shift =~ /^\s*$/;
+ }
+ push @eval2, q{CPAN::Modulelist->data;};
+ local($^W) = 0;
+ my($compmt) = Safe->new("CPAN::Safe1");
+ my($eval2) = join("\n", @eval2);
+ CPAN->debug(sprintf "length of eval2[%d]", length $eval2) if $CPAN::DEBUG;
+ my $ret = $compmt->reval($eval2);
+ Carp::confess($@) if $@;
+ return if $CPAN::Signal;
+ my $i = 0;
+ my $until = keys(%$ret);
+ my $painted = 0;
+ CPAN->debug(sprintf "until[%d]", $until) if $CPAN::DEBUG;
+ for (keys %$ret) {
+ my $obj = $CPAN::META->instance("CPAN::Module",$_);
+ delete $ret->{$_}{modid}; # not needed here, maybe elsewhere
+ $obj->set(%{$ret->{$_}});
+ $i++;
+ while (($painted/76) < ($i/$until)) {
+ $CPAN::Frontend->myprint(".");
+ $painted++;
+ }
+ return if $CPAN::Signal;
+ }
+ $CPAN::Frontend->myprint("DONE\n");
+}
+
+#-> sub CPAN::Index::write_metadata_cache ;
+sub write_metadata_cache {
+ my($self) = @_;
+ return unless $CPAN::Config->{'cache_metadata'};
+ return if CPAN::_sqlite_running();
+ return unless $CPAN::META->has_usable("Storable");
+ my $cache;
+ foreach my $k (qw(CPAN::Bundle CPAN::Author CPAN::Module
+ CPAN::Distribution)) {
+ $cache->{$k} = $CPAN::META->{readonly}{$k}; # unsafe meta access, ok
+ }
+ my $metadata_file = File::Spec->catfile($CPAN::Config->{cpan_home},"Metadata");
+ $cache->{last_time} = $LAST_TIME;
+ $cache->{DATE_OF_02} = $DATE_OF_02;
+ $cache->{PROTOCOL} = PROTOCOL;
+ $CPAN::Frontend->myprint("Going to write $metadata_file\n");
+ eval { Storable::nstore($cache, $metadata_file) };
+ $CPAN::Frontend->mywarn($@) if $@; # ?? missing "\n" after $@ in mywarn ??
+}
+
+#-> sub CPAN::Index::read_metadata_cache ;
+sub read_metadata_cache {
+ my($self) = @_;
+ return unless $CPAN::Config->{'cache_metadata'};
+ return if CPAN::_sqlite_running();
+ return unless $CPAN::META->has_usable("Storable");
+ my $metadata_file = File::Spec->catfile($CPAN::Config->{cpan_home},"Metadata");
+ return unless -r $metadata_file and -f $metadata_file;
+ $CPAN::Frontend->myprint("Going to read '$metadata_file'\n");
+ my $cache;
+ eval { $cache = Storable::retrieve($metadata_file) };
+ $CPAN::Frontend->mywarn($@) if $@; # ?? missing "\n" after $@ in mywarn ??
+ if (!$cache || !UNIVERSAL::isa($cache, 'HASH')) {
+ $LAST_TIME = 0;
+ return;
+ }
+ if (exists $cache->{PROTOCOL}) {
+ if (PROTOCOL > $cache->{PROTOCOL}) {
+ $CPAN::Frontend->mywarn(sprintf("Ignoring Metadata cache written ".
+ "with protocol v%s, requiring v%s\n",
+ $cache->{PROTOCOL},
+ PROTOCOL)
+ );
+ return;
+ }
+ } else {
+ $CPAN::Frontend->mywarn("Ignoring Metadata cache written ".
+ "with protocol v1.0\n");
+ return;
+ }
+ my $clcnt = 0;
+ my $idcnt = 0;
+ while(my($class,$v) = each %$cache) {
+ next unless $class =~ /^CPAN::/;
+ $CPAN::META->{readonly}{$class} = $v; # unsafe meta access, ok
+ while (my($id,$ro) = each %$v) {
+ $CPAN::META->{readwrite}{$class}{$id} ||=
+ $class->new(ID=>$id, RO=>$ro);
+ $idcnt++;
+ }
+ $clcnt++;
+ }
+ unless ($clcnt) { # sanity check
+ $CPAN::Frontend->myprint("Warning: Found no data in $metadata_file\n");
+ return;
+ }
+ if ($idcnt < 1000) {
+ $CPAN::Frontend->myprint("Warning: Found only $idcnt objects ".
+ "in $metadata_file\n");
+ return;
+ }
+ $CPAN::META->{PROTOCOL} ||=
+ $cache->{PROTOCOL}; # reading does not up or downgrade, but it
+ # does initialize to some protocol
+ $LAST_TIME = $cache->{last_time};
+ $DATE_OF_02 = $cache->{DATE_OF_02};
+ $CPAN::Frontend->myprint(" Database was generated on $DATE_OF_02\n")
+ if defined $DATE_OF_02; # An old cache may not contain DATE_OF_02
+ return;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/InfoObj.pm b/Master/tlpkg/tlperl/lib/CPAN/InfoObj.pm
new file mode 100644
index 00000000000..9198316c69f
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/InfoObj.pm
@@ -0,0 +1,224 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+# vim: ts=4 sts=4 sw=4:
+package CPAN::InfoObj;
+use strict;
+
+use CPAN::Debug;
+@CPAN::InfoObj::ISA = qw(CPAN::Debug);
+
+use Cwd qw(chdir);
+
+use vars qw(
+ $VERSION
+);
+$VERSION = "5.5";
+
+sub ro {
+ my $self = shift;
+ exists $self->{RO} and return $self->{RO};
+}
+
+#-> sub CPAN::InfoObj::cpan_userid
+sub cpan_userid {
+ my $self = shift;
+ my $ro = $self->ro;
+ if ($ro) {
+ return $ro->{CPAN_USERID} || "N/A";
+ } else {
+ $self->debug("ID[$self->{ID}]");
+ # N/A for bundles found locally
+ return "N/A";
+ }
+}
+
+sub id { shift->{ID}; }
+
+#-> sub CPAN::InfoObj::new ;
+sub new {
+ my $this = bless {}, shift;
+ %$this = @_;
+ $this
+}
+
+# The set method may only be used by code that reads index data or
+# otherwise "objective" data from the outside world. All session
+# related material may do anything else with instance variables but
+# must not touch the hash under the RO attribute. The reason is that
+# the RO hash gets written to Metadata file and is thus persistent.
+
+#-> sub CPAN::InfoObj::safe_chdir ;
+sub safe_chdir {
+ my($self,$todir) = @_;
+ # we die if we cannot chdir and we are debuggable
+ Carp::confess("safe_chdir called without todir argument")
+ unless defined $todir and length $todir;
+ if (chdir $todir) {
+ $self->debug(sprintf "changed directory to %s", CPAN::anycwd())
+ if $CPAN::DEBUG;
+ } else {
+ if (-e $todir) {
+ unless (-x $todir) {
+ unless (chmod 0755, $todir) {
+ my $cwd = CPAN::anycwd();
+ $CPAN::Frontend->mywarn("I have neither the -x permission nor the ".
+ "permission to change the permission; cannot ".
+ "chdir to '$todir'\n");
+ $CPAN::Frontend->mysleep(5);
+ $CPAN::Frontend->mydie(qq{Could not chdir from cwd[$cwd] }.
+ qq{to todir[$todir]: $!});
+ }
+ }
+ } else {
+ $CPAN::Frontend->mydie("Directory '$todir' has gone. Cannot continue.\n");
+ }
+ if (chdir $todir) {
+ $self->debug(sprintf "changed directory to %s", CPAN::anycwd())
+ if $CPAN::DEBUG;
+ } else {
+ my $cwd = CPAN::anycwd();
+ $CPAN::Frontend->mydie(qq{Could not chdir from cwd[$cwd] }.
+ qq{to todir[$todir] (a chmod has been issued): $!});
+ }
+ }
+}
+
+#-> sub CPAN::InfoObj::set ;
+sub set {
+ my($self,%att) = @_;
+ my $class = ref $self;
+
+ # This must be ||=, not ||, because only if we write an empty
+ # reference, only then the set method will write into the readonly
+ # area. But for Distributions that spring into existence, maybe
+ # because of a typo, we do not like it that they are written into
+ # the readonly area and made permanent (at least for a while) and
+ # that is why we do not "allow" other places to call ->set.
+ unless ($self->id) {
+ CPAN->debug("Bug? Empty ID, rejecting");
+ return;
+ }
+ my $ro = $self->{RO} =
+ $CPAN::META->{readonly}{$class}{$self->id} ||= {};
+
+ while (my($k,$v) = each %att) {
+ $ro->{$k} = $v;
+ }
+}
+
+#-> sub CPAN::InfoObj::as_glimpse ;
+sub as_glimpse {
+ my($self) = @_;
+ my(@m);
+ my $class = ref($self);
+ $class =~ s/^CPAN:://;
+ my $id = $self->can("pretty_id") ? $self->pretty_id : $self->{ID};
+ push @m, sprintf "%-15s %s\n", $class, $id;
+ join "", @m;
+}
+
+#-> sub CPAN::InfoObj::as_string ;
+sub as_string {
+ my($self) = @_;
+ my(@m);
+ my $class = ref($self);
+ $class =~ s/^CPAN:://;
+ push @m, $class, " id = $self->{ID}\n";
+ my $ro;
+ unless ($ro = $self->ro) {
+ if (substr($self->{ID},-1,1) eq ".") { # directory
+ $ro = +{};
+ } else {
+ $CPAN::Frontend->mywarn("Unknown object $self->{ID}\n");
+ $CPAN::Frontend->mysleep(5);
+ return;
+ }
+ }
+ for (sort keys %$ro) {
+ # next if m/^(ID|RO)$/;
+ my $extra = "";
+ if ($_ eq "CPAN_USERID") {
+ $extra .= " (";
+ $extra .= $self->fullname;
+ my $email; # old perls!
+ if ($email = $CPAN::META->instance("CPAN::Author",
+ $self->cpan_userid
+ )->email) {
+ $extra .= " <$email>";
+ } else {
+ $extra .= " <no email>";
+ }
+ $extra .= ")";
+ } elsif ($_ eq "FULLNAME") { # potential UTF-8 conversion
+ push @m, sprintf " %-12s %s\n", $_, $self->fullname;
+ next;
+ }
+ next unless defined $ro->{$_};
+ push @m, sprintf " %-12s %s%s\n", $_, $ro->{$_}, $extra;
+ }
+ KEY: for (sort keys %$self) {
+ next if m/^(ID|RO)$/;
+ unless (defined $self->{$_}) {
+ delete $self->{$_};
+ next KEY;
+ }
+ if (ref($self->{$_}) eq "ARRAY") {
+ push @m, sprintf " %-12s %s\n", $_, "@{$self->{$_}}";
+ } elsif (ref($self->{$_}) eq "HASH") {
+ my $value;
+ if (/^CONTAINSMODS$/) {
+ $value = join(" ",sort keys %{$self->{$_}});
+ } elsif (/^prereq_pm$/) {
+ my @value;
+ my $v = $self->{$_};
+ for my $x (sort keys %$v) {
+ my @svalue;
+ for my $y (sort keys %{$v->{$x}}) {
+ push @svalue, "$y=>$v->{$x}{$y}";
+ }
+ push @value, "$x\:" . join ",", @svalue if @svalue;
+ }
+ $value = join ";", @value;
+ } else {
+ $value = $self->{$_};
+ }
+ push @m, sprintf(
+ " %-12s %s\n",
+ $_,
+ $value,
+ );
+ } else {
+ push @m, sprintf " %-12s %s\n", $_, $self->{$_};
+ }
+ }
+ join "", @m, "\n";
+}
+
+#-> sub CPAN::InfoObj::fullname ;
+sub fullname {
+ my($self) = @_;
+ $CPAN::META->instance("CPAN::Author",$self->cpan_userid)->fullname;
+}
+
+#-> sub CPAN::InfoObj::dump ;
+sub dump {
+ my($self, $what) = @_;
+ unless ($CPAN::META->has_inst("Data::Dumper")) {
+ $CPAN::Frontend->mydie("dump command requires Data::Dumper installed");
+ }
+ local $Data::Dumper::Sortkeys;
+ $Data::Dumper::Sortkeys = 1;
+ my $out = Data::Dumper::Dumper($what ? eval $what : $self);
+ if (length $out > 100000) {
+ my $fh_pager = FileHandle->new;
+ local($SIG{PIPE}) = "IGNORE";
+ my $pager = $CPAN::Config->{'pager'} || "cat";
+ $fh_pager->open("|$pager")
+ or die "Could not open pager $pager\: $!";
+ $fh_pager->print($out);
+ close $fh_pager;
+ } else {
+ $CPAN::Frontend->myprint($out);
+ }
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Kwalify.pm b/Master/tlpkg/tlperl/lib/CPAN/Kwalify.pm
new file mode 100644
index 00000000000..3cade90b91a
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Kwalify.pm
@@ -0,0 +1,136 @@
+=head1 NAME
+
+CPAN::Kwalify - Interface between CPAN.pm and Kwalify.pm
+
+=head1 SYNOPSIS
+
+ use CPAN::Kwalify;
+ validate($schema_name, $data, $file, $doc);
+
+=head1 DESCRIPTION
+
+=over
+
+=item _validate($schema_name, $data, $file, $doc)
+
+$schema_name is the name of a supported schema. Currently only
+C<distroprefs> is supported. $data is the data to be validated. $file
+is the absolute path to the file the data are coming from. $doc is the
+index of the document within $doc that is to be validated. The last
+two arguments are only there for better error reporting.
+
+Relies on being called from within CPAN.pm.
+
+Dies if something fails. Does not return anything useful.
+
+=item yaml($schema_name)
+
+Returns the YAML text of that schema. Dies if something fails.
+
+=back
+
+=head1 AUTHOR
+
+Andreas Koenig C<< <andk@cpan.org> >>
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+See L<http://www.perl.com/perl/misc/Artistic.html>
+
+
+
+=cut
+
+
+use strict;
+
+package CPAN::Kwalify;
+use vars qw($VERSION $VAR1);
+$VERSION = "5.50";
+
+use File::Spec ();
+
+my %vcache = ();
+
+my $schema_loaded = {};
+
+sub _validate {
+ my($schema_name,$data,$abs,$y) = @_;
+ my $yaml_module = CPAN->_yaml_module;
+ if (
+ $CPAN::META->has_inst($yaml_module)
+ &&
+ $CPAN::META->has_inst("Kwalify")
+ ) {
+ my $load = UNIVERSAL::can($yaml_module,"Load");
+ unless ($schema_loaded->{$schema_name}) {
+ eval {
+ my $schema_yaml = yaml($schema_name);
+ $schema_loaded->{$schema_name} = $load->($schema_yaml);
+ };
+ if ($@) {
+ # we know that YAML.pm 0.62 cannot parse the schema,
+ # so we try a fallback
+ my $content = do {
+ my $path = __FILE__;
+ $path =~ s/\.pm$//;
+ $path = File::Spec->catfile($path, "$schema_name.dd");
+ local *FH;
+ open FH, $path or die "Could not open '$path': $!";
+ local $/;
+ <FH>;
+ };
+ $VAR1 = undef;
+ eval $content;
+ if (my $err = $@) {
+ die "parsing of '$schema_name.dd' failed: $err";
+ }
+ $schema_loaded->{$schema_name} = $VAR1;
+ }
+ }
+ }
+ if (my $schema = $schema_loaded->{$schema_name}) {
+ my $mtime = (stat $abs)[9];
+ for my $k (keys %{$vcache{$abs}}) {
+ delete $vcache{$abs}{$k} unless $k eq $mtime;
+ }
+ return if $vcache{$abs}{$mtime}{$y}++;
+ eval { Kwalify::validate($schema, $data) };
+ if (my $err = $@) {
+ my $info = {}; yaml($schema_name, info => $info);
+ die "validation of distropref '$abs'[$y] against schema '$info->{path}' failed: $err";
+ }
+ }
+}
+
+sub _clear_cache {
+ %vcache = ();
+}
+
+sub yaml {
+ my($schema_name, %opt) = @_;
+ my $content = do {
+ my $path = __FILE__;
+ $path =~ s/\.pm$//;
+ $path = File::Spec->catfile($path, "$schema_name.yml");
+ if ($opt{info}) {
+ $opt{info}{path} = $path;
+ }
+ local *FH;
+ open FH, $path or die "Could not open '$path': $!";
+ local $/;
+ <FH>;
+ };
+ return $content;
+}
+
+1;
+
+# Local Variables:
+# mode: cperl
+# cperl-indent-level: 4
+# End:
+
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Kwalify/distroprefs.dd b/Master/tlpkg/tlperl/lib/CPAN/Kwalify/distroprefs.dd
new file mode 100644
index 00000000000..fd046271b87
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Kwalify/distroprefs.dd
@@ -0,0 +1,150 @@
+$VAR1 = {
+ "mapping" => {
+ "comment" => {
+ "type" => "text"
+ },
+ "cpanconfig" => {
+ "mapping" => {
+ "=" => {
+ "type" => "text"
+ }
+ },
+ "type" => "map"
+ },
+ "depends" => {
+ "mapping" => {
+ "build_requires" => {
+ "mapping" => {
+ "=" => {
+ "type" => "text"
+ }
+ },
+ "type" => "map"
+ },
+ "configure_requires" => {},
+ "requires" => {}
+ },
+ "type" => "map"
+ },
+ "disabled" => {
+ "enum" => [
+ 0,
+ 1
+ ],
+ "type" => "int"
+ },
+ "features" => {
+ "sequence" => [
+ {
+ "type" => "text"
+ }
+ ],
+ "type" => "seq"
+ },
+ "goto" => {
+ "type" => "text"
+ },
+ "install" => {
+ "mapping" => {
+ "args" => {
+ "sequence" => [
+ {
+ "type" => "text"
+ }
+ ],
+ "type" => "seq"
+ },
+ "commandline" => {
+ "type" => "text"
+ },
+ "eexpect" => {
+ "mapping" => {
+ "mode" => {
+ "enum" => [
+ "deterministic",
+ "anyorder"
+ ],
+ "type" => "text"
+ },
+ "reuse" => {
+ "type" => "int"
+ },
+ "talk" => {
+ "sequence" => [
+ {
+ "type" => "text"
+ }
+ ],
+ "type" => "seq"
+ },
+ "timeout" => {
+ "type" => "number"
+ }
+ },
+ "type" => "map"
+ },
+ "env" => {
+ "mapping" => {
+ "=" => {
+ "type" => "text"
+ }
+ },
+ "type" => "map"
+ },
+ "expect" => {
+ "sequence" => [
+ {
+ "type" => "text"
+ }
+ ],
+ "type" => "seq"
+ }
+ },
+ "type" => "map"
+ },
+ "make" => {},
+ "match" => {
+ "mapping" => {
+ "distribution" => {
+ "type" => "text"
+ },
+ "env" => {
+ "mapping" => {
+ "=" => {
+ "type" => "text"
+ }
+ },
+ "type" => "map"
+ },
+ "module" => {
+ "type" => "text"
+ },
+ "perl" => {
+ "type" => "text"
+ },
+ "perlconfig" => {}
+ },
+ "type" => "map"
+ },
+ "patches" => {
+ "sequence" => [
+ {
+ "type" => "text"
+ }
+ ],
+ "type" => "seq"
+ },
+ "pl" => {},
+ "reminder" => {
+ "type" => "text"
+ },
+ "test" => {}
+ },
+ "type" => "map"
+};
+$VAR1->{"mapping"}{"depends"}{"mapping"}{"configure_requires"} = $VAR1->{"mapping"}{"depends"}{"mapping"}{"build_requires"};
+$VAR1->{"mapping"}{"depends"}{"mapping"}{"requires"} = $VAR1->{"mapping"}{"depends"}{"mapping"}{"build_requires"};
+$VAR1->{"mapping"}{"make"} = $VAR1->{"mapping"}{"install"};
+$VAR1->{"mapping"}{"match"}{"mapping"}{"perlconfig"} = $VAR1->{"mapping"}{"match"}{"mapping"}{"env"};
+$VAR1->{"mapping"}{"pl"} = $VAR1->{"mapping"}{"install"};
+$VAR1->{"mapping"}{"test"} = $VAR1->{"mapping"}{"install"};
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Kwalify/distroprefs.yml b/Master/tlpkg/tlperl/lib/CPAN/Kwalify/distroprefs.yml
new file mode 100644
index 00000000000..431f1742767
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Kwalify/distroprefs.yml
@@ -0,0 +1,92 @@
+---
+type: map
+mapping:
+ comment:
+ type: text
+ depends:
+ type: map
+ mapping:
+ configure_requires:
+ &requires_common
+ type: map
+ mapping:
+ =:
+ type: text
+ build_requires: *requires_common
+ requires: *requires_common
+ match:
+ type: map
+ mapping:
+ distribution:
+ type: text
+ module:
+ type: text
+ perl:
+ type: text
+ perlconfig:
+ &matchhash_common
+ type: map
+ mapping:
+ =:
+ type: text
+ env: *matchhash_common
+ install:
+ &args_env_expect
+ type: map
+ mapping:
+ args:
+ type: seq
+ sequence:
+ - type: text
+ commandline:
+ type: text
+ env:
+ type: map
+ mapping:
+ =:
+ type: text
+ expect:
+ type: seq
+ sequence:
+ - type: text
+ eexpect:
+ type: map
+ mapping:
+ mode:
+ type: text
+ enum:
+ - deterministic
+ - anyorder
+ timeout:
+ type: number
+ reuse:
+ type: int
+ talk:
+ type: seq
+ sequence:
+ - type: text
+ make: *args_env_expect
+ pl: *args_env_expect
+ test: *args_env_expect
+ patches:
+ type: seq
+ sequence:
+ - type: text
+ disabled:
+ type: int
+ enum:
+ - 0
+ - 1
+ goto:
+ type: text
+ cpanconfig:
+ type: map
+ mapping:
+ =:
+ type: text
+ features:
+ type: seq
+ sequence:
+ - type: text
+ reminder:
+ type: text
diff --git a/Master/tlpkg/tlperl/lib/CPAN/LWP/UserAgent.pm b/Master/tlpkg/tlperl/lib/CPAN/LWP/UserAgent.pm
new file mode 100644
index 00000000000..7bb86f9a15d
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/LWP/UserAgent.pm
@@ -0,0 +1,135 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+# vim: ts=4 sts=4 sw=4:
+package CPAN::LWP::UserAgent;
+use strict;
+use vars qw(@ISA $USER $PASSWD $SETUPDONE);
+# we delay requiring LWP::UserAgent and setting up inheritance until we need it
+
+$CPAN::LWP::UserAgent::VERSION = $CPAN::LWP::UserAgent::VERSION = "1.94";
+
+sub config {
+ return if $SETUPDONE;
+ if ($CPAN::META->has_usable('LWP::UserAgent')) {
+ require LWP::UserAgent;
+ @ISA = qw(Exporter LWP::UserAgent); ## no critic
+ $SETUPDONE++;
+ } else {
+ $CPAN::Frontend->mywarn(" LWP::UserAgent not available\n");
+ }
+}
+
+sub get_basic_credentials {
+ my($self, $realm, $uri, $proxy) = @_;
+ if ($USER && $PASSWD) {
+ return ($USER, $PASSWD);
+ }
+ if ( $proxy ) {
+ ($USER,$PASSWD) = $self->get_proxy_credentials();
+ } else {
+ ($USER,$PASSWD) = $self->get_non_proxy_credentials();
+ }
+ return($USER,$PASSWD);
+}
+
+sub get_proxy_credentials {
+ my $self = shift;
+ my ($user, $password);
+ if ( defined $CPAN::Config->{proxy_user} ) {
+ $user = $CPAN::Config->{proxy_user};
+ $password = $CPAN::Config->{proxy_pass} || "";
+ return ($user, $password);
+ }
+ my $username_prompt = "\nProxy authentication needed!
+ (Note: to permanently configure username and password run
+ o conf proxy_user your_username
+ o conf proxy_pass your_password
+ )\nUsername:";
+ ($user, $password) =
+ _get_username_and_password_from_user($username_prompt);
+ return ($user,$password);
+}
+
+sub get_non_proxy_credentials {
+ my $self = shift;
+ my ($user,$password);
+ if ( defined $CPAN::Config->{username} ) {
+ $user = $CPAN::Config->{username};
+ $password = $CPAN::Config->{password} || "";
+ return ($user, $password);
+ }
+ my $username_prompt = "\nAuthentication needed!
+ (Note: to permanently configure username and password run
+ o conf username your_username
+ o conf password your_password
+ )\nUsername:";
+
+ ($user, $password) =
+ _get_username_and_password_from_user($username_prompt);
+ return ($user,$password);
+}
+
+sub _get_username_and_password_from_user {
+ my $username_message = shift;
+ my ($username,$password);
+
+ ExtUtils::MakeMaker->import(qw(prompt));
+ $username = prompt($username_message);
+ if ($CPAN::META->has_inst("Term::ReadKey")) {
+ Term::ReadKey::ReadMode("noecho");
+ }
+ else {
+ $CPAN::Frontend->mywarn(
+ "Warning: Term::ReadKey seems not to be available, your password will be echoed to the terminal!\n"
+ );
+ }
+ $password = prompt("Password:");
+
+ if ($CPAN::META->has_inst("Term::ReadKey")) {
+ Term::ReadKey::ReadMode("restore");
+ }
+ $CPAN::Frontend->myprint("\n\n");
+ return ($username,$password);
+}
+
+# mirror(): Its purpose is to deal with proxy authentication. When we
+# call SUPER::mirror, we relly call the mirror method in
+# LWP::UserAgent. LWP::UserAgent will then call
+# $self->get_basic_credentials or some equivalent and this will be
+# $self->dispatched to our own get_basic_credentials method.
+
+# Our own get_basic_credentials sets $USER and $PASSWD, two globals.
+
+# 407 stands for HTTP_PROXY_AUTHENTICATION_REQUIRED. Which means
+# although we have gone through our get_basic_credentials, the proxy
+# server refuses to connect. This could be a case where the username or
+# password has changed in the meantime, so I'm trying once again without
+# $USER and $PASSWD to give the get_basic_credentials routine another
+# chance to set $USER and $PASSWD.
+
+# mirror(): Its purpose is to deal with proxy authentication. When we
+# call SUPER::mirror, we relly call the mirror method in
+# LWP::UserAgent. LWP::UserAgent will then call
+# $self->get_basic_credentials or some equivalent and this will be
+# $self->dispatched to our own get_basic_credentials method.
+
+# Our own get_basic_credentials sets $USER and $PASSWD, two globals.
+
+# 407 stands for HTTP_PROXY_AUTHENTICATION_REQUIRED. Which means
+# although we have gone through our get_basic_credentials, the proxy
+# server refuses to connect. This could be a case where the username or
+# password has changed in the meantime, so I'm trying once again without
+# $USER and $PASSWD to give the get_basic_credentials routine another
+# chance to set $USER and $PASSWD.
+
+sub mirror {
+ my($self,$url,$aslocal) = @_;
+ my $result = $self->SUPER::mirror($url,$aslocal);
+ if ($result->code == 407) {
+ undef $USER;
+ undef $PASSWD;
+ $result = $self->SUPER::mirror($url,$aslocal);
+ }
+ $result;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Mirrors.pm b/Master/tlpkg/tlperl/lib/CPAN/Mirrors.pm
new file mode 100644
index 00000000000..1a3402e8de5
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Mirrors.pm
@@ -0,0 +1,260 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+# vim: ts=4 sts=4 sw=4:
+package CPAN::Mirrors;
+use strict;
+use vars qw($VERSION $urllist $silent);
+$VERSION = "1.77";
+
+use Carp;
+use FileHandle;
+use Fcntl ":flock";
+
+sub new {
+ my ($class, $file) = @_;
+ my $self = bless {
+ mirrors => [],
+ geography => {},
+ }, $class;
+
+ my $handle = FileHandle->new;
+ $handle->open($file)
+ or croak "Couldn't open $file: $!";
+ flock $handle, LOCK_SH;
+ $self->_parse($file,$handle);
+ flock $handle, LOCK_UN;
+ $handle->close;
+
+ # populate continents & countries
+
+ return $self
+}
+
+sub continents {
+ my ($self) = @_;
+ return keys %{$self->{geography}};
+}
+
+sub countries {
+ my ($self, @continents) = @_;
+ @continents = $self->continents unless @continents;
+ my @countries;
+ for my $c (@continents) {
+ push @countries, keys %{ $self->{geography}{$c} };
+ }
+ return @countries;
+}
+
+sub mirrors {
+ my ($self, @countries) = @_;
+ return @{$self->{mirrors}} unless @countries;
+ my %wanted = map { $_ => 1 } @countries;
+ my @found;
+ for my $m (@{$self->{mirrors}}) {
+ push @found, $m if exists $wanted{$m->country};
+ }
+ return @found;
+}
+
+sub best_mirrors {
+ my ($self, %args) = @_;
+ my $how_many = $args{how_many} || 1;
+ my $callback = $args{callback};
+ my $verbose = $args{verbose};
+ my $conts = $args{continents} || [];
+ $conts = [$conts] unless ref $conts;
+
+ my $seen = {};
+
+ if ( ! @$conts ) {
+ print "Searching for the best continent ...\n" if $verbose;
+ my @best = $self->_find_best_continent($seen, $verbose, $callback);
+
+ # how many continents to find enough mirrors? We should scan
+ # more than we need -- arbitrarily, we'll say x2
+ my $count = 0;
+ for my $c ( @best ) {
+ push @$conts, $c;
+ $count += $self->mirrors( $self->countries($c) );
+ last if $count >= 2 * $how_many;
+ }
+ }
+
+ print "Scanning " . join(", ", @$conts) . " ...\n" if $verbose;
+
+ my @timings;
+ for my $m ($self->mirrors($self->countries(@$conts))) {
+ next unless $m->ftp;
+ my $hostname = $m->hostname;
+ if ( $seen->{$hostname} ) {
+ push @timings, $seen->{$hostname}
+ if defined $seen->{$hostname}[1];
+ }
+ else {
+ my $ping = $m->ping;
+ next unless defined $ping;
+ push @timings, [$m, $ping];
+ $callback->($m,$ping) if $callback;
+ }
+ }
+ return unless @timings;
+ $how_many = @timings if $how_many > @timings;
+ my @best =
+ map { $_->[0] }
+ sort { $a->[1] <=> $b->[1] } @timings;
+
+ return wantarray ? @best[0 .. $how_many-1] : $best[0];
+}
+
+sub _find_best_continent {
+ my ($self, $seen, $verbose, $callback) = @_;
+
+ my %median;
+ CONT: for my $c ( $self->continents ) {
+ my @mirrors = $self->mirrors( $self->countries($c) );
+ next CONT unless @mirrors;
+ my $sample = 9;
+ my $n = (@mirrors < $sample) ? @mirrors : $sample;
+ my @tests;
+ RANDOM: while ( @mirrors && @tests < $n ) {
+ my $m = splice( @mirrors, int(rand(@mirrors)), 1 );
+ my $ping = $m->ping;
+ $callback->($m,$ping) if $callback;
+ # record undef so we don't try again
+ $seen->{$m->hostname} = [$m, $ping];
+ next RANDOM unless defined $ping;
+ push @tests, $ping;
+ }
+ next CONT unless @tests;
+ @tests = sort { $a <=> $b } @tests;
+ if ( @tests == 1 ) {
+ $median{$c} = $tests[0];
+ }
+ elsif ( @tests % 2 ) {
+ $median{$c} = $tests[ int(@tests / 2) ];
+ }
+ else {
+ my $mid_high = int(@tests/2);
+ $median{$c} = ($tests[$mid_high-1] + $tests[$mid_high])/2;
+ }
+ }
+
+ my @best_cont = sort { $median{$a} <=> $median{$b} } keys %median ;
+
+ if ( $verbose ) {
+ print "Median result by continent:\n";
+ for my $c ( @best_cont ) {
+ printf( " %d ms %s\n", int($median{$c}*1000+.5), $c );
+ }
+ }
+
+ return wantarray ? @best_cont : $best_cont[0];
+}
+
+# Adapted from Parse::CPAN::MirroredBy by Adam Kennedy
+sub _parse {
+ my ($self, $file, $handle) = @_;
+ my $output = $self->{mirrors};
+ my $geo = $self->{geography};
+
+ local $/ = "\012";
+ my $line = 0;
+ my $mirror = undef;
+ while ( 1 ) {
+ # Next line
+ my $string = <$handle>;
+ last if ! defined $string;
+ $line = $line + 1;
+
+ # Remove the useless lines
+ chomp( $string );
+ next if $string =~ /^\s*$/;
+ next if $string =~ /^\s*#/;
+
+ # Hostname or property?
+ if ( $string =~ /^\s/ ) {
+ # Property
+ unless ( $string =~ /^\s+(\w+)\s+=\s+\"(.*)\"$/ ) {
+ croak("Invalid property on line $line");
+ }
+ my ($prop, $value) = ($1,$2);
+ $mirror ||= {};
+ if ( $prop eq 'dst_location' ) {
+ my (@location,$continent,$country);
+ @location = (split /\s*,\s*/, $value)
+ and ($continent, $country) = @location[-1,-2];
+ $continent =~ s/\s\(.*//;
+ $continent =~ s/\W+$//; # if Jarkko doesn't know latitude/longitude
+ $geo->{$continent}{$country} = 1 if $continent && $country;
+ $mirror->{continent} = $continent || "unknown";
+ $mirror->{country} = $country || "unknown";
+ }
+ elsif ( $prop eq 'dst_http' ) {
+ $mirror->{http} = $value;
+ }
+ elsif ( $prop eq 'dst_ftp' ) {
+ $mirror->{ftp} = $value;
+ }
+ elsif ( $prop eq 'dst_rsync' ) {
+ $mirror->{rsync} = $value;
+ }
+ else {
+ $prop =~ s/^dst_//;
+ $mirror->{$prop} = $value;
+ }
+ } else {
+ # Hostname
+ unless ( $string =~ /^([\w\.-]+)\:\s*$/ ) {
+ croak("Invalid host name on line $line");
+ }
+ my $current = $mirror;
+ $mirror = { hostname => "$1" };
+ if ( $current ) {
+ push @$output, CPAN::Mirrored::By->new($current);
+ }
+ }
+ }
+ if ( $mirror ) {
+ push @$output, CPAN::Mirrored::By->new($mirror);
+ }
+
+ return;
+}
+
+#--------------------------------------------------------------------------#
+
+package CPAN::Mirrored::By;
+use strict;
+use Net::Ping ();
+
+sub new {
+ my($self,$arg) = @_;
+ $arg ||= {};
+ bless $arg, $self;
+}
+sub hostname { shift->{hostname} }
+sub continent { shift->{continent} }
+sub country { shift->{country} }
+sub http { shift->{http} || '' }
+sub ftp { shift->{ftp} || '' }
+sub rsync { shift->{rsync} || '' }
+
+sub url {
+ my $self = shift;
+ return $self->{ftp} || $self->{http};
+}
+
+sub ping {
+ my $self = shift;
+ my $ping = Net::Ping->new("tcp",1);
+ my ($proto) = $self->url =~ m{^([^:]+)};
+ my $port = $proto eq 'http' ? 80 : 21;
+ return unless $port;
+ $ping->port_number($port);
+ $ping->hires(1);
+ my ($alive,$rtt) = $ping->ping($self->hostname);
+ return $alive ? $rtt : undef;
+}
+
+
+1;
+
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Module.pm b/Master/tlpkg/tlperl/lib/CPAN/Module.pm
new file mode 100644
index 00000000000..43c42bf1049
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Module.pm
@@ -0,0 +1,688 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+# vim: ts=4 sts=4 sw=4:
+package CPAN::Module;
+use strict;
+@CPAN::Module::ISA = qw(CPAN::InfoObj);
+
+use vars qw(
+ $VERSION
+);
+$VERSION = "5.5";
+
+BEGIN {
+ # alarm() is not implemented in perl 5.6.x and earlier under Windows
+ *ALARM_IMPLEMENTED = sub () { $] >= 5.007 || $^O !~ /MSWin/ };
+}
+
+# Accessors
+#-> sub CPAN::Module::userid
+sub userid {
+ my $self = shift;
+ my $ro = $self->ro;
+ return unless $ro;
+ return $ro->{userid} || $ro->{CPAN_USERID};
+}
+#-> sub CPAN::Module::description
+sub description {
+ my $self = shift;
+ my $ro = $self->ro or return "";
+ $ro->{description}
+}
+
+#-> sub CPAN::Module::distribution
+sub distribution {
+ my($self) = @_;
+ CPAN::Shell->expand("Distribution",$self->cpan_file);
+}
+
+#-> sub CPAN::Module::_is_representative_module
+sub _is_representative_module {
+ my($self) = @_;
+ return $self->{_is_representative_module} if defined $self->{_is_representative_module};
+ my $pm = $self->cpan_file or return $self->{_is_representative_module} = 0;
+ $pm =~ s|.+/||;
+ $pm =~ s{\.(?:tar\.(bz2|gz|Z)|t(?:gz|bz)|zip)$}{}i; # see base_id
+ $pm =~ s|-\d+\.\d+.+$||;
+ $pm =~ s|-[\d\.]+$||;
+ $pm =~ s/-/::/g;
+ $self->{_is_representative_module} = $pm eq $self->{ID} ? 1 : 0;
+ # warn "DEBUG: $pm eq $self->{ID} => $self->{_is_representative_module}";
+ $self->{_is_representative_module};
+}
+
+#-> sub CPAN::Module::undelay
+sub undelay {
+ my $self = shift;
+ delete $self->{later};
+ if ( my $dist = CPAN::Shell->expand("Distribution", $self->cpan_file) ) {
+ $dist->undelay;
+ }
+}
+
+# mark as dirty/clean
+#-> sub CPAN::Module::color_cmd_tmps ;
+sub color_cmd_tmps {
+ my($self) = shift;
+ my($depth) = shift || 0;
+ my($color) = shift || 0;
+ my($ancestors) = shift || [];
+ # a module needs to recurse to its cpan_file
+
+ return if exists $self->{incommandcolor}
+ && $color==1
+ && $self->{incommandcolor}==$color;
+ return if $color==0 && !$self->{incommandcolor};
+ if ($color>=1) {
+ if ( $self->uptodate ) {
+ $self->{incommandcolor} = $color;
+ return;
+ } elsif (my $have_version = $self->available_version) {
+ # maybe what we have is good enough
+ if (@$ancestors) {
+ my $who_asked_for_me = $ancestors->[-1];
+ my $obj = CPAN::Shell->expandany($who_asked_for_me);
+ if (0) {
+ } elsif ($obj->isa("CPAN::Bundle")) {
+ # bundles cannot specify a minimum version
+ return;
+ } elsif ($obj->isa("CPAN::Distribution")) {
+ if (my $prereq_pm = $obj->prereq_pm) {
+ for my $k (keys %$prereq_pm) {
+ if (my $want_version = $prereq_pm->{$k}{$self->id}) {
+ if (CPAN::Version->vcmp($have_version,$want_version) >= 0) {
+ $self->{incommandcolor} = $color;
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ $self->{incommandcolor} = $color; # set me before recursion,
+ # so we can break it
+ }
+ if ($depth>=$CPAN::MAX_RECURSION) {
+ die(CPAN::Exception::RecursiveDependency->new($ancestors));
+ }
+ # warn "color_cmd_tmps $depth $color " . $self->id; # sleep 1;
+
+ if ( my $dist = CPAN::Shell->expand("Distribution", $self->cpan_file) ) {
+ $dist->color_cmd_tmps($depth+1,$color,[@$ancestors, $self->id]);
+ }
+ # unreached code?
+ # if ($color==0) {
+ # delete $self->{badtestcnt};
+ # }
+ $self->{incommandcolor} = $color;
+}
+
+#-> sub CPAN::Module::as_glimpse ;
+sub as_glimpse {
+ my($self) = @_;
+ my(@m);
+ my $class = ref($self);
+ $class =~ s/^CPAN:://;
+ my $color_on = "";
+ my $color_off = "";
+ if (
+ $CPAN::Shell::COLOR_REGISTERED
+ &&
+ $CPAN::META->has_inst("Term::ANSIColor")
+ &&
+ $self->description
+ ) {
+ $color_on = Term::ANSIColor::color("green");
+ $color_off = Term::ANSIColor::color("reset");
+ }
+ my $uptodateness = " ";
+ unless ($class eq "Bundle") {
+ my $u = $self->uptodate;
+ $uptodateness = $u ? "=" : "<" if defined $u;
+ };
+ my $id = do {
+ my $d = $self->distribution;
+ $d ? $d -> pretty_id : $self->cpan_userid;
+ };
+ push @m, sprintf("%-7s %1s %s%-22s%s (%s)\n",
+ $class,
+ $uptodateness,
+ $color_on,
+ $self->id,
+ $color_off,
+ $id,
+ );
+ join "", @m;
+}
+
+#-> sub CPAN::Module::dslip_status
+sub dslip_status {
+ my($self) = @_;
+ my($stat);
+ # development status
+ @{$stat->{D}}{qw,i c a b R M S,} = qw,idea
+ pre-alpha alpha beta released
+ mature standard,;
+ # support level
+ @{$stat->{S}}{qw,m d u n a,} = qw,mailing-list
+ developer comp.lang.perl.*
+ none abandoned,;
+ # language
+ @{$stat->{L}}{qw,p c + o h,} = qw,perl C C++ other hybrid,;
+ # interface
+ @{$stat->{I}}{qw,f r O p h n,} = qw,functions
+ references+ties
+ object-oriented pragma
+ hybrid none,;
+ # public licence
+ @{$stat->{P}}{qw,p g l b a 2 o d r n,} = qw,Standard-Perl
+ GPL LGPL
+ BSD Artistic Artistic_2
+ open-source
+ distribution_allowed
+ restricted_distribution
+ no_licence,;
+ for my $x (qw(d s l i p)) {
+ $stat->{$x}{' '} = 'unknown';
+ $stat->{$x}{'?'} = 'unknown';
+ }
+ my $ro = $self->ro;
+ return +{} unless $ro && $ro->{statd};
+ return {
+ D => $ro->{statd},
+ S => $ro->{stats},
+ L => $ro->{statl},
+ I => $ro->{stati},
+ P => $ro->{statp},
+ DV => $stat->{D}{$ro->{statd}},
+ SV => $stat->{S}{$ro->{stats}},
+ LV => $stat->{L}{$ro->{statl}},
+ IV => $stat->{I}{$ro->{stati}},
+ PV => $stat->{P}{$ro->{statp}},
+ };
+}
+
+#-> sub CPAN::Module::as_string ;
+sub as_string {
+ my($self) = @_;
+ my(@m);
+ CPAN->debug("$self entering as_string") if $CPAN::DEBUG;
+ my $class = ref($self);
+ $class =~ s/^CPAN:://;
+ local($^W) = 0;
+ push @m, $class, " id = $self->{ID}\n";
+ my $sprintf = " %-12s %s\n";
+ push @m, sprintf($sprintf, 'DESCRIPTION', $self->description)
+ if $self->description;
+ my $sprintf2 = " %-12s %s (%s)\n";
+ my($userid);
+ $userid = $self->userid;
+ if ( $userid ) {
+ my $author;
+ if ($author = CPAN::Shell->expand('Author',$userid)) {
+ my $email = "";
+ my $m; # old perls
+ if ($m = $author->email) {
+ $email = " <$m>";
+ }
+ push @m, sprintf(
+ $sprintf2,
+ 'CPAN_USERID',
+ $userid,
+ $author->fullname . $email
+ );
+ }
+ }
+ push @m, sprintf($sprintf, 'CPAN_VERSION', $self->cpan_version)
+ if $self->cpan_version;
+ if (my $cpan_file = $self->cpan_file) {
+ push @m, sprintf($sprintf, 'CPAN_FILE', $cpan_file);
+ if (my $dist = CPAN::Shell->expand("Distribution",$cpan_file)) {
+ my $upload_date = $dist->upload_date;
+ if ($upload_date) {
+ push @m, sprintf($sprintf, 'UPLOAD_DATE', $upload_date);
+ }
+ }
+ }
+ my $sprintf3 = " %-12s %1s%1s%1s%1s%1s (%s,%s,%s,%s,%s)\n";
+ my $dslip = $self->dslip_status;
+ push @m, sprintf(
+ $sprintf3,
+ 'DSLIP_STATUS',
+ @{$dslip}{qw(D S L I P DV SV LV IV PV)},
+ ) if $dslip->{D};
+ my $local_file = $self->inst_file;
+ unless ($self->{MANPAGE}) {
+ my $manpage;
+ if ($local_file) {
+ $manpage = $self->manpage_headline($local_file);
+ } else {
+ # If we have already untarred it, we should look there
+ my $dist = $CPAN::META->instance('CPAN::Distribution',
+ $self->cpan_file);
+ # warn "dist[$dist]";
+ # mff=manifest file; mfh=manifest handle
+ my($mff,$mfh);
+ if (
+ $dist->{build_dir}
+ and
+ (-f ($mff = File::Spec->catfile($dist->{build_dir}, "MANIFEST")))
+ and
+ $mfh = FileHandle->new($mff)
+ ) {
+ CPAN->debug("mff[$mff]") if $CPAN::DEBUG;
+ my $lfre = $self->id; # local file RE
+ $lfre =~ s/::/./g;
+ $lfre .= "\\.pm\$";
+ my($lfl); # local file file
+ local $/ = "\n";
+ my(@mflines) = <$mfh>;
+ for (@mflines) {
+ s/^\s+//;
+ s/\s.*//s;
+ }
+ while (length($lfre)>5 and !$lfl) {
+ ($lfl) = grep /$lfre/, @mflines;
+ CPAN->debug("lfl[$lfl]lfre[$lfre]") if $CPAN::DEBUG;
+ $lfre =~ s/.+?\.//;
+ }
+ $lfl =~ s/\s.*//; # remove comments
+ $lfl =~ s/\s+//g; # chomp would maybe be too system-specific
+ my $lfl_abs = File::Spec->catfile($dist->{build_dir},$lfl);
+ # warn "lfl_abs[$lfl_abs]";
+ if (-f $lfl_abs) {
+ $manpage = $self->manpage_headline($lfl_abs);
+ }
+ }
+ }
+ $self->{MANPAGE} = $manpage if $manpage;
+ }
+ my($item);
+ for $item (qw/MANPAGE/) {
+ push @m, sprintf($sprintf, $item, $self->{$item})
+ if exists $self->{$item};
+ }
+ for $item (qw/CONTAINS/) {
+ push @m, sprintf($sprintf, $item, join(" ",@{$self->{$item}}))
+ if exists $self->{$item} && @{$self->{$item}};
+ }
+ push @m, sprintf($sprintf, 'INST_FILE',
+ $local_file || "(not installed)");
+ push @m, sprintf($sprintf, 'INST_VERSION',
+ $self->inst_version) if $local_file;
+ if (%{$CPAN::META->{is_tested}||{}}) { # XXX needs to be methodified somehow
+ my $available_file = $self->available_file;
+ if ($available_file && $available_file ne $local_file) {
+ push @m, sprintf($sprintf, 'AVAILABLE_FILE', $available_file);
+ push @m, sprintf($sprintf, 'AVAILABLE_VERSION', $self->available_version);
+ }
+ }
+ join "", @m, "\n";
+}
+
+#-> sub CPAN::Module::manpage_headline
+sub manpage_headline {
+ my($self,$local_file) = @_;
+ my(@local_file) = $local_file;
+ $local_file =~ s/\.pm(?!\n)\Z/.pod/;
+ push @local_file, $local_file;
+ my(@result,$locf);
+ for $locf (@local_file) {
+ next unless -f $locf;
+ my $fh = FileHandle->new($locf)
+ or $Carp::Frontend->mydie("Couldn't open $locf: $!");
+ my $inpod = 0;
+ local $/ = "\n";
+ while (<$fh>) {
+ $inpod = m/^=(?!head1\s+NAME\s*$)/ ? 0 :
+ m/^=head1\s+NAME\s*$/ ? 1 : $inpod;
+ next unless $inpod;
+ next if /^=/;
+ next if /^\s+$/;
+ chomp;
+ push @result, $_;
+ }
+ close $fh;
+ last if @result;
+ }
+ for (@result) {
+ s/^\s+//;
+ s/\s+$//;
+ }
+ join " ", @result;
+}
+
+#-> sub CPAN::Module::cpan_file ;
+# Note: also inherited by CPAN::Bundle
+sub cpan_file {
+ my $self = shift;
+ # CPAN->debug(sprintf "id[%s]", $self->id) if $CPAN::DEBUG;
+ unless ($self->ro) {
+ CPAN::Index->reload;
+ }
+ my $ro = $self->ro;
+ if ($ro && defined $ro->{CPAN_FILE}) {
+ return $ro->{CPAN_FILE};
+ } else {
+ my $userid = $self->userid;
+ if ( $userid ) {
+ if ($CPAN::META->exists("CPAN::Author",$userid)) {
+ my $author = $CPAN::META->instance("CPAN::Author",
+ $userid);
+ my $fullname = $author->fullname;
+ my $email = $author->email;
+ unless (defined $fullname && defined $email) {
+ return sprintf("Contact Author %s",
+ $userid,
+ );
+ }
+ return "Contact Author $fullname <$email>";
+ } else {
+ return "Contact Author $userid (Email address not available)";
+ }
+ } else {
+ return "N/A";
+ }
+ }
+}
+
+#-> sub CPAN::Module::cpan_version ;
+sub cpan_version {
+ my $self = shift;
+
+ my $ro = $self->ro;
+ unless ($ro) {
+ # Can happen with modules that are not on CPAN
+ $ro = {};
+ }
+ $ro->{CPAN_VERSION} = 'undef'
+ unless defined $ro->{CPAN_VERSION};
+ $ro->{CPAN_VERSION};
+}
+
+#-> sub CPAN::Module::force ;
+sub force {
+ my($self) = @_;
+ $self->{force_update} = 1;
+}
+
+#-> sub CPAN::Module::fforce ;
+sub fforce {
+ my($self) = @_;
+ $self->{force_update} = 2;
+}
+
+#-> sub CPAN::Module::notest ;
+sub notest {
+ my($self) = @_;
+ # $CPAN::Frontend->mywarn("XDEBUG: set notest for Module");
+ $self->{notest}++;
+}
+
+#-> sub CPAN::Module::rematein ;
+sub rematein {
+ my($self,$meth) = @_;
+ $CPAN::Frontend->myprint(sprintf("Running %s for module '%s'\n",
+ $meth,
+ $self->id));
+ my $cpan_file = $self->cpan_file;
+ if ($cpan_file eq "N/A" || $cpan_file =~ /^Contact Author/) {
+ $CPAN::Frontend->mywarn(sprintf qq{
+ The module %s isn\'t available on CPAN.
+
+ Either the module has not yet been uploaded to CPAN, or it is
+ temporary unavailable. Please contact the author to find out
+ more about the status. Try 'i %s'.
+},
+ $self->id,
+ $self->id,
+ );
+ return;
+ }
+ my $pack = $CPAN::META->instance('CPAN::Distribution',$cpan_file);
+ $pack->called_for($self->id);
+ if (exists $self->{force_update}) {
+ if ($self->{force_update} == 2) {
+ $pack->fforce($meth);
+ } else {
+ $pack->force($meth);
+ }
+ }
+ $pack->notest($meth) if exists $self->{notest} && $self->{notest};
+
+ $pack->{reqtype} ||= "";
+ CPAN->debug("dist-reqtype[$pack->{reqtype}]".
+ "self-reqtype[$self->{reqtype}]") if $CPAN::DEBUG;
+ if ($pack->{reqtype}) {
+ if ($pack->{reqtype} eq "b" && $self->{reqtype} =~ /^[rc]$/) {
+ $pack->{reqtype} = $self->{reqtype};
+ if (
+ exists $pack->{install}
+ &&
+ (
+ UNIVERSAL::can($pack->{install},"failed") ?
+ $pack->{install}->failed :
+ $pack->{install} =~ /^NO/
+ )
+ ) {
+ delete $pack->{install};
+ $CPAN::Frontend->mywarn
+ ("Promoting $pack->{ID} from 'build_requires' to 'requires'");
+ }
+ }
+ } else {
+ $pack->{reqtype} = $self->{reqtype};
+ }
+
+ my $success = eval {
+ $pack->$meth();
+ };
+ my $err = $@;
+ $pack->unforce if $pack->can("unforce") && exists $self->{force_update};
+ $pack->unnotest if $pack->can("unnotest") && exists $self->{notest};
+ delete $self->{force_update};
+ delete $self->{notest};
+ if ($err) {
+ die $err;
+ }
+ return $success;
+}
+
+#-> sub CPAN::Module::perldoc ;
+sub perldoc { shift->rematein('perldoc') }
+#-> sub CPAN::Module::readme ;
+sub readme { shift->rematein('readme') }
+#-> sub CPAN::Module::look ;
+sub look { shift->rematein('look') }
+#-> sub CPAN::Module::cvs_import ;
+sub cvs_import { shift->rematein('cvs_import') }
+#-> sub CPAN::Module::get ;
+sub get { shift->rematein('get',@_) }
+#-> sub CPAN::Module::make ;
+sub make { shift->rematein('make') }
+#-> sub CPAN::Module::test ;
+sub test {
+ my $self = shift;
+ # $self->{badtestcnt} ||= 0;
+ $self->rematein('test',@_);
+}
+
+#-> sub CPAN::Module::deprecated_in_core ;
+sub deprecated_in_core {
+ my ($self) = @_;
+ return unless $CPAN::META->has_inst('Module::CoreList') && Module::CoreList->can('is_deprecated');
+ return Module::CoreList::is_deprecated($self->{ID});
+}
+
+#-> sub CPAN::Module::inst_deprecated;
+# Indicates whether the *installed* version of the module is a deprecated *and*
+# installed as part of the Perl core library path
+sub inst_deprecated {
+ my ($self) = @_;
+ my $inst_file = $self->inst_file or return;
+ return $self->deprecated_in_core && $self->_in_priv_or_arch($inst_file);
+}
+
+#-> sub CPAN::Module::uptodate ;
+sub uptodate {
+ my ($self) = @_;
+ local ($_);
+ my $inst = $self->inst_version or return 0;
+ my $cpan = $self->cpan_version;
+ return 0 if CPAN::Version->vgt($cpan,$inst) || $self->inst_deprecated;
+ CPAN->debug
+ (join
+ ("",
+ "returning uptodate. ",
+ "cpan[$cpan]inst[$inst]",
+ )) if $CPAN::DEBUG;
+ return 1;
+}
+
+# returns true if installed in privlib or archlib
+sub _in_priv_or_arch {
+ my($self,$inst_file) = @_;
+ for my $confdirname (qw(archlibexp privlibexp)) {
+ my $confdir = $Config::Config{$confdirname};
+ if ($confdir eq substr($inst_file,0,length($confdir))) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#-> sub CPAN::Module::install ;
+sub install {
+ my($self) = @_;
+ my($doit) = 0;
+ if ($self->uptodate
+ &&
+ not exists $self->{force_update}
+ ) {
+ $CPAN::Frontend->myprint(sprintf("%s is up to date (%s).\n",
+ $self->id,
+ $self->inst_version,
+ ));
+ } else {
+ $doit = 1;
+ }
+ my $ro = $self->ro;
+ if ($ro && $ro->{stats} && $ro->{stats} eq "a") {
+ $CPAN::Frontend->mywarn(qq{
+\n\n\n ***WARNING***
+ The module $self->{ID} has no active maintainer (CPAN support level flag 'abandoned').\n\n\n
+});
+ $CPAN::Frontend->mysleep(5);
+ }
+ return $doit ? $self->rematein('install') : 1;
+}
+#-> sub CPAN::Module::clean ;
+sub clean { shift->rematein('clean') }
+
+#-> sub CPAN::Module::inst_file ;
+sub inst_file {
+ my($self) = @_;
+ $self->_file_in_path([@INC]);
+}
+
+#-> sub CPAN::Module::available_file ;
+sub available_file {
+ my($self) = @_;
+ my $sep = $Config::Config{path_sep};
+ my $perllib = $ENV{PERL5LIB};
+ $perllib = $ENV{PERLLIB} unless defined $perllib;
+ my @perllib = split(/$sep/,$perllib) if defined $perllib;
+ my @cpan_perl5inc;
+ if ($CPAN::Perl5lib_tempfile) {
+ my $yaml = CPAN->_yaml_loadfile($CPAN::Perl5lib_tempfile);
+ @cpan_perl5inc = @{$yaml->[0]{inc} || []};
+ }
+ $self->_file_in_path([@cpan_perl5inc,@perllib,@INC]);
+}
+
+#-> sub CPAN::Module::file_in_path ;
+sub _file_in_path {
+ my($self,$path) = @_;
+ my($dir,@packpath);
+ @packpath = split /::/, $self->{ID};
+ $packpath[-1] .= ".pm";
+ if (@packpath == 1 && $packpath[0] eq "readline.pm") {
+ unshift @packpath, "Term", "ReadLine"; # historical reasons
+ }
+ foreach $dir (@$path) {
+ my $pmfile = File::Spec->catfile($dir,@packpath);
+ if (-f $pmfile) {
+ return $pmfile;
+ }
+ }
+ return;
+}
+
+#-> sub CPAN::Module::xs_file ;
+sub xs_file {
+ my($self) = @_;
+ my($dir,@packpath);
+ @packpath = split /::/, $self->{ID};
+ push @packpath, $packpath[-1];
+ $packpath[-1] .= "." . $Config::Config{'dlext'};
+ foreach $dir (@INC) {
+ my $xsfile = File::Spec->catfile($dir,'auto',@packpath);
+ if (-f $xsfile) {
+ return $xsfile;
+ }
+ }
+ return;
+}
+
+#-> sub CPAN::Module::inst_version ;
+sub inst_version {
+ my($self) = @_;
+ my $parsefile = $self->inst_file or return;
+ my $have = $self->parse_version($parsefile);
+ $have;
+}
+
+#-> sub CPAN::Module::inst_version ;
+sub available_version {
+ my($self) = @_;
+ my $parsefile = $self->available_file or return;
+ my $have = $self->parse_version($parsefile);
+ $have;
+}
+
+#-> sub CPAN::Module::parse_version ;
+sub parse_version {
+ my($self,$parsefile) = @_;
+ if (ALARM_IMPLEMENTED) {
+ my $timeout = (exists($CPAN::Config{'version_timeout'}))
+ ? $CPAN::Config{'version_timeout'}
+ : 15;
+ alarm($timeout);
+ }
+ my $have = eval {
+ local $SIG{ALRM} = sub { die "alarm\n" };
+ MM->parse_version($parsefile);
+ };
+ if ($@) {
+ $CPAN::Frontend->mywarn("Error while parsing version number in file '$parsefile'\n");
+ }
+ alarm(0) if ALARM_IMPLEMENTED;
+ my $leastsanity = eval { defined $have && length $have; };
+ $have = "undef" unless $leastsanity;
+ $have =~ s/^ //; # since the %vd hack these two lines here are needed
+ $have =~ s/ $//; # trailing whitespace happens all the time
+
+ $have = CPAN::Version->readable($have);
+
+ $have =~ s/\s*//g; # stringify to float around floating point issues
+ $have; # no stringify needed, \s* above matches always
+}
+
+#-> sub CPAN::Module::reports
+sub reports {
+ my($self) = @_;
+ $self->distribution->reports;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Nox.pm b/Master/tlpkg/tlperl/lib/CPAN/Nox.pm
new file mode 100644
index 00000000000..5fe5a25ae6e
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Nox.pm
@@ -0,0 +1,51 @@
+package CPAN::Nox;
+use strict;
+use vars qw($VERSION @EXPORT);
+
+BEGIN{
+ $CPAN::Suppress_readline=1 unless defined $CPAN::term;
+}
+
+use base 'Exporter';
+use CPAN;
+
+$VERSION = "5.50";
+$CPAN::META->has_inst('Digest::MD5','no');
+$CPAN::META->has_inst('LWP','no');
+$CPAN::META->has_inst('Compress::Zlib','no');
+@EXPORT = @CPAN::EXPORT;
+
+*AUTOLOAD = \&CPAN::AUTOLOAD;
+
+1;
+
+__END__
+
+=head1 NAME
+
+CPAN::Nox - Wrapper around CPAN.pm without using any XS module
+
+=head1 SYNOPSIS
+
+Interactive mode:
+
+ perl -MCPAN::Nox -e shell;
+
+=head1 DESCRIPTION
+
+This package has the same functionality as CPAN.pm, but tries to
+prevent the usage of compiled extensions during its own
+execution. Its primary purpose is a rescue in case you upgraded perl
+and broke binary compatibility somehow.
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<CPAN>
+
+=cut
+
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Prompt.pm b/Master/tlpkg/tlperl/lib/CPAN/Prompt.pm
new file mode 100644
index 00000000000..7a4e2d81e13
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Prompt.pm
@@ -0,0 +1,29 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+# vim: ts=4 sts=4 sw=4:
+package CPAN::Prompt;
+use overload '""' => "as_string";
+use vars qw($prompt);
+use vars qw(
+ $VERSION
+);
+$VERSION = "5.5";
+
+
+$prompt = "cpan> ";
+$CPAN::CurrentCommandId ||= 0;
+sub new {
+ bless {}, shift;
+}
+sub as_string {
+ my $word = "cpan";
+ unless ($CPAN::META->{LOCK}) {
+ $word = "nolock_cpan";
+ }
+ if ($CPAN::Config->{commandnumber_in_prompt}) {
+ sprintf "$word\[%d]> ", $CPAN::CurrentCommandId;
+ } else {
+ "$word> ";
+ }
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Queue.pm b/Master/tlpkg/tlperl/lib/CPAN/Queue.pm
new file mode 100644
index 00000000000..b60f57c1cfe
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Queue.pm
@@ -0,0 +1,198 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+use strict;
+package CPAN::Queue::Item;
+
+# CPAN::Queue::Item::new ;
+sub new {
+ my($class,@attr) = @_;
+ my $self = bless { @attr }, $class;
+ return $self;
+}
+
+sub as_string {
+ my($self) = @_;
+ $self->{qmod};
+}
+
+# r => requires, b => build_requires, c => commandline
+sub reqtype {
+ my($self) = @_;
+ $self->{reqtype};
+}
+
+package CPAN::Queue;
+
+# One use of the queue is to determine if we should or shouldn't
+# announce the availability of a new CPAN module
+
+# Now we try to use it for dependency tracking. For that to happen
+# we need to draw a dependency tree and do the leaves first. This can
+# easily be reached by running CPAN.pm recursively, but we don't want
+# to waste memory and run into deep recursion. So what we can do is
+# this:
+
+# CPAN::Queue is the package where the queue is maintained. Dependencies
+# often have high priority and must be brought to the head of the queue,
+# possibly by jumping the queue if they are already there. My first code
+# attempt tried to be extremely correct. Whenever a module needed
+# immediate treatment, I either unshifted it to the front of the queue,
+# or, if it was already in the queue, I spliced and let it bypass the
+# others. This became a too correct model that made it impossible to put
+# an item more than once into the queue. Why would you need that? Well,
+# you need temporary duplicates as the manager of the queue is a loop
+# that
+#
+# (1) looks at the first item in the queue without shifting it off
+#
+# (2) cares for the item
+#
+# (3) removes the item from the queue, *even if its agenda failed and
+# even if the item isn't the first in the queue anymore* (that way
+# protecting against never ending queues)
+#
+# So if an item has prerequisites, the installation fails now, but we
+# want to retry later. That's easy if we have it twice in the queue.
+#
+# I also expect insane dependency situations where an item gets more
+# than two lives in the queue. Simplest example is triggered by 'install
+# Foo Foo Foo'. People make this kind of mistakes and I don't want to
+# get in the way. I wanted the queue manager to be a dumb servant, not
+# one that knows everything.
+#
+# Who would I tell in this model that the user wants to be asked before
+# processing? I can't attach that information to the module object,
+# because not modules are installed but distributions. So I'd have to
+# tell the distribution object that it should ask the user before
+# processing. Where would the question be triggered then? Most probably
+# in CPAN::Distribution::rematein.
+
+use vars qw{ @All $VERSION };
+$VERSION = "5.5";
+
+# CPAN::Queue::queue_item ;
+sub queue_item {
+ my($class,@attr) = @_;
+ my $item = "$class\::Item"->new(@attr);
+ $class->qpush($item);
+ return 1;
+}
+
+# CPAN::Queue::qpush ;
+sub qpush {
+ my($class,$obj) = @_;
+ push @All, $obj;
+ CPAN->debug(sprintf("in new All[%s]",
+ join("",map {sprintf " %s\[%s]\n",$_->{qmod},$_->{reqtype}} @All),
+ )) if $CPAN::DEBUG;
+}
+
+# CPAN::Queue::first ;
+sub first {
+ my $obj = $All[0];
+ $obj;
+}
+
+# CPAN::Queue::delete_first ;
+sub delete_first {
+ my($class,$what) = @_;
+ my $i;
+ for my $i (0..$#All) {
+ if ( $All[$i]->{qmod} eq $what ) {
+ splice @All, $i, 1;
+ return;
+ }
+ }
+}
+
+# CPAN::Queue::jumpqueue ;
+sub jumpqueue {
+ my $class = shift;
+ my @what = @_;
+ CPAN->debug(sprintf("before jumpqueue All[%s] what[%s]",
+ join("",
+ map {sprintf " %s\[%s]\n",$_->{qmod},$_->{reqtype}} @All, @what
+ ))) if $CPAN::DEBUG;
+ unless (defined $what[0]{reqtype}) {
+ # apparently it was not the Shell that sent us this enquiry,
+ # treat it as commandline
+ $what[0]{reqtype} = "c";
+ }
+ my $inherit_reqtype = $what[0]{reqtype} =~ /^(c|r)$/ ? "r" : "b";
+ WHAT: for my $what_tuple (@what) {
+ my($what,$reqtype) = @$what_tuple{qw(qmod reqtype)};
+ if ($reqtype eq "r"
+ &&
+ $inherit_reqtype eq "b"
+ ) {
+ $reqtype = "b";
+ }
+ my $jumped = 0;
+ for (my $i=0; $i<$#All;$i++) { #prevent deep recursion
+ # CPAN->debug("i[$i]this[$All[$i]{qmod}]what[$what]") if $CPAN::DEBUG;
+ if ($All[$i]{qmod} eq $what) {
+ $jumped++;
+ if ($jumped >= 50) {
+ die "PANIC: object[$what] 50 instances on the queue, looks like ".
+ "some recursiveness has hit";
+ } elsif ($jumped > 25) { # one's OK if e.g. just processing
+ # now; more are OK if user typed
+ # it several times
+ my $sleep = sprintf "%.1f", $jumped/10;
+ $CPAN::Frontend->mywarn(
+qq{Warning: Object [$what] queued $jumped times, sleeping $sleep secs!\n}
+ );
+ $CPAN::Frontend->mysleep($sleep);
+ # next WHAT;
+ }
+ }
+ }
+ my $obj = "$class\::Item"->new(
+ qmod => $what,
+ reqtype => $reqtype
+ );
+ unshift @All, $obj;
+ }
+ CPAN->debug(sprintf("after jumpqueue All[%s]",
+ join("",map {sprintf " %s\[%s]\n",$_->{qmod},$_->{reqtype}} @All)
+ )) if $CPAN::DEBUG;
+}
+
+# CPAN::Queue::exists ;
+sub exists {
+ my($self,$what) = @_;
+ my @all = map { $_->{qmod} } @All;
+ my $exists = grep { $_->{qmod} eq $what } @All;
+ # warn "in exists what[$what] all[@all] exists[$exists]";
+ $exists;
+}
+
+# CPAN::Queue::delete ;
+sub delete {
+ my($self,$mod) = @_;
+ @All = grep { $_->{qmod} ne $mod } @All;
+ CPAN->debug(sprintf("after delete mod[%s] All[%s]",
+ $mod,
+ join("",map {sprintf " %s\[%s]\n",$_->{qmod},$_->{reqtype}} @All)
+ )) if $CPAN::DEBUG;
+}
+
+# CPAN::Queue::nullify_queue ;
+sub nullify_queue {
+ @All = ();
+}
+
+# CPAN::Queue::size ;
+sub size {
+ return scalar @All;
+}
+
+1;
+
+__END__
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Shell.pm b/Master/tlpkg/tlperl/lib/CPAN/Shell.pm
new file mode 100644
index 00000000000..91cbdd22ac8
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Shell.pm
@@ -0,0 +1,1988 @@
+package CPAN::Shell;
+use strict;
+
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+# vim: ts=4 sts=4 sw=4:
+
+use vars qw(
+ $ADVANCED_QUERY
+ $AUTOLOAD
+ $COLOR_REGISTERED
+ $Help
+ $autoload_recursion
+ $reload
+ @ISA
+ @relo
+ $VERSION
+ );
+@relo = (
+ "CPAN.pm",
+ "CPAN/Author.pm",
+ "CPAN/CacheMgr.pm",
+ "CPAN/Complete.pm",
+ "CPAN/Debug.pm",
+ "CPAN/DeferredCode.pm",
+ "CPAN/Distribution.pm",
+ "CPAN/Distroprefs.pm",
+ "CPAN/Distrostatus.pm",
+ "CPAN/Exception/RecursiveDependency.pm",
+ "CPAN/Exception/yaml_not_installed.pm",
+ "CPAN/FirstTime.pm",
+ "CPAN/FTP.pm",
+ "CPAN/FTP/netrc.pm",
+ "CPAN/HandleConfig.pm",
+ "CPAN/Index.pm",
+ "CPAN/InfoObj.pm",
+ "CPAN/Kwalify.pm",
+ "CPAN/LWP/UserAgent.pm",
+ "CPAN/Module.pm",
+ "CPAN/Prompt.pm",
+ "CPAN/Queue.pm",
+ "CPAN/Reporter/Config.pm",
+ "CPAN/Reporter/History.pm",
+ "CPAN/Reporter/PrereqCheck.pm",
+ "CPAN/Reporter.pm",
+ "CPAN/Shell.pm",
+ "CPAN/SQLite.pm",
+ "CPAN/Tarzip.pm",
+ "CPAN/Version.pm",
+ );
+$VERSION = "5.5001";
+# record the initial timestamp for reload.
+$reload = { map {$INC{$_} ? ($_,(stat $INC{$_})[9]) : ()} @relo };
+@CPAN::Shell::ISA = qw(CPAN::Debug);
+use Cwd qw(chdir);
+use Carp ();
+$COLOR_REGISTERED ||= 0;
+$Help = {
+ '?' => \"help",
+ '!' => "eval the rest of the line as perl",
+ a => "whois author",
+ autobundle => "write inventory into a bundle file",
+ b => "info about bundle",
+ bye => \"quit",
+ clean => "clean up a distribution's build directory",
+ # cvs_import
+ d => "info about a distribution",
+ # dump
+ exit => \"quit",
+ failed => "list all failed actions within current session",
+ fforce => "redo a command from scratch",
+ force => "redo a command",
+ get => "download a distribution",
+ h => \"help",
+ help => "overview over commands; 'help ...' explains specific commands",
+ hosts => "statistics about recently used hosts",
+ i => "info about authors/bundles/distributions/modules",
+ install => "install a distribution",
+ install_tested => "install all distributions tested OK",
+ is_tested => "list all distributions tested OK",
+ look => "open a subshell in a distribution's directory",
+ ls => "list distributions matching a fileglob",
+ m => "info about a module",
+ make => "make/build a distribution",
+ mkmyconfig => "write current config into a CPAN/MyConfig.pm file",
+ notest => "run a (usually install) command but leave out the test phase",
+ o => "'o conf ...' for config stuff; 'o debug ...' for debugging",
+ perldoc => "try to get a manpage for a module",
+ q => \"quit",
+ quit => "leave the cpan shell",
+ r => "review upgradable modules",
+ readme => "display the README of a distro with a pager",
+ recent => "show recent uploads to the CPAN",
+ # recompile
+ reload => "'reload cpan' or 'reload index'",
+ report => "test a distribution and send a test report to cpantesters",
+ reports => "info about reported tests from cpantesters",
+ # scripts
+ # smoke
+ test => "test a distribution",
+ u => "display uninstalled modules",
+ upgrade => "combine 'r' command with immediate installation",
+ };
+{
+ $autoload_recursion ||= 0;
+
+ #-> sub CPAN::Shell::AUTOLOAD ;
+ sub AUTOLOAD { ## no critic
+ $autoload_recursion++;
+ my($l) = $AUTOLOAD;
+ my $class = shift(@_);
+ # warn "autoload[$l] class[$class]";
+ $l =~ s/.*:://;
+ if ($CPAN::Signal) {
+ warn "Refusing to autoload '$l' while signal pending";
+ $autoload_recursion--;
+ return;
+ }
+ if ($autoload_recursion > 1) {
+ my $fullcommand = join " ", map { "'$_'" } $l, @_;
+ warn "Refusing to autoload $fullcommand in recursion\n";
+ $autoload_recursion--;
+ return;
+ }
+ if ($l =~ /^w/) {
+ # XXX needs to be reconsidered
+ if ($CPAN::META->has_inst('CPAN::WAIT')) {
+ CPAN::WAIT->$l(@_);
+ } else {
+ $CPAN::Frontend->mywarn(qq{
+Commands starting with "w" require CPAN::WAIT to be installed.
+Please consider installing CPAN::WAIT to use the fulltext index.
+For this you just need to type
+ install CPAN::WAIT
+});
+ }
+ } else {
+ $CPAN::Frontend->mywarn(qq{Unknown shell command '$l'. }.
+ qq{Type ? for help.
+});
+ }
+ $autoload_recursion--;
+ }
+}
+
+
+#-> sub CPAN::Shell::h ;
+sub h {
+ my($class,$about) = @_;
+ if (defined $about) {
+ my $help;
+ if (exists $Help->{$about}) {
+ if (ref $Help->{$about}) { # aliases
+ $about = ${$Help->{$about}};
+ }
+ $help = $Help->{$about};
+ } else {
+ $help = "No help available";
+ }
+ $CPAN::Frontend->myprint("$about\: $help\n");
+ } else {
+ my $filler = " " x (80 - 28 - length($CPAN::VERSION));
+ $CPAN::Frontend->myprint(qq{
+Display Information $filler (ver $CPAN::VERSION)
+ command argument description
+ a,b,d,m WORD or /REGEXP/ about authors, bundles, distributions, modules
+ i WORD or /REGEXP/ about any of the above
+ ls AUTHOR or GLOB about files in the author's directory
+ (with WORD being a module, bundle or author name or a distribution
+ name of the form AUTHOR/DISTRIBUTION)
+
+Download, Test, Make, Install...
+ get download clean make clean
+ make make (implies get) look open subshell in dist directory
+ test make test (implies make) readme display these README files
+ install make install (implies test) perldoc display POD documentation
+
+Upgrade
+ r WORDs or /REGEXP/ or NONE report updates for some/matching/all modules
+ upgrade WORDs or /REGEXP/ or NONE upgrade some/matching/all modules
+
+Pragmas
+ force CMD try hard to do command fforce CMD try harder
+ notest CMD skip testing
+
+Other
+ h,? display this menu ! perl-code eval a perl command
+ o conf [opt] set and query options q quit the cpan shell
+ reload cpan load CPAN.pm again reload index load newer indices
+ autobundle Snapshot recent latest CPAN uploads});
+}
+}
+
+*help = \&h;
+
+#-> sub CPAN::Shell::a ;
+sub a {
+ my($self,@arg) = @_;
+ # authors are always UPPERCASE
+ for (@arg) {
+ $_ = uc $_ unless /=/;
+ }
+ $CPAN::Frontend->myprint($self->format_result('Author',@arg));
+}
+
+#-> sub CPAN::Shell::globls ;
+sub globls {
+ my($self,$s,$pragmas) = @_;
+ # ls is really very different, but we had it once as an ordinary
+ # command in the Shell (upto rev. 321) and we could not handle
+ # force well then
+ my(@accept,@preexpand);
+ if ($s =~ /[\*\?\/]/) {
+ if ($CPAN::META->has_inst("Text::Glob")) {
+ if (my($au,$pathglob) = $s =~ m|(.*?)/(.*)|) {
+ my $rau = Text::Glob::glob_to_regex(uc $au);
+ CPAN::Shell->debug("au[$au]pathglob[$pathglob]rau[$rau]")
+ if $CPAN::DEBUG;
+ push @preexpand, map { $_->id . "/" . $pathglob }
+ CPAN::Shell->expand_by_method('CPAN::Author',['id'],"/$rau/");
+ } else {
+ my $rau = Text::Glob::glob_to_regex(uc $s);
+ push @preexpand, map { $_->id }
+ CPAN::Shell->expand_by_method('CPAN::Author',
+ ['id'],
+ "/$rau/");
+ }
+ } else {
+ $CPAN::Frontend->mydie("Text::Glob not installed, cannot proceed");
+ }
+ } else {
+ push @preexpand, uc $s;
+ }
+ for (@preexpand) {
+ unless (/^[A-Z0-9\-]+(\/|$)/i) {
+ $CPAN::Frontend->mywarn("ls command rejects argument $_: not an author\n");
+ next;
+ }
+ push @accept, $_;
+ }
+ my $silent = @accept>1;
+ my $last_alpha = "";
+ my @results;
+ for my $a (@accept) {
+ my($author,$pathglob);
+ if ($a =~ m|(.*?)/(.*)|) {
+ my $a2 = $1;
+ $pathglob = $2;
+ $author = CPAN::Shell->expand_by_method('CPAN::Author',
+ ['id'],
+ $a2)
+ or $CPAN::Frontend->mydie("No author found for $a2\n");
+ } else {
+ $author = CPAN::Shell->expand_by_method('CPAN::Author',
+ ['id'],
+ $a)
+ or $CPAN::Frontend->mydie("No author found for $a\n");
+ }
+ if ($silent) {
+ my $alpha = substr $author->id, 0, 1;
+ my $ad;
+ if ($alpha eq $last_alpha) {
+ $ad = "";
+ } else {
+ $ad = "[$alpha]";
+ $last_alpha = $alpha;
+ }
+ $CPAN::Frontend->myprint($ad);
+ }
+ for my $pragma (@$pragmas) {
+ if ($author->can($pragma)) {
+ $author->$pragma();
+ }
+ }
+ CPAN->debug("author[$author]pathglob[$pathglob]silent[$silent]") if $CPAN::DEBUG;
+ push @results, $author->ls($pathglob,$silent); # silent if
+ # more than one
+ # author
+ for my $pragma (@$pragmas) {
+ my $unpragma = "un$pragma";
+ if ($author->can($unpragma)) {
+ $author->$unpragma();
+ }
+ }
+ }
+ @results;
+}
+
+#-> sub CPAN::Shell::local_bundles ;
+sub local_bundles {
+ my($self,@which) = @_;
+ my($incdir,$bdir,$dh);
+ foreach $incdir ($CPAN::Config->{'cpan_home'},@INC) {
+ my @bbase = "Bundle";
+ while (my $bbase = shift @bbase) {
+ $bdir = File::Spec->catdir($incdir,split /::/, $bbase);
+ CPAN->debug("bdir[$bdir]\@bbase[@bbase]") if $CPAN::DEBUG;
+ if ($dh = DirHandle->new($bdir)) { # may fail
+ my($entry);
+ for $entry ($dh->read) {
+ next if $entry =~ /^\./;
+ next unless $entry =~ /^\w+(\.pm)?(?!\n)\Z/;
+ if (-d File::Spec->catdir($bdir,$entry)) {
+ push @bbase, "$bbase\::$entry";
+ } else {
+ next unless $entry =~ s/\.pm(?!\n)\Z//;
+ $CPAN::META->instance('CPAN::Bundle',"$bbase\::$entry");
+ }
+ }
+ }
+ }
+ }
+}
+
+#-> sub CPAN::Shell::b ;
+sub b {
+ my($self,@which) = @_;
+ CPAN->debug("which[@which]") if $CPAN::DEBUG;
+ $self->local_bundles;
+ $CPAN::Frontend->myprint($self->format_result('Bundle',@which));
+}
+
+#-> sub CPAN::Shell::d ;
+sub d { $CPAN::Frontend->myprint(shift->format_result('Distribution',@_));}
+
+#-> sub CPAN::Shell::m ;
+sub m { # emacs confused here }; sub mimimimimi { # emacs in sync here
+ my $self = shift;
+ my @m = @_;
+ for (@m) {
+ if (m|(?:\w+/)*\w+\.pm$|) { # same regexp in expandany
+ s/.pm$//;
+ s|/|::|g;
+ }
+ }
+ $CPAN::Frontend->myprint($self->format_result('Module',@m));
+}
+
+#-> sub CPAN::Shell::i ;
+sub i {
+ my($self) = shift;
+ my(@args) = @_;
+ @args = '/./' unless @args;
+ my(@result);
+ for my $type (qw/Bundle Distribution Module/) {
+ push @result, $self->expand($type,@args);
+ }
+ # Authors are always uppercase.
+ push @result, $self->expand("Author", map { uc $_ } @args);
+
+ my $result = @result == 1 ?
+ $result[0]->as_string :
+ @result == 0 ?
+ "No objects found of any type for argument @args\n" :
+ join("",
+ (map {$_->as_glimpse} @result),
+ scalar @result, " items found\n",
+ );
+ $CPAN::Frontend->myprint($result);
+}
+
+#-> sub CPAN::Shell::o ;
+
+# CPAN::Shell::o and CPAN::HandleConfig::edit are closely related. 'o
+# conf' calls through to CPAN::HandleConfig::edit. 'o conf' should
+# probably have been called 'set' and 'o debug' maybe 'set debug' or
+# 'debug'; 'o conf ARGS' calls ->edit in CPAN/HandleConfig.pm
+sub o {
+ my($self,$o_type,@o_what) = @_;
+ $o_type ||= "";
+ CPAN->debug("o_type[$o_type] o_what[".join(" | ",@o_what)."]\n");
+ if ($o_type eq 'conf') {
+ my($cfilter);
+ ($cfilter) = $o_what[0] =~ m|^/(.*)/$| if @o_what;
+ if (!@o_what or $cfilter) { # print all things, "o conf"
+ $cfilter ||= "";
+ my $qrfilter = eval 'qr/$cfilter/';
+ my($k,$v);
+ $CPAN::Frontend->myprint("\$CPAN::Config options from ");
+ my @from;
+ if (exists $INC{'CPAN/Config.pm'}) {
+ push @from, $INC{'CPAN/Config.pm'};
+ }
+ if (exists $INC{'CPAN/MyConfig.pm'}) {
+ push @from, $INC{'CPAN/MyConfig.pm'};
+ }
+ $CPAN::Frontend->myprint(join " and ", map {"'$_'"} @from);
+ $CPAN::Frontend->myprint(":\n");
+ for $k (sort keys %CPAN::HandleConfig::can) {
+ next unless $k =~ /$qrfilter/;
+ $v = $CPAN::HandleConfig::can{$k};
+ $CPAN::Frontend->myprint(sprintf " %-18s [%s]\n", $k, $v);
+ }
+ $CPAN::Frontend->myprint("\n");
+ for $k (sort keys %CPAN::HandleConfig::keys) {
+ next unless $k =~ /$qrfilter/;
+ CPAN::HandleConfig->prettyprint($k);
+ }
+ $CPAN::Frontend->myprint("\n");
+ } else {
+ if (CPAN::HandleConfig->edit(@o_what)) {
+ } else {
+ $CPAN::Frontend->myprint(qq{Type 'o conf' to view all configuration }.
+ qq{items\n\n});
+ }
+ }
+ } elsif ($o_type eq 'debug') {
+ my(%valid);
+ @o_what = () if defined $o_what[0] && $o_what[0] =~ /help/i;
+ if (@o_what) {
+ while (@o_what) {
+ my($what) = shift @o_what;
+ if ($what =~ s/^-// && exists $CPAN::DEBUG{$what}) {
+ $CPAN::DEBUG &= $CPAN::DEBUG ^ $CPAN::DEBUG{$what};
+ next;
+ }
+ if ( exists $CPAN::DEBUG{$what} ) {
+ $CPAN::DEBUG |= $CPAN::DEBUG{$what};
+ } elsif ($what =~ /^\d/) {
+ $CPAN::DEBUG = $what;
+ } elsif (lc $what eq 'all') {
+ my($max) = 0;
+ for (values %CPAN::DEBUG) {
+ $max += $_;
+ }
+ $CPAN::DEBUG = $max;
+ } else {
+ my($known) = 0;
+ for (keys %CPAN::DEBUG) {
+ next unless lc($_) eq lc($what);
+ $CPAN::DEBUG |= $CPAN::DEBUG{$_};
+ $known = 1;
+ }
+ $CPAN::Frontend->myprint("unknown argument [$what]\n")
+ unless $known;
+ }
+ }
+ } else {
+ my $raw = "Valid options for debug are ".
+ join(", ",sort(keys %CPAN::DEBUG), 'all').
+ qq{ or a number. Completion works on the options. }.
+ qq{Case is ignored.};
+ require Text::Wrap;
+ $CPAN::Frontend->myprint(Text::Wrap::fill("","",$raw));
+ $CPAN::Frontend->myprint("\n\n");
+ }
+ if ($CPAN::DEBUG) {
+ $CPAN::Frontend->myprint("Options set for debugging ($CPAN::DEBUG):\n");
+ my($k,$v);
+ for $k (sort {$CPAN::DEBUG{$a} <=> $CPAN::DEBUG{$b}} keys %CPAN::DEBUG) {
+ $v = $CPAN::DEBUG{$k};
+ $CPAN::Frontend->myprint(sprintf " %-14s(%s)\n", $k, $v)
+ if $v & $CPAN::DEBUG;
+ }
+ } else {
+ $CPAN::Frontend->myprint("Debugging turned off completely.\n");
+ }
+ } else {
+ $CPAN::Frontend->myprint(qq{
+Known options:
+ conf set or get configuration variables
+ debug set or get debugging options
+});
+ }
+}
+
+# CPAN::Shell::paintdots_onreload
+sub paintdots_onreload {
+ my($ref) = shift;
+ sub {
+ if ( $_[0] =~ /[Ss]ubroutine ([\w:]+) redefined/ ) {
+ my($subr) = $1;
+ ++$$ref;
+ local($|) = 1;
+ # $CPAN::Frontend->myprint(".($subr)");
+ $CPAN::Frontend->myprint(".");
+ if ($subr =~ /\bshell\b/i) {
+ # warn "debug[$_[0]]";
+
+ # It would be nice if we could detect that a
+ # subroutine has actually changed, but for now we
+ # practically always set the GOTOSHELL global
+
+ $CPAN::GOTOSHELL=1;
+ }
+ return;
+ }
+ warn @_;
+ };
+}
+
+#-> sub CPAN::Shell::hosts ;
+sub hosts {
+ my($self) = @_;
+ my $fullstats = CPAN::FTP->_ftp_statistics();
+ my $history = $fullstats->{history} || [];
+ my %S; # statistics
+ while (my $last = pop @$history) {
+ my $attempts = $last->{attempts} or next;
+ my $start;
+ if (@$attempts) {
+ $start = $attempts->[-1]{start};
+ if ($#$attempts > 0) {
+ for my $i (0..$#$attempts-1) {
+ my $url = $attempts->[$i]{url} or next;
+ $S{no}{$url}++;
+ }
+ }
+ } else {
+ $start = $last->{start};
+ }
+ next unless $last->{thesiteurl}; # C-C? bad filenames?
+ $S{start} = $start;
+ $S{end} ||= $last->{end};
+ my $dltime = $last->{end} - $start;
+ my $dlsize = $last->{filesize} || 0;
+ my $url = ref $last->{thesiteurl} ? $last->{thesiteurl}->text : $last->{thesiteurl};
+ my $s = $S{ok}{$url} ||= {};
+ $s->{n}++;
+ $s->{dlsize} ||= 0;
+ $s->{dlsize} += $dlsize/1024;
+ $s->{dltime} ||= 0;
+ $s->{dltime} += $dltime;
+ }
+ my $res;
+ for my $url (keys %{$S{ok}}) {
+ next if $S{ok}{$url}{dltime} == 0; # div by zero
+ push @{$res->{ok}}, [@{$S{ok}{$url}}{qw(n dlsize dltime)},
+ $S{ok}{$url}{dlsize}/$S{ok}{$url}{dltime},
+ $url,
+ ];
+ }
+ for my $url (keys %{$S{no}}) {
+ push @{$res->{no}}, [$S{no}{$url},
+ $url,
+ ];
+ }
+ my $R = ""; # report
+ if ($S{start} && $S{end}) {
+ $R .= sprintf "Log starts: %s\n", $S{start} ? scalar(localtime $S{start}) : "unknown";
+ $R .= sprintf "Log ends : %s\n", $S{end} ? scalar(localtime $S{end}) : "unknown";
+ }
+ if ($res->{ok} && @{$res->{ok}}) {
+ $R .= sprintf "\nSuccessful downloads:
+ N kB secs kB/s url\n";
+ my $i = 20;
+ for (sort { $b->[3] <=> $a->[3] } @{$res->{ok}}) {
+ $R .= sprintf "%4d %8d %5d %9.1f %s\n", @$_;
+ last if --$i<=0;
+ }
+ }
+ if ($res->{no} && @{$res->{no}}) {
+ $R .= sprintf "\nUnsuccessful downloads:\n";
+ my $i = 20;
+ for (sort { $b->[0] <=> $a->[0] } @{$res->{no}}) {
+ $R .= sprintf "%4d %s\n", @$_;
+ last if --$i<=0;
+ }
+ }
+ $CPAN::Frontend->myprint($R);
+}
+
+# here is where 'reload cpan' is done
+#-> sub CPAN::Shell::reload ;
+sub reload {
+ my($self,$command,@arg) = @_;
+ $command ||= "";
+ $self->debug("self[$self]command[$command]arg[@arg]") if $CPAN::DEBUG;
+ if ($command =~ /^cpan$/i) {
+ my $redef = 0;
+ chdir $CPAN::iCwd if $CPAN::iCwd; # may fail
+ my $failed;
+ MFILE: for my $f (@relo) {
+ next unless exists $INC{$f};
+ my $p = $f;
+ $p =~ s/\.pm$//;
+ $p =~ s|/|::|g;
+ $CPAN::Frontend->myprint("($p");
+ local($SIG{__WARN__}) = paintdots_onreload(\$redef);
+ $self->_reload_this($f) or $failed++;
+ my $v = eval "$p\::->VERSION";
+ $CPAN::Frontend->myprint("v$v)");
+ }
+ $CPAN::Frontend->myprint("\n$redef subroutines redefined\n");
+ if ($failed) {
+ my $errors = $failed == 1 ? "error" : "errors";
+ $CPAN::Frontend->mywarn("\n$failed $errors during reload. You better quit ".
+ "this session.\n");
+ }
+ } elsif ($command =~ /^index$/i) {
+ CPAN::Index->force_reload;
+ } else {
+ $CPAN::Frontend->myprint(qq{cpan re-evals the CPAN modules
+index re-reads the index files\n});
+ }
+}
+
+# reload means only load again what we have loaded before
+#-> sub CPAN::Shell::_reload_this ;
+sub _reload_this {
+ my($self,$f,$args) = @_;
+ CPAN->debug("f[$f]") if $CPAN::DEBUG;
+ return 1 unless $INC{$f}; # we never loaded this, so we do not
+ # reload but say OK
+ my $pwd = CPAN::anycwd();
+ CPAN->debug("pwd[$pwd]") if $CPAN::DEBUG;
+ my($file);
+ for my $inc (@INC) {
+ $file = File::Spec->catfile($inc,split /\//, $f);
+ last if -f $file;
+ $file = "";
+ }
+ CPAN->debug("file[$file]") if $CPAN::DEBUG;
+ my @inc = @INC;
+ unless ($file && -f $file) {
+ # this thingie is not in the INC path, maybe CPAN/MyConfig.pm?
+ $file = $INC{$f};
+ unless (CPAN->has_inst("File::Basename")) {
+ @inc = File::Basename::dirname($file);
+ } else {
+ # do we ever need this?
+ @inc = substr($file,0,-length($f)-1); # bring in back to me!
+ }
+ }
+ CPAN->debug("file[$file]inc[@inc]") if $CPAN::DEBUG;
+ unless (-f $file) {
+ $CPAN::Frontend->mywarn("Found no file to reload for '$f'\n");
+ return;
+ }
+ my $mtime = (stat $file)[9];
+ $reload->{$f} ||= -1;
+ my $must_reload = $mtime != $reload->{$f};
+ $args ||= {};
+ $must_reload ||= $args->{reloforce}; # o conf defaults needs this
+ if ($must_reload) {
+ my $fh = FileHandle->new($file) or
+ $CPAN::Frontend->mydie("Could not open $file: $!");
+ local($/);
+ local $^W = 1;
+ my $content = <$fh>;
+ CPAN->debug(sprintf("reload file[%s] content[%s...]",$file,substr($content,0,128)))
+ if $CPAN::DEBUG;
+ delete $INC{$f};
+ local @INC = @inc;
+ eval "require '$f'";
+ if ($@) {
+ warn $@;
+ return;
+ }
+ $reload->{$f} = $mtime;
+ } else {
+ $CPAN::Frontend->myprint("__unchanged__");
+ }
+ return 1;
+}
+
+#-> sub CPAN::Shell::mkmyconfig ;
+sub mkmyconfig {
+ my($self, $cpanpm, %args) = @_;
+ require CPAN::FirstTime;
+ my $home = CPAN::HandleConfig::home();
+ $cpanpm = $INC{'CPAN/MyConfig.pm'} ||
+ File::Spec->catfile(split /\//, "$home/.cpan/CPAN/MyConfig.pm");
+ File::Path::mkpath(File::Basename::dirname($cpanpm)) unless -e $cpanpm;
+ CPAN::HandleConfig::require_myconfig_or_config();
+ $CPAN::Config ||= {};
+ $CPAN::Config = {
+ %$CPAN::Config,
+ build_dir => undef,
+ cpan_home => undef,
+ keep_source_where => undef,
+ histfile => undef,
+ };
+ CPAN::FirstTime::init($cpanpm, %args);
+}
+
+#-> sub CPAN::Shell::_binary_extensions ;
+sub _binary_extensions {
+ my($self) = shift @_;
+ my(@result,$module,%seen,%need,$headerdone);
+ for $module ($self->expand('Module','/./')) {
+ my $file = $module->cpan_file;
+ next if $file eq "N/A";
+ next if $file =~ /^Contact Author/;
+ my $dist = $CPAN::META->instance('CPAN::Distribution',$file);
+ next if $dist->isa_perl;
+ next unless $module->xs_file;
+ local($|) = 1;
+ $CPAN::Frontend->myprint(".");
+ push @result, $module;
+ }
+# print join " | ", @result;
+ $CPAN::Frontend->myprint("\n");
+ return @result;
+}
+
+#-> sub CPAN::Shell::recompile ;
+sub recompile {
+ my($self) = shift @_;
+ my($module,@module,$cpan_file,%dist);
+ @module = $self->_binary_extensions();
+ for $module (@module) { # we force now and compile later, so we
+ # don't do it twice
+ $cpan_file = $module->cpan_file;
+ my $pack = $CPAN::META->instance('CPAN::Distribution',$cpan_file);
+ $pack->force;
+ $dist{$cpan_file}++;
+ }
+ for $cpan_file (sort keys %dist) {
+ $CPAN::Frontend->myprint(" CPAN: Recompiling $cpan_file\n\n");
+ my $pack = $CPAN::META->instance('CPAN::Distribution',$cpan_file);
+ $pack->install;
+ $CPAN::Signal = 0; # it's tempting to reset Signal, so we can
+ # stop a package from recompiling,
+ # e.g. IO-1.12 when we have perl5.003_10
+ }
+}
+
+#-> sub CPAN::Shell::scripts ;
+sub scripts {
+ my($self, $arg) = @_;
+ $CPAN::Frontend->mywarn(">>>> experimental command, currently unsupported <<<<\n\n");
+
+ for my $req (qw( HTML::LinkExtor Sort::Versions List::Util )) {
+ unless ($CPAN::META->has_inst($req)) {
+ $CPAN::Frontend->mywarn(" $req not available\n");
+ }
+ }
+ my $p = HTML::LinkExtor->new();
+ my $indexfile = "/home/ftp/pub/PAUSE/scripts/new/index.html";
+ unless (-f $indexfile) {
+ $CPAN::Frontend->mydie("found no indexfile[$indexfile]\n");
+ }
+ $p->parse_file($indexfile);
+ my @hrefs;
+ my $qrarg;
+ if ($arg =~ s|^/(.+)/$|$1|) {
+ $qrarg = eval 'qr/$arg/'; # hide construct from 5.004
+ }
+ for my $l ($p->links) {
+ my $tag = shift @$l;
+ next unless $tag eq "a";
+ my %att = @$l;
+ my $href = $att{href};
+ next unless $href =~ s|^\.\./authors/id/./../||;
+ if ($arg) {
+ if ($qrarg) {
+ if ($href =~ $qrarg) {
+ push @hrefs, $href;
+ }
+ } else {
+ if ($href =~ /\Q$arg\E/) {
+ push @hrefs, $href;
+ }
+ }
+ } else {
+ push @hrefs, $href;
+ }
+ }
+ # now filter for the latest version if there is more than one of a name
+ my %stems;
+ for (sort @hrefs) {
+ my $href = $_;
+ s/-v?\d.*//;
+ my $stem = $_;
+ $stems{$stem} ||= [];
+ push @{$stems{$stem}}, $href;
+ }
+ for (sort keys %stems) {
+ my $highest;
+ if (@{$stems{$_}} > 1) {
+ $highest = List::Util::reduce {
+ Sort::Versions::versioncmp($a,$b) > 0 ? $a : $b
+ } @{$stems{$_}};
+ } else {
+ $highest = $stems{$_}[0];
+ }
+ $CPAN::Frontend->myprint("$highest\n");
+ }
+}
+
+#-> sub CPAN::Shell::report ;
+sub report {
+ my($self,@args) = @_;
+ unless ($CPAN::META->has_inst("CPAN::Reporter")) {
+ $CPAN::Frontend->mydie("CPAN::Reporter not installed; cannot continue");
+ }
+ local $CPAN::Config->{test_report} = 1;
+ $self->force("test",@args); # force is there so that the test be
+ # re-run (as documented)
+}
+
+# compare with is_tested
+#-> sub CPAN::Shell::install_tested
+sub install_tested {
+ my($self,@some) = @_;
+ $CPAN::Frontend->mywarn("install_tested() must not be called with arguments.\n"),
+ return if @some;
+ CPAN::Index->reload;
+
+ for my $b (reverse $CPAN::META->_list_sorted_descending_is_tested) {
+ my $yaml = "$b.yml";
+ unless (-f $yaml) {
+ $CPAN::Frontend->mywarn("No YAML file for $b available, skipping\n");
+ next;
+ }
+ my $yaml_content = CPAN->_yaml_loadfile($yaml);
+ my $id = $yaml_content->[0]{distribution}{ID};
+ unless ($id) {
+ $CPAN::Frontend->mywarn("No ID found in '$yaml', skipping\n");
+ next;
+ }
+ my $do = CPAN::Shell->expandany($id);
+ unless ($do) {
+ $CPAN::Frontend->mywarn("Could not expand ID '$id', skipping\n");
+ next;
+ }
+ unless ($do->{build_dir}) {
+ $CPAN::Frontend->mywarn("Distro '$id' has no build_dir, skipping\n");
+ next;
+ }
+ unless ($do->{build_dir} eq $b) {
+ $CPAN::Frontend->mywarn("Distro '$id' has build_dir '$do->{build_dir}' but expected '$b', skipping\n");
+ next;
+ }
+ push @some, $do;
+ }
+
+ $CPAN::Frontend->mywarn("No tested distributions found.\n"),
+ return unless @some;
+
+ @some = grep { $_->{make_test} && ! $_->{make_test}->failed } @some;
+ $CPAN::Frontend->mywarn("No distributions tested with this build of perl found.\n"),
+ return unless @some;
+
+ # @some = grep { not $_->uptodate } @some;
+ # $CPAN::Frontend->mywarn("No non-uptodate distributions tested with this build of perl found.\n"),
+ # return unless @some;
+
+ CPAN->debug("some[@some]");
+ for my $d (@some) {
+ my $id = $d->can("pretty_id") ? $d->pretty_id : $d->id;
+ $CPAN::Frontend->myprint("install_tested: Running for $id\n");
+ $CPAN::Frontend->mysleep(1);
+ $self->install($d);
+ }
+}
+
+#-> sub CPAN::Shell::upgrade ;
+sub upgrade {
+ my($self,@args) = @_;
+ $self->install($self->r(@args));
+}
+
+#-> sub CPAN::Shell::_u_r_common ;
+sub _u_r_common {
+ my($self) = shift @_;
+ my($what) = shift @_;
+ CPAN->debug("self[$self] what[$what] args[@_]") if $CPAN::DEBUG;
+ Carp::croak "Usage: \$obj->_u_r_common(a|r|u)" unless
+ $what && $what =~ /^[aru]$/;
+ my(@args) = @_;
+ @args = '/./' unless @args;
+ my(@result,$module,%seen,%need,$headerdone,
+ $version_undefs,$version_zeroes,
+ @version_undefs,@version_zeroes);
+ $version_undefs = $version_zeroes = 0;
+ my $sprintf = "%s%-25s%s %9s %9s %s\n";
+ my @expand = $self->expand('Module',@args);
+ if ($CPAN::DEBUG) { # Looks like noise to me, was very useful for debugging
+ # for metadata cache
+ my $expand = scalar @expand;
+ $CPAN::Frontend->myprint(sprintf "%d matches in the database, time[%d]\n", $expand, time);
+ }
+ my @sexpand;
+ if ($] < 5.008) {
+ # hard to believe that the more complex sorting can lead to
+ # stack curruptions on older perl
+ @sexpand = sort {$a->id cmp $b->id} @expand;
+ } else {
+ @sexpand = map {
+ $_->[1]
+ } sort {
+ $b->[0] <=> $a->[0]
+ ||
+ $a->[1]{ID} cmp $b->[1]{ID},
+ } map {
+ [$_->_is_representative_module,
+ $_
+ ]
+ } @expand;
+ }
+ if ($CPAN::DEBUG) {
+ $CPAN::Frontend->myprint(sprintf "sorted at time[%d]\n", time);
+ sleep 1;
+ }
+ MODULE: for $module (@sexpand) {
+ my $file = $module->cpan_file;
+ next MODULE unless defined $file; # ??
+ $file =~ s!^./../!!;
+ my($latest) = $module->cpan_version;
+ my($inst_file) = $module->inst_file;
+ CPAN->debug("file[$file]latest[$latest]") if $CPAN::DEBUG;
+ my($have);
+ return if $CPAN::Signal;
+ my($next_MODULE);
+ eval { # version.pm involved!
+ if ($inst_file) {
+ if ($what eq "a") {
+ $have = $module->inst_version;
+ } elsif ($what eq "r") {
+ $have = $module->inst_version;
+ local($^W) = 0;
+ if ($have eq "undef") {
+ $version_undefs++;
+ push @version_undefs, $module->as_glimpse;
+ } elsif (CPAN::Version->vcmp($have,0)==0) {
+ $version_zeroes++;
+ push @version_zeroes, $module->as_glimpse;
+ }
+ ++$next_MODULE unless CPAN::Version->vgt($latest, $have);
+ # to be pedantic we should probably say:
+ # && !($have eq "undef" && $latest ne "undef" && $latest gt "");
+ # to catch the case where CPAN has a version 0 and we have a version undef
+ } elsif ($what eq "u") {
+ ++$next_MODULE;
+ }
+ } else {
+ if ($what eq "a") {
+ ++$next_MODULE;
+ } elsif ($what eq "r") {
+ ++$next_MODULE;
+ } elsif ($what eq "u") {
+ $have = "-";
+ }
+ }
+ };
+ next MODULE if $next_MODULE;
+ if ($@) {
+ $CPAN::Frontend->mywarn
+ (sprintf("Error while comparing cpan/installed versions of '%s':
+INST_FILE: %s
+INST_VERSION: %s %s
+CPAN_VERSION: %s %s
+",
+ $module->id,
+ $inst_file || "",
+ (defined $have ? $have : "[UNDEFINED]"),
+ (ref $have ? ref $have : ""),
+ $latest,
+ (ref $latest ? ref $latest : ""),
+ ));
+ next MODULE;
+ }
+ return if $CPAN::Signal; # this is sometimes lengthy
+ $seen{$file} ||= 0;
+ if ($what eq "a") {
+ push @result, sprintf "%s %s\n", $module->id, $have;
+ } elsif ($what eq "r") {
+ push @result, $module->id;
+ next MODULE if $seen{$file}++;
+ } elsif ($what eq "u") {
+ push @result, $module->id;
+ next MODULE if $seen{$file}++;
+ next MODULE if $file =~ /^Contact/;
+ }
+ unless ($headerdone++) {
+ $CPAN::Frontend->myprint("\n");
+ $CPAN::Frontend->myprint(sprintf(
+ $sprintf,
+ "",
+ "Package namespace",
+ "",
+ "installed",
+ "latest",
+ "in CPAN file"
+ ));
+ }
+ my $color_on = "";
+ my $color_off = "";
+ if (
+ $COLOR_REGISTERED
+ &&
+ $CPAN::META->has_inst("Term::ANSIColor")
+ &&
+ $module->description
+ ) {
+ $color_on = Term::ANSIColor::color("green");
+ $color_off = Term::ANSIColor::color("reset");
+ }
+ $CPAN::Frontend->myprint(sprintf $sprintf,
+ $color_on,
+ $module->id,
+ $color_off,
+ $have,
+ $latest,
+ $file);
+ $need{$module->id}++;
+ }
+ unless (%need) {
+ if ($what eq "u") {
+ $CPAN::Frontend->myprint("No modules found for @args\n");
+ } elsif ($what eq "r") {
+ $CPAN::Frontend->myprint("All modules are up to date for @args\n");
+ }
+ }
+ if ($what eq "r") {
+ if ($version_zeroes) {
+ my $s_has = $version_zeroes > 1 ? "s have" : " has";
+ $CPAN::Frontend->myprint(qq{$version_zeroes installed module$s_has }.
+ qq{a version number of 0\n});
+ if ($CPAN::Config->{show_zero_versions}) {
+ local $" = "\t";
+ $CPAN::Frontend->myprint(qq{ they are\n\t@version_zeroes\n});
+ $CPAN::Frontend->myprint(qq{(use 'o conf show_zero_versions 0' }.
+ qq{to hide them)\n});
+ } else {
+ $CPAN::Frontend->myprint(qq{(use 'o conf show_zero_versions 1' }.
+ qq{to show them)\n});
+ }
+ }
+ if ($version_undefs) {
+ my $s_has = $version_undefs > 1 ? "s have" : " has";
+ $CPAN::Frontend->myprint(qq{$version_undefs installed module$s_has no }.
+ qq{parsable version number\n});
+ if ($CPAN::Config->{show_unparsable_versions}) {
+ local $" = "\t";
+ $CPAN::Frontend->myprint(qq{ they are\n\t@version_undefs\n});
+ $CPAN::Frontend->myprint(qq{(use 'o conf show_unparsable_versions 0' }.
+ qq{to hide them)\n});
+ } else {
+ $CPAN::Frontend->myprint(qq{(use 'o conf show_unparsable_versions 1' }.
+ qq{to show them)\n});
+ }
+ }
+ }
+ @result;
+}
+
+#-> sub CPAN::Shell::r ;
+sub r {
+ shift->_u_r_common("r",@_);
+}
+
+#-> sub CPAN::Shell::u ;
+sub u {
+ shift->_u_r_common("u",@_);
+}
+
+#-> sub CPAN::Shell::failed ;
+sub failed {
+ my($self,$only_id,$silent) = @_;
+ my @failed;
+ DIST: for my $d ($CPAN::META->all_objects("CPAN::Distribution")) {
+ my $failed = "";
+ NAY: for my $nosayer ( # order matters!
+ "unwrapped",
+ "writemakefile",
+ "signature_verify",
+ "make",
+ "make_test",
+ "install",
+ "make_clean",
+ ) {
+ next unless exists $d->{$nosayer};
+ next unless defined $d->{$nosayer};
+ next unless (
+ UNIVERSAL::can($d->{$nosayer},"failed") ?
+ $d->{$nosayer}->failed :
+ $d->{$nosayer} =~ /^NO/
+ );
+ next NAY if $only_id && $only_id != (
+ UNIVERSAL::can($d->{$nosayer},"commandid")
+ ?
+ $d->{$nosayer}->commandid
+ :
+ $CPAN::CurrentCommandId
+ );
+ $failed = $nosayer;
+ last;
+ }
+ next DIST unless $failed;
+ my $id = $d->id;
+ $id =~ s|^./../||;
+ #$print .= sprintf(
+ # " %-45s: %s %s\n",
+ push @failed,
+ (
+ UNIVERSAL::can($d->{$failed},"failed") ?
+ [
+ $d->{$failed}->commandid,
+ $id,
+ $failed,
+ $d->{$failed}->text,
+ $d->{$failed}{TIME}||0,
+ ] :
+ [
+ 1,
+ $id,
+ $failed,
+ $d->{$failed},
+ 0,
+ ]
+ );
+ }
+ my $scope;
+ if ($only_id) {
+ $scope = "this command";
+ } elsif ($CPAN::Index::HAVE_REANIMATED) {
+ $scope = "this or a previous session";
+ # it might be nice to have a section for previous session and
+ # a second for this
+ } else {
+ $scope = "this session";
+ }
+ if (@failed) {
+ my $print;
+ my $debug = 0;
+ if ($debug) {
+ $print = join "",
+ map { sprintf "%5d %-45s: %s %s\n", @$_ }
+ sort { $a->[0] <=> $b->[0] } @failed;
+ } else {
+ $print = join "",
+ map { sprintf " %-45s: %s %s\n", @$_[1..3] }
+ sort {
+ $a->[0] <=> $b->[0]
+ ||
+ $a->[4] <=> $b->[4]
+ } @failed;
+ }
+ $CPAN::Frontend->myprint("Failed during $scope:\n$print");
+ } elsif (!$only_id || !$silent) {
+ $CPAN::Frontend->myprint("Nothing failed in $scope\n");
+ }
+}
+
+# XXX intentionally undocumented because completely bogus, unportable,
+# useless, etc.
+
+#-> sub CPAN::Shell::status ;
+sub status {
+ my($self) = @_;
+ require Devel::Size;
+ my $ps = FileHandle->new;
+ open $ps, "/proc/$$/status";
+ my $vm = 0;
+ while (<$ps>) {
+ next unless /VmSize:\s+(\d+)/;
+ $vm = $1;
+ last;
+ }
+ $CPAN::Frontend->mywarn(sprintf(
+ "%-27s %6d\n%-27s %6d\n",
+ "vm",
+ $vm,
+ "CPAN::META",
+ Devel::Size::total_size($CPAN::META)/1024,
+ ));
+ for my $k (sort keys %$CPAN::META) {
+ next unless substr($k,0,4) eq "read";
+ warn sprintf " %-26s %6d\n", $k, Devel::Size::total_size($CPAN::META->{$k})/1024;
+ for my $k2 (sort keys %{$CPAN::META->{$k}}) {
+ warn sprintf " %-25s %6d (keys: %6d)\n",
+ $k2,
+ Devel::Size::total_size($CPAN::META->{$k}{$k2})/1024,
+ scalar keys %{$CPAN::META->{$k}{$k2}};
+ }
+ }
+}
+
+# compare with install_tested
+#-> sub CPAN::Shell::is_tested
+sub is_tested {
+ my($self) = @_;
+ CPAN::Index->reload;
+ for my $b (reverse $CPAN::META->_list_sorted_descending_is_tested) {
+ my $time;
+ if ($CPAN::META->{is_tested}{$b}) {
+ $time = scalar(localtime $CPAN::META->{is_tested}{$b});
+ } else {
+ $time = scalar localtime;
+ $time =~ s/\S/?/g;
+ }
+ $CPAN::Frontend->myprint(sprintf "%s %s\n", $time, $b);
+ }
+}
+
+#-> sub CPAN::Shell::autobundle ;
+sub autobundle {
+ my($self) = shift;
+ CPAN::HandleConfig->load unless $CPAN::Config_loaded++;
+ my(@bundle) = $self->_u_r_common("a",@_);
+ my($todir) = File::Spec->catdir($CPAN::Config->{'cpan_home'},"Bundle");
+ File::Path::mkpath($todir);
+ unless (-d $todir) {
+ $CPAN::Frontend->myprint("Couldn't mkdir $todir for some reason\n");
+ return;
+ }
+ my($y,$m,$d) = (localtime)[5,4,3];
+ $y+=1900;
+ $m++;
+ my($c) = 0;
+ my($me) = sprintf "Snapshot_%04d_%02d_%02d_%02d", $y, $m, $d, $c;
+ my($to) = File::Spec->catfile($todir,"$me.pm");
+ while (-f $to) {
+ $me = sprintf "Snapshot_%04d_%02d_%02d_%02d", $y, $m, $d, ++$c;
+ $to = File::Spec->catfile($todir,"$me.pm");
+ }
+ my($fh) = FileHandle->new(">$to") or Carp::croak "Can't open >$to: $!";
+ $fh->print(
+ "package Bundle::$me;\n\n",
+ "\$","VERSION = '0.01';\n\n", # hide from perl-reversion
+ "1;\n\n",
+ "__END__\n\n",
+ "=head1 NAME\n\n",
+ "Bundle::$me - Snapshot of installation on ",
+ $Config::Config{'myhostname'},
+ " on ",
+ scalar(localtime),
+ "\n\n=head1 SYNOPSIS\n\n",
+ "perl -MCPAN -e 'install Bundle::$me'\n\n",
+ "=head1 CONTENTS\n\n",
+ join("\n", @bundle),
+ "\n\n=head1 CONFIGURATION\n\n",
+ Config->myconfig,
+ "\n\n=head1 AUTHOR\n\n",
+ "This Bundle has been generated automatically ",
+ "by the autobundle routine in CPAN.pm.\n",
+ );
+ $fh->close;
+ $CPAN::Frontend->myprint("\nWrote bundle file
+ $to\n\n");
+}
+
+#-> sub CPAN::Shell::expandany ;
+sub expandany {
+ my($self,$s) = @_;
+ CPAN->debug("s[$s]") if $CPAN::DEBUG;
+ my $module_as_path = "";
+ if ($s =~ m|(?:\w+/)*\w+\.pm$|) { # same regexp in sub m
+ $module_as_path = $s;
+ $module_as_path =~ s/.pm$//;
+ $module_as_path =~ s|/|::|g;
+ }
+ if ($module_as_path) {
+ if ($module_as_path =~ m|^Bundle::|) {
+ $self->local_bundles;
+ return $self->expand('Bundle',$module_as_path);
+ } else {
+ return $self->expand('Module',$module_as_path)
+ if $CPAN::META->exists('CPAN::Module',$module_as_path);
+ }
+ } elsif ($s =~ m|/| or substr($s,-1,1) eq ".") { # looks like a file or a directory
+ $s = CPAN::Distribution->normalize($s);
+ return $CPAN::META->instance('CPAN::Distribution',$s);
+ # Distributions spring into existence, not expand
+ } elsif ($s =~ m|^Bundle::|) {
+ $self->local_bundles; # scanning so late for bundles seems
+ # both attractive and crumpy: always
+ # current state but easy to forget
+ # somewhere
+ return $self->expand('Bundle',$s);
+ } else {
+ return $self->expand('Module',$s)
+ if $CPAN::META->exists('CPAN::Module',$s);
+ }
+ return;
+}
+
+#-> sub CPAN::Shell::expand ;
+sub expand {
+ my $self = shift;
+ my($type,@args) = @_;
+ CPAN->debug("type[$type]args[@args]") if $CPAN::DEBUG;
+ my $class = "CPAN::$type";
+ my $methods = ['id'];
+ for my $meth (qw(name)) {
+ next unless $class->can($meth);
+ push @$methods, $meth;
+ }
+ $self->expand_by_method($class,$methods,@args);
+}
+
+#-> sub CPAN::Shell::expand_by_method ;
+sub expand_by_method {
+ my $self = shift;
+ my($class,$methods,@args) = @_;
+ my($arg,@m);
+ for $arg (@args) {
+ my($regex,$command);
+ if ($arg =~ m|^/(.*)/$|) {
+ $regex = $1;
+# FIXME: there seem to be some ='s in the author data, which trigger
+# a failure here. This needs to be contemplated.
+# } elsif ($arg =~ m/=/) {
+# $command = 1;
+ }
+ my $obj;
+ CPAN->debug(sprintf "class[%s]regex[%s]command[%s]",
+ $class,
+ defined $regex ? $regex : "UNDEFINED",
+ defined $command ? $command : "UNDEFINED",
+ ) if $CPAN::DEBUG;
+ if (defined $regex) {
+ if (CPAN::_sqlite_running()) {
+ CPAN::Index->reload;
+ $CPAN::SQLite->search($class, $regex);
+ }
+ for $obj (
+ $CPAN::META->all_objects($class)
+ ) {
+ unless ($obj && UNIVERSAL::can($obj,"id") && $obj->id) {
+ # BUG, we got an empty object somewhere
+ require Data::Dumper;
+ CPAN->debug(sprintf(
+ "Bug in CPAN: Empty id on obj[%s][%s]",
+ $obj,
+ Data::Dumper::Dumper($obj)
+ )) if $CPAN::DEBUG;
+ next;
+ }
+ for my $method (@$methods) {
+ my $match = eval {$obj->$method() =~ /$regex/i};
+ if ($@) {
+ my($err) = $@ =~ /^(.+) at .+? line \d+\.$/;
+ $err ||= $@; # if we were too restrictive above
+ $CPAN::Frontend->mydie("$err\n");
+ } elsif ($match) {
+ push @m, $obj;
+ last;
+ }
+ }
+ }
+ } elsif ($command) {
+ die "equal sign in command disabled (immature interface), ".
+ "you can set
+ ! \$CPAN::Shell::ADVANCED_QUERY=1
+to enable it. But please note, this is HIGHLY EXPERIMENTAL code
+that may go away anytime.\n"
+ unless $ADVANCED_QUERY;
+ my($method,$criterion) = $arg =~ /(.+?)=(.+)/;
+ my($matchcrit) = $criterion =~ m/^~(.+)/;
+ for my $self (
+ sort
+ {$a->id cmp $b->id}
+ $CPAN::META->all_objects($class)
+ ) {
+ my $lhs = $self->$method() or next; # () for 5.00503
+ if ($matchcrit) {
+ push @m, $self if $lhs =~ m/$matchcrit/;
+ } else {
+ push @m, $self if $lhs eq $criterion;
+ }
+ }
+ } else {
+ my($xarg) = $arg;
+ if ( $class eq 'CPAN::Bundle' ) {
+ $xarg =~ s/^(Bundle::)?(.*)/Bundle::$2/;
+ } elsif ($class eq "CPAN::Distribution") {
+ $xarg = CPAN::Distribution->normalize($arg);
+ } else {
+ $xarg =~ s/:+/::/g;
+ }
+ if ($CPAN::META->exists($class,$xarg)) {
+ $obj = $CPAN::META->instance($class,$xarg);
+ } elsif ($CPAN::META->exists($class,$arg)) {
+ $obj = $CPAN::META->instance($class,$arg);
+ } else {
+ next;
+ }
+ push @m, $obj;
+ }
+ }
+ @m = sort {$a->id cmp $b->id} @m;
+ if ( $CPAN::DEBUG ) {
+ my $wantarray = wantarray;
+ my $join_m = join ",", map {$_->id} @m;
+ # $self->debug("wantarray[$wantarray]join_m[$join_m]");
+ my $count = scalar @m;
+ $self->debug("class[$class]wantarray[$wantarray]count m[$count]");
+ }
+ return wantarray ? @m : $m[0];
+}
+
+#-> sub CPAN::Shell::format_result ;
+sub format_result {
+ my($self) = shift;
+ my($type,@args) = @_;
+ @args = '/./' unless @args;
+ my(@result) = $self->expand($type,@args);
+ my $result = @result == 1 ?
+ $result[0]->as_string :
+ @result == 0 ?
+ "No objects of type $type found for argument @args\n" :
+ join("",
+ (map {$_->as_glimpse} @result),
+ scalar @result, " items found\n",
+ );
+ $result;
+}
+
+#-> sub CPAN::Shell::report_fh ;
+{
+ my $installation_report_fh;
+ my $previously_noticed = 0;
+
+ sub report_fh {
+ return $installation_report_fh if $installation_report_fh;
+ if ($CPAN::META->has_usable("File::Temp")) {
+ $installation_report_fh
+ = File::Temp->new(
+ dir => File::Spec->tmpdir,
+ template => 'cpan_install_XXXX',
+ suffix => '.txt',
+ unlink => 0,
+ );
+ }
+ unless ( $installation_report_fh ) {
+ warn("Couldn't open installation report file; " .
+ "no report file will be generated."
+ ) unless $previously_noticed++;
+ }
+ }
+}
+
+
+# The only reason for this method is currently to have a reliable
+# debugging utility that reveals which output is going through which
+# channel. No, I don't like the colors ;-)
+
+# to turn colordebugging on, write
+# cpan> o conf colorize_output 1
+
+#-> sub CPAN::Shell::colorize_output ;
+{
+ my $print_ornamented_have_warned = 0;
+ sub colorize_output {
+ my $colorize_output = $CPAN::Config->{colorize_output};
+ if ($colorize_output && !$CPAN::META->has_inst("Term::ANSIColor")) {
+ unless ($print_ornamented_have_warned++) {
+ # no myprint/mywarn within myprint/mywarn!
+ warn "Colorize_output is set to true but Term::ANSIColor is not
+installed. To activate colorized output, please install Term::ANSIColor.\n\n";
+ }
+ $colorize_output = 0;
+ }
+ return $colorize_output;
+ }
+}
+
+
+#-> sub CPAN::Shell::print_ornamented ;
+sub print_ornamented {
+ my($self,$what,$ornament) = @_;
+ return unless defined $what;
+
+ local $| = 1; # Flush immediately
+ if ( $CPAN::Be_Silent ) {
+ print {report_fh()} $what;
+ return;
+ }
+ my $swhat = "$what"; # stringify if it is an object
+ if ($CPAN::Config->{term_is_latin}) {
+ # note: deprecated, need to switch to $LANG and $LC_*
+ # courtesy jhi:
+ $swhat
+ =~ s{([\xC0-\xDF])([\x80-\xBF])}{chr(ord($1)<<6&0xC0|ord($2)&0x3F)}eg; #};
+ }
+ if ($self->colorize_output) {
+ if ( $CPAN::DEBUG && $swhat =~ /^Debug\(/ ) {
+ # if you want to have this configurable, please file a bugreport
+ $ornament = $CPAN::Config->{colorize_debug} || "black on_cyan";
+ }
+ my $color_on = eval { Term::ANSIColor::color($ornament) } || "";
+ if ($@) {
+ print "Term::ANSIColor rejects color[$ornament]: $@\n
+Please choose a different color (Hint: try 'o conf init /color/')\n";
+ }
+ # GGOLDBACH/Test-GreaterVersion-0.008 broke without this
+ # $trailer construct. We want the newline be the last thing if
+ # there is a newline at the end ensuring that the next line is
+ # empty for other players
+ my $trailer = "";
+ $trailer = $1 if $swhat =~ s/([\r\n]+)\z//;
+ print $color_on,
+ $swhat,
+ Term::ANSIColor::color("reset"),
+ $trailer;
+ } else {
+ print $swhat;
+ }
+}
+
+#-> sub CPAN::Shell::myprint ;
+
+# where is myprint/mywarn/Frontend/etc. documented? Where to use what?
+# I think, we send everything to STDOUT and use print for normal/good
+# news and warn for news that need more attention. Yes, this is our
+# working contract for now.
+sub myprint {
+ my($self,$what) = @_;
+ $self->print_ornamented($what,
+ $CPAN::Config->{colorize_print}||'bold blue on_white',
+ );
+}
+
+my %already_printed;
+#-> sub CPAN::Shell::mywarnonce ;
+sub myprintonce {
+ my($self,$what) = @_;
+ $self->myprint($what) unless $already_printed{$what}++;
+}
+
+sub optprint {
+ my($self,$category,$what) = @_;
+ my $vname = $category . "_verbosity";
+ CPAN::HandleConfig->load unless $CPAN::Config_loaded++;
+ if (!$CPAN::Config->{$vname}
+ || $CPAN::Config->{$vname} =~ /^v/
+ ) {
+ $CPAN::Frontend->myprint($what);
+ }
+}
+
+#-> sub CPAN::Shell::myexit ;
+sub myexit {
+ my($self,$what) = @_;
+ $self->myprint($what);
+ exit;
+}
+
+#-> sub CPAN::Shell::mywarn ;
+sub mywarn {
+ my($self,$what) = @_;
+ $self->print_ornamented($what, $CPAN::Config->{colorize_warn}||'bold red on_white');
+}
+
+my %already_warned;
+#-> sub CPAN::Shell::mywarnonce ;
+sub mywarnonce {
+ my($self,$what) = @_;
+ $self->mywarn($what) unless $already_warned{$what}++;
+}
+
+# only to be used for shell commands
+#-> sub CPAN::Shell::mydie ;
+sub mydie {
+ my($self,$what) = @_;
+ $self->mywarn($what);
+
+ # If it is the shell, we want the following die to be silent,
+ # but if it is not the shell, we would need a 'die $what'. We need
+ # to take care that only shell commands use mydie. Is this
+ # possible?
+
+ die "\n";
+}
+
+# sub CPAN::Shell::colorable_makemaker_prompt ;
+sub colorable_makemaker_prompt {
+ my($foo,$bar) = @_;
+ if (CPAN::Shell->colorize_output) {
+ my $ornament = $CPAN::Config->{colorize_print}||'bold blue on_white';
+ my $color_on = eval { Term::ANSIColor::color($ornament); } || "";
+ print $color_on;
+ }
+ my $ans = ExtUtils::MakeMaker::prompt($foo,$bar);
+ if (CPAN::Shell->colorize_output) {
+ print Term::ANSIColor::color('reset');
+ }
+ return $ans;
+}
+
+# use this only for unrecoverable errors!
+#-> sub CPAN::Shell::unrecoverable_error ;
+sub unrecoverable_error {
+ my($self,$what) = @_;
+ my @lines = split /\n/, $what;
+ my $longest = 0;
+ for my $l (@lines) {
+ $longest = length $l if length $l > $longest;
+ }
+ $longest = 62 if $longest > 62;
+ for my $l (@lines) {
+ if ($l =~ /^\s*$/) {
+ $l = "\n";
+ next;
+ }
+ $l = "==> $l";
+ if (length $l < 66) {
+ $l = pack "A66 A*", $l, "<==";
+ }
+ $l .= "\n";
+ }
+ unshift @lines, "\n";
+ $self->mydie(join "", @lines);
+}
+
+#-> sub CPAN::Shell::mysleep ;
+sub mysleep {
+ my($self, $sleep) = @_;
+ if (CPAN->has_inst("Time::HiRes")) {
+ Time::HiRes::sleep($sleep);
+ } else {
+ sleep($sleep < 1 ? 1 : int($sleep + 0.5));
+ }
+}
+
+#-> sub CPAN::Shell::setup_output ;
+sub setup_output {
+ return if -t STDOUT;
+ my $odef = select STDERR;
+ $| = 1;
+ select STDOUT;
+ $| = 1;
+ select $odef;
+}
+
+#-> sub CPAN::Shell::rematein ;
+# RE-adme||MA-ke||TE-st||IN-stall : nearly everything runs through here
+sub rematein {
+ my $self = shift;
+ # this variable was global and disturbed programmers, so localize:
+ local $CPAN::Distrostatus::something_has_failed_at;
+ my($meth,@some) = @_;
+ my @pragma;
+ while($meth =~ /^(ff?orce|notest)$/) {
+ push @pragma, $meth;
+ $meth = shift @some or
+ $CPAN::Frontend->mydie("Pragma $pragma[-1] used without method: ".
+ "cannot continue");
+ }
+ setup_output();
+ CPAN->debug("pragma[@pragma]meth[$meth]some[@some]") if $CPAN::DEBUG;
+
+ # Here is the place to set "test_count" on all involved parties to
+ # 0. We then can pass this counter on to the involved
+ # distributions and those can refuse to test if test_count > X. In
+ # the first stab at it we could use a 1 for "X".
+
+ # But when do I reset the distributions to start with 0 again?
+ # Jost suggested to have a random or cycling interaction ID that
+ # we pass through. But the ID is something that is just left lying
+ # around in addition to the counter, so I'd prefer to set the
+ # counter to 0 now, and repeat at the end of the loop. But what
+ # about dependencies? They appear later and are not reset, they
+ # enter the queue but not its copy. How do they get a sensible
+ # test_count?
+
+ # With configure_requires, "get" is vulnerable in recursion.
+
+ my $needs_recursion_protection = "get|make|test|install";
+
+ # construct the queue
+ my($s,@s,@qcopy);
+ STHING: foreach $s (@some) {
+ my $obj;
+ if (ref $s) {
+ CPAN->debug("s is an object[$s]") if $CPAN::DEBUG;
+ $obj = $s;
+ } elsif ($s =~ m|[\$\@\%]|) { # looks like a perl variable
+ } elsif ($s =~ m|^/|) { # looks like a regexp
+ if (substr($s,-1,1) eq ".") {
+ $obj = CPAN::Shell->expandany($s);
+ } else {
+ my @obj;
+ CLASS: for my $class (qw(Distribution Bundle Module)) {
+ if (@obj = $self->expand($class,$s)) {
+ last CLASS;
+ }
+ }
+ if (@obj) {
+ if (1==@obj) {
+ $obj = $obj[0];
+ } else {
+ $CPAN::Frontend->mywarn("Sorry, $meth with a regular expression is ".
+ "only supported when unambiguous.\nRejecting argument '$s'\n");
+ $CPAN::Frontend->mysleep(2);
+ next STHING;
+ }
+ }
+ }
+ } elsif ($meth eq "ls") {
+ $self->globls($s,\@pragma);
+ next STHING;
+ } else {
+ CPAN->debug("calling expandany [$s]") if $CPAN::DEBUG;
+ $obj = CPAN::Shell->expandany($s);
+ }
+ if (0) {
+ } elsif (ref $obj) {
+ if ($meth =~ /^($needs_recursion_protection)$/) {
+ # it would be silly to check for recursion for look or dump
+ # (we are in CPAN::Shell::rematein)
+ CPAN->debug("Going to test against recursion") if $CPAN::DEBUG;
+ eval { $obj->color_cmd_tmps(0,1); };
+ if ($@) {
+ if (ref $@
+ and $@->isa("CPAN::Exception::RecursiveDependency")) {
+ $CPAN::Frontend->mywarn($@);
+ } else {
+ if (0) {
+ require Carp;
+ Carp::confess(sprintf "DEBUG: \$\@[%s]ref[%s]", $@, ref $@);
+ }
+ die;
+ }
+ }
+ }
+ CPAN::Queue->queue_item(qmod => $obj->id, reqtype => "c");
+ push @qcopy, $obj;
+ } elsif ($CPAN::META->exists('CPAN::Author',uc($s))) {
+ $obj = $CPAN::META->instance('CPAN::Author',uc($s));
+ if ($meth =~ /^(dump|ls|reports)$/) {
+ $obj->$meth();
+ } else {
+ $CPAN::Frontend->mywarn(
+ join "",
+ "Don't be silly, you can't $meth ",
+ $obj->fullname,
+ " ;-)\n"
+ );
+ $CPAN::Frontend->mysleep(2);
+ }
+ } elsif ($s =~ m|[\$\@\%]| && $meth eq "dump") {
+ CPAN::InfoObj->dump($s);
+ } else {
+ $CPAN::Frontend
+ ->mywarn(qq{Warning: Cannot $meth $s, }.
+ qq{don't know what it is.
+Try the command
+
+ i /$s/
+
+to find objects with matching identifiers.
+});
+ $CPAN::Frontend->mysleep(2);
+ }
+ }
+
+ # queuerunner (please be warned: when I started to change the
+ # queue to hold objects instead of names, I made one or two
+ # mistakes and never found which. I reverted back instead)
+ QITEM: while (my $q = CPAN::Queue->first) {
+ my $obj;
+ my $s = $q->as_string;
+ my $reqtype = $q->reqtype || "";
+ $obj = CPAN::Shell->expandany($s);
+ unless ($obj) {
+ # don't know how this can happen, maybe we should panic,
+ # but maybe we get a solution from the first user who hits
+ # this unfortunate exception?
+ $CPAN::Frontend->mywarn("Warning: Could not expand string '$s' ".
+ "to an object. Skipping.\n");
+ $CPAN::Frontend->mysleep(5);
+ CPAN::Queue->delete_first($s);
+ next QITEM;
+ }
+ $obj->{reqtype} ||= "";
+ {
+ # force debugging because CPAN::SQLite somehow delivers us
+ # an empty object;
+
+ # local $CPAN::DEBUG = 1024; # Shell; probably fixed now
+
+ CPAN->debug("s[$s]obj-reqtype[$obj->{reqtype}]".
+ "q-reqtype[$reqtype]") if $CPAN::DEBUG;
+ }
+ if ($obj->{reqtype}) {
+ if ($obj->{reqtype} eq "b" && $reqtype =~ /^[rc]$/) {
+ $obj->{reqtype} = $reqtype;
+ if (
+ exists $obj->{install}
+ &&
+ (
+ UNIVERSAL::can($obj->{install},"failed") ?
+ $obj->{install}->failed :
+ $obj->{install} =~ /^NO/
+ )
+ ) {
+ delete $obj->{install};
+ $CPAN::Frontend->mywarn
+ ("Promoting $obj->{ID} from 'build_requires' to 'requires'");
+ }
+ }
+ } else {
+ $obj->{reqtype} = $reqtype;
+ }
+
+ for my $pragma (@pragma) {
+ if ($pragma
+ &&
+ $obj->can($pragma)) {
+ $obj->$pragma($meth);
+ }
+ }
+ if (UNIVERSAL::can($obj, 'called_for')) {
+ $obj->called_for($s);
+ }
+ CPAN->debug(qq{pragma[@pragma]meth[$meth]}.
+ qq{ID[$obj->{ID}]}) if $CPAN::DEBUG;
+
+ push @qcopy, $obj;
+ if ($meth =~ /^(report)$/) { # they came here with a pragma?
+ $self->$meth($obj);
+ } elsif (! UNIVERSAL::can($obj,$meth)) {
+ # Must never happen
+ my $serialized = "";
+ if (0) {
+ } elsif ($CPAN::META->has_inst("YAML::Syck")) {
+ $serialized = YAML::Syck::Dump($obj);
+ } elsif ($CPAN::META->has_inst("YAML")) {
+ $serialized = YAML::Dump($obj);
+ } elsif ($CPAN::META->has_inst("Data::Dumper")) {
+ $serialized = Data::Dumper::Dumper($obj);
+ } else {
+ require overload;
+ $serialized = overload::StrVal($obj);
+ }
+ CPAN->debug("Going to panic. meth[$meth]s[$s]") if $CPAN::DEBUG;
+ $CPAN::Frontend->mydie("Panic: obj[$serialized] cannot meth[$meth]");
+ } elsif ($obj->$meth()) {
+ CPAN::Queue->delete($s);
+ CPAN->debug("From queue deleted. meth[$meth]s[$s]") if $CPAN::DEBUG;
+ } else {
+ CPAN->debug("Failed. pragma[@pragma]meth[$meth]") if $CPAN::DEBUG;
+ }
+
+ $obj->undelay;
+ for my $pragma (@pragma) {
+ my $unpragma = "un$pragma";
+ if ($obj->can($unpragma)) {
+ $obj->$unpragma();
+ }
+ }
+ if ($CPAN::Config->{halt_on_failure}
+ &&
+ CPAN::Distrostatus::something_has_just_failed()
+ ) {
+ $CPAN::Frontend->mywarn("Stopping: '$meth' failed for '$s'.\n");
+ CPAN::Queue->nullify_queue;
+ last QITEM;
+ }
+ CPAN::Queue->delete_first($s);
+ }
+ if ($meth =~ /^($needs_recursion_protection)$/) {
+ for my $obj (@qcopy) {
+ $obj->color_cmd_tmps(0,0);
+ }
+ }
+}
+
+#-> sub CPAN::Shell::recent ;
+sub recent {
+ my($self) = @_;
+ if ($CPAN::META->has_inst("XML::LibXML")) {
+ my $url = $CPAN::Defaultrecent;
+ $CPAN::Frontend->myprint("Going to fetch '$url'\n");
+ unless ($CPAN::META->has_usable("LWP")) {
+ $CPAN::Frontend->mydie("LWP not installed; cannot continue");
+ }
+ CPAN::LWP::UserAgent->config;
+ my $Ua;
+ eval { $Ua = CPAN::LWP::UserAgent->new; };
+ if ($@) {
+ $CPAN::Frontend->mydie("CPAN::LWP::UserAgent->new dies with $@\n");
+ }
+ my $resp = $Ua->get($url);
+ unless ($resp->is_success) {
+ $CPAN::Frontend->mydie(sprintf "Could not download '%s': %s\n", $url, $resp->code);
+ }
+ $CPAN::Frontend->myprint("DONE\n\n");
+ my $xml = XML::LibXML->new->parse_string($resp->content);
+ if (0) {
+ my $s = $xml->serialize(2);
+ $s =~ s/\n\s*\n/\n/g;
+ $CPAN::Frontend->myprint($s);
+ return;
+ }
+ my @distros;
+ if ($url =~ /winnipeg/) {
+ my $pubdate = $xml->findvalue("/rss/channel/pubDate");
+ $CPAN::Frontend->myprint(" pubDate: $pubdate\n\n");
+ for my $eitem ($xml->findnodes("/rss/channel/item")) {
+ my $distro = $eitem->findvalue("enclosure/\@url");
+ $distro =~ s|.*?/authors/id/./../||;
+ my $size = $eitem->findvalue("enclosure/\@length");
+ my $desc = $eitem->findvalue("description");
+ $desc =~ s/.+? - //;
+ $CPAN::Frontend->myprint("$distro [$size b]\n $desc\n");
+ push @distros, $distro;
+ }
+ } elsif ($url =~ /search.*uploads.rdf/) {
+ # xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ # xmlns="http://purl.org/rss/1.0/"
+ # xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
+ # xmlns:dc="http://purl.org/dc/elements/1.1/"
+ # xmlns:syn="http://purl.org/rss/1.0/modules/syndication/"
+ # xmlns:admin="http://webns.net/mvcb/"
+
+
+ my $dc_date = $xml->findvalue("//*[local-name(.) = 'RDF']/*[local-name(.) = 'channel']/*[local-name(.) = 'date']");
+ $CPAN::Frontend->myprint(" dc:date: $dc_date\n\n");
+ my $finish_eitem = 0;
+ local $SIG{INT} = sub { $finish_eitem = 1 };
+ EITEM: for my $eitem ($xml->findnodes("//*[local-name(.) = 'RDF']/*[local-name(.) = 'item']")) {
+ my $distro = $eitem->findvalue("\@rdf:about");
+ $distro =~ s|.*~||; # remove up to the tilde before the name
+ $distro =~ s|/$||; # remove trailing slash
+ $distro =~ s|([^/]+)|\U$1\E|; # upcase the name
+ my $author = uc $1 or die "distro[$distro] without author, cannot continue";
+ my $desc = $eitem->findvalue("*[local-name(.) = 'description']");
+ my $i = 0;
+ SUBDIRTEST: while () {
+ last SUBDIRTEST if ++$i >= 6; # half a dozen must do!
+ if (my @ret = $self->globls("$distro*")) {
+ @ret = grep {$_->[2] !~ /meta/} @ret;
+ @ret = grep {length $_->[2]} @ret;
+ if (@ret) {
+ $distro = "$author/$ret[0][2]";
+ last SUBDIRTEST;
+ }
+ }
+ $distro =~ s|/|/*/|; # allow it to reside in a subdirectory
+ }
+
+ next EITEM if $distro =~ m|\*|; # did not find the thing
+ $CPAN::Frontend->myprint("____$desc\n");
+ push @distros, $distro;
+ last EITEM if $finish_eitem;
+ }
+ }
+ return \@distros;
+ } else {
+ # deprecated old version
+ $CPAN::Frontend->mydie("no XML::LibXML installed, cannot continue\n");
+ }
+}
+
+#-> sub CPAN::Shell::smoke ;
+sub smoke {
+ my($self) = @_;
+ my $distros = $self->recent;
+ DISTRO: for my $distro (@$distros) {
+ next if $distro =~ m|/Bundle-|; # XXX crude heuristic to skip bundles
+ $CPAN::Frontend->myprint(sprintf "Going to download and test '$distro'\n");
+ {
+ my $skip = 0;
+ local $SIG{INT} = sub { $skip = 1 };
+ for (0..9) {
+ $CPAN::Frontend->myprint(sprintf "\r%2d (Hit ^C to skip)", 10-$_);
+ sleep 1;
+ if ($skip) {
+ $CPAN::Frontend->myprint(" skipped\n");
+ next DISTRO;
+ }
+ }
+ }
+ $CPAN::Frontend->myprint("\r \n"); # leave the dirty line with a newline
+ $self->test($distro);
+ }
+}
+
+{
+ # set up the dispatching methods
+ no strict "refs";
+ for my $command (qw(
+ clean
+ cvs_import
+ dump
+ force
+ fforce
+ get
+ install
+ look
+ ls
+ make
+ notest
+ perldoc
+ readme
+ reports
+ test
+ )) {
+ *$command = sub { shift->rematein($command, @_); };
+ }
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Tarzip.pm b/Master/tlpkg/tlperl/lib/CPAN/Tarzip.pm
new file mode 100644
index 00000000000..63451e7450d
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Tarzip.pm
@@ -0,0 +1,451 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+package CPAN::Tarzip;
+use strict;
+use vars qw($VERSION @ISA $BUGHUNTING);
+use CPAN::Debug;
+use File::Basename qw(basename);
+$VERSION = "5.5011";
+# module is internal to CPAN.pm
+
+@ISA = qw(CPAN::Debug); ## no critic
+$BUGHUNTING ||= 0; # released code must have turned off
+
+# it's ok if file doesn't exist, it just matters if it is .gz or .bz2
+sub new {
+ my($class,$file) = @_;
+ $CPAN::Frontend->mydie("CPAN::Tarzip->new called without arg") unless defined $file;
+ my $me = { FILE => $file };
+ if ($file =~ /\.(bz2|gz|zip|tbz|tgz)$/i) {
+ $me->{ISCOMPRESSED} = 1;
+ } else {
+ $me->{ISCOMPRESSED} = 0;
+ }
+ if (0) {
+ } elsif ($file =~ /\.(?:bz2|tbz)$/i) {
+ unless ($me->{UNGZIPPRG} = $CPAN::Config->{bzip2}) {
+ my $bzip2 = _my_which("bzip2");
+ if ($bzip2) {
+ $me->{UNGZIPPRG} = $bzip2;
+ } else {
+ $CPAN::Frontend->mydie(qq{
+CPAN.pm needs the external program bzip2 in order to handle '$file'.
+Please install it now and run 'o conf init bzip2' from the
+CPAN shell prompt to register it as external program.
+});
+ }
+ }
+ } else {
+ $me->{UNGZIPPRG} = _my_which("gzip");
+ }
+ $me->{TARPRG} = _my_which("tar") || _my_which("gtar");
+ bless $me, $class;
+}
+
+sub _my_which {
+ my($what) = @_;
+ if ($CPAN::Config->{$what}) {
+ return $CPAN::Config->{$what};
+ }
+ if ($CPAN::META->has_inst("File::Which")) {
+ return File::Which::which($what);
+ }
+ my @cand = MM->maybe_command($what);
+ return $cand[0] if @cand;
+ require File::Spec;
+ my $component;
+ PATH_COMPONENT: foreach $component (File::Spec->path()) {
+ next unless defined($component) && $component;
+ my($abs) = File::Spec->catfile($component,$what);
+ if (MM->maybe_command($abs)) {
+ return $abs;
+ }
+ }
+ return;
+}
+
+sub gzip {
+ my($self,$read) = @_;
+ my $write = $self->{FILE};
+ if ($CPAN::META->has_inst("Compress::Zlib")) {
+ my($buffer,$fhw);
+ $fhw = FileHandle->new($read)
+ or $CPAN::Frontend->mydie("Could not open $read: $!");
+ my $cwd = `pwd`;
+ my $gz = Compress::Zlib::gzopen($write, "wb")
+ or $CPAN::Frontend->mydie("Cannot gzopen $write: $! (pwd is $cwd)\n");
+ $gz->gzwrite($buffer)
+ while read($fhw,$buffer,4096) > 0 ;
+ $gz->gzclose() ;
+ $fhw->close;
+ return 1;
+ } else {
+ my $command = CPAN::HandleConfig->safe_quote($self->{UNGZIPPRG});
+ system(qq{$command -c "$read" > "$write"})==0;
+ }
+}
+
+
+sub gunzip {
+ my($self,$write) = @_;
+ my $read = $self->{FILE};
+ if ($CPAN::META->has_inst("Compress::Zlib")) {
+ my($buffer,$fhw);
+ $fhw = FileHandle->new(">$write")
+ or $CPAN::Frontend->mydie("Could not open >$write: $!");
+ my $gz = Compress::Zlib::gzopen($read, "rb")
+ or $CPAN::Frontend->mydie("Cannot gzopen $read: $!\n");
+ $fhw->print($buffer)
+ while $gz->gzread($buffer) > 0 ;
+ $CPAN::Frontend->mydie("Error reading from $read: $!\n")
+ if $gz->gzerror != Compress::Zlib::Z_STREAM_END();
+ $gz->gzclose() ;
+ $fhw->close;
+ return 1;
+ } else {
+ my $command = CPAN::HandleConfig->safe_quote($self->{UNGZIPPRG});
+ system(qq{$command -dc "$read" > "$write"})==0;
+ }
+}
+
+
+sub gtest {
+ my($self) = @_;
+ return $self->{GTEST} if exists $self->{GTEST};
+ defined $self->{FILE} or $CPAN::Frontend->mydie("gtest called but no FILE specified");
+ my $read = $self->{FILE};
+ my $success;
+ if ($read=~/\.(?:bz2|tbz)$/ && $CPAN::META->has_inst("Compress::Bzip2")) {
+ my($buffer,$len);
+ $len = 0;
+ my $gz = Compress::Bzip2::bzopen($read, "rb")
+ or $CPAN::Frontend->mydie(sprintf("Cannot gzopen %s: %s\n",
+ $read,
+ $Compress::Bzip2::bzerrno));
+ while ($gz->bzread($buffer) > 0 ) {
+ $len += length($buffer);
+ $buffer = "";
+ }
+ my $err = $gz->bzerror;
+ $success = ! $err || $err == Compress::Bzip2::BZ_STREAM_END();
+ if ($len == -s $read) {
+ $success = 0;
+ CPAN->debug("hit an uncompressed file") if $CPAN::DEBUG;
+ }
+ $gz->gzclose();
+ CPAN->debug("err[$err]success[$success]") if $CPAN::DEBUG;
+ } elsif ( $read=~/\.(?:gz|tgz)$/ && $CPAN::META->has_inst("Compress::Zlib") ) {
+ # After I had reread the documentation in zlib.h, I discovered that
+ # uncompressed files do not lead to an gzerror (anymore?).
+ my($buffer,$len);
+ $len = 0;
+ my $gz = Compress::Zlib::gzopen($read, "rb")
+ or $CPAN::Frontend->mydie(sprintf("Cannot gzopen %s: %s\n",
+ $read,
+ $Compress::Zlib::gzerrno));
+ while ($gz->gzread($buffer) > 0 ) {
+ $len += length($buffer);
+ $buffer = "";
+ }
+ my $err = $gz->gzerror;
+ $success = ! $err || $err == Compress::Zlib::Z_STREAM_END();
+ if ($len == -s $read) {
+ $success = 0;
+ CPAN->debug("hit an uncompressed file") if $CPAN::DEBUG;
+ }
+ $gz->gzclose();
+ CPAN->debug("err[$err]success[$success]") if $CPAN::DEBUG;
+ } elsif (!$self->{ISCOMPRESSED}) {
+ $success = 0;
+ } else {
+ my $command = CPAN::HandleConfig->safe_quote($self->{UNGZIPPRG});
+ $success = 0==system(qq{$command -qdt "$read"});
+ }
+ return $self->{GTEST} = $success;
+}
+
+
+sub TIEHANDLE {
+ my($class,$file) = @_;
+ my $ret;
+ $class->debug("file[$file]");
+ my $self = $class->new($file);
+ if (0) {
+ } elsif (!$self->gtest) {
+ my $fh = FileHandle->new($file)
+ or $CPAN::Frontend->mydie("Could not open file[$file]: $!");
+ binmode $fh;
+ $self->{FH} = $fh;
+ $class->debug("via uncompressed FH");
+ } elsif ($file =~ /\.(?:bz2|tbz)$/ && $CPAN::META->has_inst("Compress::Bzip2")) {
+ my $gz = Compress::Bzip2::bzopen($file,"rb") or
+ $CPAN::Frontend->mydie("Could not bzopen $file");
+ $self->{GZ} = $gz;
+ $class->debug("via Compress::Bzip2");
+ } elsif ($file =~/\.(?:gz|tgz)$/ && $CPAN::META->has_inst("Compress::Zlib")) {
+ my $gz = Compress::Zlib::gzopen($file,"rb") or
+ $CPAN::Frontend->mydie("Could not gzopen $file");
+ $self->{GZ} = $gz;
+ $class->debug("via Compress::Zlib");
+ } else {
+ my $gzip = CPAN::HandleConfig->safe_quote($self->{UNGZIPPRG});
+ my $pipe = "$gzip -dc $file |";
+ my $fh = FileHandle->new($pipe) or $CPAN::Frontend->mydie("Could not pipe[$pipe]: $!");
+ binmode $fh;
+ $self->{FH} = $fh;
+ $class->debug("via external $gzip");
+ }
+ $self;
+}
+
+
+sub READLINE {
+ my($self) = @_;
+ if (exists $self->{GZ}) {
+ my $gz = $self->{GZ};
+ my($line,$bytesread);
+ $bytesread = $gz->gzreadline($line);
+ return undef if $bytesread <= 0;
+ return $line;
+ } else {
+ my $fh = $self->{FH};
+ return scalar <$fh>;
+ }
+}
+
+
+sub READ {
+ my($self,$ref,$length,$offset) = @_;
+ $CPAN::Frontend->mydie("read with offset not implemented") if defined $offset;
+ if (exists $self->{GZ}) {
+ my $gz = $self->{GZ};
+ my $byteread = $gz->gzread($$ref,$length);# 30eaf79e8b446ef52464b5422da328a8
+ return $byteread;
+ } else {
+ my $fh = $self->{FH};
+ return read($fh,$$ref,$length);
+ }
+}
+
+
+sub DESTROY {
+ my($self) = @_;
+ if (exists $self->{GZ}) {
+ my $gz = $self->{GZ};
+ $gz->gzclose() if defined $gz; # hard to say if it is allowed
+ # to be undef ever. AK, 2000-09
+ } else {
+ my $fh = $self->{FH};
+ $fh->close if defined $fh;
+ }
+ undef $self;
+}
+
+sub untar {
+ my($self) = @_;
+ my $file = $self->{FILE};
+ my($prefer) = 0;
+
+ my $exttar = $self->{TARPRG} || "";
+ $exttar = "" if $exttar =~ /^\s+$/; # user refuses to use it
+ my $extgzip = $self->{UNGZIPPRG} || "";
+ $extgzip = "" if $extgzip =~ /^\s+$/; # user refuses to use it
+
+ if (0) { # makes changing order easier
+ } elsif ($BUGHUNTING) {
+ $prefer=2;
+ } elsif ($exttar && $extgzip && $file =~ /\.(?:bz2|tbz)$/i) {
+ # until Archive::Tar handles bzip2
+ $prefer = 1;
+ } elsif (
+ $CPAN::META->has_usable("Archive::Tar")
+ &&
+ $CPAN::META->has_inst("Compress::Zlib") ) {
+ $prefer = 2;
+ } elsif ($exttar && $extgzip) {
+ # no modules and not bz2
+ $prefer = 1;
+ # but solaris binary tar is a problem
+ if ($^O eq 'solaris' && qx($exttar --version 2>/dev/null) !~ /gnu/i) {
+ $CPAN::Frontend->mywarn(<< 'END_WARN');
+
+WARNING: Many CPAN distributions were archived with GNU tar and some of
+them may be incompatible with Solaris tar. We respectfully suggest you
+configure CPAN to use a GNU tar instead ("o conf init tar") or install
+a recent Archive::Tar instead;
+
+END_WARN
+ }
+ } else {
+ my $foundtar = $exttar ? "'$exttar'" : "nothing";
+ my $foundzip = $extgzip ? "'$extgzip'" : $foundtar ? "nothing" : "also nothing";
+ my $foundAT;
+ if ($CPAN::META->has_usable("Archive::Tar")) {
+ $foundAT = sprintf "'%s'", "Archive::Tar::"->VERSION;
+ } else {
+ $foundAT = "nothing";
+ }
+ my $foundCZ;
+ if ($CPAN::META->has_inst("Compress::Zlib")) {
+ $foundCZ = sprintf "'%s'", "Compress::Zlib::"->VERSION;
+ } elsif ($foundAT) {
+ $foundCZ = "nothing";
+ } else {
+ $foundCZ = "also nothing";
+ }
+ $CPAN::Frontend->mydie(qq{
+
+CPAN.pm needs either the external programs tar and gzip -or- both
+modules Archive::Tar and Compress::Zlib installed.
+
+For tar I found $foundtar, for gzip $foundzip.
+
+For Archive::Tar I found $foundAT, for Compress::Zlib $foundCZ;
+
+Can't continue cutting file '$file'.
+});
+ }
+ my $tar_verb = "v";
+ if (defined $CPAN::Config->{tar_verbosity}) {
+ $tar_verb = $CPAN::Config->{tar_verbosity} eq "none" ? "" :
+ $CPAN::Config->{tar_verbosity};
+ }
+ if ($prefer==1) { # 1 => external gzip+tar
+ my($system);
+ my $is_compressed = $self->gtest();
+ my $tarcommand = CPAN::HandleConfig->safe_quote($exttar);
+ if ($is_compressed) {
+ my $command = CPAN::HandleConfig->safe_quote($extgzip);
+ $system = qq{$command -dc }.
+ qq{< "$file" | $tarcommand x${tar_verb}f -};
+ } else {
+ $system = qq{$tarcommand x${tar_verb}f "$file"};
+ }
+ if (system($system) != 0) {
+ # people find the most curious tar binaries that cannot handle
+ # pipes
+ if ($is_compressed) {
+ (my $ungzf = $file) =~ s/\.gz(?!\n)\Z//;
+ $ungzf = basename $ungzf;
+ my $ct = CPAN::Tarzip->new($file);
+ if ($ct->gunzip($ungzf)) {
+ $CPAN::Frontend->myprint(qq{Uncompressed $file successfully\n});
+ } else {
+ $CPAN::Frontend->mydie(qq{Couldn\'t uncompress $file\n});
+ }
+ $file = $ungzf;
+ }
+ $system = qq{$tarcommand x${tar_verb}f "$file"};
+ $CPAN::Frontend->myprint(qq{Using Tar:$system:\n});
+ if (system($system)==0) {
+ $CPAN::Frontend->myprint(qq{Untarred $file successfully\n});
+ } else {
+ $CPAN::Frontend->mydie(qq{Couldn\'t untar $file\n});
+ }
+ return 1;
+ } else {
+ return 1;
+ }
+ } elsif ($prefer==2) { # 2 => modules
+ unless ($CPAN::META->has_usable("Archive::Tar")) {
+ $CPAN::Frontend->mydie("Archive::Tar not installed, please install it to continue");
+ }
+ # Make sure AT does not use uid/gid/permissions in the archive
+ # This leaves it to the user's umask instead
+ local $Archive::Tar::CHMOD = 1;
+ local $Archive::Tar::SAME_PERMISSIONS = 0;
+ # Make sure AT leaves current user as owner
+ local $Archive::Tar::CHOWN = 0;
+ my $tar = Archive::Tar->new($file,1);
+ my $af; # archive file
+ my @af;
+ if ($BUGHUNTING) {
+ # RCS 1.337 had this code, it turned out unacceptable slow but
+ # it revealed a bug in Archive::Tar. Code is only here to hunt
+ # the bug again. It should never be enabled in published code.
+ # GDGraph3d-0.53 was an interesting case according to Larry
+ # Virden.
+ warn(">>>Bughunting code enabled<<< " x 20);
+ for $af ($tar->list_files) {
+ if ($af =~ m!^(/|\.\./)!) {
+ $CPAN::Frontend->mydie("ALERT: Archive contains ".
+ "illegal member [$af]");
+ }
+ $CPAN::Frontend->myprint("$af\n");
+ $tar->extract($af); # slow but effective for finding the bug
+ return if $CPAN::Signal;
+ }
+ } else {
+ for $af ($tar->list_files) {
+ if ($af =~ m!^(/|\.\./)!) {
+ $CPAN::Frontend->mydie("ALERT: Archive contains ".
+ "illegal member [$af]");
+ }
+ if ($tar_verb eq "v" || $tar_verb eq "vv") {
+ $CPAN::Frontend->myprint("$af\n");
+ }
+ push @af, $af;
+ return if $CPAN::Signal;
+ }
+ $tar->extract(@af) or
+ $CPAN::Frontend->mydie("Could not untar with Archive::Tar.");
+ }
+
+ Mac::BuildTools::convert_files([$tar->list_files], 1)
+ if ($^O eq 'MacOS');
+
+ return 1;
+ }
+}
+
+sub unzip {
+ my($self) = @_;
+ my $file = $self->{FILE};
+ if ($CPAN::META->has_inst("Archive::Zip")) {
+ # blueprint of the code from Archive::Zip::Tree::extractTree();
+ my $zip = Archive::Zip->new();
+ my $status;
+ $status = $zip->read($file);
+ $CPAN::Frontend->mydie("Read of file[$file] failed\n")
+ if $status != Archive::Zip::AZ_OK();
+ $CPAN::META->debug("Successfully read file[$file]") if $CPAN::DEBUG;
+ my @members = $zip->members();
+ for my $member ( @members ) {
+ my $af = $member->fileName();
+ if ($af =~ m!^(/|\.\./)!) {
+ $CPAN::Frontend->mydie("ALERT: Archive contains ".
+ "illegal member [$af]");
+ }
+ $status = $member->extractToFileNamed( $af );
+ $CPAN::META->debug("af[$af]status[$status]") if $CPAN::DEBUG;
+ $CPAN::Frontend->mydie("Extracting of file[$af] from zipfile[$file] failed\n") if
+ $status != Archive::Zip::AZ_OK();
+ return if $CPAN::Signal;
+ }
+ return 1;
+ } elsif ( my $unzip = $CPAN::Config->{unzip} ) {
+ my @system = ($unzip, $file);
+ return system(@system) == 0;
+ }
+ else {
+ $CPAN::Frontend->mydie(<<"END");
+
+Can't unzip '$file':
+
+You have not configured an 'unzip' program and do not have Archive::Zip
+installed. Please either install Archive::Zip or else configure 'unzip'
+by running the command 'o conf init unzip' from the CPAN shell prompt.
+
+END
+ }
+}
+
+1;
+
+__END__
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/CPAN/URL.pm b/Master/tlpkg/tlperl/lib/CPAN/URL.pm
new file mode 100644
index 00000000000..52b42eec88e
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/URL.pm
@@ -0,0 +1,31 @@
+# -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*-
+# vim: ts=4 sts=4 sw=4:
+package CPAN::URL;
+use overload '""' => "as_string", fallback => 1;
+# accessors: TEXT(the url string), FROM(DEF=>defaultlist,USER=>urllist),
+# planned are things like age or quality
+
+use vars qw(
+ $VERSION
+);
+$VERSION = "5.5";
+
+sub new {
+ my($class,%args) = @_;
+ bless {
+ %args
+ }, $class;
+}
+sub as_string {
+ my($self) = @_;
+ $self->text;
+}
+sub text {
+ my($self,$set) = @_;
+ if (defined $set) {
+ $self->{TEXT} = $set;
+ }
+ $self->{TEXT};
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPAN/Version.pm b/Master/tlpkg/tlperl/lib/CPAN/Version.pm
new file mode 100644
index 00000000000..da876aac2d7
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPAN/Version.pm
@@ -0,0 +1,173 @@
+package CPAN::Version;
+
+use strict;
+use vars qw($VERSION);
+$VERSION = "5.5";
+
+# CPAN::Version::vcmp courtesy Jost Krieger
+sub vcmp {
+ my($self,$l,$r) = @_;
+ local($^W) = 0;
+ CPAN->debug("l[$l] r[$r]") if $CPAN::DEBUG;
+
+ return 0 if $l eq $r; # short circuit for quicker success
+
+ for ($l,$r) {
+ s/_//g;
+ }
+ CPAN->debug("l[$l] r[$r]") if $CPAN::DEBUG;
+ for ($l,$r) {
+ next unless tr/.// > 1 || /^v/;
+ s/^v?/v/;
+ 1 while s/\.0+(\d)/.$1/; # remove leading zeroes per group
+ }
+ CPAN->debug("l[$l] r[$r]") if $CPAN::DEBUG;
+ if ($l=~/^v/ <=> $r=~/^v/) {
+ for ($l,$r) {
+ next if /^v/;
+ $_ = $self->float2vv($_);
+ }
+ }
+ CPAN->debug("l[$l] r[$r]") if $CPAN::DEBUG;
+ my $lvstring = "v0";
+ my $rvstring = "v0";
+ if ($] >= 5.006
+ && $l =~ /^v/
+ && $r =~ /^v/) {
+ $lvstring = $self->vstring($l);
+ $rvstring = $self->vstring($r);
+ CPAN->debug(sprintf "lv[%vd] rv[%vd]", $lvstring, $rvstring) if $CPAN::DEBUG;
+ }
+
+ return (
+ ($l ne "undef") <=> ($r ne "undef")
+ ||
+ $lvstring cmp $rvstring
+ ||
+ $l <=> $r
+ ||
+ $l cmp $r
+ );
+}
+
+sub vgt {
+ my($self,$l,$r) = @_;
+ $self->vcmp($l,$r) > 0;
+}
+
+sub vlt {
+ my($self,$l,$r) = @_;
+ 0 + ($self->vcmp($l,$r) < 0);
+}
+
+sub vge {
+ my($self,$l,$r) = @_;
+ $self->vcmp($l,$r) >= 0;
+}
+
+sub vle {
+ my($self,$l,$r) = @_;
+ 0 + ($self->vcmp($l,$r) <= 0);
+}
+
+sub vstring {
+ my($self,$n) = @_;
+ $n =~ s/^v// or die "CPAN::Version::vstring() called with invalid arg [$n]";
+ pack "U*", split /\./, $n;
+}
+
+# vv => visible vstring
+sub float2vv {
+ my($self,$n) = @_;
+ my($rev) = int($n);
+ $rev ||= 0;
+ my($mantissa) = $n =~ /\.(\d{1,12})/; # limit to 12 digits to limit
+ # architecture influence
+ $mantissa ||= 0;
+ $mantissa .= "0" while length($mantissa)%3;
+ my $ret = "v" . $rev;
+ while ($mantissa) {
+ $mantissa =~ s/(\d{1,3})// or
+ die "Panic: length>0 but not a digit? mantissa[$mantissa]";
+ $ret .= ".".int($1);
+ }
+ # warn "n[$n]ret[$ret]";
+ $ret =~ s/(\.0)+/.0/; # v1.0.0 => v1.0
+ $ret;
+}
+
+sub readable {
+ my($self,$n) = @_;
+ $n =~ /^([\w\-\+\.]+)/;
+
+ return $1 if defined $1 && length($1)>0;
+ # if the first user reaches version v43, he will be treated as "+".
+ # We'll have to decide about a new rule here then, depending on what
+ # will be the prevailing versioning behavior then.
+
+ if ($] < 5.006) { # or whenever v-strings were introduced
+ # we get them wrong anyway, whatever we do, because 5.005 will
+ # have already interpreted 0.2.4 to be "0.24". So even if he
+ # indexer sends us something like "v0.2.4" we compare wrongly.
+
+ # And if they say v1.2, then the old perl takes it as "v12"
+
+ if (defined $CPAN::Frontend) {
+ $CPAN::Frontend->mywarn("Suspicious version string seen [$n]\n");
+ } else {
+ warn("Suspicious version string seen [$n]\n");
+ }
+ return $n;
+ }
+ my $better = sprintf "v%vd", $n;
+ CPAN->debug("n[$n] better[$better]") if $CPAN::DEBUG;
+ return $better;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+CPAN::Version - utility functions to compare CPAN versions
+
+=head1 SYNOPSIS
+
+ use CPAN::Version;
+
+ CPAN::Version->vgt("1.1","1.1.1"); # 1 bc. 1.1 > 1.001001
+
+ CPAN::Version->vlt("1.1","1.1"); # 0 bc. 1.1 not < 1.1
+
+ CPAN::Version->vcmp("1.1","1.1.1"); # 1 bc. first is larger
+
+ CPAN::Version->vcmp("1.1.1","1.1"); # -1 bc. first is smaller
+
+ CPAN::Version->readable(v1.2.3); # "v1.2.3"
+
+ CPAN::Version->vstring("v1.2.3"); # v1.2.3
+
+ CPAN::Version->float2vv(1.002003); # "v1.2.3"
+
+=head1 DESCRIPTION
+
+This module mediates between some version that perl sees in a package
+and the version that is published by the CPAN indexer.
+
+It's only written as a helper module for both CPAN.pm and CPANPLUS.pm.
+
+As it stands it predates version.pm but has the same goal: make
+version strings visible and comparable.
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=cut
+
+# Local Variables:
+# mode: cperl
+# cperl-indent-level: 4
+# End:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Backend.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Backend.pm
new file mode 100644
index 00000000000..a599e5429eb
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Backend.pm
@@ -0,0 +1,1330 @@
+package CPANPLUS::Backend;
+
+use strict;
+
+
+use CPANPLUS::Error;
+use CPANPLUS::Configure;
+use CPANPLUS::Internals;
+use CPANPLUS::Internals::Constants;
+use CPANPLUS::Module;
+use CPANPLUS::Module::Author;
+use CPANPLUS::Backend::RV;
+
+use FileHandle;
+use File::Spec ();
+use File::Spec::Unix ();
+use File::Basename ();
+use Params::Check qw[check];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+$Params::Check::VERBOSE = 1;
+
+use vars qw[@ISA $VERSION];
+
+@ISA = qw[CPANPLUS::Internals];
+$VERSION = $CPANPLUS::Internals::VERSION;
+
+### mark that we're running under CPANPLUS to spawned processes
+$ENV{'PERL5_CPANPLUS_IS_RUNNING'} = $$;
+
+### XXX version.pm MAY format this version, if it's in use... :(
+### so for consistency, just call ->VERSION ourselves as well.
+$ENV{'PERL5_CPANPLUS_IS_VERSION'} = __PACKAGE__->VERSION;
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Backend
+
+=head1 SYNOPSIS
+
+ my $cb = CPANPLUS::Backend->new;
+ my $conf = $cb->configure_object;
+
+ my $author = $cb->author_tree('KANE');
+ my $mod = $cb->module_tree('Some::Module');
+ my $mod = $cb->parse_module( module => 'Some::Module' );
+
+ my @objs = $cb->search( type => TYPE,
+ allow => [...] );
+
+ $cb->flush('all');
+ $cb->reload_indices;
+ $cb->local_mirror;
+
+
+=head1 DESCRIPTION
+
+This module provides the programmer's interface to the C<CPANPLUS>
+libraries.
+
+=head1 ENVIRONMENT
+
+When C<CPANPLUS::Backend> is loaded, which is necessary for just
+about every <CPANPLUS> operation, the environment variable
+C<PERL5_CPANPLUS_IS_RUNNING> is set to the current process id.
+
+Additionally, the environment variable C<PERL5_CPANPLUS_IS_VERSION>
+will be set to the version of C<CPANPLUS::Backend>.
+
+This information might be useful somehow to spawned processes.
+
+=head1 METHODS
+
+=head2 $cb = CPANPLUS::Backend->new( [CONFIGURE_OBJ] )
+
+This method returns a new C<CPANPLUS::Backend> object.
+This also initialises the config corresponding to this object.
+You have two choices in this:
+
+=over 4
+
+=item Provide a valid C<CPANPLUS::Configure> object
+
+This will be used verbatim.
+
+=item No arguments
+
+Your default config will be loaded and used.
+
+=back
+
+New will return a C<CPANPLUS::Backend> object on success and die on
+failure.
+
+=cut
+
+sub new {
+ my $class = shift;
+ my $conf;
+
+ if( $_[0] && IS_CONFOBJ->( conf => $_[0] ) ) {
+ $conf = shift;
+ } else {
+ $conf = CPANPLUS::Configure->new() or return;
+ }
+
+ my $self = $class->SUPER::_init( _conf => $conf );
+
+ return $self;
+}
+
+=pod
+
+=head2 $href = $cb->module_tree( [@modules_names_list] )
+
+Returns a reference to the CPANPLUS module tree.
+
+If you give it any arguments, they will be treated as module names
+and C<module_tree> will try to look up these module names and
+return the corresponding module objects instead.
+
+See L<CPANPLUS::Module> for the operations you can perform on a
+module object.
+
+=cut
+
+sub module_tree {
+ my $self = shift;
+ my $modtree = $self->_module_tree;
+
+ if( @_ ) {
+ my @rv;
+ for my $name ( grep { defined } @_) {
+
+ ### From John Malmberg: This is failing on VMS
+ ### because ODS-2 does not retain the case of
+ ### filenames that are created.
+ ### The problem is the filename is being converted
+ ### to a module name and then looked up in the
+ ### %$modtree hash.
+ ###
+ ### As a fix, we do a search on VMS instead --
+ ### more cpu cycles, but it gets around the case
+ ### problem --kane
+ my ($modobj) = do {
+ ON_VMS
+ ? $self->search(
+ type => 'module',
+ allow => [qr/^$name$/i],
+ )
+ : $modtree->{$name}
+ };
+
+ push @rv, $modobj || '';
+ }
+ return @rv == 1 ? $rv[0] : @rv;
+ } else {
+ return $modtree;
+ }
+}
+
+=pod
+
+=head2 $href = $cb->author_tree( [@author_names_list] )
+
+Returns a reference to the CPANPLUS author tree.
+
+If you give it any arguments, they will be treated as author names
+and C<author_tree> will try to look up these author names and
+return the corresponding author objects instead.
+
+See L<CPANPLUS::Module::Author> for the operations you can perform on
+an author object.
+
+=cut
+
+sub author_tree {
+ my $self = shift;
+ my $authtree = $self->_author_tree;
+
+ if( @_ ) {
+ my @rv;
+ for my $name (@_) {
+ push @rv, $authtree->{$name} || '';
+ }
+ return @rv == 1 ? $rv[0] : @rv;
+ } else {
+ return $authtree;
+ }
+}
+
+=pod
+
+=head2 $conf = $cb->configure_object;
+
+Returns a copy of the C<CPANPLUS::Configure> object.
+
+See L<CPANPLUS::Configure> for operations you can perform on a
+configure object.
+
+=cut
+
+sub configure_object { return shift->_conf() };
+
+=head2 $su = $cb->selfupdate_object;
+
+Returns a copy of the C<CPANPLUS::Selfupdate> object.
+
+See the L<CPANPLUS::Selfupdate> manpage for the operations
+you can perform on the selfupdate object.
+
+=cut
+
+sub selfupdate_object { return shift->_selfupdate() };
+
+=pod
+
+=head2 @mods = $cb->search( type => TYPE, allow => AREF, [data => AREF, verbose => BOOL] )
+
+C<search> enables you to search for either module or author objects,
+based on their data. The C<type> you can specify is any of the
+accessors specified in C<CPANPLUS::Module::Author> or
+C<CPANPLUS::Module>. C<search> will determine by the C<type> you
+specified whether to search by author object or module object.
+
+You have to specify an array reference of regular expressions or
+strings to match against. The rules used for this array ref are the
+same as in C<Params::Check>, so read that manpage for details.
+
+The search is an C<or> search, meaning that if C<any> of the criteria
+match, the search is considered to be successful.
+
+You can specify the result of a previous search as C<data> to limit
+the new search to these module or author objects, rather than the
+entire module or author tree. This is how you do C<and> searches.
+
+Returns a list of module or author objects on success and false
+on failure.
+
+See L<CPANPLUS::Module> for the operations you can perform on a
+module object.
+See L<CPANPLUS::Module::Author> for the operations you can perform on
+an author object.
+
+=cut
+
+sub search {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my ($type);
+ my $args = do {
+ local $Params::Check::NO_DUPLICATES = 0;
+ local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ type => { required => 1, allow => [CPANPLUS::Module->accessors(),
+ CPANPLUS::Module::Author->accessors()], store => \$type },
+ allow => { required => 1, default => [ ], strict_type => 1 },
+ };
+
+ check( $tmpl, \%hash )
+ } or return;
+
+ ### figure out whether it was an author or a module search
+ ### when ambiguous, it'll be an author search.
+ my $aref;
+ if( grep { $type eq $_ } CPANPLUS::Module::Author->accessors() ) {
+ $aref = $self->_search_author_tree( %$args );
+ } else {
+ $aref = $self->_search_module_tree( %$args );
+ }
+
+ return @$aref if $aref;
+ return;
+}
+
+=pod
+
+=head2 $backend_rv = $cb->fetch( modules => \@mods )
+
+Fetches a list of modules. C<@mods> can be a list of distribution
+names, module names or module objects--basically anything that
+L<parse_module> can understand.
+
+See the equivalent method in C<CPANPLUS::Module> for details on
+other options you can pass.
+
+Since this is a multi-module method call, the return value is
+implemented as a C<CPANPLUS::Backend::RV> object. Please consult
+that module's documentation on how to interpret the return value.
+
+=head2 $backend_rv = $cb->extract( modules => \@mods )
+
+Extracts a list of modules. C<@mods> can be a list of distribution
+names, module names or module objects--basically anything that
+L<parse_module> can understand.
+
+See the equivalent method in C<CPANPLUS::Module> for details on
+other options you can pass.
+
+Since this is a multi-module method call, the return value is
+implemented as a C<CPANPLUS::Backend::RV> object. Please consult
+that module's documentation on how to interpret the return value.
+
+=head2 $backend_rv = $cb->install( modules => \@mods )
+
+Installs a list of modules. C<@mods> can be a list of distribution
+names, module names or module objects--basically anything that
+L<parse_module> can understand.
+
+See the equivalent method in C<CPANPLUS::Module> for details on
+other options you can pass.
+
+Since this is a multi-module method call, the return value is
+implemented as a C<CPANPLUS::Backend::RV> object. Please consult
+that module's documentation on how to interpret the return value.
+
+=head2 $backend_rv = $cb->readme( modules => \@mods )
+
+Fetches the readme for a list of modules. C<@mods> can be a list of
+distribution names, module names or module objects--basically
+anything that L<parse_module> can understand.
+
+See the equivalent method in C<CPANPLUS::Module> for details on
+other options you can pass.
+
+Since this is a multi-module method call, the return value is
+implemented as a C<CPANPLUS::Backend::RV> object. Please consult
+that module's documentation on how to interpret the return value.
+
+=head2 $backend_rv = $cb->files( modules => \@mods )
+
+Returns a list of files used by these modules if they are installed.
+C<@mods> can be a list of distribution names, module names or module
+objects--basically anything that L<parse_module> can understand.
+
+See the equivalent method in C<CPANPLUS::Module> for details on
+other options you can pass.
+
+Since this is a multi-module method call, the return value is
+implemented as a C<CPANPLUS::Backend::RV> object. Please consult
+that module's documentation on how to interpret the return value.
+
+=head2 $backend_rv = $cb->distributions( modules => \@mods )
+
+Returns a list of module objects representing all releases for this
+module on success.
+C<@mods> can be a list of distribution names, module names or module
+objects, basically anything that L<parse_module> can understand.
+
+See the equivalent method in C<CPANPLUS::Module> for details on
+other options you can pass.
+
+Since this is a multi-module method call, the return value is
+implemented as a C<CPANPLUS::Backend::RV> object. Please consult
+that module's documentation on how to interpret the return value.
+
+=cut
+
+### XXX add direcotry_tree, packlist etc? or maybe remove files? ###
+for my $func (qw[fetch extract install readme files distributions]) {
+ no strict 'refs';
+
+ *$func = sub {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my ($mods);
+ my $args = do {
+ local $Params::Check::NO_DUPLICATES = 1;
+ local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ modules => { default => [], strict_type => 1,
+ required => 1, store => \$mods },
+ };
+
+ check( $tmpl, \%hash );
+ } or return;
+
+ ### make them all into module objects ###
+ my %mods = map { $_ => $self->parse_module(module => $_) || '' } @$mods;
+
+ my $flag; my $href;
+ while( my($name,$obj) = each %mods ) {
+ $href->{$name} = IS_MODOBJ->( mod => $obj )
+ ? $obj->$func( %$args )
+ : undef;
+
+ $flag++ unless $href->{$name};
+ }
+
+ return CPANPLUS::Backend::RV->new(
+ function => $func,
+ ok => !$flag,
+ rv => $href,
+ args => \%hash,
+ );
+ }
+}
+
+=pod
+
+=head2 $mod_obj = $cb->parse_module( module => $modname|$distname|$modobj|URI|PATH )
+
+C<parse_module> tries to find a C<CPANPLUS::Module> object that
+matches your query. Here's a list of examples you could give to
+C<parse_module>;
+
+=over 4
+
+=item Text::Bastardize
+
+=item Text-Bastardize
+
+=item Text-Bastardize-1.06
+
+=item AYRNIEU/Text-Bastardize
+
+=item AYRNIEU/Text-Bastardize-1.06
+
+=item AYRNIEU/Text-Bastardize-1.06.tar.gz
+
+=item http://example.com/Text-Bastardize-1.06.tar.gz
+
+=item file:///tmp/Text-Bastardize-1.06.tar.gz
+
+=item /tmp/Text-Bastardize-1.06
+
+=item ./Text-Bastardize-1.06
+
+=item .
+
+=back
+
+These items would all come up with a C<CPANPLUS::Module> object for
+C<Text::Bastardize>. The ones marked explicitly as being version 1.06
+would give back a C<CPANPLUS::Module> object of that version.
+Even if the version on CPAN is currently higher.
+
+The last three are examples of PATH resolution. In the first, we supply
+an absolute path to the unwrapped distribution. In the second the
+distribution is relative to the current working directory.
+In the third, we will use the current working directory.
+
+If C<parse_module> is unable to actually find the module you are looking
+for in its module tree, but you supplied it with an author, module
+and version part in a distribution name or URI, it will create a fake
+C<CPANPLUS::Module> object for you, that you can use just like the
+real thing.
+
+See L<CPANPLUS::Module> for the operations you can perform on a
+module object.
+
+If even this fancy guessing doesn't enable C<parse_module> to create
+a fake module object for you to use, it will warn about an error and
+return false.
+
+=cut
+
+sub parse_module {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my $mod;
+ my $tmpl = {
+ module => { required => 1, store => \$mod },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ return $mod if IS_MODOBJ->( module => $mod );
+
+ ### ok, so it's not a module object, but a ref nonetheless?
+ ### what are you smoking?
+ if( ref $mod ) {
+ error(loc("Can not parse module string from reference '%1'", $mod ));
+ return;
+ }
+
+ ### check only for allowed characters in a module name
+ unless( $mod =~ /[^\w:]/ ) {
+
+ ### perhaps we can find it in the module tree?
+ my $maybe = $self->module_tree($mod);
+ return $maybe if IS_MODOBJ->( module => $maybe );
+ }
+
+ ### Special case arbitary file paths such as '.' etc.
+ if ( $mod and -d File::Spec->rel2abs($mod) ) {
+ my $dir = File::Spec->rel2abs($mod);
+ my $parent = File::Spec->rel2abs( File::Spec->catdir( $dir, '..' ) );
+
+ ### fix paths on VMS
+ if (ON_VMS) {
+ $dir = VMS::Filespec::unixify($dir);
+ $parent = VMS::Filespec::unixify($parent);
+ }
+
+ my $dist = $mod = File::Basename::basename($dir);
+ $dist .= '-0' unless $dist =~ /\-[0-9._]+$/;
+ $dist .= '.tar.gz' unless $dist =~ /\.[A-Za-z]+$/;
+
+ my $modobj = CPANPLUS::Module::Fake->new(
+ module => $mod,
+ version => 0,
+ package => $dist,
+ path => $parent,
+ author => CPANPLUS::Module::Author::Fake->new
+ );
+
+ ### better guess for the version
+ $modobj->version( $modobj->package_version )
+ if defined $modobj->package_version;
+
+ ### better guess at module name, if possible
+ if ( my $pkgname = $modobj->package_name ) {
+ $pkgname =~ s/-/::/g;
+
+ ### no sense replacing it unless we changed something
+ $modobj->module( $pkgname )
+ if ($pkgname ne $modobj->package_name) || $pkgname !~ /-/;
+ }
+
+ $modobj->status->fetch( $parent );
+ $modobj->status->extract( $dir );
+ $modobj->get_installer_type;
+ return $modobj;
+ }
+
+ ### ok, so it looks like a distribution then?
+ my @parts = split '/', $mod;
+ my $dist = pop @parts;
+
+ ### ah, it's a URL
+ if( $mod =~ m|\w+://.+| ) {
+ my $modobj = CPANPLUS::Module::Fake->new(
+ module => $dist,
+ version => 0,
+ package => $dist,
+ path => File::Spec::Unix->catdir(
+ $conf->_get_mirror('base'),
+ UNKNOWN_DL_LOCATION ),
+ author => CPANPLUS::Module::Author::Fake->new
+ );
+
+ ### set the fetch_from accessor so we know to by pass the
+ ### usual mirrors
+ $modobj->status->_fetch_from( $mod );
+
+ ### better guess for the version
+ $modobj->version( $modobj->package_version )
+ if defined $modobj->package_version;
+
+ ### better guess at module name, if possible
+ if ( my $pkgname = $modobj->package_name ) {
+ $pkgname =~ s/-/::/g;
+
+ ### no sense replacing it unless we changed something
+ $modobj->module( $pkgname )
+ if ($pkgname ne $modobj->package_name) || $pkgname !~ /-/;
+ }
+
+ return $modobj;
+ }
+
+ ### perhaps we can find it's a third party module?
+ { my $modobj = CPANPLUS::Module::Fake->new(
+ module => $mod,
+ version => 0,
+ package => $dist,
+ path => File::Spec::Unix->catdir(
+ $conf->_get_mirror('base'),
+ UNKNOWN_DL_LOCATION ),
+ author => CPANPLUS::Module::Author::Fake->new
+ );
+ if( $modobj->is_third_party ) {
+ my $info = $modobj->third_party_information;
+
+ $modobj->author->author( $info->{author} );
+ $modobj->author->email( $info->{author_url} );
+ $modobj->description( $info->{url} );
+
+ return $modobj;
+ }
+ }
+
+ unless( $dist ) {
+ error( loc("%1 is not a proper distribution name!", $mod) );
+ return;
+ }
+
+ ### there's wonky uris out there, like this:
+ ### E/EY/EYCK/Net/Lite/Net-Lite-FTP-0.091
+ ### compensate for that
+ my $author;
+ ### you probably have an A/AB/ABC/....../Dist.tgz type uri
+ if( (defined $parts[0] and length $parts[0] == 1) and
+ (defined $parts[1] and length $parts[1] == 2) and
+ $parts[2] =~ /^$parts[0]/i and $parts[2] =~ /^$parts[1]/i
+ ) {
+ splice @parts, 0, 2; # remove the first 2 entries from the list
+ $author = shift @parts; # this is the actual author name then
+
+ ### we''ll assume a ABC/..../Dist.tgz
+ } else {
+ $author = shift @parts || '';
+ }
+
+ my($pkg, $version, $ext, $full) =
+ $self->_split_package_string( package => $dist );
+
+ ### translate a distribution into a module name ###
+ my $guess = $pkg;
+ $guess =~ s/-/::/g if $guess;
+
+ my $maybe = $self->module_tree( $guess );
+ if( IS_MODOBJ->( module => $maybe ) ) {
+
+ ### maybe you asked for a package instead
+ if ( $maybe->package eq $mod ) {
+ return $maybe;
+
+ ### perhaps an outdated version instead?
+ } elsif ( $version ) {
+ my $auth_obj; my $path;
+
+ ### did you give us an author part? ###
+ if( $author ) {
+ $auth_obj = CPANPLUS::Module::Author::Fake->new(
+ _id => $maybe->_id,
+ cpanid => uc $author,
+ author => uc $author,
+ );
+ $path = File::Spec::Unix->catdir(
+ $conf->_get_mirror('base'),
+ substr(uc $author, 0, 1),
+ substr(uc $author, 0, 2),
+ uc $author,
+ @parts, #possible sub dirs
+ );
+ } else {
+ $auth_obj = $maybe->author;
+ $path = $maybe->path;
+ }
+
+ if( $maybe->package_name eq $pkg ) {
+
+ my $modobj = CPANPLUS::Module::Fake->new(
+ module => $maybe->module,
+ version => $version,
+ ### no extension? use the extension the original package
+ ### had instead
+ package => do { $ext
+ ? $full
+ : $full .'.'. $maybe->package_extension
+ },
+ path => $path,
+ author => $auth_obj,
+ _id => $maybe->_id
+ );
+ return $modobj;
+
+ ### you asked for a specific version?
+ ### assume our $maybe is the one you wanted,
+ ### and fix up the version..
+ } else {
+
+ my $modobj = $maybe->clone;
+ $modobj->version( $version );
+ $modobj->package(
+ $maybe->package_name .'-'.
+ $version .'.'.
+ $maybe->package_extension
+ );
+
+ ### you wanted a specific author, but it's not the one
+ ### from the module tree? we'll fix it up
+ if( $author and $author ne $modobj->author->cpanid ) {
+ $modobj->author( $auth_obj );
+ $modobj->path( $path );
+ }
+
+ return $modobj;
+ }
+
+ ### you didn't care about a version, so just return the object then
+ } elsif ( !$version ) {
+ return $maybe;
+ }
+
+ ### ok, so we can't find it, and it's not an outdated dist either
+ ### perhaps we can fake one based on the author name and so on
+ } elsif ( $author and $version ) {
+
+ ### be extra friendly and pad the .tar.gz suffix where needed
+ ### it's just a guess of course, but most dists are .tar.gz
+ $dist .= '.tar.gz' unless $dist =~ /\.[A-Za-z]+$/;
+
+ ### XXX duplication from above for generating author obj + path...
+ my $modobj = CPANPLUS::Module::Fake->new(
+ module => $guess,
+ version => $version,
+ package => $dist,
+ author => CPANPLUS::Module::Author::Fake->new(
+ author => uc $author,
+ cpanid => uc $author,
+ _id => $self->_id,
+ ),
+ path => File::Spec::Unix->catdir(
+ $conf->_get_mirror('base'),
+ substr(uc $author, 0, 1),
+ substr(uc $author, 0, 2),
+ uc $author,
+ @parts, #possible subdirs
+ ),
+ _id => $self->_id,
+ );
+
+ return $modobj;
+
+ ### face it, we have /no/ idea what he or she wants...
+ ### let's start putting the blame somewhere
+ } else {
+
+ # Lets not give up too easily. There is one last chance
+ # http://perlmonks.org/?node_id=805957
+ # This should catch edge-cases where the package name
+ # is unrelated to the modules it contains.
+
+ my ($modobj) = grep { $_->package_name eq $mod }
+ $self->search( type => 'package', allow => [ qr/^\Q$mod\E/ ], );
+ return $modobj if IS_MODOBJ->( module => $modobj );
+
+ unless( $author ) {
+ error( loc( "'%1' does not contain an author part", $mod ) );
+ }
+
+ error( loc( "Cannot find '%1' in the module tree", $mod ) );
+ }
+
+ return;
+}
+
+=pod
+
+=head2 $bool = $cb->reload_indices( [update_source => BOOL, verbose => BOOL] );
+
+This method reloads the source files.
+
+If C<update_source> is set to true, this will fetch new source files
+from your CPAN mirror. Otherwise, C<reload_indices> will do its
+usual cache checking and only update them if they are out of date.
+
+By default, C<update_source> will be false.
+
+The verbose setting defaults to what you have specified in your
+config file.
+
+Returns true on success and false on failure.
+
+=cut
+
+sub reload_indices {
+ my $self = shift;
+ my %hash = @_;
+ my $conf = $self->configure_object;
+
+ my $tmpl = {
+ update_source => { default => 0, allow => [qr/^\d$/] },
+ verbose => { default => $conf->get_conf('verbose') },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ ### make a call to the internal _module_tree, so it triggers cache
+ ### file age
+ my $uptodate = $self->_check_trees( %$args );
+
+
+ return 1 if $self->_build_trees(
+ uptodate => $uptodate,
+ use_stored => 0,
+ verbose => $conf->get_conf('verbose'),
+ );
+
+ error( loc( "Error rebuilding source trees!" ) );
+
+ return;
+}
+
+=pod
+
+=head2 $bool = $cb->flush(CACHE_NAME)
+
+This method allows flushing of caches.
+There are several things which can be flushed:
+
+=over 4
+
+=item * C<methods>
+
+The return status of methods which have been attempted, such as
+different ways of fetching files. It is recommended that automatic
+flushing be used instead.
+
+=item * C<hosts>
+
+The return status of URIs which have been attempted, such as
+different hosts of fetching files. It is recommended that automatic
+flushing be used instead.
+
+=item * C<modules>
+
+Information about modules such as prerequisites and whether
+installation succeeded, failed, or was not attempted.
+
+=item * C<lib>
+
+This resets PERL5LIB, which is changed to ensure that while installing
+modules they are in our @INC.
+
+=item * C<load>
+
+This resets the cache of modules we've attempted to load, but failed.
+This enables you to load them again after a failed load, if they
+somehow have become available.
+
+=item * C<all>
+
+Flush all of the aforementioned caches.
+
+=back
+
+Returns true on success and false on failure.
+
+=cut
+
+sub flush {
+ my $self = shift;
+ my $type = shift or return;
+
+ my $cache = {
+ methods => [ qw( methods load ) ],
+ hosts => [ qw( hosts ) ],
+ modules => [ qw( modules lib) ],
+ lib => [ qw( lib ) ],
+ load => [ qw( load ) ],
+ all => [ qw( hosts lib modules methods load ) ],
+ };
+
+ my $aref = $cache->{$type}
+ or (
+ error( loc("No such cache '%1'", $type) ),
+ return
+ );
+
+ return $self->_flush( list => $aref );
+}
+
+=pod
+
+=head2 @mods = $cb->installed()
+
+Returns a list of module objects of all your installed modules.
+If an error occurs, it will return false.
+
+See L<CPANPLUS::Module> for the operations you can perform on a
+module object.
+
+=cut
+
+sub installed {
+ my $self = shift;
+ my $aref = $self->_all_installed;
+
+ return @$aref if $aref;
+ return;
+}
+
+=pod
+
+=head2 $bool = $cb->local_mirror([path => '/dir/to/save/to', index_files => BOOL, force => BOOL, verbose => BOOL] )
+
+Creates a local mirror of CPAN, of only the most recent sources in a
+location you specify. If you set this location equal to a custom host
+in your C<CPANPLUS::Config> you can use your local mirror to install
+from.
+
+It takes the following arguments:
+
+=over 4
+
+=item path
+
+The location where to create the local mirror.
+
+=item index_files
+
+Enable/disable fetching of index files. You can disable fetching of the
+index files if you don't plan to use the local mirror as your primary
+site, or if you'd like up-to-date index files be fetched from elsewhere.
+
+Defaults to true.
+
+=item force
+
+Forces refetching of packages, even if they are there already.
+
+Defaults to whatever setting you have in your C<CPANPLUS::Config>.
+
+=item verbose
+
+Prints more messages about what its doing.
+
+Defaults to whatever setting you have in your C<CPANPLUS::Config>.
+
+=back
+
+Returns true on success and false on error.
+
+=cut
+
+sub local_mirror {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my($path, $index, $force, $verbose);
+ my $tmpl = {
+ path => { default => $conf->get_conf('base'),
+ store => \$path },
+ index_files => { default => 1, store => \$index },
+ force => { default => $conf->get_conf('force'),
+ store => \$force },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ unless( -d $path ) {
+ $self->_mkdir( dir => $path )
+ or( error( loc( "Could not create '%1', giving up", $path ) ),
+ return
+ );
+ } elsif ( ! -w _ ) {
+ error( loc( "Could not write to '%1', giving up", $path ) );
+ return;
+ }
+
+ my $flag;
+ AUTHOR: {
+ for my $auth ( sort { $a->cpanid cmp $b->cpanid }
+ values %{$self->author_tree}
+ ) {
+
+ MODULE: {
+ my $i;
+ for my $mod ( $auth->modules ) {
+ my $fetchdir = File::Spec->catdir( $path, $mod->path );
+
+ my %opts = (
+ verbose => $verbose,
+ force => $force,
+ fetchdir => $fetchdir,
+ );
+
+ ### only do this the for the first module ###
+ unless( $i++ ) {
+ $mod->_get_checksums_file(
+ %opts
+ ) or (
+ error( loc( "Could not fetch %1 file, " .
+ "skipping author '%2'",
+ CHECKSUMS, $auth->cpanid ) ),
+ $flag++, next AUTHOR
+ );
+ }
+
+ $mod->fetch( %opts )
+ or( error( loc( "Could not fetch '%1'", $mod->module ) ),
+ $flag++, next MODULE
+ );
+ } }
+ } }
+
+ if( $index ) {
+ for my $name (qw[auth dslip mod]) {
+ $self->_update_source(
+ name => $name,
+ verbose => $verbose,
+ path => $path,
+ ) or ( $flag++, next );
+ }
+ }
+
+ return !$flag;
+}
+
+=pod
+
+=head2 $file = $cb->autobundle([path => OUTPUT_PATH, force => BOOL, verbose => BOOL])
+
+Writes out a snapshot of your current installation in C<CPAN> bundle
+style. This can then be used to install the same modules for a
+different or on a different machine by issuing the following commands:
+
+ ### using the default shell:
+ CPAN Terminal> i file://path/to/Snapshot_XXYY.pm
+
+ ### using the API
+ $modobj = $cb->parse_module( module => 'file://path/to/Snapshot_XXYY.pm' );
+ $modobj->install;
+
+It will, by default, write to an 'autobundle' directory under your
+cpanplus homedirectory, but you can override that by supplying a
+C<path> argument.
+
+It will return the location of the output file on success and false on
+failure.
+
+=cut
+
+sub autobundle {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my($path,$force,$verbose);
+ my $tmpl = {
+ force => { default => $conf->get_conf('force'), store => \$force },
+ verbose => { default => $conf->get_conf('verbose'), store => \$verbose },
+ path => { default => File::Spec->catdir(
+ $conf->get_conf('base'),
+ $self->_perl_version( perl => $^X ),
+ $conf->_get_build('distdir'),
+ $conf->_get_build('autobundle') ),
+ store => \$path },
+ };
+
+ check($tmpl, \%hash) or return;
+
+ unless( -d $path ) {
+ $self->_mkdir( dir => $path )
+ or( error(loc("Could not create directory '%1'", $path ) ),
+ return
+ );
+ }
+
+ my $name; my $file;
+ { ### default filename for the bundle ###
+ my($year,$month,$day) = (localtime)[5,4,3];
+ $year += 1900; $month++;
+
+ my $ext = 0;
+
+ my $prefix = $conf->_get_build('autobundle_prefix');
+ my $format = "${prefix}_%04d_%02d_%02d_%02d";
+
+ BLOCK: {
+ $name = sprintf( $format, $year, $month, $day, $ext);
+
+ $file = File::Spec->catfile( $path, $name . '.pm' );
+
+ -f $file ? ++$ext && redo BLOCK : last BLOCK;
+ }
+ }
+ my $fh;
+ unless( $fh = FileHandle->new( ">$file" ) ) {
+ error( loc( "Could not open '%1' for writing: %2", $file, $! ) );
+ return;
+ }
+
+ ### make sure we load the module tree *before* doing this, as it
+ ### starts to chdir all over the place
+ $self->module_tree;
+
+ my $string = join "\n\n",
+ map {
+ join ' ',
+ $_->module,
+ ($_->installed_version(verbose => 0) || 'undef')
+ } sort {
+ $a->module cmp $b->module
+ } $self->installed;
+
+ my $now = scalar localtime;
+ my $head = '=head1';
+ my $pkg = __PACKAGE__;
+ my $version = $self->VERSION;
+ my $perl_v = join '', `$^X -V`;
+
+ print $fh <<EOF;
+package $name;
+
+\$VERSION = '0.01';
+
+1;
+
+__END__
+
+$head NAME
+
+$name - Snapshot of your installation at $now
+
+$head SYNOPSIS
+
+To install the modules from this snapshot, run:
+
+ cpanp -i file://full/path/to/${name}.pm
+
+$head CONTENTS
+
+$string
+
+$head CONFIGURATION
+
+$perl_v
+
+$head AUTHOR
+
+This bundle has been generated autotomatically by
+ $pkg $version
+
+EOF
+
+ close $fh;
+
+ return $file;
+}
+
+=head2 $bool = $cb->save_state
+
+Explicit command to save memory state to disk. This can be used to save
+information to disk about where a module was extracted, the result of
+C<make test>, etc. This will then be re-loaded into memory when a new
+session starts.
+
+The capability of saving state to disk depends on the source engine
+being used (See C<CPANPLUS::Config> for the option to choose your
+source engine). The default storage engine supports this option.
+
+Most users will not need this command, but it can handy for automated
+systems like setting up CPAN smoke testers.
+
+The method will return true if it managed to save the state to disk,
+or false if it did not.
+
+=cut
+
+sub save_state {
+ my $self = shift;
+ return $self->_save_state( @_ );
+}
+
+
+### XXX these wrappers are not individually tested! only the underlying
+### code through source.t and indirectly trought he CustomSource plugin.
+=pod
+
+=head1 CUSTOM MODULE SOURCES
+
+Besides the sources as provided by the general C<CPAN> mirrors, it's
+possible to add your own sources list to your C<CPANPLUS> index.
+
+The methodology behind this works much like C<Debian's apt-sources>.
+
+The methods below show you how to make use of this functionality. Also
+note that most of these methods are available through the default shell
+plugin command C</cs>, making them available as shortcuts through the
+shell and via the commandline.
+
+=head2 %files = $cb->list_custom_sources
+
+Returns a mapping of registered custom sources and their local indices
+as follows:
+
+ /full/path/to/local/index => http://remote/source
+
+Note that any file starting with an C<#> is being ignored.
+
+=cut
+
+sub list_custom_sources {
+ return shift->__list_custom_module_sources( @_ );
+}
+
+=head2 $local_index = $cb->add_custom_source( uri => URI, [verbose => BOOL] );
+
+Adds an C<URI> to your own sources list and mirrors its index. See the
+documentation on C<< $cb->update_custom_source >> on how this is done.
+
+Returns the full path to the local index on success, or false on failure.
+
+Note that when adding a new C<URI>, the change to the in-memory tree is
+not saved until you rebuild or save the tree to disk again. You can do
+this using the C<< $cb->reload_indices >> method.
+
+=cut
+
+sub add_custom_source {
+ return shift->_add_custom_module_source( @_ );
+}
+
+=head2 $local_index = $cb->remove_custom_source( uri => URI, [verbose => BOOL] );
+
+Removes an C<URI> from your own sources list and removes its index.
+
+To find out what C<URI>s you have as part of your own sources list, use
+the C<< $cb->list_custom_sources >> method.
+
+Returns the full path to the deleted local index file on success, or false
+on failure.
+
+=cut
+
+### XXX do clever dispatching based on arg number?
+sub remove_custom_source {
+ return shift->_remove_custom_module_source( @_ );
+}
+
+=head2 $bool = $cb->update_custom_source( [remote => URI] );
+
+Updates the indexes for all your custom sources. It does this by fetching
+a file called C<packages.txt> in the root of the custom sources's C<URI>.
+If you provide the C<remote> argument, it will only update the index for
+that specific C<URI>.
+
+Here's an example of how custom sources would resolve into index files:
+
+ file:///path/to/sources => file:///path/to/sources/packages.txt
+ http://example.com/sources => http://example.com/sources/packages.txt
+ ftp://example.com/sources => ftp://example.com/sources/packages.txt
+
+The file C<packages.txt> simply holds a list of packages that can be found
+under the root of the C<URI>. This file can be automatically generated for
+you when the remote source is a C<file:// URI>. For C<http://>, C<ftp://>,
+and similar, the administrator of that repository should run the method
+C<< $cb->write_custom_source_index >> on the repository to allow remote
+users to index it.
+
+For details, see the C<< $cb->write_custom_source_index >> method below.
+
+All packages that are added via this mechanism will be attributed to the
+author with C<CPANID> C<LOCAL>. You can use this id to search for all
+added packages.
+
+=cut
+
+sub update_custom_source {
+ my $self = shift;
+
+ ### if it mentions /remote/, the request is to update a single uri,
+ ### not all the ones we have, so dispatch appropriately
+ my $rv = grep( /remote/i, @_)
+ ? $self->__update_custom_module_source( @_ )
+ : $self->__update_custom_module_sources( @_ );
+
+ return $rv;
+}
+
+=head2 $file = $cb->write_custom_source_index( path => /path/to/package/root, [to => /path/to/index/file, verbose => BOOL] );
+
+Writes the index for a custom repository root. Most users will not have to
+worry about this, but administrators of a repository will need to make sure
+their indexes are up to date.
+
+The index will be written to a file called C<packages.txt> in your repository
+root, which you can specify with the C<path> argument. You can override this
+location by specifying the C<to> argument, but in normal operation, that should
+not be required.
+
+Once the index file is written, users can then add the C<URI> pointing to
+the repository to their custom list of sources and start using it right away. See the C<< $cb->add_custom_source >> method for user details.
+
+=cut
+
+sub write_custom_source_index {
+ return shift->__write_custom_module_index( @_ );
+}
+
+1;
+
+=pod
+
+=head1 BUG REPORTS
+
+Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
+
+=head1 AUTHOR
+
+This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
+
+=head1 COPYRIGHT
+
+The CPAN++ interface (of which this module is a part of) is copyright (c)
+2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
+
+This library is free software; you may redistribute and/or modify it
+under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<CPANPLUS::Configure>, L<CPANPLUS::Module>, L<CPANPLUS::Module::Author>,
+L<CPANPLUS::Selfupdate>
+
+=cut
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
+
+__END__
+
+todo:
+sub dist { # not sure about this one -- probably already done
+ enough in Module.pm
+sub reports { # in Module.pm, wrapper here
+
+
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Backend/RV.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Backend/RV.pm
new file mode 100644
index 00000000000..9edbe0452c9
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Backend/RV.pm
@@ -0,0 +1,144 @@
+package CPANPLUS::Backend::RV;
+
+use strict;
+use vars qw[$STRUCT];
+
+
+use CPANPLUS::Error;
+use CPANPLUS::Internals::Constants;
+
+use IPC::Cmd qw[can_run run];
+use Params::Check qw[check];
+
+use base 'Object::Accessor';
+
+local $Params::Check::VERBOSE = 1;
+
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Backend::RV
+
+=head1 SYNOPSIS
+
+ ### create a CPANPLUS::Backend::RV object
+ $backend_rv = CPANPLUS::Backend::RV->new(
+ ok => $boolean,
+ args => $args,
+ rv => $return_value
+ function => $calling_function );
+
+ ### if you have a CPANPLUS::Backend::RV object
+ $passed_args = $backend_rv->args; # args passed to function
+ $ok = $backend_rv->ok; # boolean indication overall
+ # result of the call
+ $function = $backend_rv->fucntion # name of the calling
+ # function
+ $rv = $backend_rv->rv # the actual return value
+ # of the calling function
+
+=head1 DESCRIPTION
+
+This module provides return value objects for multi-module
+calls to CPANPLUS::Backend. In boolean context, it returns the status
+of the overall result (ie, the same as the C<ok> method would).
+
+=head1 METHODS
+
+=head2 new( ok => BOOL, args => DATA, rv => DATA, [function => $method_name] )
+
+Creates a new CPANPLUS::Backend::RV object from the data provided.
+This method should only be called by CPANPLUS::Backend functions.
+The accessors may be used by users inspecting an RV object.
+
+All the argument names can be used as accessors later to retrieve the
+data.
+
+Arguments:
+
+=over 4
+
+=item ok
+
+Boolean indicating overall success
+
+=item args
+
+The arguments provided to the function that returned this rv object.
+Useful to inspect later to see what was actually passed to the function
+in case of an error.
+
+=item rv
+
+An arbitrary data structure that has the detailed return values of each
+of your multi-module calls.
+
+=item function
+
+The name of the function that created this rv object.
+Can be explicitly passed. If not, C<new()> will try to deduce the name
+from C<caller()> information.
+
+=back
+
+=cut
+
+sub new {
+ my $class = shift;
+ my %hash = @_;
+
+ my $tmpl = {
+ ok => { required => 1, allow => BOOLEANS },
+ args => { required => 1 },
+ rv => { required => 1 },
+ function => { default => CALLING_FUNCTION->() },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+ my $self = bless {}, $class;
+
+# $self->mk_accessors( qw[ok args function rv] );
+ $self->mk_accessors( keys %$tmpl );
+
+ ### set the values passed in the struct ###
+ while( my($key,$val) = each %$args ) {
+ $self->$key( $val );
+ }
+
+ return $self;
+}
+
+sub _ok { return shift->ok }
+#sub _stringify { Carp::carp( "stringifying!" ); overload::StrVal( shift ) }
+
+### make it easier to check if($rv) { foo() }
+### this allows people to not have to explicitly say
+### if( $rv->ok ) { foo() }
+### XXX add an explicit stringify, so it doesn't fall back to "bool"? :(
+use overload bool => \&_ok,
+# '""' => \&_stringify,
+ fallback => 1;
+
+=pod
+
+=head1 BUG REPORTS
+
+Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
+
+=head1 AUTHOR
+
+This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
+
+=head1 COPYRIGHT
+
+The CPAN++ interface (of which this module is a part of) is copyright (c)
+2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
+
+This library is free software; you may redistribute and/or modify it
+under the same terms as Perl itself.
+
+=cut
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Config.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Config.pm
new file mode 100644
index 00000000000..740ef1e637f
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Config.pm
@@ -0,0 +1,797 @@
+package CPANPLUS::Config;
+
+use strict;
+use warnings;
+
+use base 'Object::Accessor';
+
+use base 'CPANPLUS::Internals::Utils';
+
+use Config;
+use File::Spec;
+use Module::Load;
+use CPANPLUS;
+use CPANPLUS::Error;
+use CPANPLUS::Internals::Constants;
+
+use File::Basename qw[dirname];
+use IPC::Cmd qw[can_run];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+use Module::Load::Conditional qw[check_install];
+
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Config
+
+=head1 SYNOPSIS
+
+ ### conf object via CPANPLUS::Backend;
+ $cb = CPANPLUS::Backend->new;
+ $conf = $cb->configure_object;
+
+ ### or as a standalone object
+ $conf = CPANPLUS::Configure->new;
+
+ ### values in 'conf' section
+ $verbose = $conf->get_conf( 'verbose' );
+ $conf->set_conf( verbose => 1 );
+
+ ### values in 'program' section
+ $editor = $conf->get_program( 'editor' );
+ $conf->set_program( editor => '/bin/vi' );
+
+=head1 DESCRIPTION
+
+This module contains defaults and heuristics for configuration
+information for CPANPLUS. To change any of these values, please
+see the documentation in C<CPANPLUS::Configure>.
+
+Below you'll find a list of configuration types and keys, and
+their meaning.
+
+=head1 CONFIGURATION
+
+=cut
+
+### BAH! you can't have POD interleaved with a hash
+### declaration.. so declare every entry seperatedly :(
+my $Conf = {
+ '_fetch' => {
+ 'blacklist' => [ 'ftp' ],
+ },
+
+ ### _source, _build and _mirror are supposed to be static
+ ### no changes should be needed unless pause/cpan changes
+ '_source' => {
+ 'hosts' => 'MIRRORED.BY',
+ 'auth' => '01mailrc.txt.gz',
+ 'stored' => 'sourcefiles',
+ 'dslip' => '03modlist.data.gz',
+ 'update' => '86400',
+ 'mod' => '02packages.details.txt.gz',
+ 'custom_index' => 'packages.txt',
+ },
+ '_build' => {
+ 'plugins' => 'plugins',
+ 'moddir' => 'build',
+ 'startdir' => '',
+ 'distdir' => 'dist',
+ 'autobundle' => 'autobundle',
+ 'autobundle_prefix' => 'Snapshot',
+ 'autdir' => 'authors',
+ 'install_log_dir' => 'install-logs',
+ 'custom_sources' => 'custom-sources',
+ 'sanity_check' => 1,
+ },
+ '_mirror' => {
+ 'base' => 'authors/id/',
+ 'auth' => 'authors/01mailrc.txt.gz',
+ 'dslip' => 'modules/03modlist.data.gz',
+ 'mod' => 'modules/02packages.details.txt.gz'
+ },
+};
+
+=head2 Section 'conf'
+
+=over 4
+
+=item hosts
+
+An array ref containing hosts entries to be queried for packages.
+
+An example entry would like this:
+
+ { 'scheme' => 'ftp',
+ 'path' => '/pub/CPAN/',
+ 'host' => 'ftp.cpan.org'
+ },
+
+=cut
+
+ ### default host list
+ $Conf->{'conf'}->{'hosts'} = [
+ {
+ 'scheme' => 'ftp',
+ 'path' => '/pub/CPAN/',
+ 'host' => 'ftp.cpan.org'
+ },
+ {
+ 'scheme' => 'http',
+ 'path' => '/',
+ 'host' => 'www.cpan.org'
+ },
+ {
+ 'scheme' => 'ftp',
+ 'path' => '/pub/CPAN/',
+ 'host' => 'ftp.nl.uu.net'
+ },
+ {
+ 'scheme' => 'ftp',
+ 'path' => '/pub/CPAN/',
+ 'host' => 'cpan.valueclick.com'
+ },
+ {
+ 'scheme' => 'ftp',
+ 'path' => '/pub/languages/perl/CPAN/',
+ 'host' => 'ftp.funet.fi'
+ }
+ ];
+
+=item allow_build_interactivity
+
+Boolean flag to indicate whether 'perl Makefile.PL' and similar
+are run interactively or not. Defaults to 'true'.
+
+=cut
+
+ $Conf->{'conf'}->{'allow_build_interactivity'} = 1;
+
+=item base
+
+The directory CPANPLUS keeps all its build and state information in.
+Defaults to ~/.cpanplus.
+
+=cut
+
+ $Conf->{'conf'}->{'base'} = File::Spec->catdir(
+ __PACKAGE__->_home_dir, DOT_CPANPLUS );
+
+=item buildflags
+
+Any flags to be passed to 'perl Build.PL'. See C<perldoc Module::Build>
+for details. Defaults to an empty string.
+
+=cut
+
+ $Conf->{'conf'}->{'buildflags'} = '';
+
+=item cpantest
+
+Boolean flag to indicate whether or not to mail test results of module
+installations to C<http://testers.cpan.org>. Defaults to 'false'.
+
+=cut
+
+ $Conf->{'conf'}->{'cpantest'} = 0;
+
+=item cpantest_mx
+
+String holding an explicit mailserver to use when sending out emails
+for C<http://testers.cpan.org>. An empty string will use your system
+settings. Defaults to an empty string.
+
+=cut
+
+ $Conf->{'conf'}->{'cpantest_mx'} = '';
+
+=item debug
+
+Boolean flag to enable or disable extensive debuggging information.
+Defaults to 'false'.
+
+=cut
+
+ $Conf->{'conf'}->{'debug'} = 0;
+
+=item dist_type
+
+Default distribution type to use when building packages. See C<cpan2dist>
+or C<CPANPLUS::Dist> for details. An empty string will not use any
+package building software. Defaults to an empty string.
+
+=cut
+
+ $Conf->{'conf'}->{'dist_type'} = '';
+
+=item email
+
+Email address to use for anonymous ftp access and as C<from> address
+when sending emails. Defaults to an C<example.com> address.
+
+=cut
+
+ $Conf->{'conf'}->{'email'} = DEFAULT_EMAIL;
+
+=item enable_custom_sources
+
+Boolean flag indicating whether custom sources should be enabled or
+not. See the C<CUSTOM MODULE SOURCES> in C<CPANPLUS::Backend> for
+details on how to use them.
+
+Defaults to C<true>
+
+=cut
+
+ ### this addresses #32248 which requests a possibillity to
+ ### turn off custom sources
+ $Conf->{'conf'}->{'enable_custom_sources'} = 1;
+
+=item extractdir
+
+String containing the directory where fetched archives should be
+extracted. An empty string will use a directory under your C<base>
+directory. Defaults to an empty string.
+
+=cut
+
+ $Conf->{'conf'}->{'extractdir'} = '';
+
+=item fetchdir
+
+String containing the directory where fetched archives should be
+stored. An empty string will use a directory under your C<base>
+directory. Defaults to an empty string.
+
+=cut
+
+ $Conf->{'conf'}->{'fetchdir'} = '';
+
+=item flush
+
+Boolean indicating whether build failures, cache dirs etc should
+be flushed after every operation or not. Defaults to 'true'.
+
+=cut
+
+ $Conf->{'conf'}->{'flush'} = 1;
+
+=item force
+
+Boolean indicating whether files should be forcefully overwritten
+if they exist, modules should be installed when they fail tests,
+etc. Defaults to 'false'.
+
+=cut
+
+ $Conf->{'conf'}->{'force'} = 0;
+
+=item lib
+
+An array ref holding directories to be added to C<@INC> when CPANPLUS
+starts up. Defaults to an empty array reference.
+
+=cut
+
+ $Conf->{'conf'}->{'lib'} = [];
+
+=item makeflags
+
+A string holding flags that will be passed to the C<make> program
+when invoked. Defaults to an empty string.
+
+=cut
+
+ $Conf->{'conf'}->{'makeflags'} = '';
+
+=item makemakerflags
+
+A string holding flags that will be passed to C<perl Makefile.PL>
+when invoked. Defaults to an empty string.
+
+=cut
+
+ $Conf->{'conf'}->{'makemakerflags'} = '';
+
+=item md5
+
+A boolean indicating whether or not md5 checks should be done when
+an archive is fetched. Defaults to 'true' if you have C<Digest::MD5>
+installed, 'false' otherwise.
+
+=cut
+
+ $Conf->{'conf'}->{'md5'} = (
+ check_install( module => 'Digest::MD5' ) ? 1 : 0 );
+
+=item no_update
+
+A boolean indicating whether or not C<CPANPLUS>' source files should be
+updated or not. Defaults to 'false'.
+
+=cut
+
+ $Conf->{'conf'}->{'no_update'} = 0;
+
+=item passive
+
+A boolean indicating whether or not to use passive ftp connections.
+Defaults to 'true'.
+
+=cut
+
+ $Conf->{'conf'}->{'passive'} = 1;
+
+=item prefer_bin
+
+A boolean indicating whether or not to prefer command line programs
+over perl modules. Defaults to 'false' unless you do not have
+C<Compress::Zlib> installed (as that would mean we could not extract
+C<.tar.gz> files)
+
+=cut
+ ### if we dont have c::zlib, we'll need to use /bin/tar or we
+ ### can not extract any files. Good time to change the default
+ $Conf->{'conf'}->{'prefer_bin'} =
+ (eval {require Compress::Zlib; 1} ? 0 : 1 );
+
+=item prefer_makefile
+
+A boolean indicating whether or not prefer a C<Makefile.PL> over a
+C<Build.PL> file if both are present. Defaults to 'true', unless
+the perl version is at least 5.10.1 or appropriate versions of L<Module::Build>
+and L<CPANPLUS::Dist::Build> are available.
+
+=cut
+
+ $Conf->{'conf'}->{'prefer_makefile'} =
+ ( $] >= 5.010001 or
+ ( check_install( module => 'Module::Build', version => '0.32' ) and
+ check_install( module => INSTALLER_BUILD, version => '0.24' ) )
+ ? 0 : 1 );
+
+=item prereqs
+
+A digit indicating what to do when a package you are installing has a
+prerequisite. Options are:
+
+ 0 Do not install
+ 1 Install
+ 2 Ask
+ 3 Ignore (dangerous, install will probably fail!)
+
+The default is to ask.
+
+=cut
+
+ $Conf->{'conf'}->{'prereqs'} = PREREQ_ASK;
+
+=item shell
+
+A string holding the shell class you wish to start up when starting
+C<CPANPLUS> in interactive mode.
+
+Defaults to C<CPANPLUS::Shell::Default>, the default CPANPLUS shell.
+
+=cut
+
+ $Conf->{'conf'}->{'shell'} = 'CPANPLUS::Shell::Default';
+
+=item show_startup_tip
+
+A boolean indicating whether or not to show start up tips in the
+interactive shell. Defaults to 'true'.
+
+=cut
+
+ $Conf->{'conf'}->{'show_startup_tip'} = 1;
+
+=item signature
+
+A boolean indicating whether or not check signatures if packages are
+signed. Defaults to 'true' if you have C<gpg> or C<Crypt::OpenPGP>
+installed, 'false' otherwise.
+
+=cut
+
+ $Conf->{'conf'}->{'signature'} = do {
+ check_install( module => 'Module::Signature', version => '0.06' )
+ and ( can_run('gpg') ||
+ check_install(module => 'Crypt::OpenPGP')
+ );
+ } ? 1 : 0;
+
+=item skiptest
+
+A boolean indicating whether or not to skip tests when installing modules.
+Defaults to 'false'.
+
+=cut
+
+ $Conf->{'conf'}->{'skiptest'} = 0;
+
+=item storable
+
+A boolean indicating whether or not to use C<Storable> to write compiled
+source file information to disk. This makes for faster startup and look
+up times, but takes extra diskspace. Defaults to 'true' if you have
+C<Storable> installed and 'false' if you don't.
+
+=cut
+
+ $Conf->{'conf'}->{'storable'} =
+ ( check_install( module => 'Storable' ) ? 1 : 0 );
+
+=item timeout
+
+Digit indicating the time before a fetch request times out (in seconds).
+Defaults to 300.
+
+=cut
+
+ $Conf->{'conf'}->{'timeout'} = 300;
+
+=item verbose
+
+A boolean indicating whether or not C<CPANPLUS> runs in verbose mode.
+Defaults to 'true' if you have the environment variable
+C<PERL5_CPANPLUS_VERBOSE> set to true, 'false' otherwise.
+
+It is recommended you run with verbose enabled, but it is disabled
+for historical reasons.
+
+=cut
+
+ $Conf->{'conf'}->{'verbose'} = $ENV{PERL5_CPANPLUS_VERBOSE} || 0;
+
+=item write_install_log
+
+A boolean indicating whether or not to write install logs after installing
+a module using the interactive shell. Defaults to 'true'.
+
+
+=cut
+
+ $Conf->{'conf'}->{'write_install_logs'} = 1;
+
+=item source_engine
+
+Class to use as the source engine, which is generally a subclass of
+C<CPANPLUS::Internals::Source>. Default to C<CPANPLUS::Internals::Source::Memory>.
+
+=cut
+
+ $Conf->{'conf'}->{'source_engine'} = DEFAULT_SOURCE_ENGINE;
+
+=item cpantest_reporter_args
+
+A hashref of key => value pairs that are passed to the constructor
+of C<Test::Reporter>. If you'd want to enable TLS for example, you'd
+set it to:
+
+ { transport => 'Net::SMTP::TLS',
+ transport_args => [ User => 'Joe', Password => '123' ],
+ }
+
+=cut
+
+ $Conf->{'conf'}->{'cpantest_reporter_args'} = {};
+
+=back
+
+=head2 Section 'program'
+
+=cut
+
+ ### Paths get stripped of whitespace on win32 in the constructor
+ ### sudo gets emptied if there's no need for it in the constructor
+
+=over 4
+
+=item editor
+
+A string holding the path to your editor of choice. Defaults to your
+$ENV{EDITOR}, $ENV{VISUAL}, 'vi' or 'pico' programs, in that order.
+
+=cut
+
+ $Conf->{'program'}->{'editor'} = do {
+ $ENV{'EDITOR'} || $ENV{'VISUAL'} ||
+ can_run('vi') || can_run('pico')
+ };
+
+=item make
+
+A string holding the path to your C<make> binary. Looks for the C<make>
+program used to build perl or failing that, a C<make> in your path.
+
+=cut
+
+ $Conf->{'program'}->{'make'} =
+ can_run($Config{'make'}) || can_run('make');
+
+=item pager
+
+A string holding the path to your pager of choice. Defaults to your
+$ENV{PAGER}, 'less' or 'more' programs, in that order.
+
+=cut
+
+ $Conf->{'program'}->{'pager'} =
+ $ENV{'PAGER'} || can_run('less') || can_run('more');
+
+ ### no one uses this feature anyway, and it's only working for EU::MM
+ ### and not for module::build
+ #'perl' => '',
+
+=item shell
+
+A string holding the path to your login shell of choice. Defaults to your
+$ENV{SHELL} setting, or $ENV{COMSPEC} on Windows.
+
+=cut
+
+ $Conf->{'program'}->{'shell'} = $^O eq 'MSWin32'
+ ? $ENV{COMSPEC}
+ : $ENV{SHELL};
+
+=item sudo
+
+A string holding the path to your C<sudo> binary if your install path
+requires super user permissions. Looks for C<sudo> in your path, or
+remains empty if you do not require super user permissions to install.
+
+=cut
+
+ $Conf->{'program'}->{'sudo'} = do {
+ ### let's assume you dont need sudo,
+ ### unless one of the below criteria tells us otherwise
+ my $sudo = undef;
+
+ ### you're a normal user, you might need sudo
+ if( $> ) {
+
+ ### check for all install dirs!
+ ### you have write permissions to the installdir,
+ ### you don't need sudo
+ if( -w $Config{'installsitelib'} && -w $Config{'installsitebin'} ) {
+
+ ### installsiteman3dir is a 5.8'ism.. don't check
+ ### it on 5.6.x...
+ if( defined $Config{'installsiteman3dir'} ) {
+ $sudo = -w $Config{'installsiteman3dir'}
+ ? undef
+ : can_run('sudo');
+ } else {
+ $sudo = undef;
+ }
+
+ ### you have PERL_MM_OPT set to some alternate
+ ### install place. You probably have write permissions
+ ### to that
+ } elsif ( $ENV{'PERL_MM_OPT'} and
+ $ENV{'PERL_MM_OPT'} =~ /INSTALL|LIB|PREFIX/
+ ) {
+ $sudo = undef;
+
+ ### you probably don't have write permissions
+ } else {
+ $sudo = can_run('sudo');
+ }
+ }
+
+ ### and return the value
+ $sudo;
+ };
+
+=item perlwrapper
+
+A string holding the path to the C<cpanp-run-perl> utility bundled
+with CPANPLUS, which is used to enable autoflushing in spawned processes.
+
+=cut
+
+ ### perlwrapper that allows us to turn on autoflushing
+ $Conf->{'program'}->{'perlwrapper'} = sub {
+ my $name = 'cpanp-run-perl';
+
+ my @bins = do{
+ require Config;
+ my $ver = $Config::Config{version};
+
+ ### if we are running with 'versiononly' enabled,
+ ### all binaries will have the perlversion appended
+ ### ie, cpanp will become cpanp5.9.5
+ ### so prefer the versioned binary in that case
+ $Config::Config{versiononly}
+ ? ($name.$ver, $name)
+ : ($name, $name.$ver);
+ };
+
+ ### patch from Steve Hay Fri 29 Jun 2007 14:26:02 GMT+02:00
+ ### Msg-Id: <4684FA5A.7030506@uk.radan.com>
+ ### look for files with a ".bat" extension as well on Win32
+ @bins = map { $_, "$_.bat" } @bins if $^O eq 'MSWin32';
+
+ my $path;
+ BIN: for my $bin (@bins) {
+
+ ### parallel to your cpanp/cpanp-boxed
+ my $maybe = File::Spec->rel2abs(
+ File::Spec->catfile( dirname($0), $bin )
+ );
+ $path = $maybe and last BIN if -f $maybe;
+
+ ### parallel to your CPANPLUS.pm:
+ ### $INC{cpanplus}/../bin/cpanp-run-perl
+ $maybe = File::Spec->rel2abs(
+ File::Spec->catfile(
+ dirname($INC{'CPANPLUS.pm'}),
+ '..', # lib dir
+ 'bin', # bin dir
+ $bin, # script
+ )
+ );
+ $path = $maybe and last BIN if -f $maybe;
+
+ ### you installed CPANPLUS in a custom prefix,
+ ### so go paralel to /that/. PREFIX=/tmp/cp
+ ### would put cpanp-run-perl in /tmp/cp/bin and
+ ### CPANPLUS.pm in
+ ### /tmp/cp/lib/perl5/site_perl/5.8.8
+ $maybe = File::Spec->rel2abs(
+ File::Spec->catfile(
+ dirname( $INC{'CPANPLUS.pm'} ),
+ '..', '..', '..', '..', # 4x updir
+ 'bin', # bin dir
+ $bin, # script
+ )
+ );
+ $path = $maybe and last BIN if -f $maybe;
+
+ ### in your path -- take this one last, the
+ ### previous two assume extracted tarballs
+ ### or user installs
+ ### note that we don't use 'can_run' as it's
+ ### not an executable, just a wrapper...
+ ### prefer anything that's found in the path paralel to your $^X
+ for my $dir (File::Spec->rel2abs( dirname($^X) ),
+ split(/\Q$Config::Config{path_sep}\E/, $ENV{PATH}),
+ File::Spec->curdir,
+ ) {
+
+ ### On VMS the path could be in UNIX format, and we
+ ### currently need it to be in VMS format
+ $dir = VMS::Filespec::vmspath($dir) if ON_VMS;
+
+ $maybe = File::Spec->catfile( $dir, $bin );
+ $path = $maybe and last BIN if -f $maybe;
+ }
+ }
+
+ ### we should have a $path by now ideally, if so return it
+ return $path if defined $path;
+
+ ### if not, warn about it and give sensible default.
+ ### XXX try to be a no-op instead then..
+ ### cross your fingers...
+ ### pass '-P' to perl: "run program through C
+ ### preprocessor before compilation"
+ ### XXX using -P actually changes the way some Makefile.PLs
+ ### are executed, so don't do that... --kane
+ error(loc(
+ "Could not find the '%1' binary in your path".
+ "--this may be a problem.\n".
+ "Please locate this program and set ".
+ "your '%2' config entry to its path.\n".
+ "From the default shell, you can do this by typing:\n\n".
+ " %3\n".
+ " %4\n",
+ $name, 'perlwrapper',
+ 's program perlwrapper FULL_PATH_TO_CPANP_RUN_PERL',
+ 's save'
+ ));
+ return '';
+ }->();
+
+=back
+
+=cut
+
+sub new {
+ my $class = shift;
+ my $obj = $class->SUPER::new;
+
+ $obj->mk_accessors( keys %$Conf );
+
+ for my $acc ( keys %$Conf ) {
+ my $subobj = Object::Accessor->new;
+ $subobj->mk_accessors( keys %{$Conf->{$acc}} );
+
+ ### read in all the settings from the sub accessors;
+ for my $subacc ( $subobj->ls_accessors ) {
+ $subobj->$subacc( $Conf->{$acc}->{$subacc} );
+ }
+
+ ### now store it in the parent object
+ $obj->$acc( $subobj );
+ }
+
+ $obj->_clean_up_paths;
+
+ ### shut up IPC::Cmd warning about not findin IPC::Run on win32
+ $IPC::Cmd::WARN = 0;
+
+ return $obj;
+}
+
+sub _clean_up_paths {
+ my $self = shift;
+
+ ### clean up paths if we are on win32
+ if( $^O eq 'MSWin32' ) {
+ for my $pgm ( $self->program->ls_accessors ) {
+ my $path = $self->program->$pgm;
+
+ ### paths with whitespace needs to be shortened
+ ### for shell outs.
+ if ($path and $path =~ /\s+/) {
+ my($prog, $args);
+
+ ### patch from Steve Hay, 13nd of June 2007
+ ### msg-id: <467012A4.6060705@uk.radan.com>
+ ### windows directories are not allowed to end with
+ ### a space, so any occurrence of '\w\s+/\w+' means
+ ### we're dealing with arguments, not directory
+ ### names.
+ if ($path =~ /^(.*?)(\s+\/.*$)/) {
+ ($prog, $args) = ($1, $2);
+
+ ### otherwise, there are no arguments
+ } else {
+ ($prog, $args) = ($path, '');
+ }
+
+ $prog = Win32::GetShortPathName( $prog );
+ $self->program->$pgm( $prog . $args );
+ }
+ }
+ }
+
+ return 1;
+}
+
+1;
+
+=pod
+
+=head1 BUG REPORTS
+
+Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
+
+=head1 AUTHOR
+
+This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
+
+=head1 COPYRIGHT
+
+The CPAN++ interface (of which this module is a part of) is copyright (c)
+2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
+
+This library is free software; you may redistribute and/or modify it
+under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<CPANPLUS::Backend>, L<CPANPLUS::Configure::Setup>, L<CPANPLUS::Configure>
+
+=cut
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Configure.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Configure.pm
new file mode 100644
index 00000000000..baac91dc886
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Configure.pm
@@ -0,0 +1,630 @@
+package CPANPLUS::Configure;
+use strict;
+
+
+use CPANPLUS::Internals::Constants;
+use CPANPLUS::Error;
+use CPANPLUS::Config;
+
+use Log::Message;
+use Module::Load qw[load];
+use Params::Check qw[check];
+use File::Basename qw[dirname];
+use Module::Loaded ();
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+use vars qw[$AUTOLOAD $VERSION $MIN_CONFIG_VERSION];
+use base qw[CPANPLUS::Internals::Utils];
+
+local $Params::Check::VERBOSE = 1;
+
+### require, avoid circular use ###
+require CPANPLUS::Internals;
+$VERSION = $CPANPLUS::Internals::VERSION = $CPANPLUS::Internals::VERSION;
+
+### can't use O::A as we're using our own AUTOLOAD to get to
+### the config options.
+for my $meth ( qw[conf _lib _perl5lib]) {
+ no strict 'refs';
+
+ *$meth = sub {
+ my $self = shift;
+ $self->{'_'.$meth} = $_[0] if @_;
+ return $self->{'_'.$meth};
+ }
+}
+
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Configure
+
+=head1 SYNOPSIS
+
+ $conf = CPANPLUS::Configure->new( );
+
+ $bool = $conf->can_save;
+ $bool = $conf->save( $where );
+
+ @opts = $conf->options( $type );
+
+ $make = $conf->get_program('make');
+ $verbose = $conf->set_conf( verbose => 1 );
+
+=head1 DESCRIPTION
+
+This module deals with all the configuration issues for CPANPLUS.
+Users can use objects created by this module to alter the behaviour
+of CPANPLUS.
+
+Please refer to the C<CPANPLUS::Backend> documentation on how to
+obtain a C<CPANPLUS::Configure> object.
+
+=head1 METHODS
+
+=head2 $Configure = CPANPLUS::Configure->new( load_configs => BOOL )
+
+This method returns a new object. Normal users will never need to
+invoke the C<new> method, but instead retrieve the desired object via
+a method call on a C<CPANPLUS::Backend> object.
+
+=item load_configs
+
+Controls whether or not additional user configurations are to be loaded
+or not. Defaults to C<true>.
+
+=cut
+
+### store teh CPANPLUS::Config object in a closure, so we only
+### initialize it once.. otherwise, on a 2nd ->new, settings
+### from configs on top of this one will be reset
+{ my $Config;
+
+ sub new {
+ my $class = shift;
+ my %hash = @_;
+
+ ### XXX pass on options to ->init() like rescan?
+ my ($load);
+ my $tmpl = {
+ load_configs => { default => 1, store => \$load },
+ };
+
+ check( $tmpl, \%hash ) or (
+ warn Params::Check->last_error, return
+ );
+
+ $Config ||= CPANPLUS::Config->new;
+ my $self = bless {}, $class;
+ $self->conf( $Config );
+
+ ### you want us to load other configs?
+ ### these can override things in the default config
+ $self->init if $load;
+
+ ### after processing the config files, check what
+ ### @INC and PERL5LIB are set to.
+ $self->_lib( \@INC );
+ $self->_perl5lib( $ENV{'PERL5LIB'} );
+
+ return $self;
+ }
+}
+
+=head2 $bool = $Configure->init( [rescan => BOOL])
+
+Initialize the configure with other config files than just
+the default 'CPANPLUS::Config'.
+
+Called from C<new()> to load user/system configurations
+
+If the C<rescan> option is provided, your disk will be
+examined again to see if there are new config files that
+could be read. Defaults to C<false>.
+
+Returns true on success, false on failure.
+
+=cut
+
+### move the Module::Pluggable detection to runtime, rather
+### than compile time, so that a simple 'require CPANPLUS'
+### doesn't start running over your filesystem for no good
+### reason. Make sure we only do the M::P call once though.
+### we use $loaded to mark it
+{ my $loaded;
+ my $warned;
+ sub init {
+ my $self = shift;
+ my $obj = $self->conf;
+ my %hash = @_;
+
+ my ($rescan);
+ my $tmpl = {
+ rescan => { default => 0, store => \$rescan },
+ };
+
+ check( $tmpl, \%hash ) or (
+ warn Params::Check->last_error, return
+ );
+
+ ### if the base dir is changed, we have to rescan it
+ ### for any CPANPLUS::Config::* files as well, so keep
+ ### track of it
+ my $cur_base = $self->get_conf('base');
+
+ ### warn if we find an old style config specified
+ ### via environment variables
+ { my $env = ENV_CPANPLUS_CONFIG;
+ if( $ENV{$env} and not $warned ) {
+ $warned++;
+ error(loc("Specifying a config file in your environment " .
+ "using %1 is obsolete.\nPlease follow the ".
+ "directions outlined in %2 or use the '%3' command\n".
+ "in the default shell to use custom config files.",
+ $env, "CPANPLUS::Configure->save", 's save'));
+ }
+ }
+
+ { ### make sure that the homedir is included now
+ local @INC = ( LIB_DIR->($cur_base), @INC );
+
+ ### only set it up once
+ if( !$loaded++ or $rescan ) {
+ ### find plugins & extra configs
+ ### check $home/.cpanplus/lib as well
+ require Module::Pluggable;
+
+ Module::Pluggable->import(
+ search_path => ['CPANPLUS::Config'],
+ search_dirs => [ LIB_DIR->($cur_base) ],
+ except => qr/::SUPER$/,
+ sub_name => 'configs'
+ );
+ }
+
+
+ ### do system config, user config, rest.. in that order
+ ### apparently, on a 2nd invocation of -->configs, a
+ ### ::ISA::CACHE package can appear.. that's bad...
+ my %confs = map { $_ => $_ }
+ grep { $_ !~ /::ISA::/ } __PACKAGE__->configs;
+ my @confs = grep { defined }
+ map { delete $confs{$_} } CONFIG_SYSTEM, CONFIG_USER;
+ push @confs, sort keys %confs;
+
+ for my $plugin ( @confs ) {
+ msg(loc("Found config '%1'", $plugin),0);
+
+ ### if we already did this the /last/ time around dont
+ ### run the setup agian.
+ if( my $loc = Module::Loaded::is_loaded( $plugin ) ) {
+ msg(loc(" Already loaded '%1' (%2)", $plugin, $loc), 0);
+ next;
+ } else {
+ msg(loc(" Loading config '%1'", $plugin),0);
+
+ if( eval { load $plugin; 1 } ) {
+ msg(loc(" Loaded '%1' (%2)",
+ $plugin, Module::Loaded::is_loaded( $plugin ) ), 0);
+ } else {
+ error(loc(" Error loading '%1': %2", $plugin, $@));
+ }
+ }
+
+ if( $@ ) {
+ error(loc("Could not load '%1': %2", $plugin, $@));
+ next;
+ }
+
+ my $sub = $plugin->can('setup');
+ $sub->( $self ) if $sub;
+ }
+ }
+
+ ### did one of the plugins change the base dir? then we should
+ ### scan the dirs again
+ if( $cur_base ne $self->get_conf('base') ) {
+ msg(loc("Base dir changed from '%1' to '%2', rescanning",
+ $cur_base, $self->get_conf('base')), 0);
+ $self->init( @_, rescan => 1 );
+ }
+
+ ### clean up the paths once more, just in case
+ $obj->_clean_up_paths;
+
+ ### XXX in case the 'lib' param got changed, we need to
+ ### add that now, or it's not propagating ;(
+ { my $lib = $self->get_conf('lib');
+ my %inc = map { $_ => $_ } @INC;
+ for my $l ( @$lib ) {
+ push @INC, $l unless $inc{$l};
+ }
+ $self->_lib( \@INC );
+ }
+
+ return 1;
+ }
+}
+=pod
+
+=head2 can_save( [$config_location] )
+
+Check if we can save the configuration to the specified file.
+If no file is provided, defaults to your personal config.
+
+Returns true if the file can be saved, false otherwise.
+
+=cut
+
+sub can_save {
+ my $self = shift;
+ my $file = shift || CONFIG_USER_FILE->();
+
+ return 1 unless -e $file;
+
+ chmod 0644, $file;
+ return (-w $file);
+}
+
+=pod
+
+=head2 $file = $conf->save( [$package_name] )
+
+Saves the configuration to the package name you provided.
+If this package is not C<CPANPLUS::Config::System>, it will
+be saved in your C<.cpanplus> directory, otherwise it will
+be attempted to be saved in the system wide directory.
+
+If no argument is provided, it will default to your personal
+config.
+
+Returns the full path to the file if the config was saved,
+false otherwise.
+
+=cut
+
+sub _config_pm_to_file {
+ my $self = shift;
+ my $pm = shift or return;
+ my $dir = shift || CONFIG_USER_LIB_DIR->();
+
+ ### only 3 types of files know: home, system and 'other'
+ ### so figure out where to save them based on their type
+ my $file;
+ if( $pm eq CONFIG_USER ) {
+ $file = CONFIG_USER_FILE->();
+
+ } elsif ( $pm eq CONFIG_SYSTEM ) {
+ $file = CONFIG_SYSTEM_FILE->();
+
+ ### third party file
+ } else {
+ my $cfg_pkg = CONFIG . '::';
+ unless( $pm =~ /^$cfg_pkg/ ) {
+ error(loc(
+ "WARNING: Your config package '%1' is not in the '%2' ".
+ "namespace and will not be automatically detected by %3",
+ $pm, $cfg_pkg, 'CPANPLUS'
+ ));
+ }
+
+ $file = File::Spec->catfile(
+ $dir,
+ split( '::', $pm )
+ ) . '.pm';
+ }
+
+ return $file;
+}
+
+
+sub save {
+ my $self = shift;
+ my $pm = shift || CONFIG_USER;
+ my $savedir = shift || '';
+
+ my $file = $self->_config_pm_to_file( $pm, $savedir ) or return;
+ my $dir = dirname( $file );
+
+ unless( -d $dir ) {
+ $self->_mkdir( dir => $dir ) or (
+ error(loc("Can not create directory '%1' to save config to",$dir)),
+ return
+ )
+ }
+ return unless $self->can_save($file);
+
+ ### find only accesors that are not private
+ my @acc = sort grep { $_ !~ /^_/ } $self->conf->ls_accessors;
+
+ ### for dumping the values
+ use Data::Dumper;
+
+ my @lines;
+ for my $acc ( @acc ) {
+
+ push @lines, "### $acc section", $/;
+
+ for my $key ( $self->conf->$acc->ls_accessors ) {
+ my $val = Dumper( $self->conf->$acc->$key );
+
+ $val =~ s/\$VAR1\s+=\s+//;
+ $val =~ s/;\n//;
+
+ push @lines, '$'. "conf->set_${acc}( $key => $val );", $/;
+ }
+ push @lines, $/,$/;
+
+ }
+
+ my $str = join '', map { " $_" } @lines;
+
+ ### use a variable to make sure the pod parser doesn't snag it
+ my $is = '=';
+ my $time = gmtime;
+
+
+ my $msg = <<_END_OF_CONFIG_;
+###############################################
+###
+### Configuration structure for $pm
+###
+###############################################
+
+#last changed: $time GMT
+
+### minimal pod, so you can find it with perldoc -l, etc
+${is}pod
+
+${is}head1 NAME
+
+$pm
+
+${is}head1 DESCRIPTION
+
+This is a CPANPLUS configuration file. Editing this
+config changes the way CPANPLUS will behave
+
+${is}cut
+
+package $pm;
+
+use strict;
+
+sub setup {
+ my \$conf = shift;
+
+$str
+
+ return 1;
+}
+
+1;
+
+_END_OF_CONFIG_
+
+ $self->_move( file => $file, to => "$file~" ) if -f $file;
+
+ my $fh = new FileHandle;
+ $fh->open(">$file")
+ or (error(loc("Could not open '%1' for writing: %2", $file, $!)),
+ return );
+
+ $fh->print($msg);
+ $fh->close;
+
+ return $file;
+}
+
+=pod
+
+=head2 options( type => TYPE )
+
+Returns a list of all valid config options given a specific type
+(like for example C<conf> of C<program>) or false if the type does
+not exist
+
+=cut
+
+sub options {
+ my $self = shift;
+ my $conf = $self->conf;
+ my %hash = @_;
+
+ my $type;
+ my $tmpl = {
+ type => { required => 1, default => '',
+ strict_type => 1, store => \$type },
+ };
+
+ check($tmpl, \%hash) or return;
+
+ my %seen;
+ return sort grep { !$seen{$_}++ }
+ map { $_->$type->ls_accessors if $_->can($type) }
+ $self->conf;
+ return;
+}
+
+=pod
+
+=head1 ACCESSORS
+
+Accessors that start with a C<_> are marked private -- regular users
+should never need to use these.
+
+See the C<CPANPLUS::Config> documentation for what items can be
+set and retrieved.
+
+=head2 get_SOMETHING( ITEM, [ITEM, ITEM, ... ] );
+
+The C<get_*> style accessors merely retrieves one or more desired
+config options.
+
+=head2 set_SOMETHING( ITEM => VAL, [ITEM => VAL, ITEM => VAL, ... ] );
+
+The C<set_*> style accessors set the current value for one
+or more config options and will return true upon success, false on
+failure.
+
+=head2 add_SOMETHING( ITEM => VAL, [ITEM => VAL, ITEM => VAL, ... ] );
+
+The C<add_*> style accessor adds a new key to a config key.
+
+Currently, the following accessors exist:
+
+=over 4
+
+=item set|get_conf
+
+Simple configuration directives like verbosity and favourite shell.
+
+=item set|get_program
+
+Location of helper programs.
+
+=item _set|_get_build
+
+Locations of where to put what files for CPANPLUS.
+
+=item _set|_get_source
+
+Locations and names of source files locally.
+
+=item _set|_get_mirror
+
+Locations and names of source files remotely.
+
+=item _set|_get_fetch
+
+Special settings pertaining to the fetching of files.
+
+=back
+
+=cut
+
+sub AUTOLOAD {
+ my $self = shift;
+ my $conf = $self->conf;
+
+ my $name = $AUTOLOAD;
+ $name =~ s/.+:://;
+
+ my ($private, $action, $field) =
+ $name =~ m/^(_)?((?:[gs]et|add))_([a-z]+)$/;
+
+ my $type = '';
+ $type .= '_' if $private;
+ $type .= $field if $field;
+
+ unless ( $conf->can($type) ) {
+ error( loc("Invalid method type: '%1'", $name) );
+ return;
+ }
+
+ unless( scalar @_ ) {
+ error( loc("No arguments provided!") );
+ return;
+ }
+
+ ### retrieve a current value for an existing key ###
+ if( $action eq 'get' ) {
+ for my $key (@_) {
+ my @list = ();
+
+ ### get it from the user config first
+ if( $conf->can($type) and $conf->$type->can($key) ) {
+ push @list, $conf->$type->$key;
+
+ ### XXX EU::AI compatibility hack to provide lookups like in
+ ### cpanplus 0.04x; we renamed ->_get_build('base') to
+ ### ->get_conf('base')
+ } elsif ( $type eq '_build' and $key eq 'base' ) {
+ return $self->get_conf($key);
+
+ } else {
+ error( loc(q[No such key '%1' in field '%2'], $key, $type) );
+ return;
+ }
+
+ return wantarray ? @list : $list[0];
+ }
+
+ ### set an existing key to a new value ###
+ } elsif ( $action eq 'set' ) {
+ my %args = @_;
+
+ while( my($key,$val) = each %args ) {
+
+ if( $conf->can($type) and $conf->$type->can($key) ) {
+ $conf->$type->$key( $val );
+
+ } else {
+ error( loc(q[No such key '%1' in field '%2'], $key, $type) );
+ return;
+ }
+ }
+
+ return 1;
+
+ ### add a new key to the config ###
+ } elsif ( $action eq 'add' ) {
+ my %args = @_;
+
+ while( my($key,$val) = each %args ) {
+
+ if( $conf->$type->can($key) ) {
+ error( loc( q[Key '%1' already exists for field '%2'],
+ $key, $type));
+ return;
+ } else {
+ $conf->$type->mk_accessors( $key );
+ $conf->$type->$key( $val );
+ }
+ }
+ return 1;
+
+ } else {
+
+ error( loc(q[Unknown action '%1'], $action) );
+ return;
+ }
+}
+
+sub DESTROY { 1 };
+
+1;
+
+=pod
+
+=head1 BUG REPORTS
+
+Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
+
+=head1 AUTHOR
+
+This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
+
+=head1 COPYRIGHT
+
+The CPAN++ interface (of which this module is a part of) is copyright (c)
+2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
+
+This library is free software; you may redistribute and/or modify it
+under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<CPANPLUS::Backend>, L<CPANPLUS::Configure::Setup>, L<CPANPLUS::Config>
+
+=cut
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
+
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Configure/Setup.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Configure/Setup.pm
new file mode 100644
index 00000000000..3bcf8f45090
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Configure/Setup.pm
@@ -0,0 +1,1653 @@
+package CPANPLUS::Configure::Setup;
+
+use strict;
+use vars qw(@ISA);
+
+use base qw[CPANPLUS::Internals::Utils];
+use base qw[Object::Accessor];
+
+use Config;
+use Term::UI;
+use Module::Load;
+use Term::ReadLine;
+
+
+use CPANPLUS::Internals::Utils;
+use CPANPLUS::Internals::Constants;
+use CPANPLUS::Error;
+
+use IPC::Cmd qw[can_run];
+use Params::Check qw[check];
+use Module::Load::Conditional qw[check_install];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+### silence Term::UI
+$Term::UI::VERBOSE = 0;
+
+#Can't ioctl TIOCGETP: Unknown error
+#Consider installing Term::ReadKey from CPAN site nearby
+# at http://www.perl.com/CPAN
+#Or use
+# perl -MCPAN -e shell
+#to reach CPAN. Falling back to 'stty'.
+# If you do not want to see this warning, set PERL_READLINE_NOWARN
+#in your environment.
+#'stty' is not recognized as an internal or external command,
+#operable program or batch file.
+#Cannot call `stty': No such file or directory at C:/Perl/site/lib/Term/ReadLine/
+
+### setting this var in the meantime to avoid this warning ###
+$ENV{PERL_READLINE_NOWARN} = 1;
+
+
+sub new {
+ my $class = shift;
+ my %hash = @_;
+
+ my $tmpl = {
+ configure_object => { },
+ term => { },
+ backend => { },
+ autoreply => { default => 0, },
+ skip_mirrors => { default => 0, },
+ use_previous => { default => 1, },
+ config_type => { default => CONFIG_USER },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ ### initialize object
+ my $obj = $class->SUPER::new( keys %$tmpl );
+ for my $acc ( $obj->ls_accessors ) {
+ $obj->$acc( $args->{$acc} );
+ }
+
+ ### otherwise there's a circular use ###
+ load CPANPLUS::Configure;
+ load CPANPLUS::Backend;
+
+ $obj->configure_object( CPANPLUS::Configure->new() )
+ unless $obj->configure_object;
+
+ $obj->backend( CPANPLUS::Backend->new( $obj->configure_object ) )
+ unless $obj->backend;
+
+ ### use empty string in case user only has T::R::Stub -- it complains
+ $obj->term( Term::ReadLine->new('') )
+ unless $obj->term;
+
+ ### enable autoreply if that was passed ###
+ $Term::UI::AUTOREPLY = $obj->autoreply;
+
+ return $obj;
+}
+
+sub init {
+ my $self = shift;
+ my $term = $self->term;
+
+ ### default setting, unless changed
+ $self->config_type( CONFIG_USER ) unless $self->config_type;
+
+ my $save = loc('Save & exit');
+ my $exit = loc('Quit without saving');
+ my @map = (
+ # key on the display # method to dispatch to
+ [ loc('Select Configuration file') => '_save_where' ],
+ [ loc('Setup CLI Programs') => '_setup_program' ],
+ [ loc('Setup CPANPLUS Home directory') => '_setup_base' ],
+ [ loc('Setup FTP/Email settings') => '_setup_ftp' ],
+ [ loc('Setup basic preferences') => '_setup_conf' ],
+ [ loc('Setup installer settings') => '_setup_installer' ],
+ [ loc('Select mirrors'), => '_setup_hosts' ],
+ [ loc('Edit configuration file') => '_edit' ],
+ [ $save => '_save' ],
+ [ $exit => 1 ],
+ );
+
+ my @keys = map { $_->[0] } @map; # sorted keys
+ my %map = map { @$_ } @map; # lookup hash
+
+ PICK_SECTION: {
+ print loc("
+=================> MAIN MENU <=================
+
+Welcome to the CPANPLUS configuration. Please select which
+parts you wish to configure
+
+Defaults are taken from your current configuration.
+If you would save now, your settings would be written to:
+
+ %1
+
+ ", $self->config_type );
+
+ my $choice = $term->get_reply(
+ prompt => "Section to configure:",
+ choices => \@keys,
+ default => $keys[0]
+ );
+
+ ### exit configuration?
+ if( $choice eq $exit ) {
+ print loc("
+Quitting setup, changes will not be saved.
+ ");
+ return 1;
+ }
+
+ my $method = $map{$choice};
+
+ my $rv = $self->$method or print loc("
+There was an error setting up this section. You might want to try again
+ ");
+
+ ### was it save & exit?
+ if( $choice eq $save and $rv ) {
+ print loc("
+Quitting setup, changes are saved to '%1'
+ ", $self->config_type
+ );
+ return 1;
+ }
+
+ ### otherwise, present choice again
+ redo PICK_SECTION;
+ }
+
+ return 1;
+}
+
+
+
+### sub that figures out what kind of config type the user wants
+sub _save_where {
+ my $self = shift;
+ my $term = $self->term;
+ my $conf = $self->configure_object;
+
+
+ ASK_CONFIG_TYPE: {
+
+ print loc( q[
+Where would you like to save your CPANPLUS Configuration file?
+
+If you want to configure CPANPLUS for this user only,
+select the '%1' option.
+The file will then be saved in your homedirectory.
+
+If you are the system administrator of this machine,
+and would like to make this config available globally,
+select the '%2' option.
+The file will be then be saved in your CPANPLUS
+installation directory.
+
+ ], CONFIG_USER, CONFIG_SYSTEM );
+
+
+ ### ask what config type we should save to
+ my $type = $term->get_reply(
+ prompt => loc("Type of configuration file"),
+ default => $self->config_type || CONFIG_USER,
+ choices => [CONFIG_USER, CONFIG_SYSTEM],
+ );
+
+ my $file = $conf->_config_pm_to_file( $type );
+
+ ### can we save to this file?
+ unless( $conf->can_save( $file ) ) {
+ error(loc(
+ "Can not save to file '%1'-- please check permissions " .
+ "and try again", $file
+ ));
+
+ redo ASK_CONFIG_FILE;
+ }
+
+ ### you already have the file -- are we allowed to overwrite
+ ### or should we try again?
+ if ( -e $file and -w _ ) {
+ print loc(q[
+I see you already have this file:
+ %1
+
+The file will not be overwritten until you explicitly save it.
+
+ ], $file );
+
+ redo ASK_CONFIG_TYPE
+ unless $term->ask_yn(
+ prompt => loc( "Do you wish to use this file?"),
+ default => 'n',
+ );
+ }
+
+ print $/, loc("Using '%1' as your configuration type", $type);
+
+ return $self->config_type($type);
+ }
+}
+
+
+### setup the build & cache dirs
+sub _setup_base {
+ my $self = shift;
+ my $term = $self->term;
+ my $conf = $self->configure_object;
+
+ my $base = $conf->get_conf('base');
+ my $home = File::Spec->catdir( $self->_home_dir, DOT_CPANPLUS );
+
+ print loc("
+CPANPLUS needs a directory of its own to cache important index
+files and maybe keep a temporary mirror of CPAN files.
+This may be a site-wide directory or a personal directory.
+
+For a single-user installation, we suggest using your home directory.
+
+");
+
+ my $where;
+ ASK_HOME_DIR: {
+ my $other = loc('Somewhere else');
+ if( $base and ($base ne $home) ) {
+ print loc("You have several choices:");
+
+ $where = $term->get_reply(
+ prompt => loc('Please pick one'),
+ choices => [$home, $base, $other],
+ default => $home,
+ );
+ } else {
+ $where = $base;
+ }
+
+ if( $where and -d $where ) {
+ print loc("
+I see you already have a directory:
+ %1
+
+ "), $where;
+
+ my $yn = $term->ask_yn(
+ prompt => loc('Should I use it?'),
+ default => 'y',
+ );
+ $where = '' unless $yn;
+ }
+
+ if( $where and ($where ne $other) and not -d $where ) {
+ if (!$self->_mkdir( dir => $where ) ) {
+ print "\n", loc("Unable to create directory '%1'", $where);
+ redo ASK_HOME_DIR;
+ }
+
+ } elsif( not $where or ($where eq $other) ) {
+ print loc("
+First of all, I'd like to create this directory.
+
+ ");
+
+ NEW_HOME: {
+ $where = $term->get_reply(
+ prompt => loc('Where shall I create it?'),
+ default => $home,
+ );
+
+ my $again;
+ if( -d $where and not -w _ ) {
+ print "\n", loc("I can't seem to write in this directory");
+ $again++;
+ } elsif (!$self->_mkdir( dir => $where ) ) {
+ print "\n", loc("Unable to create directory '%1'", $where);
+ $again++;
+ }
+
+ if( $again ) {
+ print "\n", loc('Please select another directory'), "\n\n";
+ redo NEW_HOME;
+ }
+ }
+ }
+ }
+
+ ### tidy up the path and store it
+ $where = File::Spec->rel2abs($where);
+ $conf->set_conf( base => $where );
+
+ ### create subdirectories ###
+ my @dirs =
+ File::Spec->catdir( $where, $self->_perl_version(perl => $^X),
+ $conf->_get_build('moddir') ),
+ map {
+ File::Spec->catdir( $where, $conf->_get_build($_) )
+ } qw[autdir distdir];
+
+ for my $dir ( @dirs ) {
+ unless( $self->_mkdir( dir => $dir ) ) {
+ warn loc("I wasn't able to create '%1'", $dir), "\n";
+ }
+ }
+
+ ### clear away old storable images before 0.031
+ for my $src (qw[dslip mailrc packages]) {
+ 1 while unlink File::Spec->catfile( $where, $src );
+
+ }
+
+ print loc(q[
+Your CPANPLUS build and cache directory has been set to:
+ %1
+
+ ], $where);
+
+ return 1;
+}
+
+sub _setup_ftp {
+ my $self = shift;
+ my $term = $self->term;
+ my $conf = $self->configure_object;
+
+ #########################
+ ## are you a pacifist? ##
+ #########################
+
+ print loc("
+If you are connecting through a firewall or proxy that doesn't handle
+FTP all that well you can use passive FTP.
+
+");
+
+ my $yn = $term->ask_yn(
+ prompt => loc("Use passive FTP?"),
+ default => $conf->get_conf('passive'),
+ );
+
+ $conf->set_conf(passive => $yn);
+
+ ### set the ENV var as well, else it won't get set till AFTER
+ ### the configuration is saved. but we fetch files BEFORE that.
+ $ENV{FTP_PASSIVE} = $yn;
+
+ print "\n";
+ print $yn
+ ? loc("I will use passive FTP.")
+ : loc("I won't use passive FTP.");
+ print "\n";
+
+ #############################
+ ## should fetches timeout? ##
+ #############################
+
+ print loc("
+CPANPLUS can specify a network timeout for downloads (in whole seconds).
+If none is desired (or to skip this question), enter '0'.
+
+");
+
+ my $timeout = 0 + $term->get_reply(
+ prompt => loc("Network timeout for downloads"),
+ default => $conf->get_conf('timeout') || 0,
+ allow => qr/(?!\D)/, ### whole numbers only
+ );
+
+ $conf->set_conf(timeout => $timeout);
+
+ print "\n";
+ print $timeout
+ ? loc("The network timeout for downloads is %1 seconds.", $timeout)
+ : loc("The network timeout for downloads is not set.");
+ print "\n";
+
+ ############################
+ ## where can I reach you? ##
+ ############################
+
+ print loc("
+What email address should we send as our anonymous password when
+fetching modules from CPAN servers? Some servers will NOT allow you to
+connect without a valid email address, or at least something that looks
+like one.
+Also, if you choose to report test results at some point, a valid email
+is required for the 'from' field, so choose wisely.
+
+ ");
+
+ my $other = 'Something else';
+ my @choices = (DEFAULT_EMAIL, $Config{cf_email}, $other);
+ my $current = $conf->get_conf('email');
+
+ ### if your current address is not in the list, add it to the choices
+ unless (grep { $_ eq $current } @choices) {
+ unshift @choices, $current;
+ }
+
+ my $email = $term->get_reply(
+ prompt => loc('Which email address shall I use?'),
+ default => $current || $choices[0],
+ choices => \@choices,
+ );
+
+ if( $email eq $other ) {
+ EMAIL: {
+ $email = $term->get_reply(
+ prompt => loc('Email address: '),
+ );
+
+ unless( $self->_valid_email($email) ) {
+ print loc("
+You did not enter a valid email address, please try again!
+ ") if length $email;
+
+ redo EMAIL;
+ }
+ }
+ }
+
+ print loc("
+Your 'email' is now:
+ %1
+
+ ", $email);
+
+ $conf->set_conf( email => $email );
+
+ return 1;
+}
+
+
+### commandline programs
+sub _setup_program {
+ my $self = shift;
+ my $term = $self->term;
+ my $conf = $self->configure_object;
+
+ print loc("
+CPANPLUS can use command line utilities to do certain
+tasks, rather than use perl modules.
+
+If you wish to use a certain command utility, just enter
+the full path (or accept the default). If you do not wish
+to use it, enter a single space.
+
+Note that the paths you provide should not contain spaces, which is
+needed to make a distinction between program name and options to that
+program. For Win32 machines, you can use the short name for a path,
+like '%1'.
+", 'c:\Progra~1\prog.exe' );
+
+ for my $prog ( sort $conf->options( type => 'program') ) {
+ PROGRAM: {
+ print "\n", loc("Where can I find your '%1' utility? ".
+ "(Enter a single space to disable)", $prog ), "\n";
+
+ my $loc = $term->get_reply(
+ prompt => "Path to your '$prog'",
+ default => $conf->get_program( $prog ),
+ );
+
+ ### empty line clears it
+ my $cmd = $loc =~ /^\s*$/ ? undef : $loc;
+ my ($bin) = $cmd =~ /^(\S+)/;
+
+ ### did you provide a valid program ?
+ if( $bin and not can_run( $bin ) ) {
+ print "\n";
+ print loc("Can not find the binary '%1' in your path!", $bin);
+ redo PROGRAM;
+ }
+
+ ### make is special -- we /need/ it!
+ if( $prog eq 'make' and not $bin ) {
+ print loc(
+ "==> Without your '%1' utility, I can not function! <==",
+ 'make'
+ );
+ print loc("Please provide one!");
+
+ ### show win32 where to download
+ if ( $^O eq 'MSWin32' ) {
+ print loc("You can get '%1' from:", NMAKE);
+ print "\t". NMAKE_URL ."\n";
+ }
+ print "\n";
+ redo PROGRAM;
+ }
+
+ $conf->set_program( $prog => $cmd );
+ print $cmd
+ ? loc( "Your '%1' utility has been set to '%2'.",
+ $prog, $cmd )
+ : loc( "Your '%1' has been disabled.", $prog );
+ print "\n";
+ }
+ }
+
+ return 1;
+}
+
+sub _setup_installer {
+ my $self = shift;
+ my $term = $self->term;
+ my $conf = $self->configure_object;
+
+ my $none = 'None';
+ {
+ print loc("
+CPANPLUS uses binary programs as well as Perl modules to accomplish
+various tasks. Normally, CPANPLUS will prefer the use of Perl modules
+over binary programs.
+
+You can change this setting by making CPANPLUS prefer the use of
+certain binary programs if they are available.
+
+ ");
+
+ ### default to using binaries if we don't have compress::zlib only
+ ### -- it'll get very noisy otherwise
+ my $type = 'prefer_bin';
+ my $yn = $term->ask_yn(
+ prompt => loc("Should I prefer the use of binary programs?"),
+ default => $conf->get_conf( $type ),
+ );
+
+ print $yn
+ ? loc("Ok, I will prefer to use binary programs if possible.")
+ : loc("Ok, I will prefer to use Perl modules if possible.");
+ print "\n\n";
+
+
+ $conf->set_conf( $type => $yn );
+ }
+
+ {
+ print loc("
+Makefile.PL is run by perl in a separate process, and accepts various
+flags that controls the module's installation. For instance, if you
+would like to install modules to your private user directory, set
+'makemakerflags' to:
+
+LIB=~/perl/lib INSTALLMAN1DIR=~/perl/man/man1 INSTALLMAN3DIR=~/perl/man/man3
+
+and be sure that you do NOT set UNINST=1 in 'makeflags' below.
+
+Enter a name=value list separated by whitespace, but quote any embedded
+spaces that you want to preserve. (Enter a space to clear any existing
+settings.)
+
+If you don't understand this question, just press ENTER.
+
+ ");
+
+ my $type = 'makemakerflags';
+ my $flags = $term->get_reply(
+ prompt => 'Makefile.PL flags?',
+ default => $conf->get_conf($type),
+ );
+
+ $flags = '' if $flags eq $none || $flags !~ /\S/;
+
+ print "\n", loc("Your '%1' have been set to:", 'Makefile.PL flags'),
+ "\n ", ( $flags ? $flags : loc('*nothing entered*')),
+ "\n\n";
+
+ $conf->set_conf( $type => $flags );
+ }
+
+ {
+ print loc("
+Like Makefile.PL, we run 'make' and 'make install' as separate processes.
+If you have any parameters (e.g. '-j3' in dual processor systems) you want
+to pass to the calls, please specify them here.
+
+In particular, 'UNINST=1' is recommended for root users, unless you have
+fine-tuned ideas of where modules should be installed in the \@INC path.
+
+Enter a name=value list separated by whitespace, but quote any embedded
+spaces that you want to preserve. (Enter a space to clear any existing
+settings.)
+
+Again, if you don't understand this question, just press ENTER.
+
+ ");
+ my $type = 'makeflags';
+ my $flags = $term->get_reply(
+ prompt => 'make flags?',
+ default => $conf->get_conf($type),
+ );
+
+ $flags = '' if $flags eq $none || $flags !~ /\S/;
+
+ print "\n", loc("Your '%1' have been set to:", $type),
+ "\n ", ( $flags ? $flags : loc('*nothing entered*')),
+ "\n\n";
+
+ $conf->set_conf( $type => $flags );
+ }
+
+ {
+ print loc("
+An alternative to ExtUtils::MakeMaker and Makefile.PL there's a module
+called Module::Build which uses a Build.PL.
+
+If you would like to specify any flags to pass when executing the
+Build.PL (and Build) script, please enter them below.
+
+For instance, if you would like to install modules to your private
+user directory, you could enter:
+
+ install_base=/my/private/path
+
+Or to uninstall old copies of modules before updating, you might
+want to enter:
+
+ uninst=1
+
+Again, if you don't understand this question, just press ENTER.
+
+ ");
+
+ my $type = 'buildflags';
+ my $flags = $term->get_reply(
+ prompt => 'Build.PL and Build flags?',
+ default => $conf->get_conf($type),
+ );
+
+ $flags = '' if $flags eq $none || $flags !~ /\S/;
+
+ print "\n", loc("Your '%1' have been set to:",
+ 'Build.PL and Build flags'),
+ "\n ", ( $flags ? $flags : loc('*nothing entered*')),
+ "\n\n";
+
+ $conf->set_conf( $type => $flags );
+ }
+
+ ### use EU::MM or module::build? ###
+ {
+ print loc("
+Some modules provide both a Build.PL (Module::Build) and a Makefile.PL
+(ExtUtils::MakeMaker). By default, CPANPLUS prefers Makefile.PL.
+
+Module::Build support is not bundled standard with CPANPLUS, but
+requires you to install 'CPANPLUS::Dist::Build' from CPAN.
+
+Although Module::Build is a pure perl solution, which means you will
+not need a 'make' binary, it does have some limitations. The most
+important is that CPANPLUS is unable to uninstall any modules installed
+by Module::Build.
+
+Again, if you don't understand this question, just press ENTER.
+
+ ");
+ my $type = 'prefer_makefile';
+ my $yn = $term->ask_yn(
+ prompt => loc("Prefer Makefile.PL over Build.PL?"),
+ default => $conf->get_conf($type),
+ );
+
+ $conf->set_conf( $type => $yn );
+ }
+
+ {
+ print loc('
+If you like, CPANPLUS can add extra directories to your @INC list during
+startup. These will just be used by CPANPLUS and will not change your
+external environment or perl interpreter. Enter a space separated list of
+pathnames to be added to your @INC, quoting any with embedded whitespace.
+(To clear the current value enter a single space.)
+
+ ');
+
+ my $type = 'lib';
+ my $flags = $term->get_reply(
+ prompt => loc('Additional @INC directories to add?'),
+ default => (join " ", @{$conf->get_conf($type) || []} ),
+ );
+
+ my $lib;
+ unless( $flags =~ /\S/ ) {
+ $lib = [];
+ } else {
+ (@$lib) = $flags =~ m/\s*("[^"]+"|'[^']+'|[^\s]+)/g;
+ }
+
+ print "\n", loc("Your additional libs are now:"), "\n";
+
+ print scalar @$lib
+ ? map { " $_\n" } @$lib
+ : " ", loc("*nothing entered*"), "\n";
+ print "\n\n";
+
+ $conf->set_conf( $type => $lib );
+ }
+
+ return 1;
+}
+
+
+sub _setup_conf {
+ my $self = shift;
+ my $term = $self->term;
+ my $conf = $self->configure_object;
+
+ my $none = 'None';
+ {
+ ############
+ ## noisy? ##
+ ############
+
+ print loc("
+In normal operation I can just give you basic information about what I
+am doing, or I can be more verbose and give you every little detail.
+
+ ");
+
+ my $type = 'verbose';
+ my $yn = $term->ask_yn(
+ prompt => loc("Should I be verbose?"),
+ default => $conf->get_conf( $type ), );
+
+ print "\n";
+ print $yn
+ ? loc("You asked for it!")
+ : loc("I'll try to be quiet");
+
+ $conf->set_conf( $type => $yn );
+ }
+
+ {
+ #######################
+ ## flush you animal! ##
+ #######################
+
+ print loc("
+In the interest of speed, we keep track of what modules were installed
+successfully and which failed in the current session. We can flush this
+data automatically, or you can explicitly issue a 'flush' when you want
+to purge it.
+
+ ");
+
+ my $type = 'flush';
+ my $yn = $term->ask_yn(
+ prompt => loc("Flush automatically?"),
+ default => $conf->get_conf( $type ),
+ );
+
+ print "\n";
+ print $yn
+ ? loc("I'll flush after every full module install.")
+ : loc("I won't flush until you tell me to.");
+
+ $conf->set_conf( $type => $yn );
+ }
+
+ {
+ #####################
+ ## force installs? ##
+ #####################
+
+ print loc("
+Usually, when a test fails, I won't install the module, but if you
+prefer, I can force the install anyway.
+
+ ");
+
+ my $type = 'force';
+ my $yn = $term->ask_yn(
+ prompt => loc("Force installs?"),
+ default => $conf->get_conf( $type ),
+ );
+
+ print "\n";
+ print $yn
+ ? loc("I will force installs.")
+ : loc("I won't force installs.");
+
+ $conf->set_conf( $type => $yn );
+ }
+
+ {
+ ###################
+ ## about prereqs ##
+ ###################
+
+ print loc("
+Sometimes a module will require other modules to be installed before it
+will work. CPANPLUS can attempt to install these for you automatically
+if you like, or you can do the deed yourself.
+
+If you would prefer that we NEVER try to install extra modules
+automatically, select NO. (Usually you will want this set to YES.)
+
+If you would like to build modules to satisfy testing or prerequisites,
+but not actually install them, select BUILD.
+
+NOTE: This feature requires you to flush the 'lib' cache for longer
+running programs (refer to the CPANPLUS::Backend documentations for
+more details).
+
+Otherwise, select ASK to have us ask your permission to install them.
+
+ ");
+
+ my $type = 'prereqs';
+
+ my @map = (
+ [ PREREQ_IGNORE, # conf value
+ loc('No, do not install prerequisites'), # UI Value
+ loc("I won't install prerequisites") # diag message
+ ],
+ [ PREREQ_INSTALL,
+ loc('Yes, please install prerequisites'),
+ loc("I will install prerequisites")
+ ],
+ [ PREREQ_ASK,
+ loc('Ask me before installing a prerequisite'),
+ loc("I will ask permission to install")
+ ],
+ [ PREREQ_BUILD,
+ loc('Build prerequisites, but do not install them'),
+ loc( "I will only build, but not install prerequisites" )
+ ],
+ );
+
+ my %reply = map { $_->[1] => $_->[0] } @map; # choice => value
+ my %diag = map { $_->[1] => $_->[2] } @map; # choice => diag message
+ my %conf = map { $_->[0] => $_->[1] } @map; # value => ui choice
+
+ my $reply = $term->get_reply(
+ prompt => loc('Follow prerequisites?'),
+ default => $conf{ $conf->get_conf( $type ) },
+ choices => [ @conf{ sort keys %conf } ],
+ );
+ print "\n";
+
+ my $value = $reply{ $reply };
+ my $diag = $diag{ $reply };
+
+ $conf->set_conf( $type => $value );
+ print $diag, "\n";
+ }
+
+ { print loc("
+Modules in the CPAN archives are protected with md5 checksums.
+
+This requires the Perl module Digest::MD5 to be installed (which
+CPANPLUS can do for you later);
+
+ ");
+ my $type = 'md5';
+
+ my $yn = $term->ask_yn(
+ prompt => loc("Shall I use the MD5 checksums?"),
+ default => $conf->get_conf( $type ),
+ );
+
+ print $yn
+ ? loc("I will use the MD5 checksums if you have it")
+ : loc("I won't use the MD5 checksums");
+
+ $conf->set_conf( $type => $yn );
+
+ }
+
+
+ { ###########################################
+ ## sally sells seashells by the seashore ##
+ ###########################################
+
+ print loc("
+By default CPANPLUS uses its own shell when invoked. If you would prefer
+a different shell, such as one you have written or otherwise acquired,
+please enter the full name for your shell module.
+
+ ");
+
+ my $type = 'shell';
+ my $other = 'Other';
+ my @choices = (qw| CPANPLUS::Shell::Default
+ CPANPLUS::Shell::Classic |,
+ $other );
+ my $default = $conf->get_conf($type);
+
+ unshift @choices, $default unless grep { $_ eq $default } @choices;
+
+ my $reply = $term->get_reply(
+ prompt => loc('Which CPANPLUS shell do you want to use?'),
+ default => $default,
+ choices => \@choices,
+ );
+
+ if( $reply eq $other ) {
+ SHELL: {
+ $reply = $term->get_reply(
+ prompt => loc( 'Please enter the name of the shell '.
+ 'you wish to use: '),
+ );
+
+ unless( check_install( module => $reply ) ) {
+ print "\n",
+ loc("Could not find '$reply' in your path " .
+ "-- please try again"),
+ "\n";
+ redo SHELL;
+ }
+ }
+ }
+
+ print "\n", loc("Your shell is now: %1", $reply), "\n\n";
+
+ $conf->set_conf( $type => $reply );
+ }
+
+ {
+ ###################
+ ## use storable? ##
+ ###################
+
+ print loc("
+To speed up the start time of CPANPLUS, and maintain a cache over
+multiple runs, we can use Storable to freeze some information.
+Would you like to do this?
+
+");
+ my $type = 'storable';
+ my $yn = $term->ask_yn(
+ prompt => loc("Use Storable?"),
+ default => $conf->get_conf( $type ) ? 1 : 0,
+ );
+ print "\n";
+ print $yn
+ ? loc("I will use Storable if you have it")
+ : loc("I will not use Storable");
+
+ $conf->set_conf( $type => $yn );
+ }
+
+ {
+ ###################
+ ## use sqlite ? ##
+ ###################
+
+ print loc("
+
+To limit the amount of RAM used by CPANPLUS, you can use the SQLite
+source backend instead. Note that it is currently still experimental.
+Would you like to do this?
+
+");
+ my $type = 'source_engine';
+ my $class = 'CPANPLUS::Internals::Source::SQLite';
+ my $yn = $term->ask_yn(
+ prompt => loc("Use SQLite?"),
+ default => $conf->get_conf( $type ) eq $class ? 1 : 0,
+ );
+ print "\n";
+ print $yn
+ ? loc("I will use SQLite")
+ : loc("I will not use SQLite");
+
+ $conf->set_conf( $type => $class );
+ }
+
+ {
+ ###################
+ ## use cpantest? ##
+ ###################
+
+ print loc("
+CPANPLUS has support for the Test::Reporter module, which can be utilized
+to report success and failures of modules installed by CPANPLUS. Would
+you like to do this? Note that you will still be prompted before
+sending each report.
+
+If you don't have all the required modules installed yet, you should
+consider installing '%1'
+
+This package bundles all the required modules to enable test reporting
+and querying from CPANPLUS.
+You can do so straight after this installation.
+
+ ", 'Bundle::CPANPLUS::Test::Reporter');
+
+ my $type = 'cpantest';
+ my $yn = $term->ask_yn(
+ prompt => loc('Report test results?'),
+ default => $conf->get_conf( $type ) ? 1 : 0,
+ );
+
+ print "\n";
+ print $yn
+ ? loc("I will prompt you to report test results")
+ : loc("I won't prompt you to report test results");
+
+ $conf->set_conf( $type => $yn );
+ }
+
+ {
+ ###################################
+ ## use cryptographic signatures? ##
+ ###################################
+
+ print loc("
+The Module::Signature extension allows CPAN authors to sign their
+distributions using PGP signatures. Would you like to check for
+module's cryptographic integrity before attempting to install them?
+Note that this requires either the 'gpg' utility or Crypt::OpenPGP
+to be installed.
+
+ ");
+ my $type = 'signature';
+
+ my $yn = $term->ask_yn(
+ prompt => loc('Shall I check module signatures?'),
+ default => $conf->get_conf($type) ? 1 : 0,
+ );
+
+ print "\n";
+ print $yn
+ ? loc("Ok, I will attempt to check module signatures.")
+ : loc("Ok, I won't attempt to check module signatures.");
+
+ $conf->set_conf( $type => $yn );
+ }
+
+ return 1;
+}
+
+sub _setup_hosts {
+ my $self = shift;
+ my $term = $self->term;
+ my $conf = $self->configure_object;
+
+
+ if( scalar @{ $conf->get_conf('hosts') } ) {
+
+ my $hosts;
+ for my $href ( @{$conf->get_conf('hosts')} ) {
+ $hosts .= "\t$href->{scheme}://$href->{host}$href->{path}\n";
+ }
+
+ print loc("
+I see you already have some hosts selected:
+
+$hosts
+
+If you'd like to stick with your current settings, just select 'Yes'.
+Otherwise, select 'No' and you can reconfigure your hosts
+
+");
+ my $yn = $term->ask_yn(
+ prompt => loc("Would you like to keep your current hosts?"),
+ default => 'y',
+ );
+ return 1 if $yn;
+ }
+
+ my @hosts;
+ MAIN: {
+
+ print loc("
+Now we need to know where your favorite CPAN sites are located. Make a
+list of a few sites (just in case the first on the array won't work).
+
+If you are mirroring CPAN to your local workstation, specify a file:
+URI by picking the CUSTOM option.
+
+Otherwise, let us fetch the official CPAN mirror list and you can pick
+the mirror that suits you best from a list by using the MIRROR option;
+First, pick a nearby continent and country. Then, you will be presented
+with a list of URLs of CPAN mirrors in the country you selected. Select
+one or more of those URLs.
+
+Note, the latter option requires a working net connection.
+
+You can select VIEW to see your current selection and QUIT when you
+are done.
+
+");
+
+ my $reply = $term->get_reply(
+ prompt => loc('Please choose an option'),
+ choices => [qw|Mirror Custom View Quit|],
+ default => 'Mirror',
+ );
+
+ goto MIRROR if $reply eq 'Mirror';
+ goto CUSTOM if $reply eq 'Custom';
+ goto QUIT if $reply eq 'Quit';
+
+ $self->_view_hosts(@hosts) if $reply eq 'View';
+ redo MAIN;
+ }
+
+ my $mirror_file;
+ my $hosts;
+ MIRROR: {
+ $mirror_file ||= $self->_get_mirrored_by or return;
+ $hosts ||= $self->_parse_mirrored_by($mirror_file) or return;
+
+ my ($continent, $country, $host) = $self->_guess_from_timezone( $hosts );
+
+ CONTINENT: {
+ my %seen;
+ my @choices = sort map {
+ $_->{'continent'}
+ } grep {
+ not $seen{$_->{'continent'}}++
+ } values %$hosts;
+ push @choices, qw[Custom Up Quit];
+
+ my $reply = $term->get_reply(
+ prompt => loc('Pick a continent'),
+ default => $continent,
+ choices => \@choices,
+ );
+
+ goto MAIN if $reply eq 'Up';
+ goto CUSTOM if $reply eq 'Custom';
+ goto QUIT if $reply eq 'Quit';
+
+ $continent = $reply;
+ }
+
+ COUNTRY: {
+ my %seen;
+ my @choices = sort map {
+ $_->{'country'}
+ } grep {
+ not $seen{$_->{'country'}}++
+ } grep {
+ ($_->{'continent'} eq $continent)
+ } values %$hosts;
+ push @choices, qw[Custom Up Quit];
+
+ my $reply = $term->get_reply(
+ prompt => loc('Pick a country'),
+ default => $country,
+ choices => \@choices,
+ );
+
+ goto CONTINENT if $reply eq 'Up';
+ goto CUSTOM if $reply eq 'Custom';
+ goto QUIT if $reply eq 'Quit';
+
+ $country = $reply;
+ }
+
+ HOST: {
+ my @list = grep {
+ $_->{'continent'} eq $continent and
+ $_->{'country'} eq $country
+ } values %$hosts;
+
+ my %map; my $default;
+ for my $href (@list) {
+ for my $con ( @{$href->{'connections'}} ) {
+ next unless length $con->{'host'};
+
+ my $entry = $con->{'scheme'} . '://' . $con->{'host'};
+ $default = $entry if $con->{'host'} eq $host;
+
+ $map{$entry} = $con;
+ }
+ }
+
+ CHOICE: {
+
+ ### doesn't play nice with Term::UI :(
+ ### should make t::ui figure out pager opens
+ #$self->_pager_open; # host lists might be long
+
+ print loc("
+You can enter multiple sites by seperating them by a space.
+For example:
+ 1 4 2 5
+ ");
+
+ my @reply = $term->get_reply(
+ prompt => loc('Please pick a site: '),
+ choices => [sort(keys %map),
+ qw|Custom View Up Quit|],
+ default => $default,
+ multi => 1,
+ );
+ #$self->_pager_close;
+
+
+ goto COUNTRY if grep { $_ eq 'Up' } @reply;
+ goto CUSTOM if grep { $_ eq 'Custom' } @reply;
+ goto QUIT if grep { $_ eq 'Quit' } @reply;
+
+ ### add the host, but only if it's not on the stack already ###
+ unless( grep { $_ eq 'View' } @reply ) {
+ for my $reply (@reply) {
+ if( grep { $_ eq $map{$reply} } @hosts ) {
+ print loc("Host '%1' already selected", $reply);
+ print "\n\n";
+ } else {
+ push @hosts, $map{$reply}
+ }
+ }
+ }
+
+ $self->_view_hosts(@hosts);
+
+ goto QUIT if $self->autoreply;
+ redo CHOICE;
+ }
+ }
+ }
+
+ CUSTOM: {
+ print loc("
+If there are any additional URLs you would like to use, please add them
+now. You may enter them separately or as a space delimited list.
+
+We provide a default fall-back URL, but you are welcome to override it
+with e.g. 'http://www.cpan.org/' if LWP, wget or curl is installed.
+
+(Enter a single space when you are done, or to simply skip this step.)
+
+Note that if you want to use a local depository, you will have to enter
+as follows:
+
+file://server/path/to/cpan
+
+if the file is on a server on your local network or as:
+
+file:///path/to/cpan
+
+if the file is on your local disk. Note the three /// after the file: bit
+
+");
+
+ CHOICE: {
+ my $reply = $term->get_reply(
+ prompt => loc("Additionals host(s) to add: "),
+ default => '',
+ );
+
+ last CHOICE unless $reply =~ /\S/;
+
+ my $href = $self->_parse_host($reply);
+
+ if( $href ) {
+ push @hosts, $href
+ unless grep {
+ $href->{'scheme'} eq $_->{'scheme'} and
+ $href->{'host'} eq $_->{'host'} and
+ $href->{'path'} eq $_->{'path'}
+ } @hosts;
+
+ last CHOICE if $self->autoreply;
+ } else {
+ print loc("Invalid uri! Please try again!");
+ }
+
+ $self->_view_hosts(@hosts);
+
+ redo CHOICE;
+ }
+
+ DONE: {
+
+ print loc("
+Where would you like to go now?
+
+Please pick one of the following options or Quit when you are done
+
+");
+ my $answer = $term->get_reply(
+ prompt => loc("Where to now?"),
+ default => 'Quit',
+ choices => [qw|Mirror Custom View Quit|],
+ );
+
+ if( $answer eq 'View' ) {
+ $self->_view_hosts(@hosts);
+ redo DONE;
+ }
+
+ goto MIRROR if $answer eq 'Mirror';
+ goto CUSTOM if $answer eq 'Custom';
+ goto QUIT if $answer eq 'Quit';
+ }
+ }
+
+ QUIT: {
+ $conf->set_conf( hosts => \@hosts );
+
+ print loc("
+Your host configuration has been saved
+
+");
+ }
+
+ return 1;
+}
+
+sub _view_hosts {
+ my $self = shift;
+ my @hosts = @_;
+
+ print "\n\n";
+
+ if( scalar @hosts ) {
+ my $i = 1;
+ for my $host (@hosts) {
+
+ ### show full path on file uris, otherwise, just show host
+ my $path = join '', (
+ $host->{'scheme'} eq 'file'
+ ? ( ($host->{'host'} || '[localhost]'),
+ $host->{path} )
+ : $host->{'host'}
+ );
+
+ printf "%-40s %30s\n",
+ loc("Selected %1",$host->{'scheme'} . '://' . $path ),
+ loc("%quant(%2,host) selected thus far.", $i);
+ $i++;
+ }
+ } else {
+ print loc("No hosts selected so far.");
+ }
+
+ print "\n\n";
+
+ return 1;
+}
+
+sub _get_mirrored_by {
+ my $self = shift;
+ my $cpan = $self->backend;
+ my $conf = $self->configure_object;
+
+ print loc("
+Now, we are going to fetch the mirror list for first-time configurations.
+This may take a while...
+
+");
+
+ ### use the enew configuratoin ###
+ $cpan->configure_object( $conf );
+
+ load CPANPLUS::Module::Fake;
+ load CPANPLUS::Module::Author::Fake;
+
+ my $mb = CPANPLUS::Module::Fake->new(
+ module => $conf->_get_source('hosts'),
+ path => '',
+ package => $conf->_get_source('hosts'),
+ author => CPANPLUS::Module::Author::Fake->new(
+ _id => $cpan->_id ),
+ _id => $cpan->_id,
+ );
+
+ my $file = $cpan->_fetch( fetchdir => $conf->get_conf('base'),
+ module => $mb );
+
+ return $file if $file;
+ return;
+}
+
+sub _parse_mirrored_by {
+ my $self = shift;
+ my $file = shift;
+
+ -s $file or return;
+
+ my $fh = new FileHandle;
+ $fh->open("$file")
+ or (
+ warn(loc('Could not open file "%1": %2', $file, $!)),
+ return
+ );
+
+ ### slurp the file in ###
+ { local $/; $file = <$fh> }
+
+ ### remove comments ###
+ $file =~ s/#.*$//gm;
+
+ $fh->close;
+
+ ### sample host entry ###
+ # ftp.sun.ac.za:
+ # frequency = "daily"
+ # dst_ftp = "ftp://ftp.sun.ac.za/CPAN/CPAN/"
+ # dst_location = "Stellenbosch, South Africa, Africa (-26.1992 28.0564)"
+ # dst_organisation = "University of Stellenbosch"
+ # dst_timezone = "+2"
+ # dst_contact = "ftpadm@ftp.sun.ac.za"
+ # dst_src = "ftp.funet.fi"
+ #
+ # # dst_dst = "ftp://ftp.sun.ac.za/CPAN/CPAN/"
+ # # dst_contact = "mailto:ftpadm@ftp.sun.ac.za
+ # # dst_src = "ftp.funet.fi"
+
+ ### host name as key, rest of the entry as value ###
+ my %hosts = $file =~ m/([a-zA-Z0-9\-\.]+):\s+((?:\w+\s+=\s+".*?"\s+)+)/gs;
+
+ while (my($host,$data) = each %hosts) {
+
+ my $href;
+ map {
+ s/^\s*//;
+ my @a = split /\s*=\s*/;
+ $a[1] =~ s/^"(.+?)"$/$1/g;
+ $href->{ pop @a } = pop @a;
+ } grep /\S/, split /\n/, $data;
+
+ ($href->{city_area}, $href->{country}, $href->{continent},
+ $href->{latitude}, $href->{longitude} ) =
+ $href->{dst_location} =~
+ m/
+ #Aizu-Wakamatsu, Tohoku-chiho, Fukushima
+ ^"?(
+ (?:[^,]+?)\s* # city
+ (?:
+ (?:,\s*[^,]+?)\s* # optional area
+ )*? # some have multiple areas listed
+ )
+
+ #Japan
+ ,\s*([^,]+?)\s* # country
+
+ #Asia
+ ,\s*([^,]+?)\s* # continent
+
+ # (37.4333 139.9821)
+ \((\S+)\s+(\S+?)\)"?$ # (latitude longitude)
+ /sx;
+
+ ### parse the different hosts, store them in config format ###
+ my @list;
+
+ for my $type (qw[dst_ftp dst_rsync dst_http]) {
+ my $path = $href->{$type};
+ next unless $path =~ /\w/;
+ if ($type eq 'dst_rsync' && $path !~ /^rsync:/) {
+ $path =~ s{::}{/};
+ $path = "rsync://$path/";
+ }
+ my $parts = $self->_parse_host($path);
+ push @list, $parts;
+ }
+
+ $href->{connections} = \@list;
+ $hosts{$host} = $href;
+ }
+
+ return \%hosts;
+}
+
+sub _parse_host {
+ my $self = shift;
+ my $host = shift;
+
+ my @parts = $host =~ m|^(\w*)://([^/]*)(/.*)$|s;
+
+ my $href;
+ for my $key (qw[scheme host path]) {
+ $href->{$key} = shift @parts;
+ }
+
+ return if lc($href->{'scheme'}) ne 'file' and !$href->{'host'};
+ return if !$href->{'path'};
+
+ return $href;
+}
+
+## tries to figure out close hosts based on your timezone
+##
+## Currently can only report on unique items for each of zones, countries, and
+## sites. In the future this will be combined with something else (perhaps a
+## ping?) to narrow down multiple choices.
+##
+## Tries to return the best zone, country, and site for your location. Any non-
+## unique items will be set to undef instead.
+##
+## (takes hashref, returns array)
+##
+sub _guess_from_timezone {
+ my $self = shift;
+ my $hosts = shift;
+ my (%zones, %countries, %sites);
+
+ ### autrijus - build time zone table
+ my %freq_weight = (
+ 'hourly' => 2400,
+ '4 times a day' => 400,
+ '4x daily' => 400,
+ 'daily' => 100,
+ 'twice daily' => 50,
+ 'weekly' => 15,
+ );
+
+ while (my ($site, $host) = each %{$hosts}) {
+ my ($zone, $continent, $country, $frequency) =
+ @{$host}{qw/dst_timezone continent country frequency/};
+
+
+ # skip non-well-formed ones
+ next unless $continent and $country and $zone =~ /^[-+]?\d+(?::30)?/;
+ ### fix style
+ chomp $zone;
+ $zone =~ s/:30/.5/;
+ $zone =~ s/^\+//;
+ $zone =~ s/"//g;
+
+ $zones{$zone}{$continent}++;
+ $countries{$zone}{$continent}{$country}++;
+ $sites{$zone}{$continent}{$country}{$site} = $freq_weight{$frequency};
+ }
+
+ use Time::Local;
+ my $offset = ((timegm(localtime) - timegm(gmtime)) / 3600);
+
+ local $_;
+
+ ## pick the entry with most country/site/frequency, one level each;
+ ## note it has to be sorted -- otherwise we're depending on the hash order.
+ ## also, the list context assignment (pick first one) is deliberate.
+
+ my ($continent) = map {
+ (sort { ($_->{$b} <=> $_->{$a}) or $b cmp $a } keys(%{$_}))
+ } $zones{$offset};
+
+ my ($country) = map {
+ (sort { ($_->{$b} <=> $_->{$a}) or $b cmp $a } keys(%{$_}))
+ } $countries{$offset}{$continent};
+
+ my ($site) = map {
+ (sort { ($_->{$b} <=> $_->{$a}) or $b cmp $a } keys(%{$_}))
+ } $sites{$offset}{$continent}{$country};
+
+ return ($continent, $country, $site);
+} # _guess_from_timezone
+
+
+### big big regex, stolen to check if you enter a valid address
+{
+ my $RFC822PAT; # RFC pattern to match for valid email address
+
+ sub _valid_email {
+ my $self = shift;
+ if (!$RFC822PAT) {
+ my $esc = '\\\\'; my $Period = '\.'; my $space = '\040';
+ my $tab = '\t'; my $OpenBR = '\['; my $CloseBR = '\]';
+ my $OpenParen = '\('; my $CloseParen = '\)'; my $NonASCII = '\x80-\xff';
+ my $ctrl = '\000-\037'; my $CRlist = '\012\015';
+
+ my $qtext = qq/[^$esc$NonASCII$CRlist\"]/;
+ my $dtext = qq/[^$esc$NonASCII$CRlist$OpenBR$CloseBR]/;
+ my $quoted_pair = qq< $esc [^$NonASCII] >; # an escaped character
+ my $ctext = qq< [^$esc$NonASCII$CRlist()] >;
+ my $Cnested = qq< $OpenParen $ctext* (?: $quoted_pair $ctext* )* $CloseParen >;
+ my $comment = qq< $OpenParen $ctext* (?: (?: $quoted_pair | $Cnested ) $ctext* )* $CloseParen >;
+ my $X = qq< [$space$tab]* (?: $comment [$space$tab]* )* >;
+ my $atom_char = qq/[^($space)<>\@,;:\".$esc$OpenBR$CloseBR$ctrl$NonASCII]/;
+ my $atom = qq< $atom_char+ (?!$atom_char) >;
+ my $quoted_str = qq< \" $qtext * (?: $quoted_pair $qtext * )* \" >;
+ my $word = qq< (?: $atom | $quoted_str ) >;
+ my $domain_ref = $atom;
+ my $domain_lit = qq< $OpenBR (?: $dtext | $quoted_pair )* $CloseBR >;
+ my $sub_domain = qq< (?: $domain_ref | $domain_lit) $X >;
+ my $domain = qq< $sub_domain (?: $Period $X $sub_domain)* >;
+ my $route = qq< \@ $X $domain (?: , $X \@ $X $domain )* : $X >;
+ my $local_part = qq< $word $X (?: $Period $X $word $X )* >;
+ my $addr_spec = qq< $local_part \@ $X $domain >;
+ my $route_addr = qq[ < $X (?: $route )? $addr_spec > ];
+ my $phrase_ctrl = '\000-\010\012-\037'; # like ctrl, but without tab
+ my $phrase_char = qq/[^()<>\@,;:\".$esc$OpenBR$CloseBR$NonASCII$phrase_ctrl]/;
+ my $phrase = qq< $word $phrase_char * (?: (?: $comment | $quoted_str ) $phrase_char * )* >;
+ $RFC822PAT = qq< $X (?: $addr_spec | $phrase $route_addr) >;
+ }
+
+ return scalar ($_[0] =~ /$RFC822PAT/ox);
+ }
+}
+
+
+
+
+
+
+1;
+
+
+sub _edit {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my $file = shift || $conf->_config_pm_to_file( $self->config_type );
+ my $editor = shift || $conf->get_program('editor');
+ my $term = $self->term;
+
+ unless( $editor ) {
+ print loc("
+I'm sorry, I can't find a suitable editor, so I can't offer you
+post-configuration editing of the config file
+
+");
+ return 1;
+ }
+
+ ### save the thing first, so there's something to edit
+ $self->_save;
+
+ return !system("$editor $file");
+}
+
+sub _save {
+ my $self = shift;
+ my $conf = $self->configure_object;
+
+ return $conf->save( $self->config_type );
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Dist.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Dist.pm
new file mode 100644
index 00000000000..551b8ec405f
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Dist.pm
@@ -0,0 +1,688 @@
+package CPANPLUS::Dist;
+
+use strict;
+
+use CPANPLUS::Error;
+use CPANPLUS::Internals::Constants;
+
+use Cwd ();
+use Object::Accessor;
+use Parse::CPAN::Meta;
+
+use IPC::Cmd qw[run];
+use Params::Check qw[check];
+use Module::Load::Conditional qw[can_load check_install];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+use base 'Object::Accessor';
+
+local $Params::Check::VERBOSE = 1;
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Dist
+
+=head1 SYNOPSIS
+
+ my $dist = CPANPLUS::Dist::YOUR_DIST_TYPE_HERE->new(
+ module => $modobj,
+ );
+
+=head1 DESCRIPTION
+
+C<CPANPLUS::Dist> is a base class for C<CPANPLUS::Dist::MM>
+and C<CPANPLUS::Dist::Build>. Developers of other C<CPANPLUS::Dist::*>
+plugins should look at C<CPANPLUS::Dist::Base>.
+
+=head1 ACCESSORS
+
+=over 4
+
+=item parent()
+
+Returns the C<CPANPLUS::Module> object that parented this object.
+
+=item status()
+
+Returns the C<Object::Accessor> object that keeps the status for
+this module.
+
+=back
+
+=head1 STATUS ACCESSORS
+
+All accessors can be accessed as follows:
+ $deb->status->ACCESSOR
+
+=over 4
+
+=item created()
+
+Boolean indicating whether the dist was created successfully.
+Explicitly set to C<0> when failed, so a value of C<undef> may be
+interpreted as C<not yet attempted>.
+
+=item installed()
+
+Boolean indicating whether the dist was installed successfully.
+Explicitly set to C<0> when failed, so a value of C<undef> may be
+interpreted as C<not yet attempted>.
+
+=item uninstalled()
+
+Boolean indicating whether the dist was uninstalled successfully.
+Explicitly set to C<0> when failed, so a value of C<undef> may be
+interpreted as C<not yet attempted>.
+
+=item dist()
+
+The location of the final distribution. This may be a file or
+directory, depending on how your distribution plug in of choice
+works. This will be set upon a successful create.
+
+=cut
+
+=back
+
+=head2 $dist = CPANPLUS::Dist::YOUR_DIST_TYPE_HERE->new( module => MODOBJ );
+
+Create a new C<CPANPLUS::Dist::YOUR_DIST_TYPE_HERE> object based on the
+provided C<MODOBJ>.
+
+*** DEPRECATED ***
+The optional argument C<format> is used to indicate what type of dist
+you would like to create (like C<CPANPLUS::Dist::MM> or
+C<CPANPLUS::Dist::Build> and so on ).
+
+C<< CPANPLUS::Dist->new >> is exlusively meant as a method to be
+inherited by C<CPANPLUS::Dist::MM|Build>.
+
+Returns a C<CPANPLUS::Dist::YOUR_DIST_TYPE_HERE> object on success
+and false on failure.
+
+=cut
+
+sub new {
+ my $self = shift;
+ my $class = ref $self || $self;
+ my %hash = @_;
+
+ ### first verify we got a module object ###
+ my( $mod, $format );
+ my $tmpl = {
+ module => { required => 1, allow => IS_MODOBJ, store => \$mod },
+ ### for backwards compatibility
+ format => { default => $class, store => \$format,
+ allow => [ __PACKAGE__->dist_types ],
+ },
+ };
+ check( $tmpl, \%hash ) or return;
+
+ unless( can_load( modules => { $format => '0.0' }, verbose => 1 ) ) {
+ error(loc("'%1' not found -- you need '%2' version '%3' or higher ".
+ "to detect plugins", $format, 'Module::Pluggable','2.4'));
+ return;
+ }
+
+ ### get an empty o::a object for this class
+ my $obj = $format->SUPER::new;
+
+ $obj->mk_accessors( qw[parent status] );
+
+ ### set the parent
+ $obj->parent( $mod );
+
+ ### create a status object ###
+ { my $acc = Object::Accessor->new;
+ $obj->status($acc);
+
+ ### add minimum supported accessors
+ $acc->mk_accessors( qw[prepared created installed uninstalled
+ distdir dist] );
+ }
+
+ ### get the conf object ###
+ my $conf = $mod->parent->configure_object();
+
+ ### check if the format is available in this environment ###
+ if( $conf->_get_build('sanity_check') and not $obj->format_available ) {
+ error( loc( "Format '%1' is not available", $format) );
+ return;
+ }
+
+ ### now initialize it or admit failure
+ unless( $obj->init ) {
+ error(loc("Dist initialization of '%1' failed for '%2'",
+ $format, $mod->module));
+ return;
+ }
+
+ ### return the object
+ return $obj;
+}
+
+=head2 @dists = CPANPLUS::Dist->dist_types;
+
+Returns a list of the CPANPLUS::Dist::* classes available
+
+=cut
+
+### returns a list of dist_types we support
+### will get overridden by Module::Pluggable if loaded
+### XXX add support for 'plugin' dir in config as well
+{ my $Loaded;
+ my @Dists = (INSTALLER_MM);
+ my @Ignore = ();
+
+ ### backdoor method to add more dist types
+ sub _add_dist_types { my $self = shift; push @Dists, @_ };
+
+ ### backdoor method to exclude dist types
+ sub _ignore_dist_types { my $self = shift; push @Ignore, @_ };
+ sub _reset_dist_ignore { @Ignore = () };
+
+ ### locally add the plugins dir to @INC, so we can find extra plugins
+ #local @INC = @INC, File::Spec->catdir(
+ # $conf->get_conf('base'),
+ # $conf->_get_build('plugins') );
+
+ ### load any possible plugins
+ sub dist_types {
+
+ if ( !$Loaded++ and check_install( module => 'Module::Pluggable',
+ version => '2.4')
+ ) {
+ require Module::Pluggable;
+
+ my $only_re = __PACKAGE__ . '::\w+$';
+ my %except = map { $_ => 1 }
+ INSTALLER_SAMPLE,
+ INSTALLER_BASE;
+
+ Module::Pluggable->import(
+ sub_name => '_dist_types',
+ search_path => __PACKAGE__,
+ only => qr/$only_re/,
+ require => 1,
+ except => [ keys %except ]
+ );
+ my %ignore = map { $_ => $_ } @Ignore;
+
+ push @Dists, grep { not $ignore{$_} and not $except{$_} }
+ __PACKAGE__->_dist_types;
+ }
+
+ return @Dists;
+ }
+
+=head2 $bool = CPANPLUS::Dist->rescan_dist_types;
+
+Rescans C<@INC> for available dist types. Useful if you've installed new
+C<CPANPLUS::Dist::*> classes and want to make them available to the
+current process.
+
+=cut
+
+ sub rescan_dist_types {
+ my $dist = shift;
+ $Loaded = 0; # reset the flag;
+ return $dist->dist_types;
+ }
+}
+
+=head2 $bool = CPANPLUS::Dist->has_dist_type( $type )
+
+Returns true if distribution type C<$type> is loaded/supported.
+
+=cut
+
+sub has_dist_type {
+ my $dist = shift;
+ my $type = shift or return;
+
+ return scalar grep { $_ eq $type } CPANPLUS::Dist->dist_types;
+}
+
+=head2 $bool = $dist->prereq_satisfied( modobj => $modobj, version => $version_spec )
+
+Returns true if this prereq is satisfied. Returns false if it's not.
+Also issues an error if it seems "unsatisfiable," i.e. if it can't be
+found on CPAN or the latest CPAN version doesn't satisfy it.
+
+=cut
+
+sub prereq_satisfied {
+ my $dist = shift;
+ my $cb = $dist->parent->parent;
+ my %hash = @_;
+
+ my($mod,$ver);
+ my $tmpl = {
+ version => { required => 1, store => \$ver },
+ modobj => { required => 1, store => \$mod, allow => IS_MODOBJ },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ return 1 if $mod->is_uptodate( version => $ver );
+
+ if ( $cb->_vcmp( $ver, $mod->version ) > 0 ) {
+
+ error(loc(
+ "This distribution depends on %1, but the latest version".
+ " of %2 on CPAN (%3) doesn't satisfy the specific version".
+ " dependency (%4). You may have to resolve this dependency ".
+ "manually.",
+ $mod->module, $mod->module, $mod->version, $ver ));
+
+ }
+
+ return;
+}
+
+=head2 $configure_requires = $dist->find_configure_requires( [file => /path/to/META.yml] )
+
+Reads the configure_requires for this distribution from the META.yml
+file in the root directory and returns a hashref with module names
+and versions required.
+
+=cut
+
+sub find_configure_requires {
+ my $self = shift;
+ my $mod = $self->parent;
+ my $meth = 'configure_requires';
+
+ ### the prereqs as we have them now
+ my @args = (
+ defaults => $mod->status->$meth || {},
+ keys => [ $meth ],
+ );
+
+ ### the default file to use, which may be overriden
+ push @args, ( file => META_YML->( $mod->status->extract ) )
+ if defined $mod->status->extract;
+
+ my $href = $self->_prereqs_from_meta_file( @args, @_ );
+
+ ### and store it in the module
+ $mod->status->$meth( $href );
+
+ return { %$href };
+}
+
+sub find_mymeta_requires {
+ my $self = shift;
+ my $mod = $self->parent;
+ my $meth = 'prereqs';
+
+ ### the prereqs as we have them now
+ my @args = (
+ defaults => $mod->status->$meth || {},
+ keys => [qw|requires build_requires|],
+ );
+
+ ### the default file to use, which may be overriden
+ push @args, ( file => MYMETA_YML->( $mod->status->extract ) )
+ if defined $mod->status->extract;
+
+ my $href = $self->_prereqs_from_meta_file( @args, @_ );
+
+ ### and store it in the module
+ $mod->status->$meth( $href );
+
+ return { %$href };
+}
+
+sub _prereqs_from_meta_file {
+ my $self = shift;
+ my $mod = $self->parent;
+ my %hash = @_;
+
+ my( $meta, $defaults, $keys );
+ my $tmpl = { ### check if we have an extract path. if not, we
+ ### get 'undef value' warnings from file::spec
+ file => { default => do { defined $mod->status->extract
+ ? META_YML->( $mod->status->extract )
+ : '' },
+ store => \$meta,
+ },
+ defaults => { required => 1, default => {}, strict_type => 1,
+ store => \$defaults },
+ keys => { required => 1, default => [], strict_type => 1,
+ store => \$keys },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### if there's a meta file, we read it;
+ if( -e $meta ) {
+
+ ### Parse::CPAN::Meta uses exceptions for errors
+ ### hash returned in list context!!!
+ my ($doc) = eval { Parse::CPAN::Meta::LoadFile( $meta ) };
+
+ unless( $doc ) {
+ error(loc( "Could not read %1: '%2'", $meta, $@ ));
+ return $defaults;
+ }
+
+ ### read the keys now, make sure not to throw
+ ### away anything that was already added
+ for my $key ( @$keys ) {
+ $defaults = {
+ %$defaults,
+ %{ $doc->{$key} },
+ } if $doc->{ $key };
+ }
+ }
+
+ ### and return a copy
+ return \%{ $defaults };
+}
+
+=head2 $bool = $dist->_resolve_prereqs( ... )
+
+Makes sure prerequisites are resolved
+
+ format The dist class to use to make the prereqs
+ (ie. CPANPLUS::Dist::MM)
+
+ prereqs Hash of the prerequisite modules and their versions
+
+ target What to do with the prereqs.
+ create => Just build them
+ install => Install them
+ ignore => Ignore them
+
+ prereq_build If true, always build the prereqs even if already
+ resolved
+
+ verbose Be verbose
+
+ force Force the prereq to be built, even if already resolved
+
+=cut
+
+sub _resolve_prereqs {
+ my $dist = shift;
+ my $self = $dist->parent;
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my ($prereqs, $format, $verbose, $target, $force, $prereq_build);
+ my $tmpl = {
+ ### XXX perhaps this should not be required, since it may not be
+ ### packaged, just installed...
+ ### Let it be empty as well -- that means the $modobj->install
+ ### routine will figure it out, which is fine if we didn't have any
+ ### very specific wishes (it will even detect the favourite
+ ### dist_type).
+ format => { required => 1, store => \$format,
+ allow => ['',__PACKAGE__->dist_types], },
+ prereqs => { required => 1, default => { },
+ strict_type => 1, store => \$prereqs },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ force => { default => $conf->get_conf('force'),
+ store => \$force },
+ ### make sure allow matches with $mod->install's list
+ target => { default => '', store => \$target,
+ allow => ['',qw[create ignore install]] },
+ prereq_build => { default => 0, store => \$prereq_build },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### so there are no prereqs? then don't even bother
+ return 1 unless keys %$prereqs;
+
+ ### Make sure we wound up where we started.
+ my $original_wd = Cwd::cwd;
+
+ ### so you didn't provide an explicit target.
+ ### maybe your config can tell us what to do.
+ $target ||= {
+ PREREQ_ASK, TARGET_INSTALL, # we'll bail out if the user says no
+ PREREQ_BUILD, TARGET_CREATE,
+ PREREQ_IGNORE, TARGET_IGNORE,
+ PREREQ_INSTALL, TARGET_INSTALL,
+ }->{ $conf->get_conf('prereqs') } || '';
+
+ ### XXX BIG NASTY HACK XXX FIXME at some point.
+ ### when installing Bundle::CPANPLUS::Dependencies, we want to
+ ### install all packages matching 'cpanplus' to be installed last,
+ ### as all CPANPLUS' prereqs are being installed as well, but are
+ ### being loaded for bootstrapping purposes. This means CPANPLUS
+ ### can find them, but for example cpanplus::dist::build won't,
+ ### which gets messy FAST. So, here we sort our prereqs only IF
+ ### the parent module is Bundle::CPANPLUS::Dependencies.
+ ### Really, we would wnat some sort of sorted prereq mechanism,
+ ### but Bundle:: doesn't support it, and we flatten everything
+ ### to a hash internally. A sorted hash *might* do the trick if
+ ### we got a transparent implementation.. that would mean we would
+ ### just have to remove the 'sort' here, and all will be well
+ my @sorted_prereqs;
+
+ ### use regex, could either be a module name, or a package name
+ if( $self->module =~ /^Bundle(::|-)CPANPLUS(::|-)Dependencies/ ) {
+ my (@first, @last);
+ for my $mod ( sort keys %$prereqs ) {
+ $mod =~ /CPANPLUS/
+ ? push @last, $mod
+ : push @first, $mod;
+ }
+ @sorted_prereqs = (@first, @last);
+ } else {
+ @sorted_prereqs = sort keys %$prereqs;
+ }
+
+ ### first, transfer this key/value pairing into a
+ ### list of module objects + desired versions
+ my @install_me;
+
+ for my $mod ( @sorted_prereqs ) {
+ my $version = $prereqs->{$mod};
+
+ ### 'perl' is a special case, there's no mod object for it
+ if( $mod eq PERL_CORE ) {
+
+ ### run a CLI invocation to see if the perl you specified is
+ ### uptodate
+ my $ok = run( command => "$^X -M$version -e1", verbose => 0 );
+
+ unless( $ok ) {
+ error(loc( "Module '%1' needs perl version '%2', but you ".
+ "only have version '%3' -- can not proceed",
+ $self->module, $version,
+ $cb->_perl_version( perl => $^X ) ) );
+ return;
+ }
+
+ next;
+ }
+
+ my $modobj = $cb->module_tree($mod);
+
+ #### XXX we ignore the version, and just assume that the latest
+ #### version from cpan will meet your requirements... dodgy =/
+ unless( $modobj ) {
+ # Check if it is a core module
+ my $sub = CPANPLUS::Module->can(
+ 'module_is_supplied_with_perl_core' );
+ my $core = $sub->( $mod );
+ unless ( $core ) {
+ error( loc( "No such module '%1' found on CPAN", $mod ) );
+ next;
+ }
+ if ( $cb->_vcmp( $version, $core ) > 0 ) {
+ error(loc( "Version of core module '%1' ('%2') is too low for ".
+ "'%3' (needs '%4') -- carrying on but this may be a problem",
+ $mod, $core,
+ $self->module, $version ));
+ }
+ next;
+ }
+
+ ### it's not uptodate, we need to install it
+ if( !$dist->prereq_satisfied(modobj => $modobj, version => $version)) {
+ msg(loc("Module '%1' requires '%2' version '%3' to be installed ",
+ $self->module, $modobj->module, $version), $verbose );
+
+ push @install_me, [$modobj, $version];
+
+ ### it's not an MM or Build format, that means it's a package
+ ### manager... we'll need to install it as well, via the PM
+ } elsif ( INSTALL_VIA_PACKAGE_MANAGER->($format) and
+ !$modobj->package_is_perl_core and
+ ($target ne TARGET_IGNORE)
+ ) {
+ msg(loc("Module '%1' depends on '%2', may need to build a '%3' ".
+ "package for it as well", $self->module, $modobj->module,
+ $format));
+ push @install_me, [$modobj, $version];
+ }
+ }
+
+
+
+ ### so you just want to ignore prereqs? ###
+ if( $target eq TARGET_IGNORE ) {
+
+ ### but you have modules you need to install
+ if( @install_me ) {
+ msg(loc("Ignoring prereqs, this may mean your install will fail"),
+ $verbose);
+ msg(loc("'%1' listed the following dependencies:", $self->module),
+ $verbose);
+
+ for my $aref (@install_me) {
+ my ($mod,$version) = @$aref;
+
+ my $str = sprintf "\t%-35s %8s\n", $mod->module, $version;
+ msg($str,$verbose);
+ }
+
+ return;
+
+ ### ok, no problem, you have all needed prereqs anyway
+ } else {
+ return 1;
+ }
+ }
+
+ my $flag;
+ for my $aref (@install_me) {
+ my($modobj,$version) = @$aref;
+
+ ### another prereq may have already installed this one...
+ ### so dont ask again if the module turns out to be uptodate
+ ### see bug [#11840]
+ ### if either force or prereq_build are given, the prereq
+ ### should be built anyway
+ next if (!$force and !$prereq_build) &&
+ $dist->prereq_satisfied(modobj => $modobj, version => $version);
+
+ ### either we're told to ignore the prereq,
+ ### or the user wants us to ask him
+ if( ( $conf->get_conf('prereqs') == PREREQ_ASK and not
+ $cb->_callbacks->install_prerequisite->($self, $modobj)
+ )
+ ) {
+ msg(loc("Will not install prerequisite '%1' -- Note " .
+ "that the overall install may fail due to this",
+ $modobj->module), $verbose);
+ next;
+ }
+
+ ### value set and false -- means failure ###
+ if( defined $modobj->status->installed
+ && !$modobj->status->installed
+ ) {
+ error( loc( "Prerequisite '%1' failed to install before in " .
+ "this session", $modobj->module ) );
+ $flag++;
+ last;
+ }
+
+ ### part of core?
+ if( $modobj->package_is_perl_core ) {
+ error(loc("Prerequisite '%1' is perl-core (%2) -- not ".
+ "installing that. Aborting install",
+ $modobj->module, $modobj->package ) );
+ $flag++;
+ last;
+ }
+
+ ### circular dependency code ###
+ my $pending = $cb->_status->pending_prereqs || {};
+
+ ### recursive dependency ###
+ if ( $pending->{ $modobj->module } ) {
+ error( loc( "Recursive dependency detected (%1) -- skipping",
+ $modobj->module ) );
+ next;
+ }
+
+ ### register this dependency as pending ###
+ $pending->{ $modobj->module } = $modobj;
+ $cb->_status->pending_prereqs( $pending );
+
+ ### call $modobj->install rather than doing
+ ### CPANPLUS::Dist->new and the like ourselves,
+ ### since ->install will take care of fetch &&
+ ### extract as well
+ my $pa = $dist->status->_prepare_args || {};
+ my $ca = $dist->status->_create_args || {};
+ my $ia = $dist->status->_install_args || {};
+
+ unless( $modobj->install( %$pa, %$ca, %$ia,
+ force => $force,
+ verbose => $verbose,
+ format => $format,
+ target => $target )
+ ) {
+ error(loc("Failed to install '%1' as prerequisite " .
+ "for '%2'", $modobj->module, $self->module ) );
+ $flag++;
+ }
+
+ ### unregister the pending dependency ###
+ $pending->{ $modobj->module } = 0;
+ $cb->_status->pending_prereqs( $pending );
+
+ last if $flag;
+
+ ### don't want us to install? ###
+ if( $target ne TARGET_INSTALL ) {
+ my $dir = $modobj->status->extract
+ or error(loc("No extraction dir for '%1' found ".
+ "-- weird", $modobj->module));
+
+ $modobj->add_to_includepath();
+
+ next;
+ }
+ }
+
+ ### reset the $prereqs iterator, in case we bailed out early ###
+ keys %$prereqs;
+
+ ### chdir back to where we started
+ chdir $original_wd;
+
+ return 1 unless $flag;
+ return;
+}
+
+1;
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Autobundle.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Autobundle.pm
new file mode 100644
index 00000000000..16638b258f8
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Autobundle.pm
@@ -0,0 +1,117 @@
+package CPANPLUS::Dist::Autobundle;
+
+use strict;
+use warnings;
+use CPANPLUS::Error qw[error msg];
+use Params::Check qw[check];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+use base qw[CPANPLUS::Dist::Base];
+
+=head1 NAME
+
+CPANPLUS::Dist::Autobundle
+
+=head1 SYNOPSIS
+
+ $modobj = $cb->parse_module( module => 'file://path/to/Snapshot_XXYY.pm' );
+ $modobj->install;
+
+=head1 DESCRIPTION
+
+C<CPANPLUS::Dist::Autobundle> is a distribution class for installing installation
+snapshots as created by C<CPANPLUS>' C<autobundle> command.
+
+All modules as mentioned in the snapshot will be installed on your system.
+
+=cut
+
+sub init {
+ my $dist = shift;
+ my $status = $dist->status;
+
+ $status->mk_accessors(
+ qw[prepared created installed _prepare_args _create_args _install_args]
+ );
+
+ return 1;
+}
+
+sub prepare {
+ my $dist = shift;
+ my %args = @_;
+
+ ### store the arguments, so ->install can use them in recursive loops ###
+ $dist->status->_prepare_args( \%args );
+
+ return $dist->status->prepared( 1 );
+}
+
+sub create {
+ my $dist = shift;
+ my $self = $dist->parent;
+
+ ### we're also the cpan_dist, since we don't need to have anything
+ ### prepared
+ $dist = $self->status->dist_cpan if $self->status->dist_cpan;
+ $self->status->dist_cpan( $dist ) unless $self->status->dist_cpan;
+
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my( $force, $verbose, $prereq_target, $prereq_format, $prereq_build);
+
+ my $args = do {
+ local $Params::Check::ALLOW_UNKNOWN = 1;
+ my $tmpl = {
+ force => { default => $conf->get_conf('force'),
+ store => \$force },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ prereq_target => { default => '', store => \$prereq_target },
+
+ ### don't set the default prereq format to 'makemaker' -- wrong!
+ prereq_format => { #default => $self->status->installer_type,
+ default => '',
+ store => \$prereq_format },
+ prereq_build => { default => 0, store => \$prereq_build },
+ };
+
+ check( $tmpl, \%hash ) or return;
+ };
+
+ ### maybe we already ran a create on this object? ###
+ return 1 if $dist->status->created && !$force;
+
+ ### store the arguments, so ->install can use them in recursive loops ###
+ $dist->status->_create_args( \%hash );
+
+ msg(loc("Resolving prerequisites mentioned in the bundle"), $verbose);
+
+ ### this will set the directory back to the start
+ ### dir, so we must chdir /again/
+ my $ok = $dist->_resolve_prereqs(
+ format => $prereq_format,
+ verbose => $verbose,
+ prereqs => $self->status->prereqs,
+ target => $prereq_target,
+ force => $force,
+ prereq_build => $prereq_build,
+ );
+
+ ### if all went well, mark it & return
+ return $dist->status->created( $ok ? 1 : 0);
+}
+
+sub install {
+ my $dist = shift;
+ my %args = @_;
+
+ ### store the arguments, so ->install can use them in recursive loops ###
+ $dist->status->_install_args( \%args );
+
+ return $dist->status->installed( 1 );
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Base.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Base.pm
new file mode 100644
index 00000000000..c7108ed1392
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Base.pm
@@ -0,0 +1,261 @@
+package CPANPLUS::Dist::Base;
+
+use strict;
+
+use base qw[CPANPLUS::Dist];
+use vars qw[$VERSION];
+$VERSION = $CPANPLUS::Internals::VERSION = $CPANPLUS::Internals::VERSION;
+
+
+=head1 NAME
+
+CPANPLUS::Dist::Base - Base class for custom distribution classes
+
+=head1 SYNOPSIS
+
+ package CPANPLUS::Dist::MY_IMPLEMENTATION
+
+ use base 'CPANPLUS::Dist::Base';
+
+ sub prepare {
+ my $dist = shift;
+
+ ### do the 'standard' things
+ $dist->SUPER::prepare( @_ ) or return;
+
+ ### do MY_IMPLEMENTATION specific things
+ ...
+
+ ### don't forget to set the status!
+ return $dist->status->prepared( $SUCCESS ? 1 : 0 );
+ }
+
+
+=head1 DESCRIPTION
+
+CPANPLUS::Dist::Base functions as a base class for all custom
+distribution implementations. It does all the mundane work
+CPANPLUS would have done without a custom distribution, so you
+can override just the parts you need to make your own implementation
+work.
+
+=head1 FLOW
+
+Below is a brief outline when and in which order methods in this
+class are called:
+
+ $Class->format_available; # can we use this class on this system?
+
+ $dist->init; # set up custom accessors, etc
+ $dist->prepare; # find/write meta information
+ $dist->create; # write the distribution file
+ $dist->install; # install the distribution file
+
+ $dist->uninstall; # remove the distribution (OPTIONAL)
+
+=head1 METHODS
+
+=cut
+
+=head2 @subs = $Class->methods
+
+Returns a list of methods that this class implements that you can
+override.
+
+=cut
+
+sub methods {
+ return qw[format_available init prepare create install uninstall]
+}
+
+=head2 $bool = $Class->format_available
+
+This method is called when someone requests a module to be installed
+via the superclass. This gives you the opportunity to check if all
+the needed requirements to build and install this distribution have
+been met.
+
+For example, you might need a command line program, or a certain perl
+module installed to do your job. Now is the time to check.
+
+Simply return true if the request can proceed and false if it can not.
+
+The C<CPANPLUS::Dist::Base> implementation always returns true.
+
+=cut
+
+sub format_available { return 1 }
+
+
+=head2 $bool = $dist->init
+
+This method is called just after the new dist object is set up and
+before the C<prepare> method is called. This is the time to set up
+the object so it can be used with your class.
+
+For example, you might want to add extra accessors to the C<status>
+object, which you might do as follows:
+
+ $dist->status->mk_accessors( qw[my_implementation_accessor] );
+
+The C<status> object is implemented as an instance of the
+C<Object::Accessor> class. Please refer to its documentation for
+details.
+
+Return true if the initialization was successul, and false if it was
+not.
+
+The C<CPANPLUS::Dist::Base> implementation does not alter your object
+and always returns true.
+
+=cut
+
+sub init { return 1; }
+
+=head2 $bool = $dist->prepare
+
+This runs the preparation step of your distribution. This step is meant
+to set up the environment so the C<create> step can create the actual
+distribution(file).
+A C<prepare> call in the standard C<ExtUtils::MakeMaker> distribution
+would, for example, run C<perl Makefile.PL> to find the dependencies
+for a distribution. For a C<debian> distribution, this is where you
+would write all the metafiles required for the C<dpkg-*> tools.
+
+The C<CPANPLUS::Dist::Base> implementation simply calls the underlying
+distribution class (Typically C<CPANPLUS::Dist::MM> or
+C<CPANPLUS::Dist::Build>).
+
+Sets C<< $dist->status->prepared >> to the return value of this function.
+If you override this method, you should make sure to set this value.
+
+=cut
+
+sub prepare {
+ ### just in case you already did a create call for this module object
+ ### just via a different dist object
+ my $dist = shift;
+ my $self = $dist->parent;
+ my $dist_cpan = $self->status->dist_cpan;
+
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+
+ $dist->status->prepared( $dist_cpan->prepare( @_ ) );
+}
+
+=head2 $bool = $dist->create
+
+This runs the creation step of your distribution. This step is meant
+to follow up on the C<prepare> call, that set up your environment so
+the C<create> step can create the actual distribution(file).
+A C<create> call in the standard C<ExtUtils::MakeMaker> distribution
+would, for example, run C<make> and C<make test> to build and test
+a distribution. For a C<debian> distribution, this is where you
+would create the actual C<.deb> file using C<dpkg>.
+
+The C<CPANPLUS::Dist::Base> implementation simply calls the underlying
+distribution class (Typically C<CPANPLUS::Dist::MM> or
+C<CPANPLUS::Dist::Build>).
+
+Sets C<< $dist->status->dist >> to the location of the created
+distribution.
+If you override this method, you should make sure to set this value.
+
+Sets C<< $dist->status->created >> to the return value of this function.
+If you override this method, you should make sure to set this value.
+
+=cut
+
+sub create {
+ ### just in case you already did a create call for this module object
+ ### just via a different dist object
+ my $dist = shift;
+ my $self = $dist->parent;
+ my $dist_cpan = $self->status->dist_cpan;
+ $dist = $self->status->dist if $self->status->dist;
+ $self->status->dist( $dist ) unless $self->status->dist;
+
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my $format = ref $dist;
+
+ ### make sure to set this variable, if the caller hasn't yet
+ ### just so we have some clue where the dist left off.
+ $dist->status->dist( $dist_cpan->status->distdir )
+ unless defined $dist->status->dist;
+
+ $dist->status->created( $dist_cpan->create(prereq_format => $format, @_) );
+}
+
+=head2 $bool = $dist->install
+
+This runs the install step of your distribution. This step is meant
+to follow up on the C<create> call, which prepared a distribution(file)
+to install.
+A C<create> call in the standard C<ExtUtils::MakeMaker> distribution
+would, for example, run C<make install> to copy the distribution files
+to their final destination. For a C<debian> distribution, this is where
+you would run C<dpkg --install> on the created C<.deb> file.
+
+The C<CPANPLUS::Dist::Base> implementation simply calls the underlying
+distribution class (Typically C<CPANPLUS::Dist::MM> or
+C<CPANPLUS::Dist::Build>).
+
+Sets C<< $dist->status->installed >> to the return value of this function.
+If you override this method, you should make sure to set this value.
+
+=cut
+
+sub install {
+ ### just in case you already did a create call for this module object
+ ### just via a different dist object
+ my $dist = shift;
+ my $self = $dist->parent;
+ my $dist_cpan = $self->status->dist_cpan;
+
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+
+ $dist->status->installed( $dist_cpan->install( @_ ) );
+}
+
+=head2 $bool = $dist->uninstall
+
+This runs the uninstall step of your distribution. This step is meant
+to remove the distribution from the file system.
+A C<uninstall> call in the standard C<ExtUtils::MakeMaker> distribution
+would, for example, run C<make uninstall> to remove the distribution
+files the file system. For a C<debian> distribution, this is where you
+would run C<dpkg --uninstall PACKAGE>.
+
+The C<CPANPLUS::Dist::Base> implementation simply calls the underlying
+distribution class (Typically C<CPANPLUS::Dist::MM> or
+C<CPANPLUS::Dist::Build>).
+
+Sets C<< $dist->status->uninstalled >> to the return value of this function.
+If you override this method, you should make sure to set this value.
+
+=cut
+
+sub uninstall {
+ ### just in case you already did a create call for this module object
+ ### just via a different dist object
+ my $dist = shift;
+ my $self = $dist->parent;
+ my $dist_cpan = $self->status->dist_cpan;
+
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+
+ $dist->status->uninstalled( $dist_cpan->uninstall( @_ ) );
+}
+
+1;
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Build.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Build.pm
new file mode 100644
index 00000000000..0f27639cda5
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Build.pm
@@ -0,0 +1,836 @@
+package CPANPLUS::Dist::Build;
+
+use strict;
+use warnings;
+use vars qw[@ISA $STATUS $VERSION];
+@ISA = qw[CPANPLUS::Dist];
+
+use CPANPLUS::Internals::Constants;
+
+### these constants were exported by CPANPLUS::Internals::Constants
+### in previous versions.. they do the same though. If we want to have
+### a normal 'use' here, up the dependency to CPANPLUS 0.056 or higher
+BEGIN {
+ require CPANPLUS::Dist::Build::Constants;
+ CPANPLUS::Dist::Build::Constants->import()
+ if not __PACKAGE__->can('BUILD') && __PACKAGE__->can('BUILD_DIR');
+}
+
+use CPANPLUS::Error;
+
+use Config;
+use FileHandle;
+use Cwd;
+use version;
+
+use IPC::Cmd qw[run];
+use Params::Check qw[check];
+use Module::Load::Conditional qw[can_load check_install];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+local $Params::Check::VERBOSE = 1;
+
+$VERSION = '0.46';
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Dist::Build - CPANPLUS plugin to install packages that use Build.PL
+
+=head1 SYNOPSIS
+
+ my $build = CPANPLUS::Dist->new(
+ format => 'CPANPLUS::Dist::Build',
+ module => $modobj,
+ );
+
+ $build->prepare; # runs Build.PL
+ $build->create; # runs build && build test
+ $build->install; # runs build install
+
+
+=head1 DESCRIPTION
+
+C<CPANPLUS::Dist::Build> is a distribution class for C<Module::Build>
+related modules.
+Using this package, you can create, install and uninstall perl
+modules. It inherits from C<CPANPLUS::Dist>.
+
+Normal users won't have to worry about the interface to this module,
+as it functions transparently as a plug-in to C<CPANPLUS> and will
+just C<Do The Right Thing> when it's loaded.
+
+=head1 ACCESSORS
+
+=over 4
+
+=item C<parent()>
+
+Returns the C<CPANPLUS::Module> object that parented this object.
+
+=item C<status()>
+
+Returns the C<Object::Accessor> object that keeps the status for
+this module.
+
+=back
+
+=head1 STATUS ACCESSORS
+
+All accessors can be accessed as follows:
+ $build->status->ACCESSOR
+
+=over 4
+
+=item C<build_pl ()>
+
+Location of the Build file.
+Set to 0 explicitly if something went wrong.
+
+=item C<build ()>
+
+BOOL indicating if the C<Build> command was successful.
+
+=item C<test ()>
+
+BOOL indicating if the C<Build test> command was successful.
+
+=item C<prepared ()>
+
+BOOL indicating if the C<prepare> call exited succesfully
+This gets set after C<perl Build.PL>
+
+=item C<distdir ()>
+
+Full path to the directory in which the C<prepare> call took place,
+set after a call to C<prepare>.
+
+=item C<created ()>
+
+BOOL indicating if the C<create> call exited succesfully. This gets
+set after C<Build> and C<Build test>.
+
+=item C<installed ()>
+
+BOOL indicating if the module was installed. This gets set after
+C<Build install> exits successfully.
+
+=item uninstalled ()
+
+BOOL indicating if the module was uninstalled properly.
+
+=item C<_create_args ()>
+
+Storage of the arguments passed to C<create> for this object. Used
+for recursive calls when satisfying prerequisites.
+
+=item C<_install_args ()>
+
+Storage of the arguments passed to C<install> for this object. Used
+for recursive calls when satisfying prerequisites.
+
+=back
+
+=cut
+
+=head1 METHODS
+
+=head2 $bool = CPANPLUS::Dist::Build->format_available();
+
+Returns a boolean indicating whether or not you can use this package
+to create and install modules in your environment.
+
+=cut
+
+### check if the format is available ###
+sub format_available {
+ my $mod = "Module::Build";
+ unless( can_load( modules => { $mod => '0.2611' } ) ) {
+ error( loc( "You do not have '%1' -- '%2' not available",
+ $mod, __PACKAGE__ ) );
+ return;
+ }
+
+ return 1;
+}
+
+
+=head2 $bool = $dist->init();
+
+Sets up the C<CPANPLUS::Dist::Build> object for use.
+Effectively creates all the needed status accessors.
+
+Called automatically whenever you create a new C<CPANPLUS::Dist> object.
+
+=cut
+
+sub init {
+ my $dist = shift;
+ my $status = $dist->status;
+
+ $status->mk_accessors(qw[build_pl build test created installed uninstalled
+ _create_args _install_args _prepare_args
+ _mb_object _buildflags
+ ]);
+
+ ### just in case 'format_available' didn't get called
+ require Module::Build;
+
+ return 1;
+}
+
+=pod
+
+=head2 $bool = $dist->prepare([perl => '/path/to/perl', buildflags => 'EXTRA=FLAGS', force => BOOL, verbose => BOOL])
+
+C<prepare> prepares a distribution, running C<Build.PL>
+and establishing any prerequisites this
+distribution has.
+
+The variable C<PERL5_CPANPLUS_IS_EXECUTING> will be set to the full path
+of the C<Build.PL> that is being executed. This enables any code inside
+the C<Build.PL> to know that it is being installed via CPANPLUS.
+
+After a succcesfull C<prepare> you may call C<create> to create the
+distribution, followed by C<install> to actually install it.
+
+Returns true on success and false on failure.
+
+=cut
+
+sub prepare {
+ ### just in case you already did a create call for this module object
+ ### just via a different dist object
+ my $dist = shift;
+ my $self = $dist->parent;
+
+ ### we're also the cpan_dist, since we don't need to have anything
+ ### prepared from another installer
+ $dist = $self->status->dist_cpan if $self->status->dist_cpan;
+ $self->status->dist_cpan( $dist ) unless $self->status->dist_cpan;
+
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my $dir;
+ unless( $dir = $self->status->extract ) {
+ error( loc( "No dir found to operate on!" ) );
+ return;
+ }
+
+ my $args;
+ my( $force, $verbose, $buildflags, $perl, $prereq_target, $prereq_format,
+ $prereq_build );
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+ my $tmpl = {
+ force => { default => $conf->get_conf('force'),
+ store => \$force },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ perl => { default => $^X, store => \$perl },
+ buildflags => { default => $conf->get_conf('buildflags'),
+ store => \$buildflags },
+ prereq_target => { default => '', store => \$prereq_target },
+ prereq_format => { default => '',
+ store => \$prereq_format },
+ prereq_build => { default => 0, store => \$prereq_build },
+ };
+
+ $args = check( $tmpl, \%hash ) or return;
+ }
+
+ return 1 if $dist->status->prepared && !$force;
+
+ $dist->status->_prepare_args( $args );
+
+ ### chdir to work directory ###
+ my $orig = cwd();
+ unless( $cb->_chdir( dir => $dir ) ) {
+ error( loc( "Could not chdir to build directory '%1'", $dir ) );
+ return;
+ }
+
+ ### by now we've loaded module::build, and we're using the API, so
+ ### it's safe to remove CPANPLUS::inc from our inc path, especially
+ ### because it can trip up tests run under taint (just like EU::MM).
+ ### turn off our PERL5OPT so no modules from CPANPLUS::inc get
+ ### included in make test -- it should build without.
+ ### also, modules that run in taint mode break if we leave
+ ### our code ref in perl5opt
+ ### XXX we've removed the ENV settings from cp::inc, so only need
+ ### to reset the @INC
+ #local $ENV{PERL5OPT} = CPANPLUS::inc->original_perl5opt;
+ #local $ENV{PERL5LIB} = CPANPLUS::inc->original_perl5lib;
+ #local @INC = CPANPLUS::inc->original_inc;
+
+ ### this will generate warnings under anything lower than M::B 0.2606
+ my @buildflags = $dist->_buildflags_as_list( $buildflags );
+ $dist->status->_buildflags( $buildflags );
+
+ my $fail;
+ RUN: {
+ # 0.85_01
+ ### we resolve 'configure requires' here, so we can run the 'perl
+ ### Makefile.PL' command
+ ### XXX for tests: mock f_c_r to something that *can* resolve and
+ ### something that *doesnt* resolve. Check the error log for ok
+ ### on this step or failure
+ ### XXX make a seperate tarball to test for this scenario: simply
+ ### containing a makefile.pl/build.pl for test purposes?
+ my $safe_ver = version->new('0.85_01');
+ if ( version->new($CPANPLUS::Internals::VERSION) >= $safe_ver )
+ { my $configure_requires = $dist->find_configure_requires;
+ my $ok = $dist->_resolve_prereqs(
+ format => $prereq_format,
+ verbose => $verbose,
+ prereqs => $configure_requires,
+ target => $prereq_target,
+ force => $force,
+ prereq_build => $prereq_build,
+ );
+
+ unless( $ok ) {
+
+ #### use $dist->flush to reset the cache ###
+ error( loc( "Unable to satisfy '%1' for '%2' " .
+ "-- aborting install",
+ 'configure_requires', $self->module ) );
+ $dist->status->prepared(0);
+ $fail++;
+ last RUN;
+ }
+ ### end of prereq resolving ###
+ }
+
+ # Wrap the exception that may be thrown here (should likely be
+ # done at a much higher level).
+ my $prep_output;
+
+ my $env = ENV_CPANPLUS_IS_EXECUTING;
+ local $ENV{$env} = BUILD_PL->( $dir );
+ my $run_perl = $conf->get_program('perlwrapper');
+ my $cmd = [$perl, $run_perl, BUILD_PL->($dir), @buildflags];
+
+ unless ( scalar run( command => $cmd,
+ buffer => \$prep_output,
+ verbose => $verbose )
+ ) {
+ error( loc( "Build.PL failed: %1", $prep_output ) );
+ $fail++; last RUN;
+ }
+
+ msg( $prep_output, 0 );
+
+ my $prereqs = $self->status->prereqs;
+
+ $prereqs ||= $dist->_find_prereqs( verbose => $verbose,
+ dir => $dir,
+ perl => $perl,
+ buildflags => $buildflags );
+
+ }
+
+ ### send out test report? ###
+ if( $fail and $conf->get_conf('cpantest') ) {
+ $cb->_send_report(
+ module => $self,
+ failed => $fail,
+ buffer => CPANPLUS::Error->stack_as_string,
+ verbose => $verbose,
+ force => $force,
+ ) or error(loc("Failed to send test report for '%1'",
+ $self->module ) );
+ }
+
+ unless( $cb->_chdir( dir => $orig ) ) {
+ error( loc( "Could not chdir back to start dir '%1'", $orig ) );
+ }
+
+ ### save where we wrote this stuff -- same as extract dir in normal
+ ### installer circumstances
+ $dist->status->distdir( $self->status->extract );
+
+ return $dist->status->prepared( $fail ? 0 : 1 );
+}
+
+sub _find_prereqs {
+ my $dist = shift;
+ my $self = $dist->parent;
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my ($verbose, $dir, $buildflags, $perl);
+ my $tmpl = {
+ verbose => { default => $conf->get_conf('verbose'), store => \$verbose },
+ dir => { default => $self->status->extract, store => \$dir },
+ perl => { default => $^X, store => \$perl },
+ buildflags => { default => $conf->get_conf('buildflags'),
+ store => \$buildflags },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ my $prereqs = {};
+
+ $prereqs = $dist->find_mymeta_requires()
+ if $dist->can('find_mymeta_requires');
+
+ if ( keys %$prereqs ) {
+ # Ugly hack
+ }
+ else {
+ my $safe_ver = version->new('0.31_03');
+ my $content;
+ PREREQS: {
+ if ( version->new( $Module::Build::VERSION ) >= $safe_ver and IPC::Cmd->can_capture_buffer ) {
+ my @buildflags = $dist->_buildflags_as_list( $buildflags );
+
+ # Use the new Build action 'prereq_data'
+ my $run_perl = $conf->get_program('perlwrapper');
+
+ unless ( scalar run( command => [$perl, $run_perl, BUILD->($dir), 'prereq_data', @buildflags],
+ buffer => \$content,
+ verbose => 0 )
+ ) {
+ error( loc( "Build 'prereq_data' failed: %1 %2", $!, $content ) );
+ #return;
+ }
+ else {
+ last PREREQS;
+ }
+
+ }
+
+ my $file = File::Spec->catfile( $dir, '_build', 'prereqs' );
+ return unless -f $file;
+
+ my $fh = FileHandle->new();
+
+ unless( $fh->open( $file ) ) {
+ error( loc( "Cannot open '%1': %2", $file, $! ) );
+ return;
+ }
+
+ $content = do { local $/; <$fh> };
+
+ }
+
+ return unless $content;
+ my $bphash = eval $content;
+ return unless $bphash and ref $bphash eq 'HASH';
+ foreach my $type ('requires', 'build_requires') {
+ next unless $bphash->{$type} and ref $bphash->{$type} eq 'HASH';
+ $prereqs->{$_} = $bphash->{$type}->{$_} for keys %{ $bphash->{$type} };
+ }
+ }
+ # Temporary fix
+ delete $prereqs->{'perl'};
+
+ ### allows for a user defined callback to filter the prerequisite
+ ### list as they see fit, to remove (or add) any prereqs they see
+ ### fit. The default installed callback will return the hashref in
+ ### an unmodified form
+ ### this callback got added after cpanplus 0.0562, so use a 'can'
+ ### to find out if it's supported. For older versions, we'll just
+ ### return the hashref as is ourselves.
+ my $href = $cb->_callbacks->can('filter_prereqs')
+ ? $cb->_callbacks->filter_prereqs->( $cb, $prereqs )
+ : $prereqs;
+
+ $self->status->prereqs( $href );
+
+ ### make sure it's not the same ref
+ return { %$href };
+}
+
+=pod
+
+=head2 $dist->create([perl => '/path/to/perl', buildflags => 'EXTRA=FLAGS', prereq_target => TARGET, force => BOOL, verbose => BOOL, skiptest => BOOL])
+
+C<create> preps a distribution for installation. This means it will
+run C<Build> and C<Build test>.
+This will also satisfy any prerequisites the module may have.
+
+If you set C<skiptest> to true, it will skip the C<Build test> stage.
+If you set C<force> to true, it will go over all the stages of the
+C<Build> process again, ignoring any previously cached results. It
+will also ignore a bad return value from C<Build test> and still allow
+the operation to return true.
+
+Returns true on success and false on failure.
+
+You may then call C<< $dist->install >> on the object to actually
+install it.
+
+=cut
+
+sub create {
+ ### just in case you already did a create call for this module object
+ ### just via a different dist object
+ my $dist = shift;
+ my $self = $dist->parent;
+
+ ### we're also the cpan_dist, since we don't need to have anything
+ ### prepared from another installer
+ $dist = $self->status->dist_cpan if $self->status->dist_cpan;
+ $self->status->dist_cpan( $dist ) unless $self->status->dist_cpan;
+
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my $dir;
+ unless( $dir = $self->status->extract ) {
+ error( loc( "No dir found to operate on!" ) );
+ return;
+ }
+
+ my $args;
+ my( $force, $verbose, $buildflags, $skiptest, $prereq_target,
+ $perl, $prereq_format, $prereq_build);
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+ my $tmpl = {
+ force => { default => $conf->get_conf('force'),
+ store => \$force },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ perl => { default => $^X, store => \$perl },
+ buildflags => { default => $conf->get_conf('buildflags'),
+ store => \$buildflags },
+ skiptest => { default => $conf->get_conf('skiptest'),
+ store => \$skiptest },
+ prereq_target => { default => '', store => \$prereq_target },
+ ### don't set the default format to 'build' -- that is wrong!
+ prereq_format => { #default => $self->status->installer_type,
+ default => '',
+ store => \$prereq_format },
+ prereq_build => { default => 0, store => \$prereq_build },
+ };
+
+ $args = check( $tmpl, \%hash ) or return;
+ }
+
+ # restore the state as we have created this already.
+ if ( $dist->status->created && !$force ) {
+ ### add this directory to your lib ###
+ $self->add_to_includepath();
+ return 1;
+ }
+
+ $dist->status->_create_args( $args );
+
+ ### is this dist prepared?
+ unless( $dist->status->prepared ) {
+ error( loc( "You have not successfully prepared a '%2' distribution ".
+ "yet -- cannot create yet", __PACKAGE__ ) );
+ return;
+ }
+
+ ### chdir to work directory ###
+ my $orig = cwd();
+ unless( $cb->_chdir( dir => $dir ) ) {
+ error( loc( "Could not chdir to build directory '%1'", $dir ) );
+ return;
+ }
+
+ ### by now we've loaded module::build, and we're using the API, so
+ ### it's safe to remove CPANPLUS::inc from our inc path, especially
+ ### because it can trip up tests run under taint (just like EU::MM).
+ ### turn off our PERL5OPT so no modules from CPANPLUS::inc get
+ ### included in make test -- it should build without.
+ ### also, modules that run in taint mode break if we leave
+ ### our code ref in perl5opt
+ ### XXX we've removed the ENV settings from cp::inc, so only need
+ ### to reset the @INC
+ #local $ENV{PERL5OPT} = CPANPLUS::inc->original_perl5opt;
+ #local $ENV{PERL5LIB} = CPANPLUS::inc->original_perl5lib;
+ #local @INC = CPANPLUS::inc->original_inc;
+
+ ### but do it *before* the new_from_context, as M::B seems
+ ### to be actually running the file...
+ ### an unshift in the block seems to be ignored.. somehow...
+ #{ my $lib = $self->best_path_to_module_build;
+ # unshift @INC, $lib if $lib;
+ #}
+ unshift @INC, $self->best_path_to_module_build
+ if $self->best_path_to_module_build;
+
+ ### this will generate warnings under anything lower than M::B 0.2606
+ my @buildflags = $dist->_buildflags_as_list( $buildflags );
+ $dist->status->_buildflags( $buildflags );
+
+ my $fail; my $prereq_fail; my $test_fail;
+ RUN: {
+
+ my $run_perl = $conf->get_program('perlwrapper');
+
+ ### this will set the directory back to the start
+ ### dir, so we must chdir /again/
+ my $ok = $dist->_resolve_prereqs(
+ force => $force,
+ format => $prereq_format,
+ verbose => $verbose,
+ prereqs => $self->status->prereqs,
+ target => $prereq_target,
+ prereq_build => $prereq_build,
+ );
+
+ unless( $cb->_chdir( dir => $dir ) ) {
+ error( loc( "Could not chdir to build directory '%1'", $dir ) );
+ return;
+ }
+
+ unless( $ok ) {
+ #### use $dist->flush to reset the cache ###
+ error( loc( "Unable to satisfy prerequisites for '%1' " .
+ "-- aborting install", $self->module ) );
+ $dist->status->build(0);
+ $fail++; $prereq_fail++;
+ last RUN;
+ }
+
+ my ($captured, $cmd);
+ if ( ON_VMS ) {
+ $cmd = [$perl, BUILD->($dir), @buildflags];
+ }
+ else {
+ $cmd = [$perl, $run_perl, BUILD->($dir), @buildflags];
+ }
+
+ unless ( scalar run( command => $cmd,
+ buffer => \$captured,
+ verbose => $verbose )
+ ) {
+ error( loc( "MAKE failed:\n%1", $captured ) );
+ $dist->status->build(0);
+ $fail++; last RUN;
+ }
+
+ msg( $captured, 0 );
+
+ $dist->status->build(1);
+
+ ### add this directory to your lib ###
+ $self->add_to_includepath();
+
+ ### this buffer will not include what tests failed due to a
+ ### M::B/Test::Harness bug. Reported as #9793 with patch
+ ### against 0.2607 on 26/1/2005
+ unless( $skiptest ) {
+ my $test_output;
+ if ( ON_VMS ) {
+ $cmd = [$perl, BUILD->($dir), "test", @buildflags];
+ }
+ else {
+ $cmd = [$perl, $run_perl, BUILD->($dir), "test", @buildflags];
+ }
+ unless ( scalar run( command => $cmd,
+ buffer => \$test_output,
+ verbose => $verbose )
+ ) {
+ error( loc( "MAKE TEST failed:\n%1 ", $test_output ) );
+
+ ### mark specifically *test* failure.. so we dont
+ ### send success on force...
+ $test_fail++;
+
+ if( !$force and !$cb->_callbacks->proceed_on_test_failure->(
+ $self, $@ )
+ ) {
+ $dist->status->test(0);
+ $fail++; last RUN;
+ }
+
+ }
+ else {
+ msg( loc( "MAKE TEST passed:\n%1", $test_output ), 0 );
+ #msg( $test_output, 0 );
+ $dist->status->test(1);
+ }
+ }
+ else {
+ msg(loc("Tests skipped"), $verbose);
+ }
+ }
+
+ unless( $cb->_chdir( dir => $orig ) ) {
+ error( loc( "Could not chdir back to start dir '%1'", $orig ) );
+ }
+
+ ### send out test report? ###
+ if( $conf->get_conf('cpantest') and not $prereq_fail ) {
+ $cb->_send_report(
+ module => $self,
+ failed => $test_fail || $fail,
+ buffer => CPANPLUS::Error->stack_as_string,
+ verbose => $verbose,
+ force => $force,
+ tests_skipped => $skiptest,
+ ) or error(loc("Failed to send test report for '%1'",
+ $self->module ) );
+ }
+
+ return $dist->status->created( $fail ? 0 : 1 );
+}
+
+=head2 $dist->install([verbose => BOOL, perl => /path/to/perl])
+
+Actually installs the created dist.
+
+Returns true on success and false on failure.
+
+=cut
+
+sub install {
+ ### just in case you already did a create call for this module object
+ ### just via a different dist object
+ my $dist = shift;
+ my $self = $dist->parent;
+
+ ### we're also the cpan_dist, since we don't need to have anything
+ ### prepared from another installer
+ $dist = $self->status->dist_cpan if $self->status->dist_cpan;
+
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+
+ my $verbose; my $perl; my $force; my $buildflags;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+ my $tmpl = {
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ force => { default => $conf->get_conf('force'),
+ store => \$force },
+ buildflags => { default => $conf->get_conf('buildflags'),
+ store => \$buildflags },
+ perl => { default => $^X, store => \$perl },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+ $dist->status->_install_args( $args );
+ }
+
+ my $dir;
+ unless( $dir = $self->status->extract ) {
+ error( loc( "No dir found to operate on!" ) );
+ return;
+ }
+
+ my $orig = cwd();
+
+ unless( $cb->_chdir( dir => $dir ) ) {
+ error( loc( "Could not chdir to build directory '%1'", $dir ) );
+ return;
+ }
+
+ ### value set and false -- means failure ###
+ if( defined $self->status->installed &&
+ !$self->status->installed && !$force
+ ) {
+ error( loc( "Module '%1' has failed to install before this session " .
+ "-- aborting install", $self->module ) );
+ return;
+ }
+
+ my $fail;
+ my @buildflags = $dist->_buildflags_as_list( $buildflags );
+ my $run_perl = $conf->get_program('perlwrapper');
+
+ ### hmm, how is this going to deal with sudo?
+ ### for now, check effective uid, if it's not root,
+ ### shell out, otherwise use the method
+ if( $> ) {
+
+ ### don't worry about loading the right version of M::B anymore
+ ### the 'new_from_context' already added the 'right' path to
+ ### M::B at the top of the build.pl
+ my $cmd;
+ if ( ON_VMS ) {
+ $cmd = [$perl, BUILD->($dir), "install", @buildflags];
+ }
+ else {
+ $cmd = [$perl, $run_perl, BUILD->($dir), "install", @buildflags];
+ }
+ my $sudo = $conf->get_program('sudo');
+ unshift @$cmd, $sudo if $sudo;
+
+
+ my $buffer;
+ unless( scalar run( command => $cmd,
+ buffer => \$buffer,
+ verbose => $verbose )
+ ) {
+ error(loc("Could not run '%1': %2", 'Build install', $buffer));
+ $fail++;
+ }
+ } else {
+ my ($install_output, $cmd);
+ if ( ON_VMS ) {
+ $cmd = [$perl, BUILD->($dir), "install", @buildflags];
+ }
+ else {
+ $cmd = [$perl, $run_perl, BUILD->($dir), "install", @buildflags];
+ }
+ unless( scalar run( command => $cmd,
+ buffer => \$install_output,
+ verbose => $verbose )
+ ) {
+ error(loc("Could not run '%1': %2", 'Build install', $install_output));
+ $fail++;
+ }
+ else {
+ msg( $install_output, 0 );
+ }
+ }
+
+
+ unless( $cb->_chdir( dir => $orig ) ) {
+ error( loc( "Could not chdir back to start dir '%1'", $orig ) );
+ }
+
+ return $dist->status->installed( $fail ? 0 : 1 );
+}
+
+### returns the string 'foo=bar --zot quux'
+### as the list 'foo=bar', '--zot', 'qux'
+sub _buildflags_as_list {
+ my $self = shift;
+ my $flags = shift or return;
+
+ return Module::Build->split_like_shell($flags);
+}
+
+=head1 AUTHOR
+
+Originally by Jos Boumans E<lt>kane@cpan.orgE<gt>. Brought to working
+condition by Ken Williams E<lt>kwilliams@cpan.orgE<gt>.
+
+Other hackery and currently maintained by Chris C<BinGOs> Williams ( no relation ). E<lt>bingos@cpan.orgE<gt>.
+
+=head1 LICENSE
+
+The CPAN++ interface (of which this module is a part of) is
+copyright (c) 2001, 2002, 2003, 2004, 2005 Jos Boumans E<lt>kane@cpan.orgE<gt>.
+All rights reserved.
+
+This library is free software;
+you may redistribute and/or modify it under the same
+terms as Perl itself.
+
+=cut
+
+qq[Putting the Module::Build into CPANPLUS];
+
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
+
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Build/Constants.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Build/Constants.pm
new file mode 100644
index 00000000000..1ac02108e44
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Build/Constants.pm
@@ -0,0 +1,69 @@
+package CPANPLUS::Dist::Build::Constants;
+
+use strict;
+use warnings;
+use File::Spec;
+
+BEGIN {
+
+ require Exporter;
+ use vars qw[$VERSION @ISA @EXPORT];
+
+ $VERSION = '0.46';
+ @ISA = qw[Exporter];
+ @EXPORT = qw[ BUILD_DIR BUILD ];
+}
+
+
+use constant BUILD_DIR => sub { return @_
+ ? File::Spec->catdir($_[0], '_build')
+ : '_build';
+ };
+use constant BUILD => sub { my $file = @_
+ ? File::Spec->catfile($_[0], 'Build')
+ : 'Build';
+
+ ### on VMS, '.com' is appended when
+ ### creating the Build file
+ $file .= '.com' if $^O eq 'VMS';
+
+ return $file;
+ };
+
+1;
+
+=head1 NAME
+
+CPANPLUS::Dist::Build::Constants - Constants for CPANPLUS::Dist::Build
+
+=head1 SYNOPSIS
+
+ use CPANPLUS::Dist::Build::Constants;
+
+=head1 DESCRIPTION
+
+CPANPLUS::Dist::Build::Constants provides some constants required by L<CPANPLUS::Dist::Build>.
+
+=head1 AUTHOR
+
+Originally by Jos Boumans E<lt>kane@cpan.orgE<gt>. Brought to working
+condition and currently maintained by Ken Williams E<lt>kwilliams@cpan.orgE<gt>.
+
+=head1 LICENSE
+
+The CPAN++ interface (of which this module is a part of) is
+copyright (c) 2001, 2002, 2003, 2004, 2005 Jos Boumans E<lt>kane@cpan.orgE<gt>.
+All rights reserved.
+
+This library is free software;
+you may redistribute and/or modify it under the same
+terms as Perl itself.
+
+=cut
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Dist/MM.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Dist/MM.pm
new file mode 100644
index 00000000000..be65cd43cc8
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Dist/MM.pm
@@ -0,0 +1,1007 @@
+package CPANPLUS::Dist::MM;
+
+use warnings;
+use strict;
+use vars qw[@ISA $STATUS];
+use base 'CPANPLUS::Dist::Base';
+
+use CPANPLUS::Internals::Constants;
+use CPANPLUS::Internals::Constants::Report;
+use CPANPLUS::Error;
+use FileHandle;
+use Cwd;
+
+use IPC::Cmd qw[run];
+use Params::Check qw[check];
+use File::Basename qw[dirname];
+use Module::Load::Conditional qw[can_load check_install];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+local $Params::Check::VERBOSE = 1;
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Dist::MM
+
+=head1 SYNOPSIS
+
+ $mm = CPANPLUS::Dist::MM->new( module => $modobj );
+
+ $mm->create; # runs make && make test
+ $mm->install; # runs make install
+
+
+=head1 DESCRIPTION
+
+C<CPANPLUS::Dist::MM> is a distribution class for MakeMaker related
+modules.
+Using this package, you can create, install and uninstall perl
+modules. It inherits from C<CPANPLUS::Dist>.
+
+=head1 ACCESSORS
+
+=over 4
+
+=item parent()
+
+Returns the C<CPANPLUS::Module> object that parented this object.
+
+=item status()
+
+Returns the C<Object::Accessor> object that keeps the status for
+this module.
+
+=back
+
+=head1 STATUS ACCESSORS
+
+All accessors can be accessed as follows:
+ $mm->status->ACCESSOR
+
+=over 4
+
+=item makefile ()
+
+Location of the Makefile (or Build file).
+Set to 0 explicitly if something went wrong.
+
+=item make ()
+
+BOOL indicating if the C<make> (or C<Build>) command was successful.
+
+=item test ()
+
+BOOL indicating if the C<make test> (or C<Build test>) command was
+successful.
+
+=item prepared ()
+
+BOOL indicating if the C<prepare> call exited succesfully
+This gets set after C<perl Makefile.PL>
+
+=item distdir ()
+
+Full path to the directory in which the C<prepare> call took place,
+set after a call to C<prepare>.
+
+=item created ()
+
+BOOL indicating if the C<create> call exited succesfully. This gets
+set after C<make> and C<make test>.
+
+=item installed ()
+
+BOOL indicating if the module was installed. This gets set after
+C<make install> (or C<Build install>) exits successfully.
+
+=item uninstalled ()
+
+BOOL indicating if the module was uninstalled properly.
+
+=item _create_args ()
+
+Storage of the arguments passed to C<create> for this object. Used
+for recursive calls when satisfying prerequisites.
+
+=item _install_args ()
+
+Storage of the arguments passed to C<install> for this object. Used
+for recursive calls when satisfying prerequisites.
+
+=back
+
+=cut
+
+=head1 METHODS
+
+=head2 $bool = $dist->format_available();
+
+Returns a boolean indicating whether or not you can use this package
+to create and install modules in your environment.
+
+=cut
+
+### check if the format is available ###
+sub format_available {
+ my $dist = shift;
+
+ ### we might be called as $class->format_available =/
+ require CPANPLUS::Internals;
+ my $cb = CPANPLUS::Internals->_retrieve_id(
+ CPANPLUS::Internals->_last_id );
+ my $conf = $cb->configure_object;
+
+ my $mod = "ExtUtils::MakeMaker";
+ unless( can_load( modules => { $mod => 0.0 } ) ) {
+ error( loc( "You do not have '%1' -- '%2' not available",
+ $mod, __PACKAGE__ ) );
+ return;
+ }
+
+ for my $pgm ( qw[make] ) {
+ unless( $conf->get_program( $pgm ) ) {
+ error(loc(
+ "You do not have '%1' in your path -- '%2' not available\n" .
+ "Please check your config entry for '%1'",
+ $pgm, __PACKAGE__ , $pgm
+ ));
+ return;
+ }
+ }
+
+ return 1;
+}
+
+=pod $bool = $dist->init();
+
+Sets up the C<CPANPLUS::Dist::MM> object for use.
+Effectively creates all the needed status accessors.
+
+Called automatically whenever you create a new C<CPANPLUS::Dist> object.
+
+=cut
+
+sub init {
+ my $dist = shift;
+ my $status = $dist->status;
+
+ $status->mk_accessors(qw[makefile make test created installed uninstalled
+ bin_make _prepare_args _create_args _install_args]
+ );
+
+ return 1;
+}
+
+=pod $bool = $dist->prepare([perl => '/path/to/perl', makemakerflags => 'EXTRA=FLAGS', force => BOOL, verbose => BOOL])
+
+C<prepare> preps a distribution for installation. This means it will
+run C<perl Makefile.PL> and determine what prerequisites this distribution
+declared.
+
+If you set C<force> to true, it will go over all the stages of the
+C<prepare> process again, ignoring any previously cached results.
+
+When running C<perl Makefile.PL>, the environment variable
+C<PERL5_CPANPLUS_IS_EXECUTING> will be set to the full path of the
+C<Makefile.PL> that is being executed. This enables any code inside
+the C<Makefile.PL> to know that it is being installed via CPANPLUS.
+
+Returns true on success and false on failure.
+
+You may then call C<< $dist->create >> on the object to create the
+installable files.
+
+=cut
+
+sub prepare {
+ ### just in case you already did a create call for this module object
+ ### just via a different dist object
+ my $dist = shift;
+ my $self = $dist->parent;
+
+ ### we're also the cpan_dist, since we don't need to have anything
+ ### prepared
+ $dist = $self->status->dist_cpan if $self->status->dist_cpan;
+ $self->status->dist_cpan( $dist ) unless $self->status->dist_cpan;
+
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my $dir;
+ unless( $dir = $self->status->extract ) {
+ error( loc( "No dir found to operate on!" ) );
+ return;
+ }
+
+ my $args;
+ my( $force, $verbose, $perl, @mmflags, $prereq_target, $prereq_format,
+ $prereq_build );
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+ my $tmpl = {
+ perl => { default => $^X, store => \$perl },
+ makemakerflags => { default =>
+ $conf->get_conf('makemakerflags') || '',
+ store => \$mmflags[0] },
+ force => { default => $conf->get_conf('force'),
+ store => \$force },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ prereq_target => { default => '', store => \$prereq_target },
+ prereq_format => { default => '',
+ store => \$prereq_format },
+ prereq_build => { default => 0, store => \$prereq_build },
+ };
+
+ $args = check( $tmpl, \%hash ) or return;
+ }
+
+
+ ### maybe we already ran a create on this object? ###
+ return 1 if $dist->status->prepared && !$force;
+
+ ### store the arguments, so ->install can use them in recursive loops ###
+ $dist->status->_prepare_args( $args );
+
+ ### chdir to work directory ###
+ my $orig = cwd();
+ unless( $cb->_chdir( dir => $dir ) ) {
+ error( loc( "Could not chdir to build directory '%1'", $dir ) );
+ return;
+ }
+
+ my $fail;
+ RUN: {
+
+ ### we resolve 'configure requires' here, so we can run the 'perl
+ ### Makefile.PL' command
+ ### XXX for tests: mock f_c_r to something that *can* resolve and
+ ### something that *doesnt* resolve. Check the error log for ok
+ ### on this step or failure
+ ### XXX make a seperate tarball to test for this scenario: simply
+ ### containing a makefile.pl/build.pl for test purposes?
+ { my $configure_requires = $dist->find_configure_requires;
+ my $ok = $dist->_resolve_prereqs(
+ format => $prereq_format,
+ verbose => $verbose,
+ prereqs => $configure_requires,
+ target => $prereq_target,
+ force => $force,
+ prereq_build => $prereq_build,
+ );
+
+ unless( $ok ) {
+
+ #### use $dist->flush to reset the cache ###
+ error( loc( "Unable to satisfy '%1' for '%2' " .
+ "-- aborting install",
+ 'configure_requires', $self->module ) );
+ $dist->status->prepared(0);
+ $fail++;
+ last RUN;
+ }
+ ### end of prereq resolving ###
+ }
+
+
+
+ ### don't run 'perl makefile.pl' again if there's a makefile already
+ if( -e MAKEFILE->() && (-M MAKEFILE->() < -M $dir) && !$force ) {
+ msg(loc("'%1' already exists, not running '%2 %3' again ".
+ " unless you force",
+ MAKEFILE->(), $perl, MAKEFILE_PL->() ), $verbose );
+
+ } else {
+ unless( -e MAKEFILE_PL->() ) {
+ msg(loc("No '%1' found - attempting to generate one",
+ MAKEFILE_PL->() ), $verbose );
+
+ $dist->write_makefile_pl(
+ verbose => $verbose,
+ force => $force
+ );
+
+ ### bail out if there's no makefile.pl ###
+ unless( -e MAKEFILE_PL->() ) {
+ error( loc( "Could not find '%1' - cannot continue",
+ MAKEFILE_PL->() ) );
+
+ ### mark that we screwed up ###
+ $dist->status->makefile(0);
+ $fail++; last RUN;
+ }
+ }
+
+ ### you can turn off running this verbose by changing
+ ### the config setting below, although it is really not
+ ### recommended
+ my $run_verbose = $verbose ||
+ $conf->get_conf('allow_build_interactivity') ||
+ 0;
+
+ ### this makes MakeMaker use defaults if possible, according
+ ### to schwern. See ticket 8047 for details.
+ local $ENV{PERL_MM_USE_DEFAULT} = 1 unless $run_verbose;
+
+ ### turn off our PERL5OPT so no modules from CPANPLUS::inc get
+ ### included in the makefile.pl -- it should build without
+ ### also, modules that run in taint mode break if we leave
+ ### our code ref in perl5opt
+ ### XXX we've removed the ENV settings from cp::inc, so only need
+ ### to reset the @INC
+ #local $ENV{PERL5OPT} = CPANPLUS::inc->original_perl5opt || '';
+
+ ### make sure it's a string, so that mmflags that have more than
+ ### one key value pair are passed as is, rather than as:
+ ### perl Makefile.PL "key=val key=>val"
+
+
+ #### XXX this needs to be the absolute path to the Makefile.PL
+ ### since cpanp-run-perl uses 'do' to execute the file, and do()
+ ### checks your @INC.. so, if there's _another_ makefile.pl in
+ ### your @INC, it will execute that one...
+ my $makefile_pl = MAKEFILE_PL->( $cb->_safe_path( path => $dir ) );
+
+ ### setting autoflush to true fixes issue from rt #8047
+ ### XXX this means that we need to keep the path to CPANPLUS
+ ### in @INC, stopping us from resolving dependencies on CPANPLUS
+ ### at bootstrap time properly.
+
+ ### XXX this fails under ipc::run due to the extra quotes,
+ ### but it works in ipc::open3. however, ipc::open3 doesn't work
+ ### on win32/cygwin. XXX TODO get a windows box and sort this out
+ # my $cmd = qq[$perl -MEnglish -le ] .
+ # QUOTE_PERL_ONE_LINER->(
+ # qq[\$OUTPUT_AUTOFLUSH++,do(q($makefile_pl))]
+ # )
+ # . $mmflags;
+
+ # my $flush = OPT_AUTOFLUSH;
+ # my $cmd = "$perl $flush $makefile_pl $mmflags";
+
+ my $run_perl = $conf->get_program('perlwrapper');
+ my $cmd = [$perl, $run_perl, $makefile_pl, @mmflags];
+
+ ### set ENV var to tell underlying code this is what we're
+ ### executing.
+ my $captured;
+ my $rv = do {
+ my $env = ENV_CPANPLUS_IS_EXECUTING;
+ local $ENV{$env} = $makefile_pl;
+ scalar run( command => $cmd,
+ buffer => \$captured,
+ verbose => $run_verbose, # may be interactive
+ );
+ };
+
+ unless( $rv ) {
+ error( loc( "Could not run '%1 %2': %3 -- cannot continue",
+ $perl, MAKEFILE_PL->(), $captured ) );
+
+ $dist->status->makefile(0);
+ $fail++; last RUN;
+ }
+
+ ### put the output on the stack, don't print it
+ msg( $captured, 0 );
+ }
+
+ ### so, nasty feature in Module::Build, that when a Makefile.PL
+ ### is a disguised Build.PL, it generates a Build file, not a
+ ### Makefile. this breaks everything :( see rt bug #19741
+ if( not -e MAKEFILE->( $dir ) and -e BUILD_PL->( $dir ) ) {
+ error(loc(
+ "We just ran '%1' without errors, but no '%2' is ".
+ "present. However, there is a '%3' file, so this may ".
+ "be related to bug #19741 in %4, which describes a ".
+ "fake '%5' which generates a '%6' file instead of a '%7'. ".
+ "You could try to work around this issue by setting '%8' ".
+ "to false and trying again. This will attempt to use the ".
+ "'%9' instead.",
+ "$^X ".MAKEFILE_PL->(), MAKEFILE->(), BUILD_PL->(),
+ 'Module::Build', MAKEFILE_PL->(), 'Build', MAKEFILE->(),
+ 'prefer_makefile', BUILD_PL->()
+ ));
+
+ $fail++, last RUN;
+ }
+
+ ### if we got here, we managed to make a 'makefile' ###
+ $dist->status->makefile( MAKEFILE->($dir) );
+
+ ### start resolving prereqs ###
+ my $prereqs = $self->status->prereqs;
+
+ ### a hashref of prereqs on success, undef on failure ###
+ $prereqs ||= $dist->_find_prereqs(
+ verbose => $verbose,
+ file => $dist->status->makefile
+ );
+
+ unless( $prereqs ) {
+ error( loc( "Unable to scan '%1' for prereqs",
+ $dist->status->makefile ) );
+
+ $fail++; last RUN;
+ }
+ }
+
+ unless( $cb->_chdir( dir => $orig ) ) {
+ error( loc( "Could not chdir back to start dir '%1'", $orig ) );
+ }
+
+ ### save where we wrote this stuff -- same as extract dir in normal
+ ### installer circumstances
+ $dist->status->distdir( $self->status->extract );
+
+ return $dist->status->prepared( $fail ? 0 : 1);
+}
+
+=pod
+
+=head2 $href = $dist->_find_prereqs( file => '/path/to/Makefile', [verbose => BOOL])
+
+Parses a C<Makefile> for C<PREREQ_PM> entries and distills from that
+any prerequisites mentioned in the C<Makefile>
+
+Returns a hash with module-version pairs on success and false on
+failure.
+
+=cut
+
+sub _find_prereqs {
+ my $dist = shift;
+ my $self = $dist->parent;
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my ($verbose, $file);
+ my $tmpl = {
+ verbose => { default => $conf->get_conf('verbose'), store => \$verbose },
+ file => { required => 1, allow => FILE_READABLE, store => \$file },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ ### see if we got prereqs from MYMETA
+ my $prereqs = $dist->find_mymeta_requires();
+
+ ### we found some prereqs, we'll trust MYMETA
+ ### but we do need to run it through the callback
+ return $cb->_callbacks->filter_prereqs->( $cb, $prereqs ) if keys %$prereqs;
+
+ my $fh = FileHandle->new();
+ unless( $fh->open( $file ) ) {
+ error( loc( "Cannot open '%1': %2", $file, $! ) );
+ return;
+ }
+
+ my %p;
+ while( local $_ = <$fh> ) {
+ my ($found) = m|^[\#]\s+PREREQ_PM\s+=>\s+(.+)|;
+
+ next unless $found;
+
+ while( $found =~ m/(?:\s)([\w\:]+)=>(?:q\[(.*?)\],?|undef)/g ) {
+ if( defined $p{$1} ) {
+ my $ver = $cb->_version_to_number(version => $2);
+ $p{$1} = $ver
+ if $cb->_vcmp( $ver, $p{$1} ) > 0;
+ }
+ else {
+ $p{$1} = $cb->_version_to_number(version => $2);
+ }
+ }
+ last;
+ }
+
+ my $href = $cb->_callbacks->filter_prereqs->( $cb, \%p );
+
+ $self->status->prereqs( $href );
+
+ ### just to make sure it's not the same reference ###
+ return { %$href };
+}
+
+=pod
+
+=head2 $bool = $dist->create([perl => '/path/to/perl', make => '/path/to/make', makeflags => 'EXTRA=FLAGS', prereq_target => TARGET, skiptest => BOOL, force => BOOL, verbose => BOOL])
+
+C<create> creates the files necessary for installation. This means
+it will run C<make> and C<make test>. This will also scan for and
+attempt to satisfy any prerequisites the module may have.
+
+If you set C<skiptest> to true, it will skip the C<make test> stage.
+If you set C<force> to true, it will go over all the stages of the
+C<make> process again, ignoring any previously cached results. It
+will also ignore a bad return value from C<make test> and still allow
+the operation to return true.
+
+Returns true on success and false on failure.
+
+You may then call C<< $dist->install >> on the object to actually
+install it.
+
+=cut
+
+sub create {
+ ### just in case you already did a create call for this module object
+ ### just via a different dist object
+ my $dist = shift;
+ my $self = $dist->parent;
+
+ ### we're also the cpan_dist, since we don't need to have anything
+ ### prepared
+ $dist = $self->status->dist_cpan if $self->status->dist_cpan;
+ $self->status->dist_cpan( $dist ) unless $self->status->dist_cpan;
+
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my $dir;
+ unless( $dir = $self->status->extract ) {
+ error( loc( "No dir found to operate on!" ) );
+ return;
+ }
+
+ my $args;
+ my( $force, $verbose, $make, $makeflags, $skiptest, $prereq_target, $perl,
+ @mmflags, $prereq_format, $prereq_build);
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+ my $tmpl = {
+ perl => { default => $^X, store => \$perl },
+ force => { default => $conf->get_conf('force'),
+ store => \$force },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ make => { default => $conf->get_program('make'),
+ store => \$make },
+ makeflags => { default => $conf->get_conf('makeflags'),
+ store => \$makeflags },
+ skiptest => { default => $conf->get_conf('skiptest'),
+ store => \$skiptest },
+ prereq_target => { default => '', store => \$prereq_target },
+ ### don't set the default prereq format to 'makemaker' -- wrong!
+ prereq_format => { #default => $self->status->installer_type,
+ default => '',
+ store => \$prereq_format },
+ prereq_build => { default => 0, store => \$prereq_build },
+ };
+
+ $args = check( $tmpl, \%hash ) or return;
+ }
+
+ ### maybe we already ran a create on this object?
+ ### make sure we add to include path again, just in case we came from
+ ### ->save_state, at which point we need to restore @INC/$PERL5LIB
+ if( $dist->status->created && !$force ) {
+ $self->add_to_includepath;
+ return 1;
+ }
+
+ ### store the arguments, so ->install can use them in recursive loops ###
+ $dist->status->_create_args( $args );
+
+ unless( $dist->status->prepared ) {
+ error( loc( "You have not successfully prepared a '%2' distribution ".
+ "yet -- cannot create yet", __PACKAGE__ ) );
+ return;
+ }
+
+
+ ### chdir to work directory ###
+ my $orig = cwd();
+ unless( $cb->_chdir( dir => $dir ) ) {
+ error( loc( "Could not chdir to build directory '%1'", $dir ) );
+ return;
+ }
+
+ my $fail; my $prereq_fail; my $test_fail;
+ RUN: {
+ ### this will set the directory back to the start
+ ### dir, so we must chdir /again/
+ my $ok = $dist->_resolve_prereqs(
+ format => $prereq_format,
+ verbose => $verbose,
+ prereqs => $self->status->prereqs,
+ target => $prereq_target,
+ force => $force,
+ prereq_build => $prereq_build,
+ );
+
+ unless( $cb->_chdir( dir => $dir ) ) {
+ error( loc( "Could not chdir to build directory '%1'", $dir ) );
+ return;
+ }
+
+ unless( $ok ) {
+
+ #### use $dist->flush to reset the cache ###
+ error( loc( "Unable to satisfy prerequisites for '%1' " .
+ "-- aborting install", $self->module ) );
+ $dist->status->make(0);
+ $fail++; $prereq_fail++;
+ last RUN;
+ }
+ ### end of prereq resolving ###
+
+ my $captured;
+
+ ### 'make' section ###
+ if( -d BLIB->($dir) && (-M BLIB->($dir) < -M $dir) && !$force ) {
+ msg(loc("Already ran '%1' for this module [%2] -- " .
+ "not running again unless you force",
+ $make, $self->module ), $verbose );
+ } else {
+ unless(scalar run( command => [$make, $makeflags],
+ buffer => \$captured,
+ verbose => $verbose )
+ ) {
+ error( loc( "MAKE failed: %1 %2", $!, $captured ) );
+ $dist->status->make(0);
+ $fail++; last RUN;
+ }
+
+ ### put the output on the stack, don't print it
+ msg( $captured, 0 );
+
+ $dist->status->make(1);
+
+ ### add this directory to your lib ###
+ $self->add_to_includepath();
+
+ ### dont bail out here, there's a conditional later on
+ #last RUN if $skiptest;
+ }
+
+ ### 'make test' section ###
+ unless( $skiptest ) {
+
+ ### turn off our PERL5OPT so no modules from CPANPLUS::inc get
+ ### included in make test -- it should build without
+ ### also, modules that run in taint mode break if we leave
+ ### our code ref in perl5opt
+ ### XXX CPANPLUS::inc functionality is now obsolete.
+ #local $ENV{PERL5OPT} = CPANPLUS::inc->original_perl5opt || '';
+
+ ### you can turn off running this verbose by changing
+ ### the config setting below, although it is really not
+ ### recommended
+ my $run_verbose =
+ $verbose ||
+ $conf->get_conf('allow_build_interactivity') ||
+ 0;
+
+ ### XXX need to add makeflags here too?
+ ### yes, but they should really be split out -- see bug #4143
+ if( scalar run(
+ command => [$make, 'test', $makeflags],
+ buffer => \$captured,
+ verbose => $run_verbose,
+ ) ) {
+ ### tests might pass because it doesn't have any tests defined
+ ### log this occasion non-verbosely, so our test reporter can
+ ### pick up on this
+ if ( NO_TESTS_DEFINED->( $captured ) ) {
+ msg( NO_TESTS_DEFINED->( $captured ), 0 )
+ } else {
+ msg( loc( "MAKE TEST passed: %1", $captured ), 0 );
+ }
+
+ $dist->status->test(1);
+ } else {
+ error( loc( "MAKE TEST failed: %1 %2", $!, $captured ) );
+
+ ### send out error report here? or do so at a higher level?
+ ### --higher level --kane.
+ $dist->status->test(0);
+
+ ### mark specifically *test* failure.. so we dont
+ ### send success on force...
+ $test_fail++;
+
+ if( !$force and !$cb->_callbacks->proceed_on_test_failure->(
+ $self, $captured )
+ ) {
+ $fail++; last RUN;
+ }
+ }
+ }
+ } #</RUN>
+
+ unless( $cb->_chdir( dir => $orig ) ) {
+ error( loc( "Could not chdir back to start dir '%1'", $orig ) );
+ }
+
+ ### send out test report?
+ ### only do so if the failure is this module, not its prereq
+ if( $conf->get_conf('cpantest') and not $prereq_fail) {
+ $cb->_send_report(
+ module => $self,
+ failed => $test_fail || $fail,
+ buffer => CPANPLUS::Error->stack_as_string,
+ verbose => $verbose,
+ force => $force,
+ ) or error(loc("Failed to send test report for '%1'",
+ $self->module ) );
+ }
+
+ return $dist->status->created( $fail ? 0 : 1);
+}
+
+=pod
+
+=head2 $bool = $dist->install([make => '/path/to/make', makemakerflags => 'EXTRA=FLAGS', force => BOOL, verbose => BOOL])
+
+C<install> runs the following command:
+ make install
+
+Returns true on success, false on failure.
+
+=cut
+
+sub install {
+
+ ### just in case you did the create with ANOTHER dist object linked
+ ### to the same module object
+ my $dist = shift();
+ my $self = $dist->parent;
+ $dist = $self->status->dist_cpan if $self->status->dist_cpan;
+
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+
+ unless( $dist->status->created ) {
+ error(loc("You have not successfully created a '%2' distribution yet " .
+ "-- cannot install yet", __PACKAGE__ ));
+ return;
+ }
+
+ my $dir;
+ unless( $dir = $self->status->extract ) {
+ error( loc( "No dir found to operate on!" ) );
+ return;
+ }
+
+ my $args;
+ my($force,$verbose,$make,$makeflags);
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+ my $tmpl = {
+ force => { default => $conf->get_conf('force'),
+ store => \$force },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ make => { default => $conf->get_program('make'),
+ store => \$make },
+ makeflags => { default => $conf->get_conf('makeflags'),
+ store => \$makeflags },
+ };
+
+ $args = check( $tmpl, \%hash ) or return;
+ }
+
+ ### value set and false -- means failure ###
+ if( defined $self->status->installed &&
+ !$self->status->installed && !$force
+ ) {
+ error( loc( "Module '%1' has failed to install before this session " .
+ "-- aborting install", $self->module ) );
+ return;
+ }
+
+
+ $dist->status->_install_args( $args );
+
+ my $orig = cwd();
+ unless( $cb->_chdir( dir => $dir ) ) {
+ error( loc( "Could not chdir to build directory '%1'", $dir ) );
+ return;
+ }
+
+ my $fail; my $captured;
+
+ ### 'make install' section ###
+ ### XXX need makeflags here too?
+ ### yes, but they should really be split out.. see bug #4143
+ my $cmd = [$make, 'install', $makeflags];
+ my $sudo = $conf->get_program('sudo');
+ unshift @$cmd, $sudo if $sudo and $>;
+
+ $cb->flush('lib');
+ unless(scalar run( command => $cmd,
+ verbose => $verbose,
+ buffer => \$captured,
+ ) ) {
+ error( loc( "MAKE INSTALL failed: %1 %2", $!, $captured ) );
+ $fail++;
+ }
+
+ ### put the output on the stack, don't print it
+ msg( $captured, 0 );
+
+ unless( $cb->_chdir( dir => $orig ) ) {
+ error( loc( "Could not chdir back to start dir '%1'", $orig ) );
+ }
+
+ return $dist->status->installed( $fail ? 0 : 1 );
+
+}
+
+=pod
+
+=head2 $bool = $dist->write_makefile_pl([force => BOOL, verbose => BOOL])
+
+This routine can write a C<Makefile.PL> from the information in a
+module object. It is used to write a C<Makefile.PL> when the original
+author forgot it (!!).
+
+Returns 1 on success and false on failure.
+
+The file gets written to the directory the module's been extracted
+to.
+
+=cut
+
+sub write_makefile_pl {
+ ### just in case you already did a call for this module object
+ ### just via a different dist object
+ my $dist = shift;
+ my $self = $dist->parent;
+ $dist = $self->status->dist_cpan if $self->status->dist_cpan;
+ $self->status->dist_cpan( $dist ) unless $self->status->dist_cpan;
+
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my $dir;
+ unless( $dir = $self->status->extract ) {
+ error( loc( "No dir found to operate on!" ) );
+ return;
+ }
+
+ my ($force, $verbose);
+ my $tmpl = {
+ force => { default => $conf->get_conf('force'),
+ store => \$force },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ my $file = MAKEFILE_PL->($dir);
+ if( -s $file && !$force ) {
+ msg(loc("Already created '%1' - not doing so again without force",
+ $file ), $verbose );
+ return 1;
+ }
+
+ ### due to a bug with AS perl 5.8.4 built 810 (and maybe others)
+ ### opening files with content in them already does nasty things;
+ ### seek to pos 0 and then print, but not truncating the file
+ ### bug reported to activestate on 19 sep 2004:
+ ### http://bugs.activestate.com/show_bug.cgi?id=34051
+ unlink $file if $force;
+
+ my $fh = new FileHandle;
+ unless( $fh->open( ">$file" ) ) {
+ error( loc( "Could not create file '%1': %2", $file, $! ) );
+ return;
+ }
+
+ my $mf = MAKEFILE_PL->();
+ my $name = $self->module;
+ my $version = $self->version;
+ my $author = $self->author->author;
+ my $href = $self->status->prereqs;
+ my $prereqs = join ",\n", map {
+ (' ' x 25) . "'$_'\t=> '$href->{$_}'"
+ } keys %$href;
+ $prereqs ||= ''; # just in case there are none;
+
+ print $fh qq|
+ ### Auto-generated $mf by CPANPLUS ###
+
+ use ExtUtils::MakeMaker;
+
+ WriteMakefile(
+ NAME => '$name',
+ VERSION => '$version',
+ AUTHOR => '$author',
+ PREREQ_PM => {
+$prereqs
+ },
+ );
+ \n|;
+
+ $fh->close;
+ return 1;
+}
+
+sub dist_dir {
+ ### just in case you already did a call for this module object
+ ### just via a different dist object
+ my $dist = shift;
+ my $self = $dist->parent;
+ $dist = $self->status->dist_cpan if $self->status->dist_cpan;
+ $self->status->dist_cpan( $dist ) unless $self->status->dist_cpan;
+
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my $make; my $verbose;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+ my $tmpl = {
+ make => { default => $conf->get_program('make'),
+ store => \$make },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ };
+
+ check( $tmpl, \%hash ) or return;
+ }
+
+
+ my $dir;
+ unless( $dir = $self->status->extract ) {
+ error( loc( "No dir found to operate on!" ) );
+ return;
+ }
+
+ ### chdir to work directory ###
+ my $orig = cwd();
+ unless( $cb->_chdir( dir => $dir ) ) {
+ error( loc( "Could not chdir to build directory '%1'", $dir ) );
+ return;
+ }
+
+ my $fail; my $distdir;
+ TRY: {
+ $dist->prepare( @_ ) or (++$fail, last TRY);
+
+
+ my $captured;
+ unless(scalar run( command => [$make, 'distdir'],
+ buffer => \$captured,
+ verbose => $verbose )
+ ) {
+ error( loc( "MAKE DISTDIR failed: %1 %2", $!, $captured ) );
+ ++$fail, last TRY;
+ }
+
+ ### /path/to/Foo-Bar-1.2/Foo-Bar-1.2
+ $distdir = File::Spec->catdir( $dir, $self->package_name . '-' .
+ $self->package_version );
+
+ unless( -d $distdir ) {
+ error(loc("Do not know where '%1' got created", 'distdir'));
+ ++$fail, last TRY;
+ }
+ }
+
+ unless( $cb->_chdir( dir => $orig ) ) {
+ error( loc( "Could not chdir to start directory '%1'", $orig ) );
+ return;
+ }
+
+ return if $fail;
+ return $distdir;
+}
+
+
+1;
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Sample.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Sample.pm
new file mode 100644
index 00000000000..0b0939208ff
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Dist/Sample.pm
@@ -0,0 +1,16 @@
+package CPANPLUS::Dist::Sample;
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Dist::Sample -- Sample code to create your own Dist::* plugin
+
+=head1 Description.
+
+This document is B<Obsolete>. Please read the documentation and code
+in C<CPANPLUS::Dist::Base>.
+
+=cut
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Error.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Error.pm
new file mode 100644
index 00000000000..38710a8a857
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Error.pm
@@ -0,0 +1,201 @@
+package CPANPLUS::Error;
+
+use strict;
+
+use Log::Message private => 0;;
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Error
+
+=head1 SYNOPSIS
+
+ use CPANPLUS::Error qw[cp_msg cp_error];
+
+=head1 DESCRIPTION
+
+This module provides the error handling code for the CPANPLUS
+libraries, and is mainly intended for internal use.
+
+=head1 FUNCTIONS
+
+=head2 cp_msg("message string" [,VERBOSE])
+
+Records a message on the stack, and prints it to C<STDOUT> (or actually
+C<$MSG_FH>, see the C<GLOBAL VARIABLES> section below), if the
+C<VERBOSE> option is true.
+The C<VERBOSE> option defaults to false.
+
+=head2 msg()
+
+An alias for C<cp_msg>.
+
+=head2 cp_error("error string" [,VERBOSE])
+
+Records an error on the stack, and prints it to C<STDERR> (or actually
+C<$ERROR_FH>, see the C<GLOBAL VARIABLES> sections below), if the
+C<VERBOSE> option is true.
+The C<VERBOSE> options defaults to true.
+
+=head2 error()
+
+An alias for C<cp_error>.
+
+=head1 CLASS METHODS
+
+=head2 CPANPLUS::Error->stack()
+
+Retrieves all the items on the stack. Since C<CPANPLUS::Error> is
+implemented using C<Log::Message>, consult its manpage for the
+function C<retrieve> to see what is returned and how to use the items.
+
+=head2 CPANPLUS::Error->stack_as_string([TRACE])
+
+Returns the whole stack as a printable string. If the C<TRACE> option is
+true all items are returned with C<Carp::longmess> output, rather than
+just the message.
+C<TRACE> defaults to false.
+
+=head2 CPANPLUS::Error->flush()
+
+Removes all the items from the stack and returns them. Since
+C<CPANPLUS::Error> is implemented using C<Log::Message>, consult its
+manpage for the function C<retrieve> to see what is returned and how
+to use the items.
+
+=cut
+
+BEGIN {
+ use Exporter;
+ use Params::Check qw[check];
+ use vars qw[@EXPORT @ISA $ERROR_FH $MSG_FH];
+
+ @ISA = 'Exporter';
+ @EXPORT = qw[cp_error cp_msg error msg];
+
+ my $log = new Log::Message;
+
+ for my $func ( @EXPORT ) {
+ no strict 'refs';
+
+ my $prefix = 'cp_';
+ my $name = $func;
+ $name =~ s/^$prefix//g;
+
+ *$func = sub {
+ my $msg = shift;
+
+ ### no point storing non-messages
+ return unless defined $msg;
+
+ $log->store(
+ message => $msg,
+ tag => uc $name,
+ level => $prefix . $name,
+ extra => [@_]
+ );
+ };
+ }
+
+ sub flush {
+ return reverse $log->flush;
+ }
+
+ sub stack {
+ return $log->retrieve( chrono => 1 );
+ }
+
+ sub stack_as_string {
+ my $class = shift;
+ my $trace = shift() ? 1 : 0;
+
+ return join $/, map {
+ '[' . $_->tag . '] [' . $_->when . '] ' .
+ ($trace ? $_->message . ' ' . $_->longmess
+ : $_->message);
+ } __PACKAGE__->stack;
+ }
+}
+
+=head1 GLOBAL VARIABLES
+
+=over 4
+
+=item $ERROR_FH
+
+This is the filehandle all the messages sent to C<error()> are being
+printed. This defaults to C<*STDERR>.
+
+=item $MSG_FH
+
+This is the filehandle all the messages sent to C<msg()> are being
+printed. This default to C<*STDOUT>.
+
+=cut
+local $| = 1;
+$ERROR_FH = \*STDERR;
+$MSG_FH = \*STDOUT;
+
+package Log::Message::Handlers;
+use Carp ();
+
+{
+
+ sub cp_msg {
+ my $self = shift;
+ my $verbose = shift;
+
+ ### so you don't want us to print the msg? ###
+ return if defined $verbose && $verbose == 0;
+
+ my $old_fh = select $CPANPLUS::Error::MSG_FH;
+
+ print '['. $self->tag . '] ' . $self->message . "\n";
+ select $old_fh;
+
+ return;
+ }
+
+ sub cp_error {
+ my $self = shift;
+ my $verbose = shift;
+
+ ### so you don't want us to print the error? ###
+ return if defined $verbose && $verbose == 0;
+
+ my $old_fh = select $CPANPLUS::Error::ERROR_FH;
+
+ ### is only going to be 1 for now anyway ###
+ ### C::I may not be loaded, so do a can() check first
+ my $cb = CPANPLUS::Internals->can('_return_all_objects')
+ ? (CPANPLUS::Internals->_return_all_objects)[0]
+ : undef;
+
+ ### maybe we didn't initialize an internals object (yet) ###
+ my $debug = $cb ? $cb->configure_object->get_conf('debug') : 0;
+ my $msg = '['. $self->tag . '] ' . $self->message . "\n";
+
+ ### i'm getting this warning in the test suite:
+ ### Ambiguous call resolved as CORE::warn(), qualify as such or
+ ### use & at CPANPLUS/Error.pm line 57.
+ ### no idea where it's coming from, since there's no 'sub warn'
+ ### anywhere to be found, but i'll mark it explicitly nonetheless
+ ### --kane
+ print $debug ? Carp::shortmess($msg) : $msg . "\n";
+
+ select $old_fh;
+
+ return;
+ }
+}
+
+1;
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/FAQ.pod b/Master/tlpkg/tlperl/lib/CPANPLUS/FAQ.pod
new file mode 100644
index 00000000000..82bb57aaf47
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/FAQ.pod
@@ -0,0 +1,30 @@
+=pod
+
+=head1 NAME
+
+CPANPLUS::FAQ
+
+=head1 DESCRIPTION
+
+This document attempts to provide answers to commonly asked questions.
+
+ XXX Work in progress
+
+=head1 BUG REPORTS
+
+Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
+
+=head1 AUTHOR
+
+This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
+
+=head1 COPYRIGHT
+
+The CPAN++ interface (of which this module is a part of) is copyright (c)
+2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
+
+This library is free software; you may redistribute and/or modify it
+under the same terms as Perl itself.
+
+=cut
+
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Hacking.pod b/Master/tlpkg/tlperl/lib/CPANPLUS/Hacking.pod
new file mode 100644
index 00000000000..1a28b9e5b05
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Hacking.pod
@@ -0,0 +1,135 @@
+=pod
+
+=head1 NAME
+
+CPANPLUS::Hacking
+
+=head1 DESCRIPTION
+
+This document attempts to describe how to develop with the
+CPANPLUS environment most easily, how certain things work and why.
+
+This is basically a quick-start guide to people who want to add
+features or patches to CPANPLUS.
+
+=head1 OBTAINING CPANPLUS
+
+Checkout CPANPLUS from its Subversion repository at
+L<http://oss.dwim.org/cpanplus-devel> .
+
+=head1 INSTALLING CPANPLUS
+
+CPANPLUS follows the standard perl module installation process:
+
+ perl Makefile.PL
+ make
+ make test
+ make install
+
+=head1 CONFIGURING CPANPLUS
+
+When running C<perl Makefile.PL> you will be prompted to configure.
+If you have already done so, and merely wish to update the C<Makefile>,
+simply run:
+
+ perl Makefile.PL JFDI=1
+
+This will keep your configuration intact. Note however, if there are
+changes to the default configuration file C<Config.pm-orig>, you should
+either delete your current config file and reconfigure, or patch your
+config file from the new entries in C<Config.pm-orig>.
+
+=head1 RUNNING CPANPLUS FROM DEVELOPMENT ENVIRONMENT
+
+If you'd rather not install the development version to your
+C<site_perl> directory, that's no problem. You can set your C<PERL5LIB>
+environment variable to CPANPLUS' C<lib> directory, and you can run it
+from there.
+
+=head1 RUNNING CPANPLUS TESTS
+
+Tests are what tells us if CPANPLUS is working. If a test is not working,
+try to run it explicilty like this:
+
+ perl -I/path/to/cpanplus/lib t/XX_name_of_test.t 1
+
+The extra '1' makes sure that all the messages and errors (they might
+be errors we're testing for!) are being printed rather than kept quiet.
+This is a great way to find out the context of any failures that may
+occur.
+
+If you believe this test failure proves a bug in CPANPLUS, the long
+output of the test file is something we'd like to see alongside your
+bug report.
+
+=head1 FINDING BUGS
+
+Sometimes you might find bugs in CPANPLUS' behaviour. If you encounter
+these in a development snapshot, we'd appreciate a complete patch (as
+described below in the L<SENDING PATCHES> section.
+
+If it's way over your head, then of course reporting the bug is always
+better than not reporting it at all. Before you do so though, make
+sure you have the B<latest> development snapshot, and the bug still
+persists there. If so, report the bug to this address:
+
+ cpanplus-devel@lists.sourceforge.net
+
+A good C<patch> would have the following characteristics:
+
+=over 4
+
+=item Problem description
+
+Describe clearly what the bug is you found, and what it should have
+done instead.
+
+=item Program demonstrating the bug
+
+Show us how to reproduce the bug, in a simple of a program as possible
+
+=item [OPTIONAL] A patch to the test suite to test for the bug
+
+Amend our test suite by making sure this bug will be found in this, and
+future versions of CPANPLUS (see L<SUPPLYING PATCHES>)
+
+=item [OPTIONAL] A patch to the code + tests + documentation
+
+Fix the bug, update the docs & tests. That way your bug will be gone
+forever :)
+
+=back
+
+=head1 SUPPLYING PATCHES
+
+Patches are a good thing, and they are welcome. Especially if they fix
+bugs you've found along the way, or that others have reported.
+
+We prefer patches in the following format:
+
+=over 4
+
+=item * In C<diff -u> or C<diff -c> format
+
+=item * From the root of the snapshot
+
+=item * Including patches for code + tests + docs
+
+=item * Sent per mail to cpanplus-devel@lists.sourceforge.net
+
+=item * With subject containing C<[PATCH]> + description of the patch
+
+=back
+
+You will always be informed if a patch is applied or rejected, and in
+case of rejection why that is (perhaps you can tweak the patch to have
+it accepted after all).
+
+=cut
+
+__END__
+
+* perl5lib
+* perl t/foo 1
+* patches to cpanplus-devel
+* snap/devel.tgz
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Internals.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals.pm
new file mode 100644
index 00000000000..fedcb670aa4
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals.pm
@@ -0,0 +1,516 @@
+package CPANPLUS::Internals;
+
+### we /need/ perl5.6.1 or higher -- we use coderefs in @INC,
+### and 5.6.0 is just too buggy
+use 5.006001;
+
+use strict;
+use Config;
+
+
+use CPANPLUS::Error;
+
+use CPANPLUS::Selfupdate;
+
+use CPANPLUS::Internals::Extract;
+use CPANPLUS::Internals::Fetch;
+use CPANPLUS::Internals::Utils;
+use CPANPLUS::Internals::Constants;
+use CPANPLUS::Internals::Search;
+use CPANPLUS::Internals::Report;
+
+
+require base;
+use Cwd qw[cwd];
+use Module::Load qw[load];
+use Params::Check qw[check];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+use Module::Load::Conditional qw[can_load];
+
+use Object::Accessor;
+
+
+local $Params::Check::VERBOSE = 1;
+
+use vars qw[@ISA $VERSION];
+
+@ISA = qw[
+ CPANPLUS::Internals::Extract
+ CPANPLUS::Internals::Fetch
+ CPANPLUS::Internals::Utils
+ CPANPLUS::Internals::Search
+ CPANPLUS::Internals::Report
+ ];
+
+$VERSION = "0.90";
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Internals
+
+=head1 SYNOPSIS
+
+ my $internals = CPANPLUS::Internals->_init( _conf => $conf );
+ my $backend = CPANPLUS::Internals->_retrieve_id( $ID );
+
+=head1 DESCRIPTION
+
+This module is the guts of CPANPLUS -- it inherits from all other
+modules in the CPANPLUS::Internals::* namespace, thus defying normal
+rules of OO programming -- but if you're reading this, you already
+know what's going on ;)
+
+Please read the C<CPANPLUS::Backend> documentation for the normal API.
+
+=head1 ACCESSORS
+
+=over 4
+
+=item _conf
+
+Get/set the configure object
+
+=item _id
+
+Get/set the id
+
+=cut
+
+### autogenerate accessors ###
+for my $key ( qw[_conf _id _modules _hosts _methods _status
+ _callbacks _selfupdate _mtree _atree]
+) {
+ no strict 'refs';
+ *{__PACKAGE__."::$key"} = sub {
+ $_[0]->{$key} = $_[1] if @_ > 1;
+ return $_[0]->{$key};
+ }
+}
+
+=pod
+
+=back
+
+=head1 METHODS
+
+=head2 $internals = CPANPLUS::Internals->_init( _conf => CONFIG_OBJ )
+
+C<_init> creates a new CPANPLUS::Internals object.
+
+You have to pass it a valid C<CPANPLUS::Configure> object.
+
+Returns the object on success, or dies on failure.
+
+=cut
+{ ### NOTE:
+ ### if extra callbacks are added, don't forget to update the
+ ### 02-internals.t test script with them!
+ my $callback_map = {
+ ### name default value
+ install_prerequisite => 1, # install prereqs when 'ask' is set?
+ edit_test_report => 0, # edit the prepared test report?
+ send_test_report => 1, # send the test report?
+ # munge the test report
+ munge_test_report => sub { return $_[1] },
+ # filter out unwanted prereqs
+ filter_prereqs => sub { return $_[1] },
+ # continue if 'make test' fails?
+ proceed_on_test_failure => sub { return 0 },
+ munge_dist_metafile => sub { return $_[1] },
+ };
+
+ my $status = Object::Accessor->new;
+ $status->mk_accessors(qw[pending_prereqs]);
+
+ my $callback = Object::Accessor->new;
+ $callback->mk_accessors(keys %$callback_map);
+
+ my $conf;
+ my $Tmpl = {
+ _conf => { required => 1, store => \$conf,
+ allow => IS_CONFOBJ },
+ _id => { default => '', no_override => 1 },
+ _authortree => { default => '', no_override => 1 },
+ _modtree => { default => '', no_override => 1 },
+ _hosts => { default => {}, no_override => 1 },
+ _methods => { default => {}, no_override => 1 },
+ _status => { default => '<empty>', no_override => 1 },
+ _callbacks => { default => '<empty>', no_override => 1 },
+ };
+
+ sub _init {
+ my $class = shift;
+ my %hash = @_;
+
+ ### temporary warning until we fix the storing of multiple id's
+ ### and their serialization:
+ ### probably not going to happen --kane
+ if( my $id = $class->_last_id ) {
+ # make it a singleton.
+ warn loc(q[%1 currently only supports one %2 object per ] .
+ qq[running program\n], 'CPANPLUS', $class);
+
+ return $class->_retrieve_id( $id );
+ }
+
+ my $args = check($Tmpl, \%hash)
+ or die loc(qq[Could not initialize '%1' object], $class);
+
+ bless $args, $class;
+
+ $args->{'_id'} = $args->_inc_id;
+ $args->{'_status'} = $status;
+ $args->{'_callbacks'} = $callback;
+
+ ### initialize callbacks to default state ###
+ for my $name ( $callback->ls_accessors ) {
+ my $rv = ref $callback_map->{$name} ? 'sub return value' :
+ $callback_map->{$name} ? 'true' : 'false';
+
+ $args->_callbacks->$name(
+ sub { msg(loc("DEFAULT '%1' HANDLER RETURNING '%2'",
+ $name, $rv), $args->_conf->get_conf('debug'));
+ return ref $callback_map->{$name}
+ ? $callback_map->{$name}->( @_ )
+ : $callback_map->{$name};
+ }
+ );
+ }
+
+ ### create a selfupdate object
+ $args->_selfupdate( CPANPLUS::Selfupdate->new( $args ) );
+
+ ### initalize it as an empty hashref ###
+ $args->_status->pending_prereqs( {} );
+
+ $conf->_set_build( startdir => cwd() ),
+ or error( loc("couldn't locate current dir!") );
+
+ $ENV{FTP_PASSIVE} = 1, if $conf->get_conf('passive');
+
+ my $id = $args->_store_id( $args );
+
+ unless ( $id == $args->_id ) {
+ error( loc("IDs do not match: %1 != %2. Storage failed!",
+ $id, $args->_id) );
+ }
+
+ ### different source engines available now, so set them here
+ { my $store = $conf->get_conf( 'source_engine' )
+ || DEFAULT_SOURCE_ENGINE;
+
+ unless( can_load( modules => { $store => '0.0' }, verbose => 1 ) ) {
+ error( loc( "Could not load source engine '%1'", $store ) );
+
+ if( $store ne DEFAULT_SOURCE_ENGINE ) {
+ msg( loc("Falling back to %1", DEFAULT_SOURCE_ENGINE), 1 );
+
+ load DEFAULT_SOURCE_ENGINE;
+
+ base->import( DEFAULT_SOURCE_ENGINE );
+ } else {
+ return;
+ }
+ } else {
+ base->import( $store );
+ }
+ }
+
+ return $args;
+ }
+
+=pod
+
+=head2 $bool = $internals->_flush( list => \@caches )
+
+Flushes the designated caches from the C<CPANPLUS> object.
+
+Returns true on success, false if one or more caches could not be
+be flushed.
+
+=cut
+
+ sub _flush {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my $aref;
+ my $tmpl = {
+ list => { required => 1, default => [],
+ strict_type => 1, store => \$aref },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ my $flag = 0;
+ for my $what (@$aref) {
+ my $cache = '_' . $what;
+
+ ### set the include paths back to their original ###
+ if( $what eq 'lib' ) {
+ $ENV{PERL5LIB} = $conf->_perl5lib || '';
+ @INC = @{$conf->_lib};
+
+ ### give all modules a new status object -- this is slightly
+ ### costly, but the best way to make sure all statusses are
+ ### forgotten --kane
+ } elsif ( $what eq 'modules' ) {
+ for my $modobj ( values %{$self->module_tree} ) {
+
+ $modobj->_flush;
+ }
+
+ ### blow away the methods cache... currently, that's only
+ ### File::Fetch's method fail list
+ } elsif ( $what eq 'methods' ) {
+
+ ### still fucking p4 :( ###
+ $File'Fetch::METHOD_FAIL = $File'Fetch::METHOD_FAIL = {};
+
+ ### blow away the m::l::c cache, so modules can be (re)loaded
+ ### again if they become available
+ } elsif ( $what eq 'load' ) {
+ undef $Module::Load::Conditional::CACHE;
+
+ } else {
+ unless ( exists $self->{$cache} && exists $Tmpl->{$cache} ) {
+ error( loc( "No such cache: '%1'", $what ) );
+ $flag++;
+ next;
+ } else {
+ $self->$cache( {} );
+ }
+ }
+ }
+ return !$flag;
+ }
+
+### NOTE:
+### if extra callbacks are added, don't forget to update the
+### 02-internals.t test script with them!
+
+=pod
+
+=head2 $bool = $internals->_register_callback( name => CALLBACK_NAME, code => CODEREF );
+
+Registers a callback for later use by the internal libraries.
+
+Here is a list of the currently used callbacks:
+
+=over 4
+
+=item install_prerequisite
+
+Is called when the user wants to be C<asked> about what to do with
+prerequisites. Should return a boolean indicating true to install
+the prerequisite and false to skip it.
+
+=item send_test_report
+
+Is called when the user should be prompted if he wishes to send the
+test report. Should return a boolean indicating true to send the
+test report and false to skip it.
+
+=item munge_test_report
+
+Is called when the test report message has been composed, giving
+the user a chance to programatically alter it. Should return the
+(munged) message to be sent.
+
+=item edit_test_report
+
+Is called when the user should be prompted to edit test reports
+about to be sent out by Test::Reporter. Should return a boolean
+indicating true to edit the test report in an editor and false
+to skip it.
+
+=item proceed_on_test_failure
+
+Is called when 'make test' or 'Build test' fails. Should return
+a boolean indicating whether the install should continue even if
+the test failed.
+
+=item munge_dist_metafile
+
+Is called when the C<CPANPLUS::Dist::*> metafile is created, like
+C<control> for C<CPANPLUS::Dist::Deb>, giving the user a chance to
+programatically alter it. Should return the (munged) text to be
+written to the metafile.
+
+=back
+
+=cut
+
+ sub _register_callback {
+ my $self = shift or return;
+ my %hash = @_;
+
+ my ($name,$code);
+ my $tmpl = {
+ name => { required => 1, store => \$name,
+ allow => [$callback->ls_accessors] },
+ code => { required => 1, allow => IS_CODEREF,
+ store => \$code },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ $self->_callbacks->$name( $code ) or return;
+
+ return 1;
+ }
+
+# =head2 $bool = $internals->_add_callback( name => CALLBACK_NAME, code => CODEREF );
+#
+# Adds a new callback to be used from anywhere in the system. If the callback
+# is already known, an error is raised and false is returned. If the callback
+# is not yet known, it is added, and the corresponding coderef is registered
+# using the
+#
+# =cut
+#
+# sub _add_callback {
+# my $self = shift or return;
+# my %hash = @_;
+#
+# my ($name,$code);
+# my $tmpl = {
+# name => { required => 1, store => \$name, },
+# code => { required => 1, allow => IS_CODEREF,
+# store => \$code },
+# };
+#
+# check( $tmpl, \%hash ) or return;
+#
+# if( $callback->can( $name ) ) {
+# error(loc("Callback '%1' is already registered"));
+# return;
+# }
+#
+# $callback->mk_accessor( $name );
+#
+# $self->_register_callback( name => $name, code => $code ) or return;
+#
+# return 1;
+# }
+
+}
+
+=pod
+
+=head2 $bool = $internals->_add_to_includepath( directories => \@dirs )
+
+Adds a list of directories to the include path.
+This means they get added to C<@INC> as well as C<$ENV{PERL5LIB}>.
+
+Returns true on success, false on failure.
+
+=cut
+
+sub _add_to_includepath {
+ my $self = shift;
+ my %hash = @_;
+
+ my $dirs;
+ my $tmpl = {
+ directories => { required => 1, default => [], store => \$dirs,
+ strict_type => 1 },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ my $s = $Config{'path_sep'};
+
+ ### only add if it's not added yet
+ for my $lib (@$dirs) {
+ push @INC, $lib unless grep { $_ eq $lib } @INC;
+ #
+ ### it will be complaining if $ENV{PERL5LIB] is not defined (yet).
+ local $^W;
+ $ENV{'PERL5LIB'} .= $s . $lib
+ unless $ENV{'PERL5LIB'} =~ qr|\Q$s$lib\E|;
+ }
+
+ return 1;
+}
+
+=pod
+
+=head2 $id = CPANPLUS::Internals->_last_id
+
+Return the id of the last object stored.
+
+=head2 $id = CPANPLUS::Internals->_store_id( $internals )
+
+Store this object; return its id.
+
+=head2 $obj = CPANPLUS::Internals->_retrieve_id( $ID )
+
+Retrieve an object based on its ID -- return false on error.
+
+=head2 CPANPLUS::Internals->_remove_id( $ID )
+
+Remove the object marked by $ID from storage.
+
+=head2 @objs = CPANPLUS::Internals->_return_all_objects
+
+Return all stored objects.
+
+=cut
+
+
+### code for storing multiple objects
+### -- although we only support one right now
+### XXX when support for multiple objects comes, saving source will have
+### to change
+{
+ my $idref = {};
+ my $count = 0;
+
+ sub _inc_id { return ++$count; }
+
+ sub _last_id { $count }
+
+ sub _store_id {
+ my $self = shift;
+ my $obj = shift or return;
+
+ unless( IS_INTERNALS_OBJ->($obj) ) {
+ error( loc("The object you passed has the wrong ref type: '%1'",
+ ref $obj) );
+ return;
+ }
+
+ $idref->{ $obj->_id } = $obj;
+ return $obj->_id;
+ }
+
+ sub _retrieve_id {
+ my $self = shift;
+ my $id = shift or return;
+
+ my $obj = $idref->{$id};
+ return $obj;
+ }
+
+ sub _remove_id {
+ my $self = shift;
+ my $id = shift or return;
+
+ return delete $idref->{$id};
+ }
+
+ sub _return_all_objects { return values %$idref }
+}
+
+1;
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Constants.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Constants.pm
new file mode 100644
index 00000000000..1a38200dfb7
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Constants.pm
@@ -0,0 +1,375 @@
+package CPANPLUS::Internals::Constants;
+
+use strict;
+
+use CPANPLUS::Error;
+
+use Config;
+use File::Spec;
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+require Exporter;
+use vars qw[$VERSION @ISA @EXPORT];
+
+use Package::Constants;
+
+@ISA = qw[Exporter];
+@EXPORT = Package::Constants->list( __PACKAGE__ );
+
+
+sub constants { @EXPORT };
+
+use constant INSTALLER_BUILD
+ => 'CPANPLUS::Dist::Build';
+use constant INSTALLER_MM => 'CPANPLUS::Dist::MM';
+use constant INSTALLER_SAMPLE
+ => 'CPANPLUS::Dist::Sample';
+use constant INSTALLER_BASE => 'CPANPLUS::Dist::Base';
+use constant INSTALLER_AUTOBUNDLE
+ => 'CPANPLUS::Dist::Autobundle';
+
+use constant SHELL_DEFAULT => 'CPANPLUS::Shell::Default';
+use constant SHELL_CLASSIC => 'CPANPLUS::Shell::Classic';
+
+use constant CONFIG => 'CPANPLUS::Config';
+use constant CONFIG_USER => 'CPANPLUS::Config::User';
+use constant CONFIG_SYSTEM => 'CPANPLUS::Config::System';
+use constant CONFIG_BOXED => 'CPANPLUS::Config::Boxed';
+
+use constant DEFAULT_SOURCE_ENGINE
+ => 'CPANPLUS::Internals::Source::Memory';
+
+use constant TARGET_INIT => 'init';
+use constant TARGET_CREATE => 'create';
+use constant TARGET_PREPARE => 'prepare';
+use constant TARGET_INSTALL => 'install';
+use constant TARGET_IGNORE => 'ignore';
+
+use constant ON_WIN32 => $^O eq 'MSWin32';
+use constant ON_NETWARE => $^O eq 'NetWare';
+use constant ON_CYGWIN => $^O eq 'cygwin';
+use constant ON_VMS => $^O eq 'VMS';
+
+use constant DOT_CPANPLUS => ON_VMS ? '_cpanplus' : '.cpanplus';
+
+use constant OPT_AUTOFLUSH => '-MCPANPLUS::Internals::Utils::Autoflush';
+
+use constant UNKNOWN_DL_LOCATION
+ => 'UNKNOWN-ORIGIN';
+
+use constant NMAKE => 'nmake.exe';
+use constant NMAKE_URL =>
+ 'ftp://ftp.microsoft.com/Softlib/MSLFILES/nmake15.exe';
+
+use constant INSTALL_VIA_PACKAGE_MANAGER
+ => sub { my $fmt = $_[0] or return;
+ return 1 if $fmt ne INSTALLER_BUILD and
+ $fmt ne INSTALLER_MM;
+ };
+
+use constant IS_CODEREF => sub { ref $_[-1] eq 'CODE' };
+use constant IS_MODOBJ => sub { UNIVERSAL::isa($_[-1],
+ 'CPANPLUS::Module') };
+use constant IS_FAKE_MODOBJ => sub { UNIVERSAL::isa($_[-1],
+ 'CPANPLUS::Module::Fake') };
+use constant IS_AUTHOBJ => sub { UNIVERSAL::isa($_[-1],
+ 'CPANPLUS::Module::Author') };
+use constant IS_FAKE_AUTHOBJ
+ => sub { UNIVERSAL::isa($_[-1],
+ 'CPANPLUS::Module::Author::Fake') };
+
+use constant IS_CONFOBJ => sub { UNIVERSAL::isa($_[-1],
+ 'CPANPLUS::Configure') };
+
+use constant IS_RVOBJ => sub { UNIVERSAL::isa($_[-1],
+ 'CPANPLUS::Backend::RV') };
+
+use constant IS_INTERNALS_OBJ
+ => sub { UNIVERSAL::isa($_[-1],
+ 'CPANPLUS::Internals') };
+
+use constant IS_FILE => sub { return 1 if -e $_[-1] };
+
+use constant FILE_EXISTS => sub {
+ my $file = $_[-1];
+ return 1 if IS_FILE->($file);
+ local $Carp::CarpLevel =
+ $Carp::CarpLevel+2;
+ error(loc( q[File '%1' does not exist],
+ $file));
+ return;
+ };
+
+use constant FILE_READABLE => sub {
+ my $file = $_[-1];
+ return 1 if -e $file && -r _;
+ local $Carp::CarpLevel =
+ $Carp::CarpLevel+2;
+ error( loc( q[File '%1' is not readable ].
+ q[or does not exist], $file));
+ return;
+ };
+use constant IS_DIR => sub { return 1 if -d $_[-1] };
+
+use constant DIR_EXISTS => sub {
+ my $dir = $_[-1];
+ return 1 if IS_DIR->($dir);
+ local $Carp::CarpLevel =
+ $Carp::CarpLevel+2;
+ error(loc(q[Dir '%1' does not exist],
+ $dir));
+ return;
+ };
+
+ ### On VMS, if the $Config{make} is either MMK
+ ### or MMS, then the makefile is 'DESCRIP.MMS'.
+use constant MAKEFILE => sub { my $file =
+ (ON_VMS and
+ $Config::Config{make} =~ /MM[S|K]/i)
+ ? 'DESCRIP.MMS'
+ : 'Makefile';
+
+ return @_
+ ? File::Spec->catfile( @_, $file )
+ : $file;
+ };
+use constant MAKEFILE_PL => sub { return @_
+ ? File::Spec->catfile( @_,
+ 'Makefile.PL' )
+ : 'Makefile.PL';
+ };
+use constant BUILD_PL => sub { return @_
+ ? File::Spec->catfile( @_,
+ 'Build.PL' )
+ : 'Build.PL';
+ };
+
+use constant META_YML => sub { return @_
+ ? File::Spec->catfile( @_, 'META.yml' )
+ : 'META.yml';
+ };
+
+use constant MYMETA_YML => sub { return @_
+ ? File::Spec->catfile( @_, 'MYMETA.yml' )
+ : 'MYMETA.yml';
+ };
+
+use constant BLIB => sub { return @_
+ ? File::Spec->catfile(@_, 'blib')
+ : 'blib';
+ };
+
+use constant LIB => 'lib';
+use constant LIB_DIR => sub { return @_
+ ? File::Spec->catdir(@_, LIB)
+ : LIB;
+ };
+use constant AUTO => 'auto';
+use constant LIB_AUTO_DIR => sub { return @_
+ ? File::Spec->catdir(@_, LIB, AUTO)
+ : File::Spec->catdir(LIB, AUTO)
+ };
+use constant ARCH => 'arch';
+use constant ARCH_DIR => sub { return @_
+ ? File::Spec->catdir(@_, ARCH)
+ : ARCH;
+ };
+use constant ARCH_AUTO_DIR => sub { return @_
+ ? File::Spec->catdir(@_,ARCH,AUTO)
+ : File::Spec->catdir(ARCH,AUTO)
+ };
+
+use constant BLIB_LIBDIR => sub { return @_
+ ? File::Spec->catdir(
+ @_, BLIB->(), LIB )
+ : File::Spec->catdir( BLIB->(), LIB );
+ };
+
+use constant CONFIG_USER_LIB_DIR => sub {
+ require CPANPLUS::Internals::Utils;
+ LIB_DIR->(
+ CPANPLUS::Internals::Utils->_home_dir,
+ DOT_CPANPLUS
+ );
+ };
+use constant CONFIG_USER_FILE => sub {
+ File::Spec->catfile(
+ CONFIG_USER_LIB_DIR->(),
+ split('::', CONFIG_USER),
+ ) . '.pm';
+ };
+use constant CONFIG_SYSTEM_FILE => sub {
+ require CPANPLUS::Internals;
+ require File::Basename;
+ my $dir = File::Basename::dirname(
+ $INC{'CPANPLUS/Internals.pm'}
+ );
+
+ ### XXX use constants
+ File::Spec->catfile(
+ $dir, qw[Config System.pm]
+ );
+ };
+
+use constant README => sub { my $obj = $_[0];
+ my $pkg = $obj->package_name;
+ $pkg .= '-' . $obj->package_version .
+ '.readme';
+ return $pkg;
+ };
+use constant META_EXT => 'meta';
+
+use constant META => sub { my $obj = $_[0];
+ my $pkg = $obj->package_name;
+ $pkg .= '-' . $obj->package_version .
+ '.' . META_EXT;
+ return $pkg;
+ };
+
+use constant OPEN_FILE => sub {
+ my($file, $mode) = (@_, '');
+ my $fh;
+ open $fh, "$mode" . $file
+ or error(loc(
+ "Could not open file '%1': %2",
+ $file, $!));
+ return $fh if $fh;
+ return;
+ };
+
+use constant OPEN_DIR => sub {
+ my $dir = shift;
+ my $dh;
+ opendir $dh, $dir or error(loc(
+ "Could not open dir '%1': %2", $dir, $!
+ ));
+
+ return $dh if $dh;
+ return;
+ };
+
+use constant READ_DIR => sub {
+ my $dir = shift;
+ my $dh = OPEN_DIR->( $dir ) or return;
+
+ ### exclude . and ..
+ my @files = grep { $_ !~ /^\.{1,2}/ }
+ readdir($dh);
+
+ ### Remove trailing dot on VMS when
+ ### using VMS syntax.
+ if( ON_VMS ) {
+ s/(?<!\^)\.$// for @files;
+ }
+
+ return @files;
+ };
+
+use constant STRIP_GZ_SUFFIX
+ => sub {
+ my $file = $_[0] or return;
+ $file =~ s/.gz$//i;
+ return $file;
+ };
+
+use constant CHECKSUMS => 'CHECKSUMS';
+use constant PGP_HEADER => '-----BEGIN PGP SIGNED MESSAGE-----';
+use constant ENV_CPANPLUS_CONFIG
+ => 'PERL5_CPANPLUS_CONFIG';
+use constant ENV_CPANPLUS_IS_EXECUTING
+ => 'PERL5_CPANPLUS_IS_EXECUTING';
+use constant DEFAULT_EMAIL => 'cpanplus@example.com';
+use constant CPANPLUS_UA => sub { ### for the version number ###
+ require CPANPLUS::Internals;
+ "CPANPLUS/$CPANPLUS::Internals::VERSION"
+ };
+use constant TESTERS_URL => sub {
+ 'http://cpantesters.org/distro/'.
+ uc(substr($_[0],0,1)) .'/'. $_[0] . '.yaml';
+ };
+use constant TESTERS_DETAILS_URL
+ => sub {
+ 'http://cpantesters.org/distro/'.
+ uc(substr($_[0],0,1)) .'/'. $_[0];
+ };
+
+use constant CREATE_FILE_URI
+ => sub {
+ my $dir = $_[0] or return;
+ return $dir =~ m|^/|
+ ? 'file://' . $dir
+ : 'file:///' . $dir;
+ };
+
+use constant EMPTY_DSLIP => ' ';
+
+use constant CUSTOM_AUTHOR_ID
+ => 'LOCAL';
+
+use constant DOT_SHELL_DEFAULT_RC
+ => '.shell-default.rc';
+
+use constant SOURCE_SQLITE_DB
+ => 'db.sql';
+
+use constant PREREQ_IGNORE => 0;
+use constant PREREQ_INSTALL => 1;
+use constant PREREQ_ASK => 2;
+use constant PREREQ_BUILD => 3;
+use constant BOOLEANS => [0,1];
+use constant CALLING_FUNCTION
+ => sub { my $lvl = $_[0] || 0;
+ return join '::', (caller(2+$lvl))[3]
+ };
+use constant PERL_CORE => 'perl';
+use constant STORABLE_EXT => '.stored';
+
+use constant GET_XS_FILES => sub { my $dir = $_[0] or return;
+ require File::Find;
+ my @files;
+ File::Find::find(
+ sub { push @files, $File::Find::name
+ if $File::Find::name =~ /\.xs$/i
+ }, $dir );
+
+ return @files;
+ };
+
+use constant INSTALL_LOG_FILE
+ => sub { my $obj = shift or return;
+ my $name = $obj->name; $name =~ s/::/-/g;
+ $name .= '-'. $obj->version;
+ $name .= '-'. scalar(time) . '.log';
+ return $name;
+ };
+
+use constant ON_OLD_CYGWIN => do { ON_CYGWIN and $] < 5.008
+ ? loc(
+ "Your perl version for %1 is too low; ".
+ "Require %2 or higher for this function",
+ $^O, '5.8.0' )
+ : '';
+ };
+
+### XXX these 2 are probably obsolete -- check & remove;
+use constant DOT_EXISTS => '.exists';
+
+use constant QUOTE_PERL_ONE_LINER
+ => sub { my $line = shift or return;
+
+ ### use double quotes on these systems
+ return qq["$line"]
+ if ON_WIN32 || ON_NETWARE || ON_VMS;
+
+ ### single quotes on the rest
+ return qq['$line'];
+ };
+
+1;
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Constants/Report.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Constants/Report.pm
new file mode 100644
index 00000000000..59a41a6083b
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Constants/Report.pm
@@ -0,0 +1,407 @@
+package CPANPLUS::Internals::Constants::Report;
+
+use strict;
+use CPANPLUS::Error;
+
+use File::Spec;
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+require Exporter;
+use vars qw[$VERSION @ISA @EXPORT];
+
+use Package::Constants;
+
+### for the version
+require CPANPLUS::Internals;
+
+$VERSION = $CPANPLUS::Internals::VERSION = $CPANPLUS::Internals::VERSION;
+@ISA = qw[Exporter];
+@EXPORT = Package::Constants->list( __PACKAGE__ );
+
+
+### OS to regex map ###
+my %OS = (
+ Amiga => 'amigaos',
+ Atari => 'mint',
+ BSD => 'bsdos|darwin|freebsd|openbsd|netbsd',
+ Be => 'beos',
+ BeOS => 'beos',
+ Cygwin => 'cygwin',
+ Darwin => 'darwin',
+ EBCDIC => 'os390|os400|posix-bc|vmesa',
+ HPUX => 'hpux',
+ Linux => 'linux',
+ MSDOS => 'dos|os2|MSWin32|cygwin',
+ 'bin\\d*Mac'=> 'MacOS|darwin', # binMac, bin56Mac, bin58Mac...
+ Mac => 'MacOS|darwin',
+ MacPerl => 'MacOS',
+ MacOS => 'MacOS|darwin',
+ MacOSX => 'darwin',
+ MPE => 'mpeix',
+ MPEiX => 'mpeix',
+ OS2 => 'os2',
+ Plan9 => 'plan9',
+ RISCOS => 'riscos',
+ SGI => 'irix',
+ Solaris => 'solaris',
+ Unix => 'aix|bsdos|darwin|dgux|dynixptx|freebsd|'.
+ 'linux|hpux|machten|netbsd|next|openbsd|dec_osf|'.
+ 'svr4|sco_sv|unicos|unicosmk|solaris|sunos',
+ VMS => 'VMS',
+ VOS => 'VOS',
+ Win32 => 'MSWin32|cygwin',
+ Win32API => 'MSWin32|cygwin',
+);
+
+use constant GRADE_FAIL => 'fail';
+use constant GRADE_PASS => 'pass';
+use constant GRADE_NA => 'na';
+use constant GRADE_UNKNOWN => 'unknown';
+
+use constant MAX_REPORT_SEND
+ => 2;
+
+use constant CPAN_TESTERS_EMAIL
+ => 'cpan-testers@perl.org';
+
+### the cpan mail account for this user ###
+use constant CPAN_MAIL_ACCOUNT
+ => sub {
+ my $username = shift or return;
+ return $username . '@cpan.org';
+ };
+
+### check if this module is platform specific and if we're on that
+### specific platform. Alternately, the module is not platform specific
+### and we're always OK to send out test results.
+use constant RELEVANT_TEST_RESULT
+ => sub {
+ my $mod = shift or return;
+ my $name = $mod->module;
+ my $specific;
+ for my $platform (keys %OS) {
+ if( $name =~ /\b$platform\b/i ) {
+ # beware the Mac != MAC
+ next if($platform eq 'Mac' &&
+ $name !~ /\b$platform\b/);
+ $specific++;
+ return 1 if
+ $^O =~ /^(?:$OS{$platform})$/
+ }
+ };
+ return $specific ? 0 : 1;
+ };
+
+use constant UNSUPPORTED_OS
+ => sub {
+ my $buffer = shift or return;
+ if( $buffer =~
+ /No support for OS|OS unsupported/im ) {
+ return 1;
+ }
+ return 0;
+ };
+
+use constant PERL_VERSION_TOO_LOW
+ => sub {
+ my $buffer = shift or return;
+ # ExtUtils::MakeMaker format
+ if( $buffer =~
+ /Perl .*? required--this is only .*?/m ) {
+ return 1;
+ }
+ # Module::Build format
+ if( $buffer =~
+ /ERROR:( perl:)? Version .*?( of perl)? is installed, but we need version >= .*?/m ) {
+ return 1;
+ }
+ return 0;
+ };
+
+use constant NO_TESTS_DEFINED
+ => sub {
+ my $buffer = shift or return;
+ if( $buffer =~
+ /(No tests defined( for [\w:]+ extension)?\.)/
+ and $buffer !~ /\*\.t/m and
+ $buffer !~ /test\.pl/m
+ ) {
+ return $1
+ }
+
+ return;
+ };
+
+### what stage did the test fail? ###
+use constant TEST_FAIL_STAGE
+ => sub {
+ my $buffer = shift or return;
+ return $buffer =~ /(MAKE [A-Z]+).*/
+ ? lc $1 :
+ 'fetch';
+ };
+
+
+use constant MISSING_PREREQS_LIST
+ => sub {
+ my $buffer = shift;
+ my $last = ( split /\[ERROR\] .+? MAKE TEST/, $buffer )[-1];
+ my @list = map { s/.pm$//; s|/|::|g; $_ }
+ ($last =~
+ m/\bCan\'t locate (\S+) in \@INC/g);
+
+ ### make sure every missing prereq is only
+ ### listed once
+ { my %seen;
+ @list = grep { !$seen{$_}++ } @list
+ }
+
+ return @list;
+ };
+
+use constant MISSING_EXTLIBS_LIST
+ => sub {
+ my $buffer = shift;
+ my @list =
+ ($buffer =~
+ m/No library found for -l([-\w]+)/g);
+
+ return @list;
+ };
+
+use constant REPORT_MESSAGE_HEADER
+ => sub {
+ my ($version, $author) = @_;
+ return << ".";
+
+Dear $author,
+
+This is a computer-generated error report created automatically by
+CPANPLUS, version $version. Testers personal comments may appear
+at the end of this report.
+
+.
+ };
+
+use constant REPORT_MESSAGE_FAIL_HEADER
+ => sub {
+ my($stage, $buffer) = @_;
+ return << ".";
+
+Thank you for uploading your work to CPAN. However, it appears that
+there were some problems testing your distribution.
+
+TEST RESULTS:
+
+Below is the error stack from stage '$stage':
+
+$buffer
+
+.
+ };
+
+use constant REPORT_MISSING_PREREQS
+ => sub {
+ my ($author,$email,@missing) = @_;
+ $author = ($author && $email)
+ ? "$author ($email)"
+ : 'Your Name Here';
+
+ my $modules = join "\n", @missing;
+ my $prereqs = join "\n",
+ map {"\t'$_'\t=> '0',".
+ " # or a minimum working version"}
+ @missing;
+
+ return << ".";
+
+MISSING PREREQUISITES:
+
+It was observed that the test suite seem to fail without these modules:
+
+$modules
+
+As such, adding the prerequisite module(s) to 'PREREQ_PM' in your
+Makefile.PL should solve this problem. For example:
+
+WriteMakefile(
+ AUTHOR => '$author',
+ ... # other information
+ PREREQ_PM => {
+$prereqs
+ }
+);
+
+Thanks! :-)
+
+.
+ };
+
+use constant REPORT_MISSING_TESTS
+ => sub {
+ return << ".";
+RECOMMENDATIONS:
+
+It would be very helpful if you could include even a simple test
+script in the next release, so people can verify which platforms
+can successfully install them, as well as avoid regression bugs?
+
+A simple 't/use.t' that says:
+
+#!/usr/bin/env perl -w
+use strict;
+use Test;
+BEGIN { plan tests => 1 }
+
+use Your::Module::Here; ok(1);
+exit;
+__END__
+
+would be appreciated. If you are interested in making a more robust
+test suite, please see the Test::Simple, Test::More and Test::Tutorial
+documentation at <http://search.cpan.org/dist/Test-Simple/>.
+
+Thanks! :-)
+
+.
+ };
+
+use constant REPORT_LOADED_PREREQS
+ => sub {
+ my $mod = shift;
+ my $cb = $mod->parent;
+ my $prq = $mod->status->prereqs || {};
+
+ ### not every prereq may be coming from CPAN
+ ### so maybe we wont find it in our module
+ ### tree at all...
+ ### skip ones that cant be found in teh list
+ ### as reported in #12723
+ my @prq = grep { defined }
+ map { $cb->module_tree($_) }
+ sort keys %$prq;
+
+ ### no prereqs?
+ return '' unless @prq;
+
+ ### some apparently, list what we loaded
+ my $str = << ".";
+PREREQUISITES:
+
+Here is a list of prerequisites you specified and versions we
+managed to load:
+
+.
+ $str .= join '',
+ map { sprintf "\t%s %-30s %8s %8s\n",
+ @$_
+
+ } [' ', 'Module Name', 'Have', 'Want'],
+ map { my $want = $prq->{$_->name};
+ [ do { $_->is_uptodate(
+ version => $want
+ ) ? ' ' : '!'
+ },
+ $_->name,
+ $_->installed_version,
+ $want
+ ],
+ ### might be empty entries in there
+ } grep { $_ } @prq;
+
+ return $str;
+ };
+
+use constant REPORT_TOOLCHAIN_VERSIONS
+ => sub {
+ my $mod = shift;
+ my $cb = $mod->parent;
+ #die unless $cb->isa('CPANPLUS::Backend');
+
+ my @toolchain_modules= qw(
+ CPANPLUS
+ CPANPLUS::Dist::Build
+ Cwd
+ ExtUtils::CBuilder
+ ExtUtils::Command
+ ExtUtils::Install
+ ExtUtils::MakeMaker
+ ExtUtils::Manifest
+ ExtUtils::ParseXS
+ File::Spec
+ Module::Build
+ Test::Harness
+ Test::More
+ version
+ );
+
+ my @toolchain =
+ grep { $_ } #module_tree returns '' when module is not found
+ map { $cb->module_tree($_) }
+ sort @toolchain_modules;
+
+ ### no prereqs?
+ return '' unless @toolchain;
+
+ ### toolchain modules
+ my $str = << ".";
+
+Perl module toolchain versions installed:
+.
+ $str .= join '',
+ map { sprintf "\t%-30s %8s\n",
+ @$_
+
+ } ['Module Name', 'Have'],
+ map {
+ [ $_->name,
+ $_->installed_version,
+ ],
+ ### might be empty entries in there
+ } @toolchain;
+
+ return $str;
+ };
+
+
+use constant REPORT_TESTS_SKIPPED
+ => sub {
+ return << ".";
+
+******************************** NOTE ********************************
+*** ***
+*** The tests for this module were skipped during this build ***
+*** ***
+**********************************************************************
+
+.
+ };
+
+use constant REPORT_MESSAGE_FOOTER
+ => sub {
+ return << ".";
+
+******************************** NOTE ********************************
+The comments above are created mechanically, possibly without manual
+checking by the sender. As there are many people performing automatic
+tests on each upload to CPAN, it is likely that you will receive
+identical messages about the same problem.
+
+If you believe that the message is mistaken, please reply to the first
+one with correction and/or additional informations, and do not take
+it personally. We appreciate your patience. :)
+**********************************************************************
+
+Additional comments:
+
+.
+ };
+
+1;
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Extract.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Extract.pm
new file mode 100644
index 00000000000..84a48a50dea
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Extract.pm
@@ -0,0 +1,243 @@
+package CPANPLUS::Internals::Extract;
+
+use strict;
+
+use CPANPLUS::Error;
+use CPANPLUS::Internals::Constants;
+
+use File::Spec ();
+use File::Basename ();
+use Archive::Extract;
+use IPC::Cmd qw[run];
+use Params::Check qw[check];
+use Module::Load::Conditional qw[can_load check_install];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+local $Params::Check::VERBOSE = 1;
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Internals::Extract
+
+=head1 SYNOPSIS
+
+ ### for source files ###
+ $self->_gunzip( file => 'foo.gz', output => 'blah.txt' );
+
+ ### for modules/packages ###
+ $dir = $self->_extract( module => $modobj,
+ extractdir => '/some/where' );
+
+=head1 DESCRIPTION
+
+CPANPLUS::Internals::Extract extracts compressed files for CPANPLUS.
+It can do this by either a pure perl solution (preferred) with the
+use of C<Archive::Tar> and C<Compress::Zlib>, or with binaries, like
+C<gzip> and C<tar>.
+
+The flow looks like this:
+
+ $cb->_extract
+ Delegate to Archive::Extract
+
+=head1 METHODS
+
+=head2 $dir = _extract( module => $modobj, [perl => '/path/to/perl', extractdir => '/path/to/extract/to', prefer_bin => BOOL, verbose => BOOL, force => BOOL] )
+
+C<_extract> will take a module object and extract it to C<extractdir>
+if provided, or the default location which is obtained from your
+config.
+
+The file name is obtained by looking at C<< $modobj->status->fetch >>
+and will be parsed to see if it's a tar or zip archive.
+
+If it's a zip archive, C<__unzip> will be called, otherwise C<__untar>
+will be called. In the unlikely event the file is of neither format,
+an error will be thrown.
+
+C<_extract> takes the following options:
+
+=over 4
+
+=item module
+
+A C<CPANPLUS::Module> object. This is required.
+
+=item extractdir
+
+The directory to extract the archive to. By default this looks
+something like:
+ /CPANPLUS_BASE/PERL_VERSION/BUILD/MODULE_NAME
+
+=item prefer_bin
+
+A flag indicating whether you prefer a pure perl solution, ie
+C<Archive::Tar> or C<Archive::Zip> respectively, or a binary solution
+like C<unzip> and C<tar>.
+
+=item perl
+
+The path to the perl executable to use for any perl calls. Also used
+to determine the build version directory for extraction.
+
+=item verbose
+
+Specifies whether to be verbose or not. Defaults to your corresponding
+config entry.
+
+=item force
+
+Specifies whether to force the extraction or not. Defaults to your
+corresponding config entry.
+
+=back
+
+All other options are passed on verbatim to C<__unzip> or C<__untar>.
+
+Returns the directory the file was extracted to on success and false
+on failure.
+
+=cut
+
+sub _extract {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my( $mod, $verbose, $force );
+ my $tmpl = {
+ force => { default => $conf->get_conf('force'),
+ store => \$force },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ prefer_bin => { default => $conf->get_conf('prefer_bin') },
+ extractdir => { default => $conf->get_conf('extractdir') },
+ module => { required => 1, allow => IS_MODOBJ, store => \$mod },
+ perl => { default => $^X },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ ### did we already extract it ? ###
+ my $loc = $mod->status->extract();
+
+ if( $loc && !$force ) {
+ msg(loc("Already extracted '%1' to '%2'. ".
+ "Won't extract again without force",
+ $mod->module, $loc), $verbose);
+ return $loc;
+ }
+
+ ### did we already fetch the file? ###
+ my $file = $mod->status->fetch();
+ unless( -s $file ) {
+ error( loc( "File '%1' has zero size: cannot extract", $file ) );
+ return;
+ }
+
+ ### the dir to extract to ###
+ my $to = $args->{'extractdir'} ||
+ File::Spec->catdir(
+ $conf->get_conf('base'),
+ $self->_perl_version( perl => $args->{'perl'} ),
+ $conf->_get_build('moddir'),
+ );
+
+ ### delegate to Archive::Extract ###
+ ### set up some flags for archive::extract ###
+ local $Archive::Extract::PREFER_BIN = $args->{'prefer_bin'};
+ local $Archive::Extract::DEBUG = $conf->get_conf('debug');
+ local $Archive::Extract::WARN = $verbose;
+
+ my $ae = Archive::Extract->new( archive => $file );
+
+ unless( $ae->extract( to => $to ) ) {
+ error( loc( "Unable to extract '%1' to '%2': %3",
+ $file, $to, $ae->error ) );
+ return;
+ }
+
+ ### if ->files is not filled, we dont know what the hell was
+ ### extracted.. try to offer a suggestion and bail :(
+ unless ( $ae->files ) {
+ error( loc( "'%1' was not able to determine extracted ".
+ "files from the archive. Instal '%2' and ensure ".
+ "it works properly and try again",
+ $ae->is_zip ? 'Archive::Zip' : 'Archive::Tar' ) );
+ return;
+ }
+
+
+ ### print out what files we extracted ###
+ msg(loc("Extracted '%1'",$_),$verbose) for @{$ae->files};
+
+ ### set them all to be +w for the owner, so we don't get permission
+ ### denied for overwriting files that are just +r
+
+ ### this is to rigurous -- just change to +w for the owner [cpan #13358]
+ #chmod 0755, map { File::Spec->rel2abs( File::Spec->catdir($to, $_) ) }
+ # @{$ae->files};
+
+ for my $file ( @{$ae->files} ) {
+ my $path = File::Spec->rel2abs( File::Spec->catfile($to, $file) );
+
+ $self->_mode_plus_w( file => $path );
+ }
+
+ ### check the return value for the extracted path ###
+ ### Make an educated guess if we didn't get an extract_path
+ ### back
+ ### XXX apparently some people make their own dists and they
+ ### pack up '.' which means the leading directory is '.'
+ ### and only the second directory is the actual module directory
+ ### so, we'll have to check if our educated guess exists first,
+ ### then see if the extract path works.. and if nothing works...
+ ### well, then we really don't know.
+
+ my $dir;
+ for my $try (
+ File::Spec->rel2abs(
+ ### _safe_path must be called before catdir because catdir on
+ ### VMS currently will not handle the extra dots in the directories.
+ File::Spec->catdir( $self->_safe_path( path => $to ) ,
+ $self->_safe_path( path =>
+ $mod->package_name .'-'.
+ $mod->package_version
+ ) ) ) ,
+ File::Spec->rel2abs( $ae->extract_path ),
+ ) {
+ ($dir = $try) && last if -d $try;
+ }
+
+ ### test if the dir exists ###
+ unless( $dir && -d $dir ) {
+ error(loc("Unable to determine extract dir for '%1'",$mod->module));
+ return;
+
+ } else {
+ msg(loc("Extracted '%1' to '%2'", $mod->module, $dir), $verbose);
+
+ ### register where we extracted the files to,
+ ### also store what files were extracted
+ $mod->status->extract( $dir );
+ $mod->status->files( $ae->files );
+ }
+
+ ### also, figure out what kind of install we're dealing with ###
+ $mod->get_installer_type();
+
+ return $mod->status->extract();
+}
+
+1;
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Fetch.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Fetch.pm
new file mode 100644
index 00000000000..395965bab60
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Fetch.pm
@@ -0,0 +1,473 @@
+package CPANPLUS::Internals::Fetch;
+
+use strict;
+
+use CPANPLUS::Error;
+use CPANPLUS::Internals::Constants;
+
+use File::Fetch;
+use File::Spec;
+use Cwd qw[cwd];
+use IPC::Cmd qw[run];
+use Params::Check qw[check];
+use Module::Load::Conditional qw[can_load];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+$Params::Check::VERBOSE = 1;
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Internals::Fetch
+
+=head1 SYNOPSIS
+
+ my $output = $cb->_fetch(
+ module => $modobj,
+ fetchdir => '/path/to/save/to',
+ verbose => BOOL,
+ force => BOOL,
+ );
+
+ $cb->_add_fail_host( host => 'foo.com' );
+ $cb->_host_ok( host => 'foo.com' );
+
+
+=head1 DESCRIPTION
+
+CPANPLUS::Internals::Fetch fetches files from either ftp, http, file
+or rsync mirrors.
+
+This is the rough flow:
+
+ $cb->_fetch
+ Delegate to File::Fetch;
+
+
+=head1 METHODS
+
+=cut
+
+=head1 $path = _fetch( module => $modobj, [fetchdir => '/path/to/save/to', fetch_from => 'scheme://path/to/fetch/from', verbose => BOOL, force => BOOL, prefer_bin => BOOL, ttl => $seconds] )
+
+C<_fetch> will fetch files based on the information in a module
+object. You always need a module object. If you want a fake module
+object for a one-off fetch, look at C<CPANPLUS::Module::Fake>.
+
+C<fetchdir> is the place to save the file to. Usually this
+information comes from your configuration, but you can override it
+expressly if needed.
+
+C<fetch_from> lets you specify an URI to get this file from. If you
+do not specify one, your list of configured hosts will be probed to
+download the file from.
+
+C<force> forces a new download, even if the file already exists.
+
+C<verbose> simply indicates whether or not to print extra messages.
+
+C<prefer_bin> indicates whether you prefer the use of commandline
+programs over perl modules. Defaults to your corresponding config
+setting.
+
+C<ttl> (in seconds) indicates how long a cached copy is valid for. If
+the fetch time of the local copy is within the ttl, the cached copy is
+returned. Otherwise, the file is refetched.
+
+C<_fetch> figures out, based on the host list, what scheme to use and
+from there, delegates to C<File::Fetch> do the actual fetching.
+
+Returns the path of the output file on success, false on failure.
+
+Note that you can set a C<blacklist> on certain methods in the config.
+Simply add the identifying name of the method (ie, C<lwp>) to:
+ $conf->_set_fetch( blacklist => ['lwp'] );
+
+And the C<LWP> function will be skipped by C<File::Fetch>.
+
+=cut
+
+sub _fetch {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ local $Params::Check::NO_DUPLICATES = 0;
+
+ my ($modobj, $verbose, $force, $fetch_from, $ttl);
+ my $tmpl = {
+ module => { required => 1, allow => IS_MODOBJ, store => \$modobj },
+ fetchdir => { default => $conf->get_conf('fetchdir') },
+ fetch_from => { default => '', store => \$fetch_from },
+ force => { default => $conf->get_conf('force'),
+ store => \$force },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ prefer_bin => { default => $conf->get_conf('prefer_bin') },
+ ttl => { default => 0, store => \$ttl },
+ };
+
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ ### check if we already downloaded the thing ###
+ if( (my $where = $modobj->status->fetch()) and not $force and not $ttl ) {
+
+ msg(loc("Already fetched '%1' to '%2', " .
+ "won't fetch again without force",
+ $modobj->module, $where ), $verbose );
+ return $where;
+ }
+
+ my ($remote_file, $local_file, $local_path);
+
+ ### build the local path to downlaod to ###
+ {
+ $local_path = $args->{fetchdir} ||
+ File::Spec->catdir(
+ $conf->get_conf('base'),
+ $modobj->path,
+ );
+
+ ### create the path if it doesn't exist ###
+ unless( -d $local_path ) {
+ unless( $self->_mkdir( dir => $local_path ) ) {
+ msg( loc("Could not create path '%1'", $local_path), $verbose);
+ return;
+ }
+ }
+
+ $local_file = File::Spec->rel2abs(
+ File::Spec->catfile(
+ $local_path,
+ $modobj->package,
+ )
+ );
+
+ ### do we already have the file? if so, can we use the cached version,
+ ### or do we need to refetch?
+ if( -e $local_file ) {
+
+ my $unlink = 0;
+ my $use_cached = 0;
+
+ ### if force is in effect, we have to refetch
+ if( $force ) {
+ $unlink++
+
+ ### if you provided a ttl, and it was exceeded, we'll refetch,
+ } elsif( $ttl and ([stat $local_file]->[9] + $ttl > time) ) {
+ msg(loc("Using cached file '%1' on disk; ".
+ "ttl (%2s) is not exceeded",
+ $local_file, $ttl), $verbose );
+
+ $use_cached++;
+
+ ### if you provided a ttl, and the above conditional didn't match,
+ ### we exceeded the ttl, so we refetch
+ } elsif ( $ttl ) {
+ $unlink++;
+
+ ### otherwise we can use the cached version
+ } else {
+ $use_cached++;
+ }
+
+ if( $unlink ) {
+ ### some fetches will fail if the files exist already, so let's
+ ### delete them first
+ 1 while unlink $local_file;
+
+ msg(loc("Could not delete %1, some methods may " .
+ "fail to force a download", $local_file), $verbose)
+ if -e $local_file;
+
+ } else {
+
+ ### store where we fetched it ###
+ $modobj->status->fetch( $local_file );
+
+ return $local_file;
+ }
+ }
+ }
+
+
+ ### we got a custom URI
+ if ( $fetch_from ) {
+ my $abs = $self->__file_fetch( from => $fetch_from,
+ to => $local_path,
+ verbose => $verbose );
+
+ unless( $abs ) {
+ error(loc("Unable to download '%1'", $fetch_from));
+ return;
+ }
+
+ ### store where we fetched it ###
+ $modobj->status->fetch( $abs );
+
+ return $abs;
+
+ ### we will get it from one of our mirrors
+ } else {
+ ### build the remote path to download from ###
+ { $remote_file = File::Spec::Unix->catfile(
+ $modobj->path,
+ $modobj->package,
+ );
+ unless( $remote_file ) {
+ error( loc('No remote file given for download') );
+ return;
+ }
+ }
+
+ ### see if we even have a host or a method to use to download with ###
+ my $found_host;
+ my @maybe_bad_host;
+
+ HOST: {
+ ### F*CKING PIECE OF F*CKING p4 SHIT makes
+ ### '$File :: Fetch::SOME_VAR'
+ ### into a meta variable and starts substituting the file name...
+ ### GRAAAAAAAAAAAAAAAAAAAAAAH!
+ ### use ' to combat it!
+
+ ### set up some flags for File::Fetch ###
+ local $File'Fetch::BLACKLIST = $conf->_get_fetch('blacklist');
+ local $File'Fetch::TIMEOUT = $conf->get_conf('timeout');
+ local $File'Fetch::DEBUG = $conf->get_conf('debug');
+ local $File'Fetch::FTP_PASSIVE = $conf->get_conf('passive');
+ local $File'Fetch::FROM_EMAIL = $conf->get_conf('email');
+ local $File'Fetch::PREFER_BIN = $conf->get_conf('prefer_bin');
+ local $File'Fetch::WARN = $verbose;
+
+
+ ### loop over all hosts we have ###
+ for my $host ( @{$conf->get_conf('hosts')} ) {
+ $found_host++;
+
+ my $where;
+
+ ### file:// uris are special and need parsing
+ if( $host->{'scheme'} eq 'file' ) {
+
+ ### the full path in the native format of the OS
+ my $host_spec =
+ File::Spec->file_name_is_absolute( $host->{'path'} )
+ ? $host->{'path'}
+ : File::Spec->rel2abs( $host->{'path'} );
+
+ ### there might be volumes involved on vms/win32
+ if( ON_WIN32 or ON_VMS ) {
+
+ ### now extract the volume in order to be Win32 and
+ ### VMS friendly.
+ ### 'no_file' indicates that there's no file part
+ ### of this path, so we only get 2 bits returned.
+ my ($vol, $host_path) = File::Spec->splitpath(
+ $host_spec, 'no_file'
+ );
+
+ ### and split up the directories
+ my @host_dirs = File::Spec->splitdir( $host_path );
+
+ ### if we got a volume we pretend its a directory for
+ ### the sake of the file:// url
+ if( defined $vol and $vol ) {
+
+ ### D:\foo\bar needs to be encoded as D|\foo\bar
+ ### For details, see the following link:
+ ### http://en.wikipedia.org/wiki/File://
+ ### The RFC doesnt seem to address Windows volume
+ ### descriptors but it does address VMS volume
+ ### descriptors, however wikipedia covers a bit of
+ ### history regarding win32
+ $vol =~ s/:$/|/ if ON_WIN32;
+
+ $vol =~ s/:// if ON_VMS;
+
+ ### XXX i'm not sure what cases this is addressing.
+ ### this comes straight from dmq's file:// patches
+ ### for win32. --kane
+ ### According to dmq, the best summary is:
+ ### "if file:// urls dont look right on VMS reuse
+ ### the win32 logic and see if that fixes things"
+
+ ### first element not empty? Might happen on VMS.
+ ### prepend the volume in that case.
+ if( $host_dirs[0] ) {
+ unshift @host_dirs, $vol;
+
+ ### element empty? reuse it to store the volume
+ ### encoded as a directory name. (Win32/VMS)
+ } else {
+ $host_dirs[0] = $vol;
+ }
+ }
+
+ ### now it's in UNIX format, which is the same format
+ ### as used for URIs
+ $host_spec = File::Spec::Unix->catdir( @host_dirs );
+ }
+
+ ### now create the file:// uri from the components
+ $where = CREATE_FILE_URI->(
+ File::Spec::Unix->catfile(
+ $host->{'host'} || '',
+ $host_spec,
+ $remote_file,
+ )
+ );
+
+ ### its components will be in unix format, for a http://,
+ ### ftp:// or any other style of URI
+ } else {
+ my $mirror_path = File::Spec::Unix->catfile(
+ $host->{'path'}, $remote_file
+ );
+
+ my %args = ( scheme => $host->{scheme},
+ host => $host->{host},
+ path => $mirror_path,
+ );
+
+ $where = $self->_host_to_uri( %args );
+ }
+
+ my $abs = $self->__file_fetch( from => $where,
+ to => $local_path,
+ verbose => $verbose );
+
+ ### we got a path back?
+ if( $abs ) {
+ ### store where we fetched it ###
+ $modobj->status->fetch( $abs );
+
+ ### this host is good, the previous ones are apparently
+ ### not, so mark them as such.
+ $self->_add_fail_host( host => $_ ) for @maybe_bad_host;
+
+ return $abs;
+ }
+
+ ### so we tried to get the file but didn't actually fetch it --
+ ### there's a chance this host is bad. mark it as such and
+ ### actually flag it back if we manage to get the file
+ ### somewhere else
+ push @maybe_bad_host, $host;
+ }
+ }
+
+ $found_host
+ ? error(loc("Fetch failed: host list exhausted " .
+ "-- are you connected today?"))
+ : error(loc("No hosts found to download from " .
+ "-- check your config"));
+ }
+
+ return;
+}
+
+sub __file_fetch {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my ($where, $local_path, $verbose);
+ my $tmpl = {
+ from => { required => 1, store => \$where },
+ to => { required => 1, store => \$local_path },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ msg(loc("Trying to get '%1'", $where ), $verbose );
+
+ ### build the object ###
+ my $ff = File::Fetch->new( uri => $where );
+
+ ### sanity check ###
+ error(loc("Bad uri '%1'",$where)), return unless $ff;
+
+ if( my $file = $ff->fetch( to => $local_path ) ) {
+ unless( -e $file && -s _ ) {
+ msg(loc("'%1' said it fetched '%2', but it was not created",
+ 'File::Fetch', $file), $verbose);
+
+ } else {
+ my $abs = File::Spec->rel2abs( $file );
+
+ ### so TTLs will work
+ $self->_update_timestamp( file => $abs );
+
+ return $abs;
+ }
+
+ } else {
+ error(loc("Fetching of '%1' failed: %2", $where, $ff->error));
+ }
+
+ return;
+}
+
+=pod
+
+=head2 _add_fail_host( host => $host_hashref )
+
+Mark a particular host as bad. This makes C<CPANPLUS::Internals::Fetch>
+skip it in fetches until this cache is flushed.
+
+=head2 _host_ok( host => $host_hashref )
+
+Query the cache to see if this host is ok, or if it has been flagged
+as bad.
+
+Returns true if the host is ok, false otherwise.
+
+=cut
+
+{ ### caching functions ###
+
+ sub _add_fail_host {
+ my $self = shift;
+ my %hash = @_;
+
+ my $host;
+ my $tmpl = {
+ host => { required => 1, default => {},
+ strict_type => 1, store => \$host },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ return $self->_hosts->{$host} = 1;
+ }
+
+ sub _host_ok {
+ my $self = shift;
+ my %hash = @_;
+
+ my $host;
+ my $tmpl = {
+ host => { required => 1, store => \$host },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ return $self->_hosts->{$host} ? 0 : 1;
+ }
+}
+
+
+1;
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Report.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Report.pm
new file mode 100644
index 00000000000..774c6b91a02
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Report.pm
@@ -0,0 +1,645 @@
+package CPANPLUS::Internals::Report;
+
+use strict;
+
+use CPANPLUS::Error;
+use CPANPLUS::Internals::Constants;
+use CPANPLUS::Internals::Constants::Report;
+
+use Data::Dumper;
+
+use Params::Check qw[check];
+use Module::Load::Conditional qw[can_load];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+$Params::Check::VERBOSE = 1;
+
+### for the version ###
+require CPANPLUS::Internals;
+
+=head1 NAME
+
+CPANPLUS::Internals::Report
+
+=head1 SYNOPSIS
+
+ ### enable test reporting
+ $cb->configure_object->set_conf( cpantest => 1 );
+
+ ### set custom mx host, shouldn't normally be needed
+ $cb->configure_object->set_conf( cpantest_mx => 'smtp.example.com' );
+
+=head1 DESCRIPTION
+
+This module provides all the functionality to send test reports to
+C<http://testers.cpan.org> using the C<Test::Reporter> module.
+
+All methods will be called automatically if you have C<CPANPLUS>
+configured to enable test reporting (see the C<SYNOPSIS>).
+
+=head1 METHODS
+
+=head2 $bool = $cb->_have_query_report_modules
+
+This function checks if all the required modules are here for querying
+reports. It returns true and loads them if they are, or returns false
+otherwise.
+
+=head2 $bool = $cb->_have_send_report_modules
+
+This function checks if all the required modules are here for sending
+reports. It returns true and loads them if they are, or returns false
+otherwise.
+
+=cut
+
+### XXX remove this list and move it into selfupdate, somehow..
+### this is dual administration
+{ my $query_list = {
+ 'File::Fetch' => '0.13_02',
+ 'Parse::CPAN::Meta' => '0.0',
+ 'File::Temp' => '0.0',
+ };
+
+ my $send_list = {
+ %$query_list,
+ 'Test::Reporter' => '1.34',
+ };
+
+ sub _have_query_report_modules {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my $tmpl = {
+ verbose => { default => $conf->get_conf('verbose') },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ return can_load( modules => $query_list, verbose => $args->{verbose} )
+ ? 1
+ : 0;
+ }
+
+ sub _have_send_report_modules {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my $tmpl = {
+ verbose => { default => $conf->get_conf('verbose') },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ return can_load( modules => $send_list, verbose => $args->{verbose} )
+ ? 1
+ : 0;
+ }
+}
+
+=head2 @list = $cb->_query_report( module => $modobj, [all_versions => BOOL, verbose => BOOL] )
+
+This function queries the CPAN testers database at
+I<http://testers.cpan.org/> for test results of specified module objects,
+module names or distributions.
+
+The optional argument C<all_versions> controls whether all versions of
+a given distribution should be grabbed. It defaults to false
+(fetching only reports for the current version).
+
+Returns the a list with the following data structures (for CPANPLUS
+version 0.042) on success, or false on failure. The contents of the
+data structure depends on what I<http://testers.cpan.org> returns,
+but generally looks like this:
+
+ {
+ 'grade' => 'PASS',
+ 'dist' => 'CPANPLUS-0.042',
+ 'platform' => 'i686-pld-linux-thread-multi'
+ 'details' => 'http://nntp.x.perl.org/group/perl.cpan.testers/98316'
+ ...
+ },
+ {
+ 'grade' => 'PASS',
+ 'dist' => 'CPANPLUS-0.042',
+ 'platform' => 'i686-linux-thread-multi'
+ 'details' => 'http://nntp.x.perl.org/group/perl.cpan.testers/99416'
+ ...
+ },
+ {
+ 'grade' => 'FAIL',
+ 'dist' => 'CPANPLUS-0.042',
+ 'platform' => 'cygwin-multi-64int',
+ 'details' => 'http://nntp.x.perl.org/group/perl.cpan.testers/99371'
+ ...
+ },
+ {
+ 'grade' => 'FAIL',
+ 'dist' => 'CPANPLUS-0.042',
+ 'platform' => 'i586-linux',
+ 'details' => 'http://nntp.x.perl.org/group/perl.cpan.testers/99396'
+ ...
+ },
+
+The status of the test can be one of the following:
+UNKNOWN, PASS, FAIL or NA (not applicable).
+
+=cut
+
+sub _query_report {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my($mod, $verbose, $all);
+ my $tmpl = {
+ module => { required => 1, allow => IS_MODOBJ,
+ store => \$mod },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ all_versions => { default => 0, store => \$all },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### check if we have the modules we need for querying
+ return unless $self->_have_query_report_modules( verbose => 1 );
+
+
+ ### XXX no longer use LWP here. However, that means we don't
+ ### automagically set proxies anymore!!!
+ # my $ua = LWP::UserAgent->new;
+ # $ua->agent( CPANPLUS_UA->() );
+ #
+ ### set proxies if we have them ###
+ # $ua->env_proxy();
+
+ my $url = TESTERS_URL->($mod->package_name);
+ my $ff = File::Fetch->new( uri => $url );
+
+ msg( loc("Fetching: '%1'", $url), $verbose );
+
+ my $res = do {
+ my $tempdir = File::Temp::tempdir();
+ my $where = $ff->fetch( to => $tempdir );
+
+ unless( $where ) {
+ error( loc( "Fetching report for '%1' failed: %2",
+ $url, $ff->error ) );
+ return;
+ }
+
+ my $fh = OPEN_FILE->( $where );
+
+ do { local $/; <$fh> };
+ };
+
+ my ($aref) = eval { Parse::CPAN::Meta::Load( $res ) };
+
+ if( $@ ) {
+ error(loc("Error reading result: %1", $@));
+ return;
+ };
+
+ my $dist = $mod->package_name .'-'. $mod->package_version;
+ my $details = TESTERS_DETAILS_URL->($mod->package_name);
+
+ my @rv;
+ for my $href ( @$aref ) {
+ next unless $all or defined $href->{'distversion'} &&
+ $href->{'distversion'} eq $dist;
+
+ $href->{'details'} = $details;
+
+ ### backwards compatibility :(
+ $href->{'dist'} ||= $href->{'distversion'};
+ $href->{'grade'} ||= $href->{'action'} || $href->{'status'};
+
+ push @rv, $href;
+ }
+
+ return @rv if @rv;
+ return;
+}
+
+=pod
+
+=head2 $bool = $cb->_send_report( module => $modobj, buffer => $make_output, failed => BOOL, [save => BOOL, address => $email_to, verbose => BOOL, force => BOOL]);
+
+This function sends a testers report to C<cpan-testers@perl.org> for a
+particular distribution.
+It returns true on success, and false on failure.
+
+It takes the following options:
+
+=over 4
+
+=item module
+
+The module object of this particular distribution
+
+=item buffer
+
+The output buffer from the 'make/make test' process
+
+=item failed
+
+Boolean indicating if the 'make/make test' went wrong
+
+=item save
+
+Boolean indicating if the report should be saved locally instead of
+mailed out. If provided, this function will return the location the
+report was saved to, rather than a simple boolean 'TRUE'.
+
+Defaults to false.
+
+=item address
+
+The email address to mail the report for. You should never need to
+override this, but it might be useful for debugging purposes.
+
+Defaults to C<cpan-testers@perl.org>.
+
+=item verbose
+
+Boolean indicating on whether or not to be verbose.
+
+Defaults to your configuration settings
+
+=item force
+
+Boolean indicating whether to force the sending, even if the max
+amount of reports for fails have already been reached, or if you
+may already have sent it before.
+
+Defaults to your configuration settings
+
+=back
+
+=cut
+
+sub _send_report {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ ### do you even /have/ test::reporter? ###
+ unless( $self->_have_send_report_modules(verbose => 1) ) {
+ error( loc( "You don't have '%1' (or modules required by '%2') ".
+ "installed, you cannot report test results.",
+ 'Test::Reporter', 'Test::Reporter' ) );
+ return;
+ }
+
+ ### check arguments ###
+ my ($buffer, $failed, $mod, $verbose, $force, $address, $save,
+ $tests_skipped );
+ my $tmpl = {
+ module => { required => 1, store => \$mod, allow => IS_MODOBJ },
+ buffer => { required => 1, store => \$buffer },
+ failed => { required => 1, store => \$failed },
+ address => { default => CPAN_TESTERS_EMAIL, store => \$address },
+ save => { default => 0, store => \$save },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ force => { default => $conf->get_conf('force'),
+ store => \$force },
+ tests_skipped
+ => { default => 0, store => \$tests_skipped },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### get the data to fill the email with ###
+ my $name = $mod->module;
+ my $dist = $mod->package_name . '-' . $mod->package_version;
+ my $author = $mod->author->author;
+ my $email = $mod->author->email || CPAN_MAIL_ACCOUNT->( $author );
+ my $cp_conf = $conf->get_conf('cpantest') || '';
+ my $int_ver = $CPANPLUS::Internals::VERSION;
+ my $cb = $mod->parent;
+
+
+ ### will be 'fetch', 'make', 'test', 'install', etc ###
+ my $stage = TEST_FAIL_STAGE->($buffer);
+
+ ### determine the grade now ###
+
+ my $grade;
+ ### check if this is a platform specific module ###
+ ### if we failed the test, there may be reasons why
+ ### an 'NA' might have to be insted
+ GRADE: { if ( $failed ) {
+
+
+ ### XXX duplicated logic between this block
+ ### and REPORTED_LOADED_PREREQS :(
+
+ ### figure out if the prereqs are on CPAN at all
+ ### -- if not, send NA grade
+ ### Also, if our version of prereqs is too low,
+ ### -- send NA grade.
+ ### This is to address bug: #25327: do not count
+ ### as FAIL modules where prereqs are not filled
+ { my $prq = $mod->status->prereqs || {};
+
+ while( my($prq_name,$prq_ver) = each %$prq ) {
+ my $obj = $cb->module_tree( $prq_name );
+ my $sub = CPANPLUS::Module->can(
+ 'module_is_supplied_with_perl_core' );
+
+ ### if we can't find the module and it's not supplied with core.
+ ### this addresses: #32064: NA reports generated for failing
+ ### tests where core prereqs are specified
+ ### Note that due to a bug in Module::CoreList, in some released
+ ### version of perl (5.8.6+ and 5.9.2-4 at the time of writing)
+ ### 'Config' is not recognized as a core module. See this bug:
+ ### http://rt.cpan.org/Ticket/Display.html?id=32155
+ if( !$obj and !$sub->( $prq_name ) ) {
+ msg(loc( "Prerequisite '%1' for '%2' could not be obtained".
+ " from CPAN -- sending N/A grade",
+ $prq_name, $name ), $verbose );
+
+ $grade = GRADE_NA;
+ last GRADE;
+ }
+
+ if ( !$obj ) {
+ my $vcore = $sub->( $prq_name );
+ if ( $cb->_vcmp( $prq_ver, $vcore ) > 0 ) {
+ msg(loc( "Version of core module '%1' ('%2') is too low for ".
+ "'%3' (needs '%4') -- sending N/A grade",
+ $prq_name, $vcore,
+ $name, $prq_ver ), $verbose );
+
+ $grade = GRADE_NA;
+ last GRADE;
+ }
+ }
+
+ if( $obj and $cb->_vcmp( $prq_ver, $obj->installed_version ) > 0 ) {
+ msg(loc( "Installed version of '%1' ('%2') is too low for ".
+ "'%3' (needs '%4') -- sending N/A grade",
+ $prq_name, $obj->installed_version,
+ $name, $prq_ver ), $verbose );
+
+ $grade = GRADE_NA;
+ last GRADE;
+ }
+ }
+ }
+
+ unless( RELEVANT_TEST_RESULT->($mod) ) {
+ msg(loc(
+ "'%1' is a platform specific module, and the test results on".
+ " your platform are not relevant --sending N/A grade.",
+ $name), $verbose);
+
+ $grade = GRADE_NA;
+
+ } elsif ( UNSUPPORTED_OS->( $buffer ) ) {
+ msg(loc(
+ "'%1' is a platform specific module, and the test results on".
+ " your platform are not relevant --sending N/A grade.",
+ $name), $verbose);
+
+ $grade = GRADE_NA;
+
+ ### you dont have a high enough perl version?
+ } elsif ( PERL_VERSION_TOO_LOW->( $buffer ) ) {
+ msg(loc("'%1' requires a higher version of perl than your current ".
+ "version -- sending N/A grade.", $name), $verbose);
+
+ $grade = GRADE_NA;
+
+ ### perhaps where were no tests...
+ ### see if the thing even had tests ###
+ } elsif ( NO_TESTS_DEFINED->( $buffer ) ) {
+ $grade = GRADE_UNKNOWN;
+ ### failures in PL or make/build stage are now considered UNKNOWN
+ } elsif ( $stage !~ /\btest\b/ ) {
+
+ $grade = GRADE_UNKNOWN
+
+ } else {
+
+ $grade = GRADE_FAIL;
+ }
+
+ ### if we got here, it didn't fail and tests were present.. so a PASS
+ ### is in order
+ } else {
+ $grade = GRADE_PASS;
+ } }
+
+ ### so an error occurred, let's see what stage it went wrong in ###
+
+ ### the header -- always include so the CPANPLUS version is apparent
+ my $message = REPORT_MESSAGE_HEADER->( $int_ver, $author );
+
+ if( $grade eq GRADE_FAIL or $grade eq GRADE_UNKNOWN) {
+
+ ### return if one or more missing external libraries
+ if( my @missing = MISSING_EXTLIBS_LIST->($buffer) ) {
+ msg(loc("Not sending test report - " .
+ "external libraries not pre-installed"));
+ return 1;
+ }
+
+ ### return if we're only supposed to report make_test failures ###
+ return 1 if $cp_conf =~ /\bmaketest_only\b/i
+ and ($stage !~ /\btest\b/);
+
+ ### the bit where we inform what went wrong
+ $message .= REPORT_MESSAGE_FAIL_HEADER->( $stage, $buffer );
+
+ ### was it missing prereqs? ###
+ if( my @missing = MISSING_PREREQS_LIST->($buffer) ) {
+ if(!$self->_verify_missing_prereqs(
+ module => $mod,
+ missing => \@missing
+ )) {
+ msg(loc("Not sending test report - " .
+ "bogus missing prerequisites report"));
+ return 1;
+ }
+ $message .= REPORT_MISSING_PREREQS->($author,$email,@missing);
+ }
+
+ ### was it missing test files? ###
+ if( NO_TESTS_DEFINED->($buffer) ) {
+ $message .= REPORT_MISSING_TESTS->();
+ }
+
+ ### add a list of what modules have been loaded of your prereqs list
+ $message .= REPORT_LOADED_PREREQS->($mod);
+
+ ### add a list of versions of toolchain modules
+ $message .= REPORT_TOOLCHAIN_VERSIONS->($mod);
+
+ ### the footer
+ $message .= REPORT_MESSAGE_FOOTER->();
+
+ ### it may be another grade than fail/unknown.. may be worth noting
+ ### that tests got skipped, since the buffer is not added in
+ } elsif ( $tests_skipped ) {
+ $message .= REPORT_TESTS_SKIPPED->();
+ } elsif( $grade eq GRADE_NA) {
+
+ ### the bit where we inform what went wrong
+ $message .= REPORT_MESSAGE_FAIL_HEADER->( $stage, $buffer );
+
+ ### the footer
+ $message .= REPORT_MESSAGE_FOOTER->();
+
+ }
+
+ msg( loc("Sending test report for '%1'", $dist), $verbose);
+
+ ### reporter object ###
+ my $reporter = do {
+ my $args = $conf->get_conf('cpantest_reporter_args') || {};
+
+ unless( UNIVERSAL::isa( $args, 'HASH' ) ) {
+ error(loc("'%1' must be a hashref, ignoring...",
+ 'cpantest_reporter_args'));
+ $args = {};
+ }
+
+ Test::Reporter->new(
+ grade => $grade,
+ distribution => $dist,
+ via => "CPANPLUS $int_ver",
+ timeout => $conf->get_conf('timeout') || 60,
+ debug => $conf->get_conf('debug'),
+ %$args,
+ );
+ };
+
+ ### set a custom mx, if requested
+ $reporter->mx( [ $conf->get_conf('cpantest_mx') ] )
+ if $conf->get_conf('cpantest_mx');
+
+ ### set the from address ###
+ $reporter->from( $conf->get_conf('email') )
+ if $conf->get_conf('email') !~ /\@example\.\w+$/i;
+
+ ### give the user a chance to programattically alter the message
+ $message = $self->_callbacks->munge_test_report->($mod, $message, $grade);
+
+ ### add the body if we have any ###
+ $reporter->comments( $message ) if defined $message && length $message;
+
+ ### do a callback to ask if we should send the report
+ unless ($self->_callbacks->send_test_report->($mod, $grade)) {
+ msg(loc("Ok, not sending test report"));
+ return 1;
+ }
+
+ ### do a callback to ask if we should edit the report
+ if ($self->_callbacks->edit_test_report->($mod, $grade)) {
+ ### test::reporter 1.20 and lower don't have a way to set
+ ### the preferred editor with a method call, but it does
+ ### respect your env variable, so let's set that.
+ local $ENV{VISUAL} = $conf->get_program('editor')
+ if $conf->get_program('editor');
+
+ $reporter->edit_comments;
+ }
+
+ ### allow to be overridden, but default to the normal address ###
+ $reporter->address( $address );
+
+ ### should we save it locally? ###
+ if( $save ) {
+ if( my $file = $reporter->write() ) {
+ msg(loc("Successfully wrote report for '%1' to '%2'",
+ $dist, $file), $verbose);
+ return $file;
+
+ } else {
+ error(loc("Failed to write report for '%1'", $dist));
+ return;
+ }
+
+ ### XXX should we do an 'already sent' check? ###
+ ### something broke :( ###
+ }
+ else {
+ my $status;
+ eval {
+ $status = $reporter->send();
+ };
+ if ( $@ ) {
+ error(loc("Could not send '%1' report for '%2': %3",
+ $grade, $dist, $@));
+ return;
+ }
+ if ( $status ) {
+ msg(loc("Successfully sent '%1' report for '%2'", $grade, $dist),
+ $verbose);
+ return 1;
+ }
+ error(loc("Could not send '%1' report for '%2': %3",
+ $grade, $dist, $reporter->errstr));
+ return;
+ }
+}
+
+sub _verify_missing_prereqs {
+ my $self = shift;
+ my %hash = @_;
+
+ ### check arguments ###
+ my ($mod, $missing);
+ my $tmpl = {
+ module => { required => 1, store => \$mod },
+ missing => { required => 1, store => \$missing },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+
+ my %missing = map {$_ => 1} @$missing;
+ my $conf = $self->configure_object;
+ my $extract = $mod->status->extract;
+
+ ### Read pre-requisites from Makefile.PL or Build.PL (if there is one),
+ ### of the form:
+ ### 'PREREQ_PM' => {
+ ### 'Compress::Zlib' => '1.20',
+ ### 'Test::More' => 0,
+ ### },
+ ### Build.PL uses 'requires' instead of 'PREREQ_PM'.
+
+ my @search;
+ push @search, ($extract ? MAKEFILE_PL->( $extract ) : MAKEFILE_PL->());
+ push @search, ($extract ? BUILD_PL->( $extract ) : BUILD_PL->());
+
+ for my $file ( @search ) {
+ if(-e $file and -r $file) {
+ my $slurp = $self->_get_file_contents(file => $file);
+ my ($prereq) =
+ ($slurp =~ /'?(?:PREREQ_PM|requires)'?\s*=>\s*{(.*?)}/s);
+ my @prereq =
+ ($prereq =~ /'?([\w\:]+)'?\s*=>\s*'?\d[\d\.\-\_]*'?/sg);
+ delete $missing{$_} for(@prereq);
+ }
+ }
+
+ return 1 if(keys %missing); # There ARE missing prerequisites
+ return; # All prerequisites accounted for
+}
+
+1;
+
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Search.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Search.pm
new file mode 100644
index 00000000000..63c4da64d92
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Search.pm
@@ -0,0 +1,363 @@
+package CPANPLUS::Internals::Search;
+
+use strict;
+
+use CPANPLUS::Error;
+use CPANPLUS::Internals::Constants;
+use CPANPLUS::Module;
+use CPANPLUS::Module::Author;
+
+use File::Find;
+use File::Spec;
+
+use Params::Check qw[check allow];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+$Params::Check::VERBOSE = 1;
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Internals::Search
+
+=head1 SYNOPSIS
+
+ my $aref = $cpan->_search_module_tree(
+ type => 'package',
+ allow => [qr/DBI/],
+ );
+
+ my $aref = $cpan->_search_author_tree(
+ type => 'cpanid',
+ data => \@old_results,
+ verbose => 1,
+ allow => [qw|KANE AUTRIJUS|],
+ );
+
+ my $aref = $cpan->_all_installed( );
+
+=head1 DESCRIPTION
+
+The functions in this module are designed to find module(objects)
+based on certain criteria and return them.
+
+=head1 METHODS
+
+=head2 _search_module_tree( type => TYPE, allow => \@regexes, [data => \@previous_results ] )
+
+Searches the moduletree for module objects matching the criteria you
+specify. Returns an array ref of module objects on success, and false
+on failure.
+
+It takes the following arguments:
+
+=over 4
+
+=item type
+
+This can be any of the accessors for the C<CPANPLUS::Module> objects.
+This is a required argument.
+
+=item allow
+
+A set of rules, or more precisely, a list of regexes (via C<qr//> or
+plain strings), that the C<type> must adhere too. You can specify as
+many as you like, and it will be treated as an C<OR> search.
+For an C<AND> search, see the C<data> argument.
+
+This is a required argument.
+
+=item data
+
+An arrayref of previous search results. This is the way to do an C<AND>
+search -- C<_search_module_tree> will only search the module objects
+specified in C<data> if provided, rather than the moduletree itself.
+
+=back
+
+=cut
+
+# Although the Params::Check solution is more graceful, it is WAY too slow.
+#
+# This sample script:
+#
+# use CPANPLUS::Backend;
+# my $cb = new CPANPLUS::Backend;
+# $cb->module_tree;
+# my @list = $cb->search( type => 'module', allow => [qr/^Acme/] );
+# print $_->module, $/ for @list;
+#
+# Produced the following output using Dprof WITH params::check code
+#
+# Total Elapsed Time = 3.670024 Seconds
+# User+System Time = 3.390373 Seconds
+# Exclusive Times
+# %Time ExclSec CumulS #Calls sec/call Csec/c Name
+# 88.7 3.008 4.463 20610 0.0001 0.0002 Params::Check::check
+# 47.4 1.610 1.610 1 1.6100 1.6100 Storable::net_pstore
+# 25.6 0.869 0.737 20491 0.0000 0.0000 Locale::Maketext::Simple::_default
+# _gettext
+# 23.2 0.789 0.524 40976 0.0000 0.0000 Params::Check::_who_was_it
+# 23.2 0.789 0.677 20610 0.0000 0.0000 Params::Check::_sanity_check
+# 19.7 0.670 0.670 1 0.6700 0.6700 Storable::pretrieve
+# 14.1 0.480 0.211 41350 0.0000 0.0000 Params::Check::_convert_case
+# 11.5 0.390 0.256 20610 0.0000 0.0000 Params::Check::_hashdefs
+# 11.5 0.390 0.255 20697 0.0000 0.0000 Params::Check::_listreqs
+# 11.4 0.389 0.177 20653 0.0000 0.0000 Params::Check::_canon_key
+# 10.9 0.370 0.356 20697 0.0000 0.0000 Params::Check::_hasreq
+# 8.02 0.272 4.750 1 0.2723 4.7501 CPANPLUS::Internals::Search::_sear
+# ch_module_tree
+# 6.49 0.220 0.086 20653 0.0000 0.0000 Params::Check::_iskey
+# 6.19 0.210 0.077 20488 0.0000 0.0000 Params::Check::_store_error
+# 5.01 0.170 0.036 20680 0.0000 0.0000 CPANPLUS::Module::__ANON__
+#
+# and this output /without/
+#
+# Total Elapsed Time = 2.803426 Seconds
+# User+System Time = 2.493426 Seconds
+# Exclusive Times
+# %Time ExclSec CumulS #Calls sec/call Csec/c Name
+# 56.9 1.420 1.420 1 1.4200 1.4200 Storable::net_pstore
+# 25.6 0.640 0.640 1 0.6400 0.6400 Storable::pretrieve
+# 9.22 0.230 0.096 20680 0.0000 0.0000 CPANPLUS::Module::__ANON__
+# 7.06 0.176 0.272 1 0.1762 0.2719 CPANPLUS::Internals::Search::_sear
+# ch_module_tree
+# 3.21 0.080 0.098 10 0.0080 0.0098 IPC::Cmd::BEGIN
+# 1.60 0.040 0.205 13 0.0031 0.0158 CPANPLUS::Internals::BEGIN
+# 1.20 0.030 0.030 29 0.0010 0.0010 vars::BEGIN
+# 1.20 0.030 0.117 10 0.0030 0.0117 Log::Message::BEGIN
+# 1.20 0.030 0.029 9 0.0033 0.0033 CPANPLUS::Internals::Search::BEGIN
+# 0.80 0.020 0.020 5 0.0040 0.0040 DynaLoader::dl_load_file
+# 0.80 0.020 0.127 10 0.0020 0.0127 CPANPLUS::Module::BEGIN
+# 0.80 0.020 0.389 2 0.0099 0.1944 main::BEGIN
+# 0.80 0.020 0.359 12 0.0017 0.0299 CPANPLUS::Backend::BEGIN
+# 0.40 0.010 0.010 30 0.0003 0.0003 Config::FETCH
+# 0.40 0.010 0.010 18 0.0006 0.0005 Locale::Maketext::Simple::load_loc
+#
+
+sub _search_module_tree {
+
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my($mods,$list,$verbose,$type);
+ my $tmpl = {
+ data => { default => [],
+ strict_type=> 1, store => \$mods },
+ allow => { required => 1, default => [ ], strict_type => 1,
+ store => \$list },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ type => { required => 1, allow => [CPANPLUS::Module->accessors()],
+ store => \$type },
+ };
+
+ my $args = do {
+ ### don't check the template for sanity
+ ### -- we know it's good and saves a lot of performance
+ local $Params::Check::SANITY_CHECK_TEMPLATE = 0;
+
+ check( $tmpl, \%hash );
+ } or return;
+
+ ### a list of module objects was supplied
+ if( @$mods ) {
+ local $Params::Check::VERBOSE = 0;
+
+ my @rv;
+ for my $mod (@$mods) {
+ #push @rv, $mod if check(
+ # { $type => { allow => $list } },
+ # { $type => $mod->$type() }
+ # );
+ push @rv, $mod if allow( $mod->$type() => $list );
+
+ }
+ return \@rv;
+
+ } else {
+ my @rv = $self->_source_search_module_tree(
+ allow => $list,
+ type => $type,
+ );
+ return \@rv;
+ }
+}
+
+=pod
+
+=head2 _search_author_tree( type => TYPE, allow => \@regexex, [data => \@previous_results ] )
+
+Searches the authortree for author objects matching the criteria you
+specify. Returns an array ref of author objects on success, and false
+on failure.
+
+It takes the following arguments:
+
+=over 4
+
+=item type
+
+This can be any of the accessors for the C<CPANPLUS::Module::Author>
+objects. This is a required argument.
+
+=item allow
+
+
+A set of rules, or more precisely, a list of regexes (via C<qr//> or
+plain strings), that the C<type> must adhere too. You can specify as
+many as you like, and it will be treated as an C<OR> search.
+For an C<AND> search, see the C<data> argument.
+
+This is a required argument.
+
+=item data
+
+An arrayref of previous search results. This is the way to do an C<and>
+search -- C<_search_author_tree> will only search the author objects
+specified in C<data> if provided, rather than the authortree itself.
+
+=back
+
+=cut
+
+sub _search_author_tree {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my($authors,$list,$verbose,$type);
+ my $tmpl = {
+ data => { default => [],
+ strict_type=> 1, store => \$authors },
+ allow => { required => 1, default => [ ], strict_type => 1,
+ store => \$list },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ type => { required => 1, allow => [CPANPLUS::Module::Author->accessors()],
+ store => \$type },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ if( @$authors ) {
+ local $Params::Check::VERBOSE = 0;
+
+ my @rv;
+ for my $auth (@$authors) {
+ #push @rv, $auth if check(
+ # { $type => { allow => $list } },
+ # { $type => $auth->$type }
+ # );
+ push @rv, $auth if allow( $auth->$type() => $list );
+ }
+ return \@rv;
+ } else {
+ my @rv = $self->_source_search_author_tree(
+ allow => $list,
+ type => $type,
+ );
+ return \@rv;
+ }
+}
+
+=pod
+
+=head2 _all_installed()
+
+This function returns an array ref of module objects of modules that
+are installed on this system.
+
+=cut
+
+sub _all_installed {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ ### File::Find uses follow_skip => 1 by default, which doesn't die
+ ### on duplicates, unless they are directories or symlinks.
+ ### Ticket #29796 shows this code dying on Alien::WxWidgets,
+ ### which uses symlinks.
+ ### File::Find doc says to use follow_skip => 2 to ignore duplicates
+ ### so this will stop it from dying.
+ my %find_args = ( follow_skip => 2 );
+
+ ### File::Find uses lstat, which quietly becomes stat on win32
+ ### it then uses -l _ which is not allowed by the statbuffer because
+ ### you did a stat, not an lstat (duh!). so don't tell win32 to
+ ### follow symlinks, as that will break badly
+ $find_args{'follow_fast'} = 1 unless ON_WIN32;
+
+ ### never use the @INC hooks to find installed versions of
+ ### modules -- they're just there in case they're not on the
+ ### perl install, but the user shouldn't trust them for *other*
+ ### modules!
+ ### XXX CPANPLUS::inc is now obsolete, remove the calls
+ #local @INC = CPANPLUS::inc->original_inc;
+
+ my %seen; my @rv;
+ for my $dir (@INC ) {
+ next if $dir eq '.';
+
+ ### not a directory after all
+ ### may be coderef or some such
+ next unless -d $dir;
+
+ ### make sure to clean up the directories just in case,
+ ### as we're making assumptions about the length
+ ### This solves rt.cpan issue #19738
+
+ ### John M. notes: On VMS cannonpath can not currently handle
+ ### the $dir values that are in UNIX format.
+ $dir = File::Spec->canonpath( $dir ) unless ON_VMS;
+
+ ### have to use F::S::Unix on VMS, or things will break
+ my $file_spec = ON_VMS ? 'File::Spec::Unix' : 'File::Spec';
+
+ ### XXX in some cases File::Find can actually die!
+ ### so be safe and wrap it in an eval.
+ eval { File::Find::find(
+ { %find_args,
+ wanted => sub {
+
+ return unless /\.pm$/i;
+ my $mod = $File::Find::name;
+
+ ### make sure it's in Unix format, as it
+ ### may be in VMS format on VMS;
+ $mod = VMS::Filespec::unixify( $mod ) if ON_VMS;
+
+ $mod = substr($mod, length($dir) + 1, -3);
+ $mod = join '::', $file_spec->splitdir($mod);
+
+ return if $seen{$mod}++;
+
+ my $modobj = $self->module_tree($mod);
+
+ ### seperate return, a list context return with one ''
+ ### in it, is also true!
+ return unless $modobj;
+
+ push @rv, $modobj;
+ },
+ }, $dir
+ ) };
+
+ ### report the error if file::find died
+ error(loc("Error finding installed files in '%1': %2", $dir, $@)) if $@;
+ }
+
+ return \@rv;
+}
+
+1;
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Source.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Source.pm
new file mode 100644
index 00000000000..54e9d710cfd
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Source.pm
@@ -0,0 +1,1417 @@
+package CPANPLUS::Internals::Source;
+
+use strict;
+
+use CPANPLUS::Error;
+use CPANPLUS::Module;
+use CPANPLUS::Module::Fake;
+use CPANPLUS::Module::Author;
+use CPANPLUS::Internals::Constants;
+
+use File::Fetch;
+use Archive::Extract;
+
+use IPC::Cmd qw[can_run];
+use File::Temp qw[tempdir];
+use File::Basename qw[dirname];
+use Params::Check qw[check];
+use Module::Load::Conditional qw[can_load];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+$Params::Check::VERBOSE = 1;
+
+### list of methods the parent class must implement
+{ for my $sub ( qw[_init_trees _finalize_trees
+ _standard_trees_completed _custom_trees_completed
+ _add_module_object _add_author_object _save_state
+ ]
+ ) {
+ no strict 'refs';
+ *$sub = sub {
+ my $self = shift;
+ my $class = ref $self || $self;
+
+ require Carp;
+ Carp::croak( loc( "Class %1 must implement method '%2'",
+ $class, $sub ) );
+ }
+ }
+}
+
+{
+ my $recurse; # flag to prevent recursive calls to *_tree functions
+
+ ### lazy loading of module tree
+ sub _module_tree {
+ my $self = $_[0];
+
+ unless ($self->_mtree or $recurse++ > 0) {
+ my $uptodate = $self->_check_trees( @_[1..$#_] );
+ $self->_build_trees(uptodate => $uptodate);
+ }
+
+ $recurse--;
+ return $self->_mtree;
+ }
+
+ ### lazy loading of author tree
+ sub _author_tree {
+ my $self = $_[0];
+
+ unless ($self->_atree or $recurse++ > 0) {
+ my $uptodate = $self->_check_trees( @_[1..$#_] );
+ $self->_build_trees(uptodate => $uptodate);
+ }
+
+ $recurse--;
+ return $self->_atree;
+ }
+
+}
+
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Internals::Source
+
+=head1 SYNOPSIS
+
+ ### lazy load author/module trees ###
+
+ $cb->_author_tree;
+ $cb->_module_tree;
+
+=head1 DESCRIPTION
+
+CPANPLUS::Internals::Source controls the updating of source files and
+the parsing of them into usable module/author trees to be used by
+C<CPANPLUS>.
+
+Functions exist to check if source files are still C<good to use> as
+well as update them, and then parse them.
+
+The flow looks like this:
+
+ $cb->_author_tree || $cb->_module_tree
+ $cb->_check_trees
+ $cb->__check_uptodate
+ $cb->_update_source
+ $cb->__update_custom_module_sources
+ $cb->__update_custom_module_source
+ $cb->_build_trees
+ ### engine methods
+ { $cb->_init_trees;
+ $cb->_standard_trees_completed
+ $cb->_custom_trees_completed
+ }
+ $cb->__create_author_tree
+ ### engine methods
+ { $cb->_add_author_object }
+ $cb->__create_module_tree
+ $cb->__create_dslip_tree
+ ### engine methods
+ { $cb->_add_module_object }
+ $cb->__create_custom_module_entries
+
+ $cb->_dslip_defs
+
+=head1 METHODS
+
+=cut
+
+=pod
+
+=head2 $cb->_build_trees( uptodate => BOOL, [use_stored => BOOL, path => $path, verbose => BOOL] )
+
+This method rebuilds the author- and module-trees from source.
+
+It takes the following arguments:
+
+=over 4
+
+=item uptodate
+
+Indicates whether any on disk caches are still ok to use.
+
+=item path
+
+The absolute path to the directory holding the source files.
+
+=item verbose
+
+A boolean flag indicating whether or not to be verbose.
+
+=item use_stored
+
+A boolean flag indicating whether or not it is ok to use previously
+stored trees. Defaults to true.
+
+=back
+
+Returns a boolean indicating success.
+
+=cut
+
+### (re)build the trees ###
+sub _build_trees {
+ my ($self, %hash) = @_;
+ my $conf = $self->configure_object;
+
+ my($path,$uptodate,$use_stored,$verbose);
+ my $tmpl = {
+ path => { default => $conf->get_conf('base'), store => \$path },
+ verbose => { default => $conf->get_conf('verbose'), store => \$verbose },
+ uptodate => { required => 1, store => \$uptodate },
+ use_stored => { default => 1, store => \$use_stored },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ $self->_init_trees(
+ path => $path,
+ uptodate => $uptodate,
+ verbose => $verbose,
+ use_stored => $use_stored,
+ ) or do {
+ error( loc("Could not initialize trees" ) );
+ return;
+ };
+
+ ### return if we weren't able to build the trees ###
+ return unless $self->_mtree && $self->_atree;
+
+ ### did we get everything from a stored state? if not,
+ ### process them now.
+ if( not $self->_standard_trees_completed ) {
+
+ ### first, prep the author tree
+ $self->__create_author_tree(
+ uptodate => $uptodate,
+ path => $path,
+ verbose => $verbose,
+ ) or return;
+
+ ### and now the module tree
+ $self->_create_mod_tree(
+ uptodate => $uptodate,
+ path => $path,
+ verbose => $verbose,
+ ) or return;
+ }
+
+ ### XXX unpleasant hack. since custom sources uses ->parse_module, we
+ ### already have a special module object with extra meta data. that
+ ### doesn't gelwell with the sqlite storage engine. So, we check 'normal'
+ ### trees from seperate trees, so the engine can treat them differently.
+ ### Effectively this means that with the SQLite engine, for now, custom
+ ### sources are continuously reparsed =/ -kane
+ if( not $self->_custom_trees_completed ) {
+
+ ### update them if the other sources are also deemed out of date
+ if( $conf->get_conf('enable_custom_sources') ) {
+ $self->__update_custom_module_sources( verbose => $verbose )
+ or error(loc("Could not update custom module sources"));
+ }
+
+ ### add custom sources here if enabled
+ if( $conf->get_conf('enable_custom_sources') ) {
+ $self->__create_custom_module_entries( verbose => $verbose )
+ or error(loc("Could not create custom module entries"));
+ }
+ }
+
+ ### give the source engine a chance to wrap up creation
+ $self->_finalize_trees(
+ path => $path,
+ uptodate => $uptodate,
+ verbose => $verbose,
+ use_stored => $use_stored,
+ ) or do {
+ error(loc( "Could not finalize trees" ));
+ return;
+ };
+
+ ### still necessary? can only run one instance now ###
+ ### will probably stay that way --kane
+# my $id = $self->_store_id( $self );
+#
+# unless ( $id == $self->_id ) {
+# error( loc("IDs do not match: %1 != %2. Storage failed!", $id, $self->_id) );
+# }
+
+ return 1;
+}
+
+=pod
+
+=head2 $cb->_check_trees( [update_source => BOOL, path => PATH, verbose => BOOL] )
+
+Retrieve source files and return a boolean indicating whether or not
+the source files are up to date.
+
+Takes several arguments:
+
+=over 4
+
+=item update_source
+
+A flag to force re-fetching of the source files, even
+if they are still up to date.
+
+=item path
+
+The absolute path to the directory holding the source files.
+
+=item verbose
+
+A boolean flag indicating whether or not to be verbose.
+
+=back
+
+Will get information from the config file by default.
+
+=cut
+
+### retrieve source files, and returns a boolean indicating if it's up to date
+sub _check_trees {
+ my ($self, %hash) = @_;
+ my $conf = $self->configure_object;
+
+ my $update_source;
+ my $verbose;
+ my $path;
+
+ my $tmpl = {
+ path => { default => $conf->get_conf('base'),
+ store => \$path
+ },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose
+ },
+ update_source => { default => 0, store => \$update_source },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ ### if the user never wants to update their source without explicitly
+ ### telling us, shortcircuit here
+ return 1 if $conf->get_conf('no_update') && !$update_source;
+
+ ### a check to see if our source files are still up to date ###
+ msg( loc("Checking if source files are up to date"), $verbose );
+
+ my $uptodate = 1; # default return value
+
+ for my $name (qw[auth dslip mod]) {
+ for my $file ( $conf->_get_source( $name ) ) {
+ $self->__check_uptodate(
+ file => File::Spec->catfile( $path, $file ),
+ name => $name,
+ update_source => $update_source,
+ verbose => $verbose,
+ ) or $uptodate = 0;
+ }
+ }
+
+ ### if we're explicitly asked to update the sources, or if the
+ ### standard source files are out of date, update the custom sources
+ ### as well
+ ### RT #47820: Don't try to update custom sources if they are disabled
+ ### in the configuration.
+ $self->__update_custom_module_sources( verbose => $verbose )
+ if $conf->get_conf('enable_custom_sources') and ( $update_source or !$uptodate );
+
+ return $uptodate;
+}
+
+=pod
+
+=head2 $cb->__check_uptodate( file => $file, name => $name, [update_source => BOOL, verbose => BOOL] )
+
+C<__check_uptodate> checks if a given source file is still up-to-date
+and if not, or when C<update_source> is true, will re-fetch the source
+file.
+
+Takes the following arguments:
+
+=over 4
+
+=item file
+
+The source file to check.
+
+=item name
+
+The internal shortcut name for the source file (used for config
+lookups).
+
+=item update_source
+
+Flag to force updating of sourcefiles regardless.
+
+=item verbose
+
+Boolean to indicate whether to be verbose or not.
+
+=back
+
+Returns a boolean value indicating whether the current files are up
+to date or not.
+
+=cut
+
+### this method checks whether or not the source files we are using are still up to date
+sub __check_uptodate {
+ my $self = shift;
+ my %hash = @_;
+ my $conf = $self->configure_object;
+
+
+ my $tmpl = {
+ file => { required => 1 },
+ name => { required => 1 },
+ update_source => { default => 0 },
+ verbose => { default => $conf->get_conf('verbose') },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ my $flag;
+ unless ( -e $args->{'file'} && (
+ ( stat $args->{'file'} )[9]
+ + $conf->_get_source('update') )
+ > time ) {
+ $flag = 1;
+ }
+
+ if ( $flag or $args->{'update_source'} ) {
+
+ if ( $self->_update_source( name => $args->{'name'} ) ) {
+ return 0; # return 0 so 'uptodate' will be set to 0, meaning no
+ # use of previously stored hashrefs!
+ } else {
+ msg( loc("Unable to update source, attempting to get away with using old source file!"), $args->{verbose} );
+ return 1;
+ }
+
+ } else {
+ return 1;
+ }
+}
+
+=pod
+
+=head2 $cb->_update_source( name => $name, [path => $path, verbose => BOOL] )
+
+This method does the actual fetching of source files.
+
+It takes the following arguments:
+
+=over 4
+
+=item name
+
+The internal shortcut name for the source file (used for config
+lookups).
+
+=item path
+
+The full path where to write the files.
+
+=item verbose
+
+Boolean to indicate whether to be verbose or not.
+
+=back
+
+Returns a boolean to indicate success.
+
+=cut
+
+### this sub fetches new source files ###
+sub _update_source {
+ my $self = shift;
+ my %hash = @_;
+ my $conf = $self->configure_object;
+
+ my $verbose;
+ my $tmpl = {
+ name => { required => 1 },
+ path => { default => $conf->get_conf('base') },
+ verbose => { default => $conf->get_conf('verbose'), store => \$verbose },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+
+ my $path = $args->{path};
+ { ### this could use a clean up - Kane
+ ### no worries about the / -> we get it from the _ftp configuration, so
+ ### it's not platform dependant. -kane
+ my ($dir, $file) = $conf->_get_mirror( $args->{'name'} ) =~ m|(.+/)(.+)$|sg;
+
+ msg( loc("Updating source file '%1'", $file), $verbose );
+
+ my $fake = CPANPLUS::Module::Fake->new(
+ module => $args->{'name'},
+ path => $dir,
+ package => $file,
+ _id => $self->_id,
+ );
+
+ ### can't use $fake->fetch here, since ->parent won't work --
+ ### the sources haven't been saved yet
+ my $rv = $self->_fetch(
+ module => $fake,
+ fetchdir => $path,
+ force => 1,
+ );
+
+
+ unless ($rv) {
+ error( loc("Couldn't fetch '%1'", $file) );
+ return;
+ }
+
+ $self->_update_timestamp( file => File::Spec->catfile($path, $file) );
+ }
+
+ return 1;
+}
+
+=pod
+
+=head2 $cb->__create_author_tree([path => $path, uptodate => BOOL, verbose => BOOL])
+
+This method opens a source files and parses its contents into a
+searchable author-tree or restores a file-cached version of a
+previous parse, if the sources are uptodate and the file-cache exists.
+
+It takes the following arguments:
+
+=over 4
+
+=item uptodate
+
+A flag indicating whether the file-cache is uptodate or not.
+
+=item path
+
+The absolute path to the directory holding the source files.
+
+=item verbose
+
+A boolean flag indicating whether or not to be verbose.
+
+=back
+
+Will get information from the config file by default.
+
+Returns a tree on success, false on failure.
+
+=cut
+
+sub __create_author_tree {
+ my $self = shift;
+ my %hash = @_;
+ my $conf = $self->configure_object;
+
+
+ my $tmpl = {
+ path => { default => $conf->get_conf('base') },
+ verbose => { default => $conf->get_conf('verbose') },
+ uptodate => { default => 0 },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ my $file = File::Spec->catfile(
+ $args->{path},
+ $conf->_get_source('auth')
+ );
+
+ msg(loc("Rebuilding author tree, this might take a while"),
+ $args->{verbose});
+
+ ### extract the file ###
+ my $ae = Archive::Extract->new( archive => $file ) or return;
+ my $out = STRIP_GZ_SUFFIX->($file);
+
+ ### make sure to set the PREFER_BIN flag if desired ###
+ { local $Archive::Extract::PREFER_BIN = $conf->get_conf('prefer_bin');
+ $ae->extract( to => $out ) or return;
+ }
+
+ my $cont = $self->_get_file_contents( file => $out ) or return;
+
+ ### don't need it anymore ###
+ unlink $out;
+
+ for ( split /\n/, $cont ) {
+ my($id, $name, $email) = m/^alias \s+
+ (\S+) \s+
+ "\s* ([^\"\<]+?) \s* <(.+)> \s*"
+ /x;
+
+ $self->_add_author_object(
+ author => $name, #authors name
+ email => $email, #authors email address
+ cpanid => $id, #authors CPAN ID
+ ) or error( loc("Could not add author '%1'", $name ) );
+
+ }
+
+ return $self->_atree;
+
+} #__create_author_tree
+
+=pod
+
+=head2 $cb->_create_mod_tree([path => $path, uptodate => BOOL, verbose => BOOL])
+
+This method opens a source files and parses its contents into a
+searchable module-tree or restores a file-cached version of a
+previous parse, if the sources are uptodate and the file-cache exists.
+
+It takes the following arguments:
+
+=over 4
+
+=item uptodate
+
+A flag indicating whether the file-cache is up-to-date or not.
+
+=item path
+
+The absolute path to the directory holding the source files.
+
+=item verbose
+
+A boolean flag indicating whether or not to be verbose.
+
+=back
+
+Will get information from the config file by default.
+
+Returns a tree on success, false on failure.
+
+=cut
+
+### this builds a hash reference with the structure of the cpan module tree ###
+sub _create_mod_tree {
+ my $self = shift;
+ my %hash = @_;
+ my $conf = $self->configure_object;
+
+
+ my $tmpl = {
+ path => { default => $conf->get_conf('base') },
+ verbose => { default => $conf->get_conf('verbose') },
+ uptodate => { default => 0 },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return undef;
+ my $file = File::Spec->catfile($args->{path}, $conf->_get_source('mod'));
+
+ msg(loc("Rebuilding module tree, this might take a while"),
+ $args->{verbose});
+
+
+ my $dslip_tree = $self->__create_dslip_tree( %$args );
+
+ ### extract the file ###
+ my $ae = Archive::Extract->new( archive => $file ) or return;
+ my $out = STRIP_GZ_SUFFIX->($file);
+
+ ### make sure to set the PREFER_BIN flag if desired ###
+ { local $Archive::Extract::PREFER_BIN = $conf->get_conf('prefer_bin');
+ $ae->extract( to => $out ) or return;
+ }
+
+ my $content = $self->_get_file_contents( file => $out ) or return;
+ my $lines = $content =~ tr/\n/\n/;
+
+ ### don't need it anymore ###
+ unlink $out;
+
+ my($past_header, $count);
+ for ( split /\n/, $content ) {
+
+ ### quick hack to read past the header of the file ###
+ ### this is still rather evil... fix some time - Kane
+ if( m|^\s*$| ) {
+ unless( $count ) {
+ error(loc("Could not determine line count from %1", $file));
+ return;
+ }
+ $past_header = 1;
+ }
+
+ ### we're still in the header -- find the amount of lines we expect
+ unless( $past_header ) {
+
+ ### if the line count doesn't match what we expect, bail out
+ ### this should address: #45644: detect broken index
+ $count = $1 if /^Line-Count:\s+(\d+)/;
+ if( $count ) {
+ if( $lines < $count ) {
+ error(loc("Expected to read at least %1 lines, but %2 ".
+ "contains only %3 lines!",
+ $count, $file, $lines ));
+ return;
+ }
+ }
+ ### still in the header, keep moving
+ next;
+ }
+
+ ### skip empty lines ###
+ next unless /\S/;
+ chomp;
+
+ my @data = split /\s+/;
+
+ ### filter out the author and filename as well ###
+ ### authors can apparently have digits in their names,
+ ### and dirs can have dots... blah!
+ my ($author, $package) = $data[2] =~
+ m| (?:[A-Z\d-]/)?
+ (?:[A-Z\d-]{2}/)?
+ ([A-Z\d-]+) (?:/[\S]+)?/
+ ([^/]+)$
+ |xsg;
+
+ ### remove file name from the path
+ $data[2] =~ s|/[^/]+$||;
+
+ my $aobj = $self->author_tree($author);
+ unless( $aobj ) {
+ error( loc( "No such author '%1' -- can't make module object " .
+ "'%2' that is supposed to belong to this author",
+ $author, $data[0] ) );
+ next;
+ }
+
+ ### adding the dslip info
+ ### probably can use some optimization
+ my $dslip;
+ for my $item ( qw[ statd stats statl stati statp ] ) {
+ ### checking if there's an entry in the dslip info before
+ ### catting it on. appeasing warnings this way
+ $dslip .= $dslip_tree->{ $data[0] }->{$item}
+ ? $dslip_tree->{ $data[0] }->{$item}
+ : ' ';
+ }
+
+ ### XXX this could be sped up if we used author names, not author
+ ### objects in creation, and then look them up in the author tree
+ ### when needed. This will need a fix to all the places that create
+ ### fake author/module objects as well.
+
+ ### callback to store the individual object
+ $self->_add_module_object(
+ module => $data[0], # full module name
+ version => ($data[1] eq 'undef' # version number
+ ? '0.0'
+ : $data[1]),
+ path => File::Spec::Unix->catfile(
+ $conf->_get_mirror('base'),
+ $data[2],
+ ), # extended path on the cpan mirror,
+ # like /A/AB/ABIGAIL
+ comment => $data[3], # comment on the module
+ author => $aobj,
+ package => $package, # package name, like
+ # 'foo-bar-baz-1.03.tar.gz'
+ description => $dslip_tree->{ $data[0] }->{'description'},
+ dslip => $dslip,
+ mtime => '',
+ ) or error( loc( "Could not add module '%1'", $data[0] ) );
+
+ } #for
+
+ return $self->_mtree;
+
+} #_create_mod_tree
+
+=pod
+
+=head2 $cb->__create_dslip_tree([path => $path, uptodate => BOOL, verbose => BOOL])
+
+This method opens a source files and parses its contents into a
+searchable dslip-tree or restores a file-cached version of a
+previous parse, if the sources are uptodate and the file-cache exists.
+
+It takes the following arguments:
+
+=over 4
+
+=item uptodate
+
+A flag indicating whether the file-cache is uptodate or not.
+
+=item path
+
+The absolute path to the directory holding the source files.
+
+=item verbose
+
+A boolean flag indicating whether or not to be verbose.
+
+=back
+
+Will get information from the config file by default.
+
+Returns a tree on success, false on failure.
+
+=cut
+
+sub __create_dslip_tree {
+ my $self = shift;
+ my %hash = @_;
+ my $conf = $self->configure_object;
+
+ my $tmpl = {
+ path => { default => $conf->get_conf('base') },
+ verbose => { default => $conf->get_conf('verbose') },
+ uptodate => { default => 0 },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ ### get the file name of the source ###
+ my $file = File::Spec->catfile($args->{path}, $conf->_get_source('dslip'));
+
+ ### extract the file ###
+ my $ae = Archive::Extract->new( archive => $file ) or return;
+ my $out = STRIP_GZ_SUFFIX->($file);
+
+ ### make sure to set the PREFER_BIN flag if desired ###
+ { local $Archive::Extract::PREFER_BIN = $conf->get_conf('prefer_bin');
+ $ae->extract( to => $out ) or return;
+ }
+
+ my $in = $self->_get_file_contents( file => $out ) or return;
+
+ ### don't need it anymore ###
+ unlink $out;
+
+
+ ### get rid of the comments and the code ###
+ ### need a smarter parser, some people have this in their dslip info:
+ # [
+ # 'Statistics::LTU',
+ # 'R',
+ # 'd',
+ # 'p',
+ # 'O',
+ # '?',
+ # 'Implements Linear Threshold Units',
+ # ...skipping...
+ # "\x{c4}dd \x{fc}ml\x{e4}\x{fc}ts t\x{f6} \x{eb}v\x{eb}r\x{ff}th\x{ef}ng!",
+ # 'BENNIE',
+ # '11'
+ # ],
+ ### also, older versions say:
+ ### $cols = [....]
+ ### and newer versions say:
+ ### $CPANPLUS::Modulelist::cols = [...]
+ ### split '$cols' and '$data' into 2 variables ###
+ ### use this regex to make sure dslips with ';' in them don't cause
+ ### parser errors
+ my ($ds_one, $ds_two) = ($in =~ m|.+}\s+
+ (\$(?:CPAN::Modulelist::)?cols.*?)
+ (\$(?:CPAN::Modulelist::)?data.*)
+ |sx);
+
+ ### eval them into existence ###
+ ### still not too fond of this solution - kane ###
+ my ($cols, $data);
+ { #local $@; can't use this, it's buggy -kane
+
+ $cols = eval $ds_one;
+ error( loc("Error in eval of dslip source files: %1", $@) ) if $@;
+
+ $data = eval $ds_two;
+ error( loc("Error in eval of dslip source files: %1", $@) ) if $@;
+
+ }
+
+ my $tree = {};
+ my $primary = "modid";
+
+ ### this comes from CPAN::Modulelist
+ ### which is in 03modlist.data.gz
+ for (@$data){
+ my %hash;
+ @hash{@$cols} = @$_;
+ $tree->{$hash{$primary}} = \%hash;
+ }
+
+ return $tree;
+
+} #__create_dslip_tree
+
+=pod
+
+=head2 $cb->_dslip_defs ()
+
+This function returns the definition structure (ARRAYREF) of the
+dslip tree.
+
+=cut
+
+### these are the definitions used for dslip info
+### they shouldn't change over time.. so hardcoding them doesn't appear to
+### be a problem. if it is, we need to parse 03modlist.data better to filter
+### all this out.
+### right now, this is just used to look up dslip info from a module
+sub _dslip_defs {
+ my $self = shift;
+
+ my $aref = [
+
+ # D
+ [ q|Development Stage|, {
+ i => loc('Idea, listed to gain consensus or as a placeholder'),
+ c => loc('under construction but pre-alpha (not yet released)'),
+ a => loc('Alpha testing'),
+ b => loc('Beta testing'),
+ R => loc('Released'),
+ M => loc('Mature (no rigorous definition)'),
+ S => loc('Standard, supplied with Perl 5'),
+ }],
+
+ # S
+ [ q|Support Level|, {
+ m => loc('Mailing-list'),
+ d => loc('Developer'),
+ u => loc('Usenet newsgroup comp.lang.perl.modules'),
+ n => loc('None known, try comp.lang.perl.modules'),
+ a => loc('Abandoned; volunteers welcome to take over maintainance'),
+ }],
+
+ # L
+ [ q|Language Used|, {
+ p => loc('Perl-only, no compiler needed, should be platform independent'),
+ c => loc('C and perl, a C compiler will be needed'),
+ h => loc('Hybrid, written in perl with optional C code, no compiler needed'),
+ '+' => loc('C++ and perl, a C++ compiler will be needed'),
+ o => loc('perl and another language other than C or C++'),
+ }],
+
+ # I
+ [ q|Interface Style|, {
+ f => loc('plain Functions, no references used'),
+ h => loc('hybrid, object and function interfaces available'),
+ n => loc('no interface at all (huh?)'),
+ r => loc('some use of unblessed References or ties'),
+ O => loc('Object oriented using blessed references and/or inheritance'),
+ }],
+
+ # P
+ [ q|Public License|, {
+ p => loc('Standard-Perl: user may choose between GPL and Artistic'),
+ g => loc('GPL: GNU General Public License'),
+ l => loc('LGPL: "GNU Lesser General Public License" (previously known as "GNU Library General Public License")'),
+ b => loc('BSD: The BSD License'),
+ a => loc('Artistic license alone'),
+ o => loc('other (but distribution allowed without restrictions)'),
+ }],
+ ];
+
+ return $aref;
+}
+
+=head2 $file = $cb->_add_custom_module_source( uri => URI, [verbose => BOOL] );
+
+Adds a custom source index and updates it based on the provided URI.
+
+Returns the full path to the index file on success or false on failure.
+
+=cut
+
+sub _add_custom_module_source {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my($verbose,$uri);
+ my $tmpl = {
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ uri => { required => 1, store => \$uri }
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### what index file should we use on disk?
+ my $index = $self->__custom_module_source_index_file( uri => $uri );
+
+ ### already have it.
+ if( IS_FILE->( $index ) ) {
+ msg(loc("Source '%1' already added", $uri));
+ return 1;
+ }
+
+ ### do we need to create the targe dir?
+ { my $dir = dirname( $index );
+ unless( IS_DIR->( $dir ) ) {
+ $self->_mkdir( dir => $dir ) or return
+ }
+ }
+
+ ### write the file
+ my $fh = OPEN_FILE->( $index => '>' ) or do {
+ error(loc("Could not open index file for '%1'", $uri));
+ return;
+ };
+
+ ### basically we 'touched' it. Check the return value, may be
+ ### important on win32 and similar OS, where there's file length
+ ### limits
+ close $fh or do {
+ error(loc("Could not write index file to disk for '%1'", $uri));
+ return;
+ };
+
+ $self->__update_custom_module_source(
+ remote => $uri,
+ local => $index,
+ verbose => $verbose,
+ ) or do {
+ ### we faild to update it, we probably have an empty
+ ### possibly silly filename on disk now -- remove it
+ 1 while unlink $index;
+ return;
+ };
+
+ return $index;
+}
+
+=head2 $index = $cb->__custom_module_source_index_file( uri => $uri );
+
+Returns the full path to the encoded index file for C<$uri>, as used by
+all C<custom module source> routines.
+
+=cut
+
+sub __custom_module_source_index_file {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my($verbose,$uri);
+ my $tmpl = {
+ uri => { required => 1, store => \$uri }
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ my $index = File::Spec->catfile(
+ $conf->get_conf('base'),
+ $conf->_get_build('custom_sources'),
+ $self->_uri_encode( uri => $uri ),
+ );
+
+ return $index;
+}
+
+=head2 $file = $cb->_remove_custom_module_source( uri => URI, [verbose => BOOL] );
+
+Removes a custom index file based on the URI provided.
+
+Returns the full path to the index file on success or false on failure.
+
+=cut
+
+sub _remove_custom_module_source {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my($verbose,$uri);
+ my $tmpl = {
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ uri => { required => 1, store => \$uri }
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### use uri => local, instead of the other way around
+ my %files = reverse $self->__list_custom_module_sources;
+
+ ### On VMS the case of key to %files can be either exact or lower case
+ ### XXX abstract this lookup out? --kane
+ my $file = $files{ $uri };
+ $file = $files{ lc $uri } if !defined($file) && ON_VMS;
+
+ unless (defined $file) {
+ error(loc("No such custom source '%1'", $uri));
+ return;
+ };
+
+ 1 while unlink $file;
+
+ if( IS_FILE->( $file ) ) {
+ error(loc("Could not remove index file '%1' for custom source '%2'",
+ $file, $uri));
+ return;
+ }
+
+ msg(loc("Successfully removed index file for '%1'", $uri), $verbose);
+
+ return $file;
+}
+
+=head2 %files = $cb->__list_custom_module_sources
+
+This method scans the 'custom-sources' directory in your base directory
+for additional sources to include in your module tree.
+
+Returns a list of key value pairs as follows:
+
+ /full/path/to/source/file%3Fencoded => http://decoded/mirror/path
+
+=cut
+
+sub __list_custom_module_sources {
+ my $self = shift;
+ my $conf = $self->configure_object;
+
+ my($verbose);
+ my $tmpl = {
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ };
+
+ my $dir = File::Spec->catdir(
+ $conf->get_conf('base'),
+ $conf->_get_build('custom_sources'),
+ );
+
+ unless( IS_DIR->( $dir ) ) {
+ msg(loc("No '%1' dir, skipping custom sources", $dir), $verbose);
+ return;
+ }
+
+ ### unencode the files
+ ### skip ones starting with # though
+ my %files = map {
+ my $org = $_;
+ my $dec = $self->_uri_decode( uri => $_ );
+ File::Spec->catfile( $dir, $org ) => $dec
+ } grep { $_ !~ /^#/ } READ_DIR->( $dir );
+
+ return %files;
+}
+
+=head2 $bool = $cb->__update_custom_module_sources( [verbose => BOOL] );
+
+Attempts to update all the index files to your custom module sources.
+
+If the index is missing, and it's a C<file://> uri, it will generate
+a new local index for you.
+
+Return true on success, false on failure.
+
+=cut
+
+sub __update_custom_module_sources {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my $verbose;
+ my $tmpl = {
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose }
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ my %files = $self->__list_custom_module_sources;
+
+ ### uptodate check has been done a few levels up.
+ my $fail;
+ while( my($local,$remote) = each %files ) {
+
+ $self->__update_custom_module_source(
+ remote => $remote,
+ local => $local,
+ verbose => $verbose,
+ ) or ( $fail++, next );
+ }
+
+ error(loc("Failed updating one or more remote sources files")) if $fail;
+
+ return if $fail;
+ return 1;
+}
+
+=head2 $ok = $cb->__update_custom_module_source
+
+Attempts to update all the index files to your custom module sources.
+
+If the index is missing, and it's a C<file://> uri, it will generate
+a new local index for you.
+
+Return true on success, false on failure.
+
+=cut
+
+sub __update_custom_module_source {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my($verbose,$local,$remote);
+ my $tmpl = {
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ local => { store => \$local, allow => FILE_EXISTS },
+ remote => { required => 1, store => \$remote },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ msg( loc("Updating sources from '%1'", $remote), $verbose);
+
+ ### if you didn't provide a local file, we'll look in your custom
+ ### dir to find the local encoded version for you
+ $local ||= do {
+ ### find all files we know of
+ my %files = reverse $self->__list_custom_module_sources or do {
+ error(loc("No custom modules sources defined -- need '%1' argument",
+ 'local'));
+ return;
+ };
+
+ ### On VMS the case of key to %files can be either exact or lower case
+ ### XXX abstract this lookup out? --kane
+ my $file = $files{ $remote };
+ $file = $files{ lc $remote } if !defined ($file) && ON_VMS;
+
+ ### return the local file we're supposed to use
+ $file or do {
+ error(loc("Remote source '%1' unknown -- needs '%2' argument",
+ $remote, 'local'));
+ return;
+ };
+ };
+
+ my $uri = join '/', $remote, $conf->_get_source('custom_index');
+ my $ff = File::Fetch->new( uri => $uri );
+
+ ### tempdir doesn't clean up by default, as opposed to tempfile()
+ ### so add it explicitly.
+ my $dir = tempdir( CLEANUP => 1 );
+
+ my $res = do { local $File::Fetch::WARN = 0;
+ local $File::Fetch::WARN = 0;
+ $ff->fetch( to => $dir );
+ };
+
+ ### couldn't get the file
+ unless( $res ) {
+
+ ### it's not a local scheme, so can't auto index
+ unless( $ff->scheme eq 'file' ) {
+ error(loc("Could not update sources from '%1': %2",
+ $remote, $ff->error ));
+ return;
+
+ ### it's a local uri, we can index it ourselves
+ } else {
+ msg(loc("No index file found at '%1', generating one",
+ $ff->uri), $verbose );
+
+ ### ON VMS, if you are working with a UNIX file specification,
+ ### you need currently use the UNIX variants of the File::Spec.
+ my $ff_path = do {
+ my $file_class = 'File::Spec';
+ $file_class .= '::Unix' if ON_VMS;
+ $file_class->catdir( File::Spec::Unix->splitdir( $ff->path ) );
+ };
+
+ $self->__write_custom_module_index(
+ path => $ff_path,
+ to => $local,
+ verbose => $verbose,
+ ) or return;
+
+ ### XXX don't write that here, __write_custom_module_index
+ ### already prints this out
+ #msg(loc("Index file written to '%1'", $to), $verbose);
+ }
+
+ ### copy it to the real spot and update its timestamp
+ } else {
+ $self->_move( file => $res, to => $local ) or return;
+ $self->_update_timestamp( file => $local );
+
+ msg(loc("Index file saved to '%1'", $local), $verbose);
+ }
+
+ return $local;
+}
+
+=head2 $bool = $cb->__write_custom_module_index( path => /path/to/packages, [to => /path/to/index/file, verbose => BOOL] )
+
+Scans the C<path> you provided for packages and writes an index with all
+the available packages to C<$path/packages.txt>. If you'd like the index
+to be written to a different file, provide the C<to> argument.
+
+Returns true on success and false on failure.
+
+=cut
+
+sub __write_custom_module_index {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my ($verbose, $path, $to);
+ my $tmpl = {
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ path => { required => 1, allow => DIR_EXISTS, store => \$path },
+ to => { store => \$to },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### no explicit to? then we'll use our default
+ $to ||= File::Spec->catfile( $path, $conf->_get_source('custom_index') );
+
+ my @files;
+ require File::Find;
+ File::Find::find( sub {
+ ### let's see if A::E can even parse it
+ my $ae = do {
+ local $Archive::Extract::WARN = 0;
+ local $Archive::Extract::WARN = 0;
+ Archive::Extract->new( archive => $File::Find::name )
+ } or return;
+
+ ### it's a type A::E recognize, so we can add it
+ $ae->type or return;
+
+ ### neither $_ nor $File::Find::name have the chunk of the path in
+ ### it starting $path -- it's either only the filename, or the full
+ ### path, so we have to strip it ourselves
+ ### make sure to remove the leading slash as well.
+ my $copy = $File::Find::name;
+ my $re = quotemeta($path);
+ $copy =~ s|^$re[\\/]?||i;
+
+ push @files, $copy;
+
+ }, $path );
+
+ ### does the dir exist? if not, create it.
+ { my $dir = dirname( $to );
+ unless( IS_DIR->( $dir ) ) {
+ $self->_mkdir( dir => $dir ) or return
+ }
+ }
+
+ ### create the index file
+ my $fh = OPEN_FILE->( $to => '>' ) or return;
+
+ print $fh "$_\n" for @files;
+ close $fh;
+
+ msg(loc("Successfully written index file to '%1'", $to), $verbose);
+
+ return $to;
+}
+
+
+=head2 $bool = $cb->__create_custom_module_entries( [verbose => BOOL] )
+
+Creates entries in the module tree based upon the files as returned
+by C<__list_custom_module_sources>.
+
+Returns true on success, false on failure.
+
+=cut
+
+### use $auth_obj as a persistant version, so we don't have to recreate
+### modules all the time
+{ my $auth_obj;
+
+ sub __create_custom_module_entries {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my $verbose;
+ my $tmpl = {
+ verbose => { default => $conf->get_conf('verbose'), store => \$verbose },
+ };
+
+ check( $tmpl, \%hash ) or return undef;
+
+ my %files = $self->__list_custom_module_sources;
+
+ while( my($file,$name) = each %files ) {
+
+ msg(loc("Adding packages from custom source '%1'", $name), $verbose);
+
+ my $fh = OPEN_FILE->( $file ) or next;
+
+ while( local $_ = <$fh> ) {
+ chomp;
+ next if /^#/;
+ next unless /\S+/;
+
+ ### join on / -- it's a URI after all!
+ my $parse = join '/', $name, $_;
+
+ ### try to make a module object out of it
+ my $mod = $self->parse_module( module => $parse ) or (
+ error(loc("Could not parse '%1'", $_)),
+ next
+ );
+
+ ### mark this object with a custom author
+ $auth_obj ||= do {
+ my $id = CUSTOM_AUTHOR_ID;
+
+ ### if the object is being created for the first time,
+ ### make sure there's an entry in the author tree as
+ ### well, so we can search on the CPAN ID
+ $self->author_tree->{ $id } =
+ CPANPLUS::Module::Author::Fake->new( cpanid => $id );
+ };
+
+ $mod->author( $auth_obj );
+
+ ### and now add it to the modlue tree -- this MAY
+ ### override things of course
+ if( my $old_mod = $self->module_tree( $mod->module ) ) {
+
+ ### On VMS use the old module name to get the real case
+ $mod->module( $old_mod->module ) if ON_VMS;
+
+ msg(loc("About to overwrite module tree entry for '%1' with '%2'",
+ $mod->module, $mod->package), $verbose);
+ }
+
+ ### mark where it came from
+ $mod->description( loc("Custom source from '%1'",$name) );
+
+ ### store it in the module tree
+ $self->module_tree->{ $mod->module } = $mod;
+ }
+ }
+
+ return 1;
+ }
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Source/Memory.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Source/Memory.pm
new file mode 100644
index 00000000000..cb3fd4f1e76
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Source/Memory.pm
@@ -0,0 +1,374 @@
+package CPANPLUS::Internals::Source::Memory;
+
+use base 'CPANPLUS::Internals::Source';
+
+use strict;
+
+use CPANPLUS::Error;
+use CPANPLUS::Module;
+use CPANPLUS::Module::Fake;
+use CPANPLUS::Module::Author;
+use CPANPLUS::Internals::Constants;
+
+use File::Fetch;
+use Archive::Extract;
+
+use IPC::Cmd qw[can_run];
+use File::Temp qw[tempdir];
+use File::Basename qw[dirname];
+use Params::Check qw[allow check];
+use Module::Load::Conditional qw[can_load];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+$Params::Check::VERBOSE = 1;
+
+=head1 NAME
+
+CPANPLUS::Internals::Source::Memory - In memory implementation
+
+=cut
+
+### flag to show if init_trees got its' data from storable. This allows
+### us to not write an existing stored file back to disk
+{ my $from_storable;
+
+ sub _init_trees {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my($path,$uptodate,$verbose,$use_stored);
+ my $tmpl = {
+ path => { default => $conf->get_conf('base'), store => \$path },
+ verbose => { default => $conf->get_conf('verbose'), store => \$verbose },
+ uptodate => { required => 1, store => \$uptodate },
+ use_stored => { default => 1, store => \$use_stored },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### retrieve the stored source files ###
+ my $stored = $self->__memory_retrieve_source(
+ path => $path,
+ uptodate => $uptodate && $use_stored,
+ verbose => $verbose,
+ ) || {};
+
+ ### we got this from storable if $stored has keys..
+ $from_storable = keys %$stored ? 1 : 0;
+
+ ### set up the trees
+ $self->_atree( $stored->{_atree} || {} );
+ $self->_mtree( $stored->{_mtree} || {} );
+
+ return 1;
+ }
+
+ sub _standard_trees_completed { return $from_storable }
+ sub _custom_trees_completed { return $from_storable }
+
+ sub _finalize_trees {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my($path,$uptodate,$verbose);
+ my $tmpl = {
+ path => { default => $conf->get_conf('base'), store => \$path },
+ verbose => { default => $conf->get_conf('verbose'), store => \$verbose },
+ uptodate => { required => 1, store => \$uptodate },
+ };
+
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+ check( $tmpl, \%hash ) or return;
+ }
+
+ ### write the stored files to disk, so we can keep using them
+ ### from now on, till they become invalid
+ ### write them if the original sources weren't uptodate, or
+ ### we didn't just load storable files
+ $self->__memory_save_source() if !$uptodate or not $from_storable;
+
+ return 1;
+ }
+
+ ### saves current memory state
+ sub _save_state {
+ my $self = shift;
+ return $self->_finalize_trees( @_, uptodate => 0 );
+ }
+}
+
+sub _add_author_object {
+ my $self = shift;
+ my %hash = @_;
+
+ my $class;
+ my $tmpl = {
+ class => { default => 'CPANPLUS::Module::Author', store => \$class },
+ map { $_ => { required => 1 } }
+ qw[ author cpanid email ]
+ };
+
+ my $href = do {
+ local $Params::Check::NO_DUPLICATES = 1;
+ check( $tmpl, \%hash ) or return;
+ };
+
+ my $obj = $class->new( %$href, _id => $self->_id );
+
+ $self->author_tree->{ $href->{'cpanid'} } = $obj or return;
+
+ return $obj;
+}
+
+sub _add_module_object {
+ my $self = shift;
+ my %hash = @_;
+
+ my $class;
+ my $tmpl = {
+ class => { default => 'CPANPLUS::Module', store => \$class },
+ map { $_ => { required => 1 } }
+ qw[ module version path comment author package description dslip mtime ]
+ };
+
+ my $href = do {
+ local $Params::Check::NO_DUPLICATES = 1;
+ check( $tmpl, \%hash ) or return;
+ };
+
+ my $obj = $class->new( %$href, _id => $self->_id );
+
+ ### Every module get's stored as a module object ###
+ $self->module_tree->{ $href->{module} } = $obj or return;
+
+ return $obj;
+}
+
+{ my %map = (
+ _source_search_module_tree => [ module_tree => 'CPANPLUS::Module' ],
+ _source_search_author_tree => [ author_tree => 'CPANPLUS::Module::Author' ],
+ );
+
+ while( my($sub, $aref) = each %map ) {
+ no strict 'refs';
+
+ my($meth, $class) = @$aref;
+
+ *$sub = sub {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my($authors,$list,$verbose,$type);
+ my $tmpl = {
+ data => { default => [],
+ strict_type=> 1, store => \$authors },
+ allow => { required => 1, default => [ ], strict_type => 1,
+ store => \$list },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ type => { required => 1, allow => [$class->accessors()],
+ store => \$type },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ my @rv;
+ for my $obj ( values %{ $self->$meth } ) {
+ #push @rv, $auth if check(
+ # { $type => { allow => $list } },
+ # { $type => $auth->$type }
+ # );
+ push @rv, $obj if allow( $obj->$type() => $list );
+ }
+
+ return @rv;
+ }
+ }
+}
+
+=pod
+
+=head2 $cb->__memory_retrieve_source(name => $name, [path => $path, uptodate => BOOL, verbose => BOOL])
+
+This method retrieves a I<storable>d tree identified by C<$name>.
+
+It takes the following arguments:
+
+=over 4
+
+=item name
+
+The internal name for the source file to retrieve.
+
+=item uptodate
+
+A flag indicating whether the file-cache is up-to-date or not.
+
+=item path
+
+The absolute path to the directory holding the source files.
+
+=item verbose
+
+A boolean flag indicating whether or not to be verbose.
+
+=back
+
+Will get information from the config file by default.
+
+Returns a tree on success, false on failure.
+
+=cut
+
+sub __memory_retrieve_source {
+ my $self = shift;
+ my %hash = @_;
+ my $conf = $self->configure_object;
+
+ my $tmpl = {
+ path => { default => $conf->get_conf('base') },
+ verbose => { default => $conf->get_conf('verbose') },
+ uptodate => { default => 0 },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ ### check if we can retrieve a frozen data structure with storable ###
+ my $storable = can_load( modules => {'Storable' => '0.0'} )
+ if $conf->get_conf('storable');
+
+ return unless $storable;
+
+ ### $stored is the name of the frozen data structure ###
+ my $stored = $self->__memory_storable_file( $args->{path} );
+
+ if ($storable && -e $stored && -s _ && $args->{'uptodate'}) {
+ msg( loc("Retrieving %1", $stored), $args->{'verbose'} );
+
+ my $href = Storable::retrieve($stored);
+ return $href;
+ } else {
+ return;
+ }
+}
+
+=pod
+
+=head2 $cb->__memory_save_source([verbose => BOOL, path => $path])
+
+This method saves all the parsed trees in I<storable>d format if
+C<Storable> is available.
+
+It takes the following arguments:
+
+=over 4
+
+=item path
+
+The absolute path to the directory holding the source files.
+
+=item verbose
+
+A boolean flag indicating whether or not to be verbose.
+
+=back
+
+Will get information from the config file by default.
+
+Returns true on success, false on failure.
+
+=cut
+
+sub __memory_save_source {
+ my $self = shift;
+ my %hash = @_;
+ my $conf = $self->configure_object;
+
+
+ my $tmpl = {
+ path => { default => $conf->get_conf('base'), allow => DIR_EXISTS },
+ verbose => { default => $conf->get_conf('verbose') },
+ force => { default => 1 },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ my $aref = [qw[_mtree _atree]];
+
+ ### check if we can retrieve a frozen data structure with storable ###
+ my $storable;
+ $storable = can_load( modules => {'Storable' => '0.0'} )
+ if $conf->get_conf('storable');
+ return unless $storable;
+
+ my $to_write = {};
+ foreach my $key ( @$aref ) {
+ next unless ref( $self->$key );
+ $to_write->{$key} = $self->$key;
+ }
+
+ return unless keys %$to_write;
+
+ ### $stored is the name of the frozen data structure ###
+ my $stored = $self->__memory_storable_file( $args->{path} );
+
+ if (-e $stored && not -w $stored) {
+ msg( loc("%1 not writable; skipped.", $stored), $args->{'verbose'} );
+ return;
+ }
+
+ msg( loc("Writing compiled source information to disk. This might take a little while."),
+ $args->{'verbose'} );
+
+ my $flag;
+ unless( Storable::nstore( $to_write, $stored ) ) {
+ error( loc("could not store %1!", $stored) );
+ $flag++;
+ }
+
+ return $flag ? 0 : 1;
+}
+
+sub __memory_storable_file {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my $path = shift or return;
+
+ ### check if we can retrieve a frozen data structure with storable ###
+ my $storable = $conf->get_conf('storable')
+ ? can_load( modules => {'Storable' => '0.0'} )
+ : 0;
+
+ return unless $storable;
+
+ ### $stored is the name of the frozen data structure ###
+ ### changed to use File::Spec->catfile -jmb
+ my $stored = File::Spec->rel2abs(
+ File::Spec->catfile(
+ $path, #base dir
+ $conf->_get_source('stored') #file
+ . '.s' .
+ $Storable::VERSION #the version of storable
+ . '.c' .
+ $self->VERSION #the version of CPANPLUS
+ . STORABLE_EXT #append a suffix
+ )
+ );
+
+ return $stored;
+}
+
+
+
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Source/SQLite.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Source/SQLite.pm
new file mode 100644
index 00000000000..a0ddf499bf6
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Source/SQLite.pm
@@ -0,0 +1,326 @@
+package CPANPLUS::Internals::Source::SQLite;
+
+use strict;
+use warnings;
+
+use base 'CPANPLUS::Internals::Source';
+
+use CPANPLUS::Error;
+use CPANPLUS::Internals::Constants;
+use CPANPLUS::Internals::Source::SQLite::Tie;
+
+use Data::Dumper;
+use DBIx::Simple;
+use DBD::SQLite;
+
+use Params::Check qw[allow check];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+use constant TXN_COMMIT => 1000;
+
+=head1 NAME
+
+CPANPLUS::Internals::Source::SQLite - SQLite implementation
+
+=cut
+
+{ my $Dbh;
+ my $DbFile;
+
+ sub __sqlite_file {
+ return $DbFile if $DbFile;
+
+ my $self = shift;
+ my $conf = $self->configure_object;
+
+ $DbFile = File::Spec->catdir(
+ $conf->get_conf('base'),
+ SOURCE_SQLITE_DB
+ );
+
+ return $DbFile;
+ };
+
+ sub __sqlite_dbh {
+ return $Dbh if $Dbh;
+
+ my $self = shift;
+ $Dbh = DBIx::Simple->connect(
+ "dbi:SQLite:dbname=" . $self->__sqlite_file,
+ '', '',
+ { AutoCommit => 1 }
+ );
+ #$Dbh->dbh->trace(1);
+
+ return $Dbh;
+ };
+}
+
+{ my $used_old_copy = 0;
+
+ sub _init_trees {
+ my $self = shift;
+ my $conf = $self->configure_object;
+ my %hash = @_;
+
+ my($path,$uptodate,$verbose,$use_stored);
+ my $tmpl = {
+ path => { default => $conf->get_conf('base'), store => \$path },
+ verbose => { default => $conf->get_conf('verbose'), store => \$verbose },
+ uptodate => { required => 1, store => \$uptodate },
+ use_stored => { default => 1, store => \$use_stored },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### if it's not uptodate, or the file doesn't exist, we need to create
+ ### a new sqlite db
+ if( not $uptodate or not -e $self->__sqlite_file ) {
+ $used_old_copy = 0;
+
+ ### chuck the file
+ 1 while unlink $self->__sqlite_file;
+
+ ### and create a new one
+ $self->__sqlite_create_db or do {
+ error(loc("Could not create new SQLite DB"));
+ return;
+ }
+ } else {
+ $used_old_copy = 1;
+ }
+
+ ### set up the author tree
+ { my %at;
+ tie %at, 'CPANPLUS::Internals::Source::SQLite::Tie',
+ dbh => $self->__sqlite_dbh, table => 'author',
+ key => 'cpanid', cb => $self;
+
+ $self->_atree( \%at );
+ }
+
+ ### set up the author tree
+ { my %mt;
+ tie %mt, 'CPANPLUS::Internals::Source::SQLite::Tie',
+ dbh => $self->__sqlite_dbh, table => 'module',
+ key => 'module', cb => $self;
+
+ $self->_mtree( \%mt );
+ }
+
+ ### start a transaction
+ $self->__sqlite_dbh->query('BEGIN');
+
+ return 1;
+
+ }
+
+ sub _standard_trees_completed { return $used_old_copy }
+ sub _custom_trees_completed { return }
+ ### finish transaction
+ sub _finalize_trees { $_[0]->__sqlite_dbh->query('COMMIT'); return 1 }
+
+ ### saves current memory state, but not implemented in sqlite
+ sub _save_state {
+ error(loc("%1 has not implemented writing state to disk", __PACKAGE__));
+ return;
+ }
+}
+
+{ my $txn_count = 0;
+
+ ### XXX move this outside the sub, so we only compute it once
+ my $class;
+ my @keys = qw[ author cpanid email ];
+ my $tmpl = {
+ class => { default => 'CPANPLUS::Module::Author', store => \$class },
+ map { $_ => { required => 1 } } @keys
+ };
+
+ ### dbix::simple's expansion of (??) is REALLY expensive, so do it manually
+ my $ph = join ',', map { '?' } @keys;
+
+
+ sub _add_author_object {
+ my $self = shift;
+ my %hash = @_;
+ my $dbh = $self->__sqlite_dbh;
+
+ my $href = do {
+ local $Params::Check::NO_DUPLICATES = 1;
+ local $Params::Check::SANITY_CHECK_TEMPLATE = 0;
+ check( $tmpl, \%hash ) or return;
+ };
+
+ ### keep counting how many we inserted
+ unless( ++$txn_count % TXN_COMMIT ) {
+ #warn "Committing transaction $txn_count";
+ $dbh->query('COMMIT') or error( $dbh->error ); # commit previous transaction
+ $dbh->query('BEGIN') or error( $dbh->error ); # and start a new one
+ }
+
+ $dbh->query(
+ "INSERT INTO author (". join(',',keys(%$href)) .") VALUES ($ph)",
+ values %$href
+ ) or do {
+ error( $dbh->error );
+ return;
+ };
+
+ return 1;
+ }
+}
+
+{ my $txn_count = 0;
+
+ ### XXX move this outside the sub, so we only compute it once
+ my $class;
+ my @keys = qw[ module version path comment author package description dslip mtime ];
+ my $tmpl = {
+ class => { default => 'CPANPLUS::Module', store => \$class },
+ map { $_ => { required => 1 } } @keys
+ };
+
+ ### dbix::simple's expansion of (??) is REALLY expensive, so do it manually
+ my $ph = join ',', map { '?' } @keys;
+
+ sub _add_module_object {
+ my $self = shift;
+ my %hash = @_;
+ my $dbh = $self->__sqlite_dbh;
+
+ my $href = do {
+ local $Params::Check::NO_DUPLICATES = 1;
+ local $Params::Check::SANITY_CHECK_TEMPLATE = 0;
+ check( $tmpl, \%hash ) or return;
+ };
+
+ ### fix up author to be 'plain' string
+ $href->{'author'} = $href->{'author'}->cpanid;
+
+ ### keep counting how many we inserted
+ unless( ++$txn_count % TXN_COMMIT ) {
+ #warn "Committing transaction $txn_count";
+ $dbh->query('COMMIT') or error( $dbh->error ); # commit previous transaction
+ $dbh->query('BEGIN') or error( $dbh->error ); # and start a new one
+ }
+
+ $dbh->query(
+ "INSERT INTO module (". join(',',keys(%$href)) .") VALUES ($ph)",
+ values %$href
+ ) or do {
+ error( $dbh->error );
+ return;
+ };
+
+ return 1;
+ }
+}
+
+{ my %map = (
+ _source_search_module_tree
+ => [ module => module => 'CPANPLUS::Module' ],
+ _source_search_author_tree
+ => [ author => cpanid => 'CPANPLUS::Module::Author' ],
+ );
+
+ while( my($sub, $aref) = each %map ) {
+ no strict 'refs';
+
+ my($table, $key, $class) = @$aref;
+ *$sub = sub {
+ my $self = shift;
+ my %hash = @_;
+ my $dbh = $self->__sqlite_dbh;
+
+ my($list,$type);
+ my $tmpl = {
+ allow => { required => 1, default => [ ], strict_type => 1,
+ store => \$list },
+ type => { required => 1, allow => [$class->accessors()],
+ store => \$type },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+
+ ### we aliased 'module' to 'name', so change that here too
+ $type = 'module' if $type eq 'name';
+
+ my $res = $dbh->query( "SELECT * from $table" );
+
+ my $meth = $table .'_tree';
+ my @rv = map { $self->$meth( $_->{$key} ) }
+ grep { allow( $_->{$type} => $list ) } $res->hashes;
+
+ return @rv;
+ }
+ }
+}
+
+
+
+sub __sqlite_create_db {
+ my $self = shift;
+ my $dbh = $self->__sqlite_dbh;
+
+ ### we can ignore the result/error; not all sqlite implemantation
+ ### support this
+ $dbh->query( qq[
+ DROP TABLE IF EXISTS author;
+ \n]
+ ) or do {
+ msg( $dbh->error );
+ };
+ $dbh->query( qq[
+ DROP TABLE IF EXISTS module;
+ \n]
+ ) or do {
+ msg( $dbh->error );
+ };
+
+
+
+ $dbh->query( qq[
+ /* the author information */
+ CREATE TABLE author (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+
+ author varchar(255),
+ email varchar(255),
+ cpanid varchar(255)
+ );
+ \n]
+
+ ) or do {
+ error( $dbh->error );
+ return;
+ };
+
+ $dbh->query( qq[
+ /* the module information */
+ CREATE TABLE module (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+
+ module varchar(255),
+ version varchar(255),
+ path varchar(255),
+ comment varchar(255),
+ author varchar(255),
+ package varchar(255),
+ description varchar(255),
+ dslip varchar(255),
+ mtime varchar(255)
+ );
+
+ \n]
+
+ ) or do {
+ error( $dbh->error );
+ return;
+ };
+
+ return 1;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Source/SQLite/Tie.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Source/SQLite/Tie.pm
new file mode 100644
index 00000000000..f908c9803e4
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Source/SQLite/Tie.pm
@@ -0,0 +1,145 @@
+package CPANPLUS::Internals::Source::SQLite::Tie;
+
+use strict;
+use warnings;
+
+use CPANPLUS::Error;
+use CPANPLUS::Module;
+use CPANPLUS::Module::Fake;
+use CPANPLUS::Module::Author::Fake;
+use CPANPLUS::Internals::Constants;
+
+
+use Params::Check qw[check];
+use Module::Load::Conditional qw[can_load];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+
+use Data::Dumper;
+$Data::Dumper::Indent = 1;
+
+require Tie::Hash;
+use vars qw[@ISA];
+push @ISA, 'Tie::StdHash';
+
+
+sub TIEHASH {
+ my $class = shift;
+ my %hash = @_;
+
+ my $tmpl = {
+ dbh => { required => 1 },
+ table => { required => 1 },
+ key => { required => 1 },
+ cb => { required => 1 },
+ offset => { default => 0 },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+ my $obj = bless { %$args, store => {} } , $class;
+
+ return $obj;
+}
+
+sub FETCH {
+ my $self = shift;
+ my $key = shift or return;
+ my $dbh = $self->{dbh};
+ my $cb = $self->{cb};
+ my $table = $self->{table};
+
+
+ ### did we look this one up before?
+ if( my $obj = $self->{store}->{$key} ) {
+ return $obj;
+ }
+
+ my $res = $dbh->query(
+ "SELECT * from $table where $self->{key} = ?", $key
+ ) or do {
+ error( $dbh->error );
+ return;
+ };
+
+ my $href = $res->hash;
+
+ ### get rid of the primary key
+ delete $href->{'id'};
+
+ ### no results?
+ return unless keys %$href;
+
+ ### expand author if needed
+ ### XXX no longer generic :(
+ if( $table eq 'module' ) {
+ $href->{author} = $cb->author_tree( $href->{author } ) or return;
+ }
+
+ my $class = {
+ module => 'CPANPLUS::Module',
+ author => 'CPANPLUS::Module::Author',
+ }->{ $table };
+
+ my $obj = $self->{store}->{$key} = $class->new( %$href, _id => $cb->_id );
+
+ return $obj;
+}
+
+sub STORE {
+ my $self = shift;
+ my $key = shift;
+ my $val = shift;
+
+ $self->{store}->{$key} = $val;
+}
+
+1;
+
+sub FIRSTKEY {
+ my $self = shift;
+ my $dbh = $self->{'dbh'};
+
+ my $res = $dbh->query(
+ "select $self->{key} from $self->{table} order by $self->{key} limit 1"
+ );
+
+ $self->{offset} = 0;
+
+ my $key = $res->flat->[0];
+
+ return $key;
+}
+
+sub NEXTKEY {
+ my $self = shift;
+ my $dbh = $self->{'dbh'};
+
+ my $res = $dbh->query(
+ "select $self->{key} from $self->{table} ".
+ "order by $self->{key} limit 1 offset $self->{offset}"
+ );
+
+ $self->{offset} +=1;
+
+ my $key = $res->flat->[0];
+ my $val = $self->FETCH( $key );
+
+ ### use each() semantics
+ return wantarray ? ( $key, $val ) : $key;
+}
+
+sub EXISTS { !!$_[0]->FETCH( $_[1] ) }
+
+sub SCALAR {
+ my $self = shift;
+ my $dbh = $self->{'dbh'};
+
+ my $res = $dbh->query( "select count(*) from $self->{table}" );
+
+ return $res->flat;
+}
+
+### intentionally left blank
+sub DELETE { }
+sub CLEAR { }
+
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Utils.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Utils.pm
new file mode 100644
index 00000000000..27d2abcdad1
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Utils.pm
@@ -0,0 +1,657 @@
+package CPANPLUS::Internals::Utils;
+
+use strict;
+
+use CPANPLUS::Error;
+use CPANPLUS::Internals::Constants;
+
+use Cwd qw[chdir];
+use File::Copy;
+use Params::Check qw[check];
+use Module::Load::Conditional qw[can_load];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+local $Params::Check::VERBOSE = 1;
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Internals::Utils
+
+=head1 SYNOPSIS
+
+ my $bool = $cb->_mkdir( dir => 'blah' );
+ my $bool = $cb->_chdir( dir => 'blah' );
+ my $bool = $cb->_rmdir( dir => 'blah' );
+
+ my $bool = $cb->_move( from => '/some/file', to => '/other/file' );
+ my $bool = $cb->_move( from => '/some/dir', to => '/other/dir' );
+
+ my $cont = $cb->_get_file_contents( file => '/path/to/file' );
+
+
+ my $version = $cb->_perl_version( perl => $^X );
+
+=head1 DESCRIPTION
+
+C<CPANPLUS::Internals::Utils> holds a few convenience functions for
+CPANPLUS libraries.
+
+=head1 METHODS
+
+=head2 $cb->_mkdir( dir => '/some/dir' )
+
+C<_mkdir> creates a full path to a directory.
+
+Returns true on success, false on failure.
+
+=cut
+
+sub _mkdir {
+ my $self = shift;
+
+ my %hash = @_;
+
+ my $tmpl = {
+ dir => { required => 1 },
+ };
+
+ my $args = check( $tmpl, \%hash ) or (
+ error(loc( Params::Check->last_error ) ), return
+ );
+
+ unless( can_load( modules => { 'File::Path' => 0.0 } ) ) {
+ error( loc("Could not use File::Path! This module should be core!") );
+ return;
+ }
+
+ eval { File::Path::mkpath($args->{dir}) };
+
+ if($@) {
+ chomp($@);
+ error(loc(qq[Could not create directory '%1': %2], $args->{dir}, $@ ));
+ return;
+ }
+
+ return 1;
+}
+
+=pod
+
+=head2 $cb->_chdir( dir => '/some/dir' )
+
+C<_chdir> changes directory to a dir.
+
+Returns true on success, false on failure.
+
+=cut
+
+sub _chdir {
+ my $self = shift;
+ my %hash = @_;
+
+ my $tmpl = {
+ dir => { required => 1, allow => DIR_EXISTS },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ unless( chdir $args->{dir} ) {
+ error( loc(q[Could not chdir into '%1'], $args->{dir}) );
+ return;
+ }
+
+ return 1;
+}
+
+=pod
+
+=head2 $cb->_rmdir( dir => '/some/dir' );
+
+Removes a directory completely, even if it is non-empty.
+
+Returns true on success, false on failure.
+
+=cut
+
+sub _rmdir {
+ my $self = shift;
+ my %hash = @_;
+
+ my $tmpl = {
+ dir => { required => 1, allow => IS_DIR },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ unless( can_load( modules => { 'File::Path' => 0.0 } ) ) {
+ error( loc("Could not use File::Path! This module should be core!") );
+ return;
+ }
+
+ eval { File::Path::rmtree($args->{dir}) };
+
+ if($@) {
+ chomp($@);
+ error(loc(qq[Could not delete directory '%1': %2], $args->{dir}, $@ ));
+ return;
+ }
+
+ return 1;
+}
+
+=pod
+
+=head2 $cb->_perl_version ( perl => 'some/perl/binary' );
+
+C<_perl_version> returns the version of a certain perl binary.
+It does this by actually running a command.
+
+Returns the perl version on success and false on failure.
+
+=cut
+
+sub _perl_version {
+ my $self = shift;
+ my %hash = @_;
+
+ my $perl;
+ my $tmpl = {
+ perl => { required => 1, store => \$perl },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ my $perl_version;
+ ### special perl, or the one we are running under?
+ if( $perl eq $^X ) {
+ ### just load the config
+ require Config;
+ $perl_version = $Config::Config{version};
+
+ } else {
+ my $cmd = $perl .
+ ' -MConfig -eprint+Config::config_vars+version';
+ ($perl_version) = (`$cmd` =~ /version='(.*)'/);
+ }
+
+ return $perl_version if defined $perl_version;
+ return;
+}
+
+=pod
+
+=head2 $cb->_version_to_number( version => $version );
+
+Returns a proper module version, or '0.0' if none was available.
+
+=cut
+
+sub _version_to_number {
+ my $self = shift;
+ my %hash = @_;
+
+ my $version;
+ my $tmpl = {
+ version => { default => '0.0', store => \$version },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ return $version if $version =~ /^\.?\d/;
+ return '0.0';
+}
+
+=pod
+
+=head2 $cb->_whoami
+
+Returns the name of the subroutine you're currently in.
+
+=cut
+
+sub _whoami { my $name = (caller 1)[3]; $name =~ s/.+:://; $name }
+
+=pod
+
+=head2 _get_file_contents( file => $file );
+
+Returns the contents of a file
+
+=cut
+
+sub _get_file_contents {
+ my $self = shift;
+ my %hash = @_;
+
+ my $file;
+ my $tmpl = {
+ file => { required => 1, store => \$file }
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ my $fh = OPEN_FILE->($file) or return;
+ my $contents = do { local $/; <$fh> };
+
+ return $contents;
+}
+
+=pod $cb->_move( from => $file|$dir, to => $target );
+
+Moves a file or directory to the target.
+
+Returns true on success, false on failure.
+
+=cut
+
+sub _move {
+ my $self = shift;
+ my %hash = @_;
+
+ my $from; my $to;
+ my $tmpl = {
+ file => { required => 1, allow => [IS_FILE,IS_DIR],
+ store => \$from },
+ to => { required => 1, store => \$to }
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ if( File::Copy::move( $from, $to ) ) {
+ return 1;
+ } else {
+ error(loc("Failed to move '%1' to '%2': %3", $from, $to, $!));
+ return;
+ }
+}
+
+=pod $cb->_copy( from => $file|$dir, to => $target );
+
+Moves a file or directory to the target.
+
+Returns true on success, false on failure.
+
+=cut
+
+sub _copy {
+ my $self = shift;
+ my %hash = @_;
+
+ my($from,$to);
+ my $tmpl = {
+ file =>{ required => 1, allow => [IS_FILE,IS_DIR],
+ store => \$from },
+ to => { required => 1, store => \$to }
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ if( File::Copy::copy( $from, $to ) ) {
+ return 1;
+ } else {
+ error(loc("Failed to copy '%1' to '%2': %3", $from, $to, $!));
+ return;
+ }
+}
+
+=head2 $cb->_mode_plus_w( file => '/path/to/file' );
+
+Sets the +w bit for the file.
+
+Returns true on success, false on failure.
+
+=cut
+
+sub _mode_plus_w {
+ my $self = shift;
+ my %hash = @_;
+
+ require File::stat;
+
+ my $file;
+ my $tmpl = {
+ file => { required => 1, allow => IS_FILE, store => \$file },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### set the mode to +w for a file and +wx for a dir
+ my $x = File::stat::stat( $file );
+ my $mask = -d $file ? 0100 : 0200;
+
+ if( $x and chmod( $x->mode|$mask, $file ) ) {
+ return 1;
+
+ } else {
+ error(loc("Failed to '%1' '%2': '%3'", 'chmod +w', $file, $!));
+ return;
+ }
+}
+
+=head2 $uri = $cb->_host_to_uri( scheme => SCHEME, host => HOST, path => PATH );
+
+Turns a CPANPLUS::Config style C<host> entry into an URI string.
+
+Returns the uri on success, and false on failure
+
+=cut
+
+sub _host_to_uri {
+ my $self = shift;
+ my %hash = @_;
+
+ my($scheme, $host, $path);
+ my $tmpl = {
+ scheme => { required => 1, store => \$scheme },
+ host => { default => 'localhost', store => \$host },
+ path => { default => '', store => \$path },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### it's an URI, so unixify the path.
+ ### VMS has a special method for just that
+ $path = ON_VMS
+ ? VMS::Filespec::unixify($path)
+ : File::Spec::Unix->catdir( File::Spec->splitdir( $path ) );
+
+ return "$scheme://" . File::Spec::Unix->catdir( $host, $path );
+}
+
+=head2 $cb->_vcmp( VERSION, VERSION );
+
+Normalizes the versions passed and does a '<=>' on them, returning the result.
+
+=cut
+
+sub _vcmp {
+ my $self = shift;
+ my ($x, $y) = @_;
+
+ s/_//g foreach $x, $y;
+
+ return $x <=> $y;
+}
+
+=head2 $cb->_home_dir
+
+Returns the user's homedir, or C<cwd> if it could not be found
+
+=cut
+
+sub _home_dir {
+ my @os_home_envs = qw( APPDATA HOME USERPROFILE WINDIR SYS$LOGIN );
+
+ for my $env ( @os_home_envs ) {
+ next unless exists $ENV{ $env };
+ next unless defined $ENV{ $env } && length $ENV{ $env };
+ return $ENV{ $env } if -d $ENV{ $env };
+ }
+
+ return cwd();
+}
+
+=head2 $path = $cb->_safe_path( path => $path );
+
+Returns a path that's safe to us on Win32 and VMS.
+
+Only cleans up the path on Win32 if the path exists.
+
+On VMS, it encodes dots to _ using C<VMS::Filespec::vmsify>
+
+=cut
+
+sub _safe_path {
+ my $self = shift;
+
+ my %hash = @_;
+
+ my $path;
+ my $tmpl = {
+ path => { required => 1, store => \$path },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ if( ON_WIN32 ) {
+ ### only need to fix it up if there's spaces in the path
+ return $path unless $path =~ /\s+/;
+
+ ### clean up paths if we are on win32
+ return Win32::GetShortPathName( $path ) || $path;
+
+ } elsif ( ON_VMS ) {
+ ### XXX According to John Malmberg, there's an VMS issue:
+ ### catdir on VMS can not currently deal with directory components
+ ### with dots in them.
+ ### Fixing this is a a three step procedure, which will work for
+ ### VMS in its traditional ODS-2 mode, and it will also work if
+ ### VMS is in the ODS-5 mode that is being implemented.
+ ### If the path is already in VMS syntax, assume that we are done.
+
+ ### VMS format is a path with a trailing ']' or ':'
+ return $path if $path =~ /\:|\]$/;
+
+ ### 1. Make sure that the value to be converted, $path is
+ ### in UNIX directory syntax by appending a '/' to it.
+ $path .= '/' unless $path =~ m|/$|;
+
+ ### 2. Use VMS::Filespec::vmsify($path . '/') to convert the dots to
+ ### underscores if needed. The trailing '/' is needed as so that
+ ### C<vmsify> knows that it should use directory translation instead of
+ ### filename translation, as filename translation leaves one dot.
+ $path = VMS::Filespec::vmsify( $path );
+
+ ### 3. Use $path = File::Spec->splitdir( VMS::Filespec::vmsify(
+ ### $path . '/') to remove the directory delimiters.
+
+ ### From John Malmberg:
+ ### File::Spec->catdir will put the path back together.
+ ### The '/' trick only works if the string is a directory name
+ ### with UNIX style directory delimiters or no directory delimiters.
+ ### It is to force vmsify to treat the input specification as UNIX.
+ ###
+ ### There is a VMS::Filespec::unixpath() to do the appending of the '/'
+ ### to the specification, which will do a VMS::Filespec::vmsify()
+ ### if needed.
+ ### However it is not a good idea to call vmsify() on a pathname
+ ### returned by unixify(), and it is not a good idea to call unixify()
+ ### on a pathname returned by vmsify(). Because of the nature of the
+ ### conversion, not all file specifications can make the round trip.
+ ###
+ ### I think that directory specifications can safely make the round
+ ### trip, but not ones containing filenames.
+ $path = File::Spec->catdir( File::Spec->splitdir( $path ) )
+ }
+
+ return $path;
+}
+
+
+=head2 ($pkg, $version, $ext) = $cb->_split_package_string( package => PACKAGE_STRING );
+
+Splits the name of a CPAN package string up into its package, version
+and extension parts.
+
+For example, C<Foo-Bar-1.2.tar.gz> would return the following parts:
+
+ Package: Foo-Bar
+ Version: 1.2
+ Extension: tar.gz
+
+=cut
+
+{ my $del_re = qr/[-_\+]/i; # delimiter between elements
+ my $pkg_re = qr/[a-z] # any letters followed by
+ [a-z\d]* # any letters, numbers
+ (?i:\.pm)? # followed by '.pm'--authors do this :(
+ (?: # optionally repeating:
+ $del_re # followed by a delimiter
+ [a-z] # any letters followed by
+ [a-z\d]* # any letters, numbers
+ (?i:\.pm)? # followed by '.pm'--authors do this :(
+ )*
+ /xi;
+
+ my $ver_re = qr/[a-z]*\d*?[a-z]* # contains a digit and possibly letters
+ (?: # however, some start with a . only :(
+ [-._] # followed by a delimiter
+ [a-z\d]+ # and more digits and or letters
+ )*?
+ /xi;
+
+ my $ext_re = qr/[a-z] # a letter, followed by
+ [a-z\d]* # letters and or digits, optionally
+ (?:
+ \. # followed by a dot and letters
+ [a-z\d]+ # and or digits (like .tar.bz2)
+ )? # optionally
+ /xi;
+
+ my $ver_ext_re = qr/
+ ($ver_re+) # version, optional
+ (?:
+ \. # a literal .
+ ($ext_re) # extension,
+ )? # optional, but requires version
+ /xi;
+
+ ### composed regex for CPAN packages
+ my $full_re = qr/
+ ^
+ ( # the whole thing
+ ($pkg_re+) # package
+ (?:
+ $del_re # delimiter
+ $ver_ext_re # version + extension
+ )?
+ )
+ $
+ /xi;
+
+ ### composed regex for perl packages
+ my $perl = PERL_CORE;
+ my $perl_re = qr/
+ ^
+ ( # the whole thing
+ ($perl) # package name for 'perl'
+ (?:
+ $ver_ext_re # version + extension
+ )?
+ )
+ $
+ /xi;
+
+
+sub _split_package_string {
+ my $self = shift;
+ my %hash = @_;
+
+ my $str;
+ my $tmpl = { package => { required => 1, store => \$str } };
+ check( $tmpl, \%hash ) or return;
+
+
+ ### 2 different regexes, one for the 'perl' package,
+ ### one for ordinary CPAN packages.. try them both,
+ ### first match wins.
+ for my $re ( $full_re, $perl_re ) {
+
+ ### try the next if the match fails
+ $str =~ $re or next;
+
+ my $full = $1 || '';
+ my $pkg = $2 || '';
+ my $ver = $3 || '';
+ my $ext = $4 || '';
+
+ ### this regex resets the capture markers!
+ ### strip the trailing delimiter
+ $pkg =~ s/$del_re$//;
+
+ ### strip the .pm package suffix some authors insist on adding
+ $pkg =~ s/\.pm$//i;
+
+ return ($pkg, $ver, $ext, $full );
+ }
+
+ return;
+ }
+}
+
+{ my %escapes = map {
+ chr($_) => sprintf("%%%02X", $_)
+ } 0 .. 255;
+
+ sub _uri_encode {
+ my $self = shift;
+ my %hash = @_;
+
+ my $str;
+ my $tmpl = {
+ uri => { store => \$str, required => 1 }
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### XXX taken straight from URI::Encode
+ ### Default unsafe characters. RFC 2732 ^(uric - reserved)
+ $str =~ s|([^A-Za-z0-9\-_.!~*'()])|$escapes{$1}|g;
+
+ return $str;
+ }
+
+
+ sub _uri_decode {
+ my $self = shift;
+ my %hash = @_;
+
+ my $str;
+ my $tmpl = {
+ uri => { store => \$str, required => 1 }
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### XXX use unencode routine in utils?
+ $str =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
+
+ return $str;
+ }
+}
+
+sub _update_timestamp {
+ my $self = shift;
+ my %hash = @_;
+
+ my $file;
+ my $tmpl = {
+ file => { required => 1, store => \$file, allow => FILE_EXISTS }
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### `touch` the file, so windoze knows it's new -jmb
+ ### works on *nix too, good fix -Kane
+ ### make sure it is writable first, otherwise the `touch` will fail
+
+ my $now = time;
+ unless( chmod( 0644, $file) && utime ($now, $now, $file) ) {
+ error( loc("Couldn't touch %1", $file) );
+ return;
+ }
+
+ return 1;
+}
+
+
+1;
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Utils/Autoflush.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Utils/Autoflush.pm
new file mode 100644
index 00000000000..56566436a14
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Internals/Utils/Autoflush.pm
@@ -0,0 +1,5 @@
+package CPANPLUS::Internals::Utils::Autoflush;
+
+BEGIN { $|++ };
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Module.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Module.pm
new file mode 100644
index 00000000000..9e4b67e4a38
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Module.pm
@@ -0,0 +1,1815 @@
+package CPANPLUS::Module;
+
+use strict;
+use vars qw[@ISA];
+
+
+use CPANPLUS::Dist;
+use CPANPLUS::Error;
+use CPANPLUS::Module::Signature;
+use CPANPLUS::Module::Checksums;
+use CPANPLUS::Internals::Constants;
+
+use FileHandle;
+
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+use IPC::Cmd qw[can_run run];
+use File::Find qw[find];
+use Params::Check qw[check];
+use File::Basename qw[dirname];
+use Module::Load::Conditional qw[can_load check_install];
+
+$Params::Check::VERBOSE = 1;
+
+@ISA = qw[ CPANPLUS::Module::Signature CPANPLUS::Module::Checksums];
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Module
+
+=head1 SYNOPSIS
+
+ ### get a module object from the CPANPLUS::Backend object
+ my $mod = $cb->module_tree('Some::Module');
+
+ ### accessors
+ $mod->version;
+ $mod->package;
+
+ ### methods
+ $mod->fetch;
+ $mod->extract;
+ $mod->install;
+
+
+=head1 DESCRIPTION
+
+C<CPANPLUS::Module> creates objects from the information in the
+source files. These can then be used to query and perform actions
+on, like fetching or installing.
+
+These objects should only be created internally. For C<fake> objects,
+there's the C<CPANPLUS::Module::Fake> class. To obtain a module object
+consult the C<CPANPLUS::Backend> documentation.
+
+=cut
+
+my $tmpl = {
+ module => { default => '', required => 1 }, # full module name
+ version => { default => '0.0' }, # version number
+ path => { default => '', required => 1 }, # extended path on the
+ # cpan mirror, like
+ # /author/id/K/KA/KANE
+ comment => { default => ''}, # comment on module
+ package => { default => '', required => 1 }, # package name, like
+ # 'bar-baz-1.03.tgz'
+ description => { default => '' }, # description of the
+ # module
+ dslip => { default => EMPTY_DSLIP }, # dslip information
+ _id => { required => 1 }, # id of the Internals
+ # parent object
+ _status => { no_override => 1 }, # stores status object
+ author => { default => '', required => 1,
+ allow => IS_AUTHOBJ }, # module author
+ mtime => { default => '' },
+};
+
+### some of these will be resolved by wrapper functions that
+### do Clever Things to find the actual value, so don't create
+### an autogenerated sub for that just here, take an alternate
+### name to allow for a wrapper
+{ my %rename = (
+ dslip => '_dslip'
+ );
+
+ ### autogenerate accessors ###
+ for my $key ( keys %$tmpl ) {
+ no strict 'refs';
+
+ my $sub = $rename{$key} || $key;
+
+ *{__PACKAGE__."::$sub"} = sub {
+ $_[0]->{$key} = $_[1] if @_ > 1;
+ return $_[0]->{$key};
+ }
+ }
+}
+
+
+=pod
+
+=head1 CLASS METHODS
+
+=head2 accessors ()
+
+Returns a list of all accessor methods to the object
+
+=cut
+
+### *name is an alias, include it explicitly
+sub accessors { return ('name', keys %$tmpl) };
+
+=head1 ACCESSORS
+
+An objects of this class has the following accessors:
+
+=over 4
+
+=item name
+
+Name of the module.
+
+=item module
+
+Name of the module.
+
+=item version
+
+Version of the module. Defaults to '0.0' if none was provided.
+
+=item path
+
+Extended path on the mirror.
+
+=item comment
+
+Any comment about the module -- largely unused.
+
+=item package
+
+The name of the package.
+
+=item description
+
+Description of the module -- only registered modules have this.
+
+=item dslip
+
+The five character dslip string, that represents meta-data of the
+module -- again, only registered modules have this.
+
+=cut
+
+sub dslip {
+ my $self = shift;
+
+ ### if this module has relevant dslip info, return it
+ return $self->_dslip if $self->_dslip ne EMPTY_DSLIP;
+
+ ### if not, look at other modules in the same package,
+ ### see if *they* have any dslip info
+ for my $mod ( $self->contains ) {
+ return $mod->_dslip if $mod->_dslip ne EMPTY_DSLIP;
+ }
+
+ ### ok, really no dslip info found, return the default
+ return EMPTY_DSLIP;
+}
+
+
+=pod
+
+=item status
+
+The C<CPANPLUS::Module::Status> object associated with this object.
+(see below).
+
+=item author
+
+The C<CPANPLUS::Module::Author> object associated with this object.
+
+=item parent
+
+The C<CPANPLUS::Internals> object that spawned this module object.
+
+=back
+
+=cut
+
+### Alias ->name to ->module, for human beings.
+*name = *module;
+
+sub parent {
+ my $self = shift;
+ my $obj = CPANPLUS::Internals->_retrieve_id( $self->_id );
+
+ return $obj;
+}
+
+=head1 STATUS ACCESSORS
+
+C<CPANPLUS> caches a lot of results from method calls and saves data
+it collected along the road for later reuse.
+
+C<CPANPLUS> uses this internally, but it is also available for the end
+user. You can get a status object by calling:
+
+ $modobj->status
+
+You can then query the object as follows:
+
+=over 4
+
+=item installer_type
+
+The installer type used for this distribution. Will be one of
+'makemaker' or 'build'. This determines whether C<CPANPLUS::Dist::MM>
+or C<CPANPLUS::Dist::Build> will be used to build this distribution.
+
+=item dist_cpan
+
+The dist object used to do the CPAN-side of the installation. Either
+a C<CPANPLUS::Dist::MM> or C<CPANPLUS::Dist::Build> object.
+
+=item dist
+
+The custom dist object used to do the operating specific side of the
+installation, if you've chosen to use this. For example, if you've
+chosen to install using the C<ports> format, this may be a
+C<CPANPLUS::Dist::Ports> object.
+
+Undefined if you didn't specify a separate format to install through.
+
+=item prereqs | requires
+
+A hashref of prereqs this distribution was found to have. Will look
+something like this:
+
+ { Carp => 0.01, strict => 0 }
+
+Might be undefined if the distribution didn't have any prerequisites.
+
+=item configure_requires
+
+Like prereqs, but these are necessary to be installed before the
+build process can even begin.
+
+=item signature
+
+Flag indicating, if a signature check was done, whether it was OK or
+not.
+
+=item extract
+
+The directory this distribution was extracted to.
+
+=item fetch
+
+The location this distribution was fetched to.
+
+=item readme
+
+The text of this distributions README file.
+
+=item uninstall
+
+Flag indicating if an uninstall call was done successfully.
+
+=item created
+
+Flag indicating if the C<create> call to your dist object was done
+successfully.
+
+=item installed
+
+Flag indicating if the C<install> call to your dist object was done
+successfully.
+
+=item checksums
+
+The location of this distributions CHECKSUMS file.
+
+=item checksum_ok
+
+Flag indicating if the checksums check was done successfully.
+
+=item checksum_value
+
+The checksum value this distribution is expected to have
+
+=back
+
+=head1 METHODS
+
+=head2 $self = CPANPLUS::Module->new( OPTIONS )
+
+This method returns a C<CPANPLUS::Module> object. Normal users
+should never call this method directly, but instead use the
+C<CPANPLUS::Backend> to obtain module objects.
+
+This example illustrates a C<new()> call with all required arguments:
+
+ CPANPLUS::Module->new(
+ module => 'Foo',
+ path => 'authors/id/A/AA/AAA',
+ package => 'Foo-1.0.tgz',
+ author => $author_object,
+ _id => INTERNALS_OBJECT_ID,
+ );
+
+Every accessor is also a valid option to pass to C<new>.
+
+Returns a module object on success and false on failure.
+
+=cut
+
+
+sub new {
+ my($class, %hash) = @_;
+
+ ### don't check the template for sanity
+ ### -- we know it's good and saves a lot of performance
+ local $Params::Check::SANITY_CHECK_TEMPLATE = 0;
+
+ my $object = check( $tmpl, \%hash ) or return;
+
+ bless $object, $class;
+
+ return $object;
+}
+
+### only create status objects when they're actually asked for
+sub status {
+ my $self = shift;
+ return $self->_status if $self->_status;
+
+ my $acc = Object::Accessor->new;
+ $acc->mk_accessors( qw[ installer_type dist_cpan dist prereqs
+ signature extract fetch readme uninstall
+ created installed prepared checksums files
+ checksum_ok checksum_value _fetch_from
+ configure_requires
+ ] );
+
+ ### create an alias from 'requires' to 'prereqs', so it's more in
+ ### line with 'configure_requires';
+ $acc->mk_aliases( requires => 'prereqs' );
+
+ $self->_status( $acc );
+
+ return $self->_status;
+}
+
+
+### flush the cache of this object ###
+sub _flush {
+ my $self = shift;
+ $self->status->mk_flush;
+ return 1;
+}
+
+=head2 $mod->package_name( [$package_string] )
+
+Returns the name of the package a module is in. For C<Acme::Bleach>
+that might be C<Acme-Bleach>.
+
+=head2 $mod->package_version( [$package_string] )
+
+Returns the version of the package a module is in. For a module
+in the package C<Acme-Bleach-1.1.tar.gz> this would be C<1.1>.
+
+=head2 $mod->package_extension( [$package_string] )
+
+Returns the suffix added by the compression method of a package a
+certain module is in. For a module in C<Acme-Bleach-1.1.tar.gz>, this
+would be C<tar.gz>.
+
+=head2 $mod->package_is_perl_core
+
+Returns a boolean indicating of the package a particular module is in,
+is actually a core perl distribution.
+
+=head2 $mod->module_is_supplied_with_perl_core( [version => $]] )
+
+Returns a boolean indicating whether C<ANY VERSION> of this module
+was supplied with the current running perl's core package.
+
+=head2 $mod->is_bundle
+
+Returns a boolean indicating if the module you are looking at, is
+actually a bundle. Bundles are identified as modules whose name starts
+with C<Bundle::>.
+
+=head2 $mod->is_autobundle;
+
+Returns a boolean indicating if the module you are looking at, is
+actually an autobundle as generated by C<< $cb->autobundle >>.
+
+=head2 $mod->is_third_party
+
+Returns a boolean indicating whether the package is a known third-party
+module (i.e. it's not provided by the standard Perl distribution and
+is not available on the CPAN, but on a third party software provider).
+See L<Module::ThirdParty> for more details.
+
+=head2 $mod->third_party_information
+
+Returns a reference to a hash with more information about a third-party
+module. See the documentation about C<module_information()> in
+L<Module::ThirdParty> for more details.
+
+=cut
+
+{ ### fetches the test reports for a certain module ###
+ my %map = (
+ name => 0,
+ version => 1,
+ extension => 2,
+ );
+
+ while ( my($type, $index) = each %map ) {
+ my $name = 'package_' . $type;
+
+ no strict 'refs';
+ *$name = sub {
+ my $self = shift;
+ my $val = shift || $self->package;
+ my @res = $self->parent->_split_package_string( package => $val );
+
+ ### return the corresponding index from the result
+ return $res[$index] if @res;
+ return;
+ };
+ }
+
+ sub package_is_perl_core {
+ my $self = shift;
+ my $cb = $self->parent;
+
+ ### check if the package looks like a perl core package
+ return 1 if $self->package_name eq PERL_CORE;
+
+ ### address #44562: ::Module->package_is_perl_code : problem comparing
+ ### version strings -- use $cb->_vcmp to avoid warnings when version
+ ### have _ in them
+
+ my $core = $self->module_is_supplied_with_perl_core;
+ ### ok, so it's found in the core, BUT it could be dual-lifed
+ if ($core) {
+ ### if the package is newer than installed, then it's dual-lifed
+ return if $cb->_vcmp($self->version, $self->installed_version) > 0;
+
+ ### if the package is newer or equal to the corelist,
+ ### then it's dual-lifed
+ return if $cb->_vcmp( $self->version, $core ) >= 0;
+
+ ### otherwise, it's older than corelist, thus unsuitable.
+ return 1;
+ }
+
+ ### not in corelist, not a perl core package.
+ return;
+ }
+
+ sub module_is_supplied_with_perl_core {
+ my $self = shift;
+ my $ver = shift || $];
+
+ ### allow it to be called as a package function as well like:
+ ### CPANPLUS::Module::module_is_supplied_with_perl_core('Config')
+ ### so that we can check the status of modules that aren't released
+ ### to CPAN, but are part of the core.
+ my $name = ref $self ? $self->module : $self;
+
+ ### check Module::CoreList to see if it's a core package
+ require Module::CoreList;
+
+ ### Address #41157: Module::module_is_supplied_with_perl_core()
+ ### broken for perl 5.10: Module::CoreList's version key for the
+ ### hash has a different number of trailing zero than $] aka
+ ### $PERL_VERSION.
+ my $core = $Module::CoreList::version{ 0+$ver }->{ $name };
+
+ return $core;
+ }
+
+ ### make sure Bundle-Foo also gets flagged as bundle
+ sub is_bundle {
+ my $self = shift;
+
+ ### cpan'd bundle
+ return 1 if $self->module =~ /^bundle(?:-|::)/i;
+
+ ### autobundle
+ return 1 if $self->is_autobundle;
+
+ ### neither
+ return;
+ }
+
+ ### full path to a generated autobundle
+ sub is_autobundle {
+ my $self = shift;
+ my $conf = $self->parent->configure_object;
+ my $prefix = $conf->_get_build('autobundle_prefix');
+
+ return 1 if $self->module eq $prefix;
+ return;
+ }
+
+ sub is_third_party {
+ my $self = shift;
+
+ return unless can_load( modules => { 'Module::ThirdParty' => 0 } );
+
+ return Module::ThirdParty::is_3rd_party( $self->name );
+ }
+
+ sub third_party_information {
+ my $self = shift;
+
+ return unless $self->is_third_party;
+
+ return Module::ThirdParty::module_information( $self->name );
+ }
+}
+
+=pod
+
+=head2 $clone = $self->clone
+
+Clones the current module object for tinkering with.
+It will have a clean C<CPANPLUS::Module::Status> object, as well as
+a fake C<CPANPLUS::Module::Author> object.
+
+=cut
+
+{ ### accessors dont change during run time, so only compute once
+ my @acc = grep !/status/, __PACKAGE__->accessors();
+
+ sub clone {
+ my $self = shift;
+
+ ### clone the object ###
+ my %data = map { $_ => $self->$_ } @acc;
+
+ my $obj = CPANPLUS::Module::Fake->new( %data );
+
+ return $obj;
+ }
+}
+
+=pod
+
+=head2 $where = $self->fetch
+
+Fetches the module from a CPAN mirror.
+Look at L<CPANPLUS::Internals::Fetch::_fetch()> for details on the
+options you can pass.
+
+=cut
+
+sub fetch {
+ my $self = shift;
+ my $cb = $self->parent;
+
+ ### custom args
+ my %args = ( module => $self );
+
+ ### if a custom fetch location got specified before, add that here
+ $args{fetch_from} = $self->status->_fetch_from
+ if $self->status->_fetch_from;
+
+ my $where = $cb->_fetch( @_, %args ) or return;
+
+ ### do an md5 check ###
+ if( !$self->status->_fetch_from and
+ $cb->configure_object->get_conf('md5') and
+ $self->package ne CHECKSUMS
+ ) {
+ unless( $self->_validate_checksum ) {
+ error( loc( "Checksum error for '%1' -- will not trust package",
+ $self->package) );
+ return;
+ }
+ }
+
+ return $where;
+}
+
+=pod
+
+=head2 $path = $self->extract
+
+Extracts the fetched module.
+Look at L<CPANPLUS::Internals::Extract::_extract()> for details on
+the options you can pass.
+
+=cut
+
+sub extract {
+ my $self = shift;
+ my $cb = $self->parent;
+
+ unless( $self->status->fetch ) {
+ error( loc( "You have not fetched '%1' yet -- cannot extract",
+ $self->module) );
+ return;
+ }
+
+ ### can't extract these, so just use the basedir for the file
+ if( $self->is_autobundle ) {
+
+ ### this is expected to be set after an extract call
+ $self->get_installer_type;
+
+ return $self->status->extract( dirname( $self->status->fetch ) );
+ }
+
+ return $cb->_extract( @_, module => $self );
+}
+
+=head2 $type = $self->get_installer_type([prefer_makefile => BOOL])
+
+Gets the installer type for this module. This may either be C<build> or
+C<makemaker>. If C<Module::Build> is unavailable or no installer type
+is available, it will fall back to C<makemaker>. If both are available,
+it will pick the one indicated by your config, or by the
+C<prefer_makefile> option you can pass to this function.
+
+Returns the installer type on success, and false on error.
+
+=cut
+
+sub get_installer_type {
+ my $self = shift;
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my ($prefer_makefile,$verbose);
+ my $tmpl = {
+ prefer_makefile => { default => $conf->get_conf('prefer_makefile'),
+ store => \$prefer_makefile, allow => BOOLEANS },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ my $type;
+
+ ### autobundles use their own installer, so return that
+ if( $self->is_autobundle ) {
+ $type = INSTALLER_AUTOBUNDLE;
+
+ } else {
+ my $extract = $self->status->extract();
+ unless( $extract ) {
+ error(loc(
+ "Cannot determine installer type of unextracted module '%1'",
+ $self->module
+ ));
+ return;
+ }
+
+ ### check if it's a makemaker or a module::build type dist ###
+ my $found_build = -e BUILD_PL->( $extract );
+ my $found_makefile = -e MAKEFILE_PL->( $extract );
+
+ $type = INSTALLER_BUILD if !$prefer_makefile && $found_build;
+ $type = INSTALLER_BUILD if $found_build && !$found_makefile;
+ $type = INSTALLER_MM if $prefer_makefile && $found_makefile;
+ $type = INSTALLER_MM if $found_makefile && !$found_build;
+ }
+
+ ### ok, so it's a 'build' installer, but you don't /have/ module build
+ ### XXX duplicated from CPANPLUS::Selfupdate. fix somehow?
+ if( $type and $type eq INSTALLER_BUILD and (
+ not CPANPLUS::Dist->has_dist_type( INSTALLER_BUILD )
+ or not $cb->module_tree( INSTALLER_BUILD )
+ ->is_uptodate( version => '0.24' )
+ ) ) {
+
+ ### XXX this is for recording purposes only. We *have* to install
+ ### these before even creating a dist object, or we'll get an error
+ ### saying 'no such dist type';
+ ### XXX duplicated from CPANPLUS::Selfupdate. fix somehow?
+ my $href = $self->status->configure_requires || {};
+ my $deps = { INSTALLER_BUILD, '0.24', %$href };
+
+ $self->status->configure_requires( $deps );
+
+ msg(loc("This module requires '%1' and '%2' to be installed first. ".
+ "Adding these modules to your prerequisites list",
+ 'Module::Build', INSTALLER_BUILD
+ ), $verbose );
+
+
+ ### ok, actually we found neither ###
+ } elsif ( !$type ) {
+ error( loc( "Unable to find '%1' or '%2' for '%3'; ".
+ "Will default to '%4' but might be unable ".
+ "to install!", BUILD_PL->(), MAKEFILE_PL->(),
+ $self->module, INSTALLER_MM ) );
+ $type = INSTALLER_MM;
+ }
+
+ return $self->status->installer_type( $type ) if $type;
+ return;
+}
+
+=pod
+
+=head2 $dist = $self->dist([target => 'prepare|create', format => DISTRIBUTION_TYPE, args => {key => val}]);
+
+Create a distribution object, ready to be installed.
+Distribution type defaults to your config settings
+
+The optional C<args> hashref is passed on to the specific distribution
+types' C<create> method after being dereferenced.
+
+Returns a distribution object on success, false on failure.
+
+See C<CPANPLUS::Dist> for details.
+
+=cut
+
+sub dist {
+ my $self = shift;
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ ### have you determined your installer type yet? if not, do it here,
+ ### we need the info
+ $self->get_installer_type unless $self->status->installer_type;
+
+ my($type,$args,$target);
+ my $tmpl = {
+ format => { default => $conf->get_conf('dist_type') ||
+ $self->status->installer_type,
+ store => \$type },
+ target => { default => TARGET_CREATE, store => \$target },
+ args => { default => {}, store => \$args },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### ok, check for $type. Do we have it?
+ unless( CPANPLUS::Dist->has_dist_type( $type ) ) {
+
+ ### ok, we don't have it. Is it C::D::Build? if so we can install the
+ ### whole thing now
+ ### XXX we _could_ do this for any type we dont have actually...
+ if( $type eq INSTALLER_BUILD ) {
+ msg(loc("Bootstrapping installer '%1'", $type));
+
+ ### don't propagate the format, it's the one we're trying to
+ ### bootstrap, so it'll be an infinite loop if we do
+
+ $cb->module_tree( $type )->install( target => $target, %$args ) or
+ do {
+ error(loc("Could not bootstrap installer '%1' -- ".
+ "can not continue", $type));
+ return;
+ };
+
+ ### re-scan for available modules now
+ CPANPLUS::Dist->rescan_dist_types;
+
+ unless( CPANPLUS::Dist->has_dist_type( $type ) ) {
+ error(loc("Newly installed installer type '%1' should be ".
+ "available, but is not! -- aborting", $type));
+ return;
+ } else {
+ msg(loc("Installer '%1' succesfully bootstrapped", $type));
+ }
+
+ ### some other plugin you dont have. Abort
+ } else {
+ error(loc("Installer type '%1' not found. Please verify your ".
+ "installation -- aborting", $type ));
+ return;
+ }
+ }
+
+ ### make sure we don't overwrite it, just in case we came
+ ### back from a ->save_state. This allows restoration to
+ ### work correctly
+ my( $dist, $dist_cpan );
+
+ unless( $dist = $self->status->dist ) {
+ $dist = $type->new( module => $self ) or return;
+ $self->status->dist( $dist );
+ }
+
+ unless( $dist_cpan = $self->status->dist_cpan ) {
+
+ $dist_cpan = $type eq $self->status->installer_type
+ ? $self->status->dist
+ : $self->status->installer_type->new( module => $self );
+
+
+ $self->status->dist_cpan( $dist_cpan );
+ }
+
+
+ DIST: {
+ ### just wanted the $dist object?
+ last DIST if $target eq TARGET_INIT;
+
+ ### first prepare the dist
+ $dist->prepare( %$args ) or return;
+ $self->status->prepared(1);
+
+ ### you just wanted us to prepare?
+ last DIST if $target eq TARGET_PREPARE;
+
+ $dist->create( %$args ) or return;
+ $self->status->created(1);
+ }
+
+ return $dist;
+}
+
+=pod
+
+=head2 $bool = $mod->prepare( )
+
+Convenience method around C<install()> that prepares a module
+without actually building it. This is equivalent to invoking C<install>
+with C<target> set to C<prepare>
+
+Returns true on success, false on failure.
+
+=cut
+
+sub prepare {
+ my $self = shift;
+ return $self->install( @_, target => TARGET_PREPARE );
+}
+
+=head2 $bool = $mod->create( )
+
+Convenience method around C<install()> that creates a module.
+This is equivalent to invoking C<install> with C<target> set to
+C<create>
+
+Returns true on success, false on failure.
+
+=cut
+
+sub create {
+ my $self = shift;
+ return $self->install( @_, target => TARGET_CREATE );
+}
+
+=head2 $bool = $mod->test( )
+
+Convenience wrapper around C<install()> that tests a module, without
+installing it.
+It's the equivalent to invoking C<install()> with C<target> set to
+C<create> and C<skiptest> set to C<0>.
+
+Returns true on success, false on failure.
+
+=cut
+
+sub test {
+ my $self = shift;
+ return $self->install( @_, target => TARGET_CREATE, skiptest => 0 );
+}
+
+=pod
+
+=head2 $bool = $self->install([ target => 'init|prepare|create|install', format => FORMAT_TYPE, extractdir => DIRECTORY, fetchdir => DIRECTORY, prefer_bin => BOOL, force => BOOL, verbose => BOOL, ..... ]);
+
+Installs the current module. This includes fetching it and extracting
+it, if this hasn't been done yet, as well as creating a distribution
+object for it.
+
+This means you can pass it more arguments than described above, which
+will be passed on to the relevant methods as they are called.
+
+See C<CPANPLUS::Internals::Fetch>, C<CPANPLUS::Internals::Extract> and
+C<CPANPLUS::Dist> for details.
+
+Returns true on success, false on failure.
+
+=cut
+
+sub install {
+ my $self = shift;
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my $args; my $target; my $format;
+ { ### so we can use the rest of the args to the create calls etc ###
+ local $Params::Check::NO_DUPLICATES = 1;
+ local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ ### targets 'dist' and 'test' are now completely ignored ###
+ my $tmpl = {
+ ### match this allow list with Dist->_resolve_prereqs
+ target => { default => TARGET_INSTALL, store => \$target,
+ allow => [TARGET_PREPARE, TARGET_CREATE,
+ TARGET_INSTALL, TARGET_INIT ] },
+ force => { default => $conf->get_conf('force'), },
+ verbose => { default => $conf->get_conf('verbose'), },
+ format => { default => $conf->get_conf('dist_type'),
+ store => \$format },
+ };
+
+ $args = check( $tmpl, \%hash ) or return;
+ }
+
+
+ ### if this target isn't 'install', we will need to at least 'create'
+ ### every prereq, so it can build
+ ### XXX prereq_target of 'prepare' will do weird things here, and is
+ ### not supported.
+ $args->{'prereq_target'} ||= TARGET_CREATE if $target ne TARGET_INSTALL;
+
+ ### check if it's already upto date ###
+ if( $target eq TARGET_INSTALL and !$args->{'force'} and
+ !$self->package_is_perl_core() and # separate rules apply
+ ( $self->status->installed() or $self->is_uptodate ) and
+ !INSTALL_VIA_PACKAGE_MANAGER->($format)
+ ) {
+ msg(loc("Module '%1' already up to date, won't install without force",
+ $self->module), $args->{'verbose'} );
+ return $self->status->installed(1);
+ }
+
+ # if it's a non-installable core package, abort the install.
+ if( $self->package_is_perl_core() ) {
+ # if the installed is newer, say so.
+ if( $self->installed_version > $self->version ) {
+ error(loc("The core Perl %1 module '%2' (%3) is more ".
+ "recent than the latest release on CPAN (%4). ".
+ "Aborting install.",
+ $], $self->module, $self->installed_version,
+ $self->version ) );
+ # if the installed matches, say so.
+ } elsif( $self->installed_version == $self->version ) {
+ error(loc("The core Perl %1 module '%2' (%3) can only ".
+ "be installed by Perl itself. ".
+ "Aborting install.",
+ $], $self->module, $self->installed_version ) );
+ # otherwise, the installed is older; say so.
+ } else {
+ error(loc("The core Perl %1 module '%2' can only be ".
+ "upgraded from %3 to %4 by Perl itself (%5). ".
+ "Aborting install.",
+ $], $self->module, $self->installed_version,
+ $self->version, $self->package ) );
+ }
+ return;
+
+ ### it might be a known 3rd party module
+ } elsif ( $self->is_third_party ) {
+ my $info = $self->third_party_information;
+ error(loc(
+ "%1 is a known third-party module.\n\n".
+ "As it isn't available on the CPAN, CPANPLUS can't install " .
+ "it automatically. Therefore you need to install it manually " .
+ "before proceeding.\n\n".
+ "%2 is part of %3, published by %4, and should be available ".
+ "for download at the following address:\n\t%5",
+ $self->name, $self->name, $info->{name}, $info->{author},
+ $info->{url}
+ ));
+
+ return;
+ }
+
+ ### fetch it if need be ###
+ unless( $self->status->fetch ) {
+ my $params;
+ for (qw[prefer_bin fetchdir]) {
+ $params->{$_} = $args->{$_} if exists $args->{$_};
+ }
+ for (qw[force verbose]) {
+ $params->{$_} = $args->{$_} if defined $args->{$_};
+ }
+ $self->fetch( %$params ) or return;
+ }
+
+ ### extract it if need be ###
+ unless( $self->status->extract ) {
+ my $params;
+ for (qw[prefer_bin extractdir]) {
+ $params->{$_} = $args->{$_} if exists $args->{$_};
+ }
+ for (qw[force verbose]) {
+ $params->{$_} = $args->{$_} if defined $args->{$_};
+ }
+ $self->extract( %$params ) or return;
+ }
+
+ $format ||= $self->status->installer_type;
+
+ unless( $format ) {
+ error( loc( "Don't know what installer to use; " .
+ "Couldn't find either '%1' or '%2' in the extraction " .
+ "directory '%3' -- will be unable to install",
+ BUILD_PL->(), MAKEFILE_PL->(), $self->status->extract ) );
+
+ $self->status->installed(0);
+ return;
+ }
+
+
+ ### do SIGNATURE checks? ###
+ ### XXX check status and not recheck EVERY time?
+ if( $conf->get_conf('signature') ) {
+ unless( $self->check_signature( verbose => $args->{verbose} ) ) {
+ error( loc( "Signature check failed for module '%1' ".
+ "-- Not trusting this module, aborting install",
+ $self->module ) );
+ $self->status->signature(0);
+
+ ### send out test report on broken sig
+ if( $conf->get_conf('cpantest') ) {
+ $cb->_send_report(
+ module => $self,
+ failed => 1,
+ buffer => CPANPLUS::Error->stack_as_string,
+ verbose => $args->{verbose},
+ force => $args->{force},
+ ) or error(loc("Failed to send test report for '%1'",
+ $self->module ) );
+ }
+
+ return;
+
+ } else {
+ ### signature OK ###
+ $self->status->signature(1);
+ }
+ }
+
+ ### a target of 'create' basically means not to run make test ###
+ ### eh, no it /doesn't/.. skiptest => 1 means skiptest => 1.
+ #$args->{'skiptest'} = 1 if $target eq 'create';
+
+ ### bundle rules apply ###
+ if( $self->is_bundle ) {
+ ### check what we need to install ###
+ my @prereqs = $self->bundle_modules();
+ unless( @prereqs ) {
+ error( loc( "Bundle '%1' does not specify any modules to install",
+ $self->module ) );
+
+ ### XXX mark an error here? ###
+ }
+ }
+
+ my $dist = $self->dist( format => $format,
+ target => $target,
+ args => $args );
+ unless( $dist ) {
+ error( loc( "Unable to create a new distribution object for '%1' " .
+ "-- cannot continue", $self->module ) );
+ return;
+ }
+
+ return 1 if $target ne TARGET_INSTALL;
+
+ my $ok = $dist->install( %$args ) ? 1 : 0;
+
+ $self->status->installed($ok);
+
+ return 1 if $ok;
+ return;
+}
+
+=pod @list = $self->bundle_modules()
+
+Returns a list of module objects the Bundle specifies.
+
+This requires you to have extracted the bundle already, using the
+C<extract()> method.
+
+Returns false on error.
+
+=cut
+
+sub bundle_modules {
+ my $self = shift;
+ my $cb = $self->parent;
+
+ unless( $self->is_bundle ) {
+ error( loc("'%1' is not a bundle", $self->module ) );
+ return;
+ }
+
+ my @files;
+
+ ### autobundles are special files generated by CPANPLUS. If we can
+ ### read the file, we can determine the prereqs
+ if( $self->is_autobundle ) {
+ my $where;
+ unless( $where = $self->status->fetch ) {
+ error(loc("Don't know where '%1' was fetched to", $self->package));
+ return;
+ }
+
+ push @files, $where
+
+ ### regular bundle::* upload
+ } else {
+ my $dir;
+ unless( $dir = $self->status->extract ) {
+ error(loc("Don't know where '%1' was extracted to", $self->module));
+ return;
+ }
+
+ find( {
+ wanted => sub { push @files, File::Spec->rel2abs($_) if /\.pm/i },
+ no_chdir => 1,
+ }, $dir );
+ }
+
+ my $prereqs = {}; my @list; my $seen = {};
+ for my $file ( @files ) {
+ my $fh = FileHandle->new($file)
+ or( error(loc("Could not open '%1' for reading: %2",
+ $file,$!)), next );
+
+ my $flag;
+ while( local $_ = <$fh> ) {
+ ### quick hack to read past the header of the file ###
+ last if $flag && m|^=head|i;
+
+ ### from perldoc cpan:
+ ### =head1 CONTENTS
+ ### In this pod section each line obeys the format
+ ### Module_Name [Version_String] [- optional text]
+ $flag = 1 if m|^=head1 CONTENTS|i;
+
+ if ($flag && /^(?!=)(\S+)\s*(\S+)?/) {
+ my $module = $1;
+ my $version = $cb->_version_to_number( version => $2 );
+
+ my $obj = $cb->module_tree($module);
+
+ unless( $obj ) {
+ error(loc("Cannot find bundled module '%1'", $module),
+ loc("-- it does not seem to exist") );
+ next;
+ }
+
+ ### make sure we list no duplicates ###
+ unless( $seen->{ $obj->module }++ ) {
+ push @list, $obj;
+ $prereqs->{ $module } =
+ $cb->_version_to_number( version => $version );
+ }
+ }
+ }
+ }
+
+ ### store the prereqs we just found ###
+ $self->status->prereqs( $prereqs );
+
+ return @list;
+}
+
+=pod
+
+=head2 $text = $self->readme
+
+Fetches the readme belonging to this module and stores it under
+C<< $obj->status->readme >>. Returns the readme as a string on
+success and returns false on failure.
+
+=cut
+
+sub readme {
+ my $self = shift;
+ my $conf = $self->parent->configure_object;
+
+ ### did we already dl the readme once? ###
+ return $self->status->readme() if $self->status->readme();
+
+ ### this should be core ###
+ return unless can_load( modules => { FileHandle => '0.0' },
+ verbose => 1,
+ );
+
+ ### get a clone of the current object, with a fresh status ###
+ my $obj = $self->clone or return;
+
+ ### munge the package name
+ my $pkg = README->( $obj );
+ $obj->package($pkg);
+
+ my $file;
+ { ### disable checksum fetches on readme downloads
+
+ my $tmp = $conf->get_conf( 'md5' );
+ $conf->set_conf( md5 => 0 );
+
+ $file = $obj->fetch;
+
+ $conf->set_conf( md5 => $tmp );
+
+ return unless $file;
+ }
+
+ ### read the file into a scalar, to store in the original object ###
+ my $fh = new FileHandle;
+ unless( $fh->open($file) ) {
+ error( loc( "Could not open file '%1': %2", $file, $! ) );
+ return;
+ }
+
+ my $in = do{ local $/; <$fh> };
+ $fh->close;
+
+ return $self->status->readme( $in );
+}
+
+=pod
+
+=head2 $version = $self->installed_version()
+
+Returns the currently installed version of this module, if any.
+
+=head2 $where = $self->installed_file()
+
+Returns the location of the currently installed file of this module,
+if any.
+
+=head2 $dir = $self->installed_dir()
+
+Returns the directory (or more accurately, the C<@INC> handle) from
+which this module was loaded, if any.
+
+=head2 $bool = $self->is_uptodate([version => VERSION_NUMBER])
+
+Returns a boolean indicating if this module is uptodate or not.
+
+=cut
+
+### uptodate/installed functions
+{ my $map = { # hashkey, alternate rv
+ installed_version => ['version', 0 ],
+ installed_file => ['file', ''],
+ installed_dir => ['dir', ''],
+ is_uptodate => ['uptodate', 0 ],
+ };
+
+ while( my($method, $aref) = each %$map ) {
+ my($key,$alt_rv) = @$aref;
+
+ no strict 'refs';
+ *$method = sub {
+ ### never use the @INC hooks to find installed versions of
+ ### modules -- they're just there in case they're not on the
+ ### perl install, but the user shouldn't trust them for *other*
+ ### modules!
+ ### XXX CPANPLUS::inc is now obsolete, so this should not
+ ### be needed anymore
+ #local @INC = CPANPLUS::inc->original_inc;
+
+ my $self = shift;
+
+ ### make sure check_install is not looking in %INC, as
+ ### that may contain some of our sneakily loaded modules
+ ### that aren't installed as such. -- kane
+ local $Module::Load::Conditional::CHECK_INC_HASH = 0;
+ ### this should all that is required for deprecated core modules
+ local $Module::Load::Conditional::DEPRECATED = 1;
+ my $href = check_install(
+ module => $self->module,
+ version => $self->version,
+ @_,
+ );
+
+ return $href->{$key} || $alt_rv;
+ }
+ }
+}
+
+
+
+=pod
+
+=head2 $href = $self->details()
+
+Returns a hashref with key/value pairs offering more information about
+a particular module. For example, for C<Time::HiRes> it might look like
+this:
+
+ Author Jarkko Hietaniemi (jhi@iki.fi)
+ Description High resolution time, sleep, and alarm
+ Development Stage Released
+ Installed File /usr/local/perl/lib/Time/Hires.pm
+ Interface Style plain Functions, no references used
+ Language Used C and perl, a C compiler will be needed
+ Package Time-HiRes-1.65.tar.gz
+ Public License Unknown
+ Support Level Developer
+ Version Installed 1.52
+ Version on CPAN 1.65
+
+=cut
+
+sub details {
+ my $self = shift;
+ my $conf = $self->parent->configure_object();
+ my $cb = $self->parent;
+ my %hash = @_;
+
+ my $res = {
+ Author => loc("%1 (%2)", $self->author->author(),
+ $self->author->email() ),
+ Package => $self->package,
+ Description => $self->description || loc('None given'),
+ 'Version on CPAN' => $self->version,
+ };
+
+ ### check if we have the module installed
+ ### if so, add version have and version on cpan
+ $res->{'Version Installed'} = $self->installed_version
+ if $self->installed_version;
+ $res->{'Installed File'} = $self->installed_file if $self->installed_file;
+
+ my $i = 0;
+ for my $item( split '', $self->dslip ) {
+ $res->{ $cb->_dslip_defs->[$i]->[0] } =
+ $cb->_dslip_defs->[$i]->[1]->{$item} || loc('Unknown');
+ $i++;
+ }
+
+ return $res;
+}
+
+=head2 @list = $self->contains()
+
+Returns a list of module objects that represent the modules also
+present in the package of this module.
+
+For example, for C<Archive::Tar> this might return:
+
+ Archive::Tar
+ Archive::Tar::Constant
+ Archive::Tar::File
+
+=cut
+
+sub contains {
+ my $self = shift;
+ my $cb = $self->parent;
+ my $pkg = $self->package;
+
+ my @mods = $cb->search( type => 'package', allow => [qr/^$pkg$/] );
+
+ return @mods;
+}
+
+=pod
+
+=head2 @list_of_hrefs = $self->fetch_report()
+
+This function queries the CPAN testers database at
+I<http://testers.cpan.org/> for test results of specified module
+objects, module names or distributions.
+
+Look at L<CPANPLUS::Internals::Report::_query_report()> for details on
+the options you can pass and the return value to expect.
+
+=cut
+
+sub fetch_report {
+ my $self = shift;
+ my $cb = $self->parent;
+
+ return $cb->_query_report( @_, module => $self );
+}
+
+=pod
+
+=head2 $bool = $self->uninstall([type => [all|man|prog])
+
+This function uninstalls the specified module object.
+
+You can install 2 types of files, either C<man> pages or C<prog>ram
+files. Alternately you can specify C<all> to uninstall both (which
+is the default).
+
+Returns true on success and false on failure.
+
+Do note that this does an uninstall via the so-called C<.packlist>,
+so if you used a module installer like say, C<ports> or C<apt>, you
+should not use this, but use your package manager instead.
+
+=cut
+
+sub uninstall {
+ my $self = shift;
+ my $conf = $self->parent->configure_object();
+ my %hash = @_;
+
+ my ($type,$verbose);
+ my $tmpl = {
+ type => { default => 'all', allow => [qw|man prog all|],
+ store => \$type },
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ force => { default => $conf->get_conf('force') },
+ };
+
+ ### XXX add a warning here if your default install dist isn't
+ ### makefile or build -- that means you are using a package manager
+ ### and this will not do what you think!
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ if( $conf->get_conf('dist_type') and (
+ ($conf->get_conf('dist_type') ne INSTALLER_BUILD) or
+ ($conf->get_conf('dist_type') ne INSTALLER_MM))
+ ) {
+ msg(loc("You have a default installer type set (%1) ".
+ "-- you should probably use that package manager to " .
+ "uninstall modules", $conf->get_conf('dist_type')), $verbose);
+ }
+
+ ### check if we even have the module installed -- no point in continuing
+ ### otherwise
+ unless( $self->installed_version ) {
+ error( loc( "Module '%1' is not installed, so cannot uninstall",
+ $self->module ) );
+ return;
+ }
+
+ ### nothing to uninstall ###
+ my $files = $self->files( type => $type ) or return;
+ my $dirs = $self->directory_tree( type => $type ) or return;
+ my $sudo = $conf->get_program('sudo');
+
+ ### just in case there's no file; M::B doensn't provide .packlists yet ###
+ my $pack = $self->packlist;
+ $pack = $pack->[0]->packlist_file() if $pack;
+
+ ### first remove the files, then the dirs if they are empty ###
+ my $flag = 0;
+ for my $file( @$files, $pack ) {
+ next unless defined $file && -f $file;
+
+ msg(loc("Unlinking '%1'", $file), $verbose);
+
+ my @cmd = ($^X, "-eunlink+q[$file]");
+ unshift @cmd, $sudo if $sudo;
+
+ my $buffer;
+ unless ( run( command => \@cmd,
+ verbose => $verbose,
+ buffer => \$buffer )
+ ) {
+ error(loc("Failed to unlink '%1': '%2'",$file, $buffer));
+ $flag++;
+ }
+ }
+
+ for my $dir ( sort @$dirs ) {
+ local *DIR;
+ opendir DIR, $dir or next;
+ my @count = readdir(DIR);
+ close DIR;
+
+ next unless @count == 2; # . and ..
+
+ msg(loc("Removing '%1'", $dir), $verbose);
+
+ ### this fails on my win2k machines.. it indeed leaves the
+ ### dir, but it's not a critical error, since the files have
+ ### been removed. --kane
+ #unless( rmdir $dir ) {
+ # error( loc( "Could not remove '%1': %2", $dir, $! ) )
+ # unless $^O eq 'MSWin32';
+ #}
+
+ my @cmd = ($^X, "-e", "rmdir q[$dir]");
+ unshift @cmd, $sudo if $sudo;
+
+ my $buffer;
+ unless ( run( command => \@cmd,
+ verbose => $verbose,
+ buffer => \$buffer )
+ ) {
+ error(loc("Failed to rmdir '%1': %2",$dir,$buffer));
+ $flag++;
+ }
+ }
+
+ $self->status->uninstall(!$flag);
+ $self->status->installed( $flag ? 1 : undef);
+
+ return !$flag;
+}
+
+=pod
+
+=head2 @modobj = $self->distributions()
+
+Returns a list of module objects representing all releases for this
+module on success, false on failure.
+
+=cut
+
+sub distributions {
+ my $self = shift;
+ my %hash = @_;
+
+ my @list = $self->author->distributions( %hash, module => $self ) or return;
+
+ ### it's another release then by the same author ###
+ return grep { $_->package_name eq $self->package_name } @list;
+}
+
+=pod
+
+=head2 @list = $self->files ()
+
+Returns a list of files used by this module, if it is installed.
+
+=head2 @list = $self->directory_tree ()
+
+Returns a list of directories used by this module.
+
+=head2 @list = $self->packlist ()
+
+Returns the C<ExtUtils::Packlist> object for this module.
+
+=head2 @list = $self->validate ()
+
+Returns a list of files that are missing for this modules, but
+are present in the .packlist file.
+
+=cut
+
+for my $sub (qw[files directory_tree packlist validate]) {
+ no strict 'refs';
+ *$sub = sub {
+ return shift->_extutils_installed( @_, method => $sub );
+ }
+}
+
+### generic method to call an ExtUtils::Installed method ###
+sub _extutils_installed {
+ my $self = shift;
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my $home = $cb->_home_dir; # may be needed to fix up prefixes
+ my %hash = @_;
+
+ my ($verbose,$type,$method);
+ my $tmpl = {
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose, },
+ type => { default => 'all',
+ allow => [qw|prog man all|],
+ store => \$type, },
+ method => { required => 1,
+ store => \$method,
+ allow => [qw|files directory_tree packlist
+ validate|],
+ },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ ### old versions of cygwin + perl < 5.8 are buggy here. bail out if we
+ ### find we're being used by them
+ { my $err = ON_OLD_CYGWIN;
+ if($err) { error($err); return };
+ }
+
+ return unless can_load(
+ modules => { 'ExtUtils::Installed' => '0.0' },
+ verbose => $verbose,
+ );
+
+ my @config_names = (
+ ### lib
+ { lib => 'privlib', # perl-only
+ arch => 'archlib', # compiled code
+ prefix => 'prefix', # prefix to both
+ },
+ ### site
+ { lib => 'sitelib',
+ arch => 'sitearch',
+ prefix => 'siteprefix',
+ },
+ ### vendor
+ { lib => 'vendorlib',
+ arch => 'vendorarch',
+ prefix => 'vendorprefix',
+ },
+ );
+
+ ### search in your regular @INC, and anything you added to your config.
+ ### this lets EU::Installed find .packlists that are *not* in the standard
+ ### compiled in @INC path. Requires EU::I 1.42 or up. this addresses #33438
+ ### make sure the archname path is also added, as that's where the .packlist
+ ### files are written
+ my @libs;
+ for my $lib ( @{ $conf->get_conf('lib') } ) {
+ require Config;
+
+ ### and just the standard dir
+ push @libs, $lib;
+
+ ### figure out what an MM prefix expands to. Basically, it's the
+ ### site install target from %Config, ie: /opt/lib/perl5/site_perl/5.8.8
+ ### minus the site wide prefix, ie: /opt
+ ### this lets users add the dir they have set as their EU::MM PREFIX
+ ### to our 'lib' config and it Just Works
+ ### the arch specific dir, ie:
+ ### /opt/lib/perl5/site_perl/5.8.8/darwin-2level
+ ### XXX is this the right thing to do?
+
+ ### we add all 6 dir combos for prefixes:
+ ### /foo/lib
+ ### /foo/lib/arch
+ ### /foo/site/lib
+ ### /foo/site/lib/arch
+ ### /foo/vendor/lib
+ ### /foo/vendor/lib/arch
+ for my $href ( @config_names ) {
+ for my $key ( qw[lib arch] ) {
+
+ ### look up the config value -- use EXP for the EXPANDED
+ ### version, so no ~ etc are found in there
+ my $dir = $Config::Config{ $href->{ $key } .'exp' } or next;
+ my $prefix = $Config::Config{ $href->{prefix} };
+
+ ### prefix may be relative to home, and contain a ~
+ ### if so, fix it up.
+ $prefix =~ s/^~/$home/;
+
+ ### remove the prefix from it, so we can append to our $lib
+ $dir =~ s/^\Q$prefix\E//;
+
+ ### do the appending
+ push @libs, File::Spec->catdir( $lib, $dir );
+
+ }
+ }
+ }
+
+ my $inst;
+ unless( $inst = ExtUtils::Installed->new( extra_libs => \@libs ) ) {
+ error( loc("Could not create an '%1' object", 'ExtUtils::Installed' ) );
+
+ ### in case it's being used directly... ###
+ return;
+ }
+
+
+ { ### EU::Installed can die =/
+ my @files;
+ eval { @files = $inst->$method( $self->module, $type ) };
+
+ if( $@ ) {
+ chomp $@;
+ error( loc("Could not get '%1' for '%2': %3",
+ $method, $self->module, $@ ) );
+ return;
+ }
+
+ return wantarray ? @files : \@files;
+ }
+}
+
+=head2 $bool = $self->add_to_includepath;
+
+Adds the current modules path to C<@INC> and C<$PERL5LIB>. This allows
+you to add the module from its build dir to your path.
+
+You can reset C<@INC> and C<$PERL5LIB> to its original state when you
+started the program, by calling:
+
+ $self->parent->flush('lib');
+
+=cut
+
+sub add_to_includepath {
+ my $self = shift;
+ my $cb = $self->parent;
+
+ if( my $dir = $self->status->extract ) {
+
+ $cb->_add_to_includepath(
+ directories => [
+ File::Spec->catdir(BLIB->($dir), LIB),
+ File::Spec->catdir(BLIB->($dir), ARCH),
+ BLIB->($dir),
+ ]
+ ) or return;
+
+ } else {
+ error(loc( "No extract dir registered for '%1' -- can not add ".
+ "add builddir to search path!", $self->module ));
+ return;
+ }
+
+ return 1;
+
+}
+
+=pod
+
+=head2 $path = $self->best_path_to_module_build();
+
+B<OBSOLETE>
+
+If a newer version of Module::Build is found in your path, it will
+return this C<special> path. If the newest version of C<Module::Build>
+is found in your regular C<@INC>, the method will return false. This
+indicates you do not need to add a special directory to your C<@INC>.
+
+Note that this is only relevant if you're building your own
+C<CPANPLUS::Dist::*> plugin -- the built-in dist types already have
+this taken care of.
+
+=cut
+
+### make sure we're always running 'perl Build.PL' and friends
+### against the highest version of module::build available
+sub best_path_to_module_build {
+ my $self = shift;
+
+ ### Since M::B will actually shell out and run the Build.PL, we must
+ ### make sure it refinds the proper version of M::B in the path.
+ ### that may be either in our cp::inc or in site_perl, or even a
+ ### new M::B being installed.
+ ### don't add anything else here, as that might screw up prereq checks
+
+ ### XXX this might be needed for Dist::MM too, if a makefile.pl is
+ ### masquerading as a Build.PL
+
+ ### did we find the most recent module::build in our installer path?
+
+ ### XXX can't do changes to @INC, they're being ignored by
+ ### new_from_context when writing a Build script. see ticket:
+ ### #8826 Module::Build ignores changes to @INC when writing Build
+ ### from new_from_context
+ ### XXX applied schwern's patches (as seen on CPANPLUS::Devel 10/12/04)
+ ### and upped the version to 0.26061 of the bundled version, and things
+ ### work again
+
+ ### this functionality is now obsolete -- prereqs should be installed
+ ### and we no longer use the CPANPLUS::inc magic.. so comment this out.
+# require Module::Build;
+# if( CPANPLUS::inc->path_to('Module::Build') and (
+# CPANPLUS::inc->path_to('Module::Build') eq
+# CPANPLUS::inc->installer_path )
+# ) {
+#
+# ### if the module being installed is *not* Module::Build
+# ### itself -- as that would undoubtedly be newer -- add
+# ### the path to the installers to @INC
+# ### if it IS module::build itself, add 'lib' to its path,
+# ### as the Build.PL would do as well, but the API doesn't.
+# ### this makes self updates possible
+# return $self->module eq 'Module::Build'
+# ? 'lib'
+# : CPANPLUS::inc->installer_path;
+# }
+
+ ### otherwise, the path was found through a 'normal' way of
+ ### scanning @INC.
+ return;
+}
+
+=pod
+
+=head1 BUG REPORTS
+
+Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
+
+=head1 AUTHOR
+
+This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
+
+=head1 COPYRIGHT
+
+The CPAN++ interface (of which this module is a part of) is copyright (c)
+2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
+
+This library is free software; you may redistribute and/or modify it
+under the same terms as Perl itself.
+
+=cut
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
+
+1;
+
+__END__
+
+todo:
+reports();
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Module/Author.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Module/Author.pm
new file mode 100644
index 00000000000..92940fa51ff
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Module/Author.pm
@@ -0,0 +1,232 @@
+package CPANPLUS::Module::Author;
+
+use strict;
+
+use CPANPLUS::Error;
+use CPANPLUS::Internals::Constants;
+use Params::Check qw[check];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+local $Params::Check::VERBOSE = 1;
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Module::Author
+
+=head1 SYNOPSIS
+
+ my $author = CPANPLUS::Module::Author->new(
+ author => 'Jack Ashton',
+ cpanid => 'JACKASH',
+ _id => INTERNALS_OBJECT_ID,
+ );
+
+ $author->cpanid;
+ $author->author;
+ $author->email;
+
+ @dists = $author->distributions;
+ @mods = $author->modules;
+
+ @accessors = CPANPLUS::Module::Author->accessors;
+
+=head1 DESCRIPTION
+
+C<CPANPLUS::Module::Author> creates objects from the information in the
+source files. These can then be used to query on.
+
+These objects should only be created internally. For C<fake> objects,
+there's the C<CPANPLUS::Module::Author::Fake> class.
+
+=head1 ACCESSORS
+
+An objects of this class has the following accessors:
+
+=over 4
+
+=item author
+
+Name of the author.
+
+=item cpanid
+
+The CPAN id of the author.
+
+=item email
+
+The email address of the author, which defaults to '' if not provided.
+
+=item parent
+
+The C<CPANPLUS::Internals::Object> that spawned this module object.
+
+=back
+
+=cut
+
+my $tmpl = {
+ author => { required => 1 }, # full name of the author
+ cpanid => { required => 1 }, # cpan id
+ email => { default => '' }, # email address of the author
+ _id => { required => 1 }, # id of the Internals object that spawned us
+};
+
+### autogenerate accessors ###
+for my $key ( keys %$tmpl ) {
+ no strict 'refs';
+ *{__PACKAGE__."::$key"} = sub {
+ my $self = shift;
+ $self->{$key} = $_[0] if @_;
+ return $self->{$key};
+ }
+}
+
+sub parent {
+ my $self = shift;
+ my $obj = CPANPLUS::Internals->_retrieve_id( $self->_id );
+
+ return $obj;
+}
+
+=pod
+
+=head1 METHODS
+
+=head2 $auth = CPANPLUS::Module::Author->new( author => AUTHOR_NAME, cpanid => CPAN_ID, _id => INTERNALS_ID [, email => AUTHOR_EMAIL] )
+
+This method returns a C<CPANPLUS::Module::Author> object, based on the given
+parameters.
+
+Returns false on failure.
+
+=cut
+
+sub new {
+ my $class = shift;
+ my %hash = @_;
+
+ ### don't check the template for sanity
+ ### -- we know it's good and saves a lot of performance
+ local $Params::Check::SANITY_CHECK_TEMPLATE = 0;
+
+ my $object = check( $tmpl, \%hash ) or return;
+
+ return bless $object, $class;
+}
+
+=pod
+
+=head2 @mod_objs = $auth->modules()
+
+Return a list of module objects this author has released.
+
+=cut
+
+sub modules {
+ my $self = shift;
+ my $cb = $self->parent;
+
+ my $aref = $cb->_search_module_tree(
+ type => 'author',
+ ### XXX, depending on backend, this is either an object
+ ### or the cpanid string. Dont know an elegant way to
+ ### solve this right now, so passing both
+ allow => [$self, $self->cpanid],
+ );
+ return @$aref if $aref;
+ return;
+}
+
+=pod
+
+=head2 @dists = $auth->distributions()
+
+Returns a list of module objects representing all the distributions
+this author has released.
+
+=cut
+
+sub distributions {
+ my $self = shift;
+ my %hash = @_;
+
+ local $Params::Check::ALLOW_UNKNOWN = 1;
+ local $Params::Check::NO_DUPLICATES = 1;
+
+ my $mod;
+ my $tmpl = {
+ module => { default => '', store => \$mod },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ ### if we didn't get a module object passed, we'll find one ourselves ###
+ unless( $mod ) {
+ my @list = $self->modules;
+ if( @list ) {
+ $mod = $list[0];
+ } else {
+ error( loc( "This author has released no modules" ) );
+ return;
+ }
+ }
+
+ my $file = $mod->checksums( %hash );
+ my $href = $mod->_parse_checksums_file( file => $file ) or return;
+
+ my @rv;
+ for my $name ( keys %$href ) {
+
+ ### shortcut asap, so we avoid extra ops. On big checksums files
+ ### the call to clone() takes up a lot of time.
+ ### .meta files are now also in the checksums file,
+ ### which means we have to filter out things that dont
+ ### match our regex
+ next if $mod->package_extension( $name ) eq META_EXT;
+
+ ### used to do this wiht ->clone. However, that calls ->dslip,
+ ### (which is wrong anyway, as we're doing a different module),
+ ### which in turn calls ->contains, which scans the entire
+ ### module tree using _search_module_tree, which uses P::C
+ ### and is therefor VERY VERY slow.
+ ### so let's do this the direct way for speed ups.
+ my $dist = CPANPLUS::Module::Fake->new(
+ module => do { my $m = $mod->package_name( $name );
+ $m =~ s/-/::/g; $m;
+ },
+ version => $mod->package_version( $name ),
+ package => $name,
+ path => $mod->path, # same author after all
+ author => $mod->author, # same author after all
+ mtime => $href->{$name}->{'mtime'}, # release date
+ );
+
+ push @rv, $dist;
+ }
+
+ return @rv;
+}
+
+
+=pod
+
+=head1 CLASS METHODS
+
+=head2 accessors ()
+
+Returns a list of all accessor methods to the object
+
+=cut
+
+sub accessors { return keys %$tmpl };
+
+1;
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Module/Author/Fake.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Module/Author/Fake.pm
new file mode 100644
index 00000000000..3156c5c7abb
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Module/Author/Fake.pm
@@ -0,0 +1,80 @@
+package CPANPLUS::Module::Author::Fake;
+
+
+use CPANPLUS::Module::Author;
+use CPANPLUS::Internals;
+use CPANPLUS::Error;
+
+use strict;
+use vars qw[@ISA];
+use Params::Check qw[check];
+
+@ISA = qw[CPANPLUS::Module::Author];
+
+$Params::Check::VERBOSE = 1;
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Module::Author::Fake
+
+=head1 SYNOPSIS
+
+ my $auth = CPANPLUS::Module::Author::Fake->new(
+ author => 'Foo Bar',
+ email => 'luser@foo.com',
+ cpanid => 'FOO',
+ _id => $cpan->id,
+ );
+
+=head1 DESCRIPTION
+
+A class for creating fake author objects, for shortcut use internally
+by CPANPLUS.
+
+Inherits from C<CPANPLUS::Module::Author>.
+
+=head1 METHODS
+
+=head2 new( _id => DIGIT )
+
+Creates a dummy author object. It can take the same options as
+C<< CPANPLUS::Module::Author->new >>, but will fill in default ones
+if none are provided. Only the _id key is required.
+
+=cut
+
+sub new {
+ my $class = shift;
+ my %hash = @_;
+
+ my $tmpl = {
+ author => { default => 'CPANPLUS Internals' },
+ email => { default => 'cpanplus-info@lists.sf.net' },
+ cpanid => { default => 'CPANPLUS' },
+ _id => { default => CPANPLUS::Internals->_last_id },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ my $obj = CPANPLUS::Module::Author->new( %$args ) or return;
+
+ unless( $obj->_id ) {
+ error(loc("No '%1' specified -- No CPANPLUS object associated!",'_id'));
+ return;
+ }
+
+ ### rebless object ###
+ return bless $obj, $class;
+}
+
+1;
+
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Module/Checksums.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Module/Checksums.pm
new file mode 100644
index 00000000000..e1a2bbdb6ad
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Module/Checksums.pm
@@ -0,0 +1,251 @@
+package CPANPLUS::Module::Checksums;
+
+use strict;
+use vars qw[@ISA];
+
+
+use CPANPLUS::Error;
+use CPANPLUS::Internals::Constants;
+
+use FileHandle;
+
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+use Params::Check qw[check];
+use Module::Load::Conditional qw[can_load];
+
+$Params::Check::VERBOSE = 1;
+
+@ISA = qw[ CPANPLUS::Module::Signature ];
+
+=head1 NAME
+
+CPANPLUS::Module::Checksums
+
+=head1 SYNOPSIS
+
+ $file = $modobj->checksums;
+ $bool = $mobobj->_validate_checksum;
+
+=head1 DESCRIPTION
+
+This is a class that provides functions for checking the checksum
+of a distribution. Should not be loaded directly, but used via the
+interface provided via C<CPANPLUS::Module>.
+
+=head1 METHODS
+
+=head2 $mod->checksums
+
+Fetches the checksums file for this module object.
+For the options it can take, see C<CPANPLUS::Module::fetch()>.
+
+Returns the location of the checksums file on success and false
+on error.
+
+The location of the checksums file is also stored as
+
+ $mod->status->checksums
+
+=cut
+
+sub checksums {
+ my $mod = shift or return;
+
+ my $file = $mod->_get_checksums_file( @_ );
+
+ return $mod->status->checksums( $file ) if $file;
+
+ return;
+}
+
+### checks if the package checksum matches the one
+### from the checksums file
+sub _validate_checksum {
+ my $self = shift; #must be isa CPANPLUS::Module
+ my $conf = $self->parent->configure_object;
+ my %hash = @_;
+
+ my $verbose;
+ my $tmpl = {
+ verbose => { default => $conf->get_conf('verbose'),
+ store => \$verbose },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### if we can't check it, we must assume it's ok ###
+ return $self->status->checksum_ok(1)
+ unless can_load( modules => { 'Digest::MD5' => '0.0' } );
+ #class CPANPLUS::Module::Status is runtime-generated
+
+ my $file = $self->_get_checksums_file( verbose => $verbose ) or (
+ error(loc(q[Could not fetch '%1' file], CHECKSUMS)), return );
+
+ $self->_check_signature_for_checksum_file( file => $file ) or (
+ error(loc(q[Could not verify '%1' file], CHECKSUMS)), return );
+ #for whole CHECKSUMS file
+
+ my $href = $self->_parse_checksums_file( file => $file ) or (
+ error(loc(q[Could not parse '%1' file], CHECKSUMS)), return );
+
+ my $size = $href->{ $self->package }->{'size'};
+
+ ### the checksums file tells us the size of the archive
+ ### but the downloaded file is of different size
+ if( defined $size ) {
+ if( not (-s $self->status->fetch == $size) ) {
+ error(loc( "Archive size does not match for '%1': " .
+ "size is '%2' but should be '%3'",
+ $self->package, -s $self->status->fetch, $size));
+ return $self->status->checksum_ok(0);
+ }
+ } else {
+ msg(loc("Archive size is not known for '%1'",$self->package),$verbose);
+ }
+
+ my $md5 = $href->{ $self->package }->{'md5'};
+
+ unless( defined $md5 ) {
+ msg(loc("No 'md5' checksum known for '%1'",$self->package),$verbose);
+
+ return $self->status->checksum_ok(1);
+ }
+
+ $self->status->checksum_value($md5);
+
+
+ my $fh = FileHandle->new( $self->status->fetch ) or return;
+ binmode $fh;
+
+ my $ctx = Digest::MD5->new;
+ $ctx->addfile( $fh );
+
+ my $flag = $ctx->hexdigest eq $md5;
+ $flag
+ ? msg(loc("Checksum matches for '%1'", $self->package),$verbose)
+ : error(loc("Checksum does not match for '%1': " .
+ "MD5 is '%2' but should be '%3'",
+ $self->package, $ctx->hexdigest, $md5),$verbose);
+
+
+ return $self->status->checksum_ok(1) if $flag;
+ return $self->status->checksum_ok(0);
+}
+
+
+### fetches the module objects checksum file ###
+sub _get_checksums_file {
+ my $self = shift;
+ my %hash = @_;
+
+ my $clone = $self->clone;
+ $clone->package( CHECKSUMS );
+
+ my $file = $clone->fetch( ttl => 3600, %hash ) or return;
+
+ return $file;
+}
+
+sub _parse_checksums_file {
+ my $self = shift;
+ my %hash = @_;
+
+ my $file;
+ my $tmpl = {
+ file => { required => 1, allow => FILE_READABLE, store => \$file },
+ };
+ my $args = check( $tmpl, \%hash );
+
+ my $fh = OPEN_FILE->( $file ) or return;
+
+ ### loop over the header, there might be a pgp signature ###
+ my $signed;
+ while (local $_ = <$fh>) {
+ last if /^\$cksum = \{\s*$/; # skip till this line
+ my $header = PGP_HEADER; # but be tolerant of whitespace
+ $signed = 1 if /^${header}\s*$/;# due to crossplatform linebreaks
+ }
+
+ ### read the filehandle, parse it rather than eval it, even though it
+ ### *should* be valid perl code
+ my $dist;
+ my $cksum = {};
+ while (local $_ = <$fh>) {
+
+ if (/^\s*'([^']+)' => \{\s*$/) {
+ $dist = $1;
+
+ } elsif (/^\s*'([^']+)' => '?([^'\n]+)'?,?\s*$/ and defined $dist) {
+ $cksum->{$dist}{$1} = $2;
+
+ } elsif (/^\s*}[,;]?\s*$/) {
+ undef $dist;
+
+ } elsif (/^__END__\s*$/) {
+ last;
+
+ } else {
+ error( loc("Malformed %1 line: %2", CHECKSUMS, $_) );
+ }
+ }
+
+ return $cksum;
+}
+
+sub _check_signature_for_checksum_file {
+ my $self = shift;
+
+ my $conf = $self->parent->configure_object;
+ my %hash = @_;
+
+ ### you don't want to check signatures,
+ ### so let's just return true;
+ return 1 unless $conf->get_conf('signature');
+
+ my($force,$file,$verbose);
+ my $tmpl = {
+ file => { required => 1, allow => FILE_READABLE, store => \$file },
+ force => { default => $conf->get_conf('force'), store => \$force },
+ verbose => { default => $conf->get_conf('verbose'), store => \$verbose },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ my $fh = OPEN_FILE->($file) or return;
+
+ my $signed;
+ while (local $_ = <$fh>) {
+ my $header = PGP_HEADER;
+ $signed = 1 if /^$header$/;
+ }
+
+ if ( !$signed ) {
+ msg(loc("No signature found in %1 file '%2'",
+ CHECKSUMS, $file), $verbose);
+
+ return 1 unless $force;
+
+ error( loc( "%1 file '%2' is not signed -- aborting",
+ CHECKSUMS, $file ) );
+ return;
+
+ }
+
+ if( can_load( modules => { 'Module::Signature' => '0.06' } ) ) {
+ # local $Module::Signature::SIGNATURE = $file;
+ # ... check signatures ...
+ }
+
+ return 1;
+}
+
+
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Module/Fake.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Module/Fake.pm
new file mode 100644
index 00000000000..84d0233cf83
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Module/Fake.pm
@@ -0,0 +1,86 @@
+package CPANPLUS::Module::Fake;
+
+
+use CPANPLUS::Error;
+use CPANPLUS::Module;
+use CPANPLUS::Module::Author::Fake;
+use CPANPLUS::Internals;
+
+use strict;
+use vars qw[@ISA];
+use Params::Check qw[check];
+
+@ISA = qw[CPANPLUS::Module];
+$Params::Check::VERBOSE = 1;
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Module::Fake
+
+=head1 SYNOPSIS
+
+ my $obj = CPANPLUS::Module::Fake->new(
+ module => 'Foo',
+ path => 'ftp/path/to/foo',
+ author => CPANPLUS::Module::Author::Fake->new,
+ package => 'fake-1.1.tgz',
+ _id => $cpan->_id,
+ );
+
+=head1 DESCRIPTION
+
+A class for creating fake module objects, for shortcut use internally
+by CPANPLUS.
+
+Inherits from C<CPANPLUS::Module>.
+
+=head1 METHODS
+
+=head2 new( module => $mod, path => $path, package => $pkg, [_id => DIGIT] )
+
+Creates a dummy module object from the above parameters. It can
+take more options (same as C<< CPANPLUS::Module->new >> but the above
+are required.
+
+=cut
+
+sub new {
+ my $class = shift;
+ my %hash = @_;
+
+ local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ module => { required => 1 },
+ path => { required => 1 },
+ package => { required => 1 },
+ _id => { default => CPANPLUS::Internals->_last_id },
+ author => { default => '' },
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+
+ $args->{author} ||= CPANPLUS::Module::Author::Fake->new(
+ _id => $args->{_id} );
+
+ my $obj = CPANPLUS::Module->new( %$args ) or return;
+
+ unless( $obj->_id ) {
+ error(loc("No '%1' specified -- No CPANPLUS object associated!",'_id'));
+ return;
+ }
+
+ ### rebless object ###
+ return bless $obj, $class;
+}
+
+1;
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Module/Signature.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Module/Signature.pm
new file mode 100644
index 00000000000..cec6f2906b0
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Module/Signature.pm
@@ -0,0 +1,65 @@
+package CPANPLUS::Module::Signature;
+
+use strict;
+
+
+use Cwd;
+use CPANPLUS::Error;
+use Params::Check qw[check];
+use Module::Load::Conditional qw[can_load];
+
+
+### detached sig, not actually used afaik --kane ###
+#sub get_signature {
+# my $self = shift;
+#
+# my $clone = $self->clone;
+# $clone->package( $self->package . '.sig' );
+#
+# return $clone->fetch;
+#}
+
+sub check_signature {
+ my $self = shift;
+ my $cb = $self->parent;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my $verbose;
+ my $tmpl = {
+ verbose => {default => $conf->get_conf('verbose'), store => \$verbose},
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ my $dir = $self->status->extract or (
+ error( loc( "Do not know what dir '%1' was extracted to; ".
+ "Cannot check signature", $self->module ) ),
+ return );
+
+ my $cwd = cwd();
+ unless( $cb->_chdir( dir => $dir ) ) {
+ error(loc( "Could not chdir to '%1', cannot verify distribution '%2'",
+ $dir, $self->module ));
+ return;
+ }
+
+
+ ### check prerequisites
+ my $flag;
+ my $use_list = { 'Module::Signature' => '0.06' };
+ if( can_load( modules => $use_list, verbose => 1 ) ) {
+ my $rv = Module::Signature::verify();
+
+ unless ($rv eq Module::Signature::SIGNATURE_OK() or
+ $rv eq Module::Signature::SIGNATURE_MISSING()
+ ) {
+ $flag++; # whoops, bad sig
+ }
+ }
+
+ $cb->_chdir( dir => $cwd );
+ return $flag ? 0 : 1;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Selfupdate.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Selfupdate.pm
new file mode 100644
index 00000000000..48f918ce82e
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Selfupdate.pm
@@ -0,0 +1,547 @@
+package CPANPLUS::Selfupdate;
+
+use strict;
+use Params::Check qw[check];
+use IPC::Cmd qw[can_run];
+use CPANPLUS::Error qw[error msg];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+use CPANPLUS::Internals::Constants;
+
+$Params::Check::VERBOSE = 1;
+
+=head1 NAME
+
+CPANPLUS::Selfupdate
+
+=head1 SYNOPSIS
+
+ $su = $cb->selfupdate_object;
+
+ @feats = $su->list_features;
+ @feats = $su->list_enabled_features;
+
+ @mods = map { $su->modules_for_feature( $_ ) } @feats;
+ @mods = $su->list_core_dependencies;
+ @mods = $su->list_core_modules;
+
+ for ( @mods ) {
+ print $_->name " should be version " . $_->version_required;
+ print "Installed version is not uptodate!"
+ unless $_->is_installed_version_sufficient;
+ }
+
+ $ok = $su->selfupdate( update => 'all', latest => 0 );
+
+=cut
+
+### a config has describing our deps etc
+{
+
+ my $Modules = {
+ dependencies => {
+ 'File::Fetch' => '0.15_02', # lynx & 404 handling
+ 'File::Spec' => '0.82',
+ 'IPC::Cmd' => '0.36', # 5.6.2 compat: 2-arg open
+ 'Locale::Maketext::Simple' => '0.01',
+ 'Log::Message' => '0.01',
+ 'Module::Load' => '0.10',
+ 'Module::Load::Conditional' => '0.31_01', # returns dir for loaded
+ # modules
+ 'version' => '0.73', # needed for M::L::C
+ # addresses #24630 and
+ # #24675
+ # Address ~0 overflow issue
+ 'Params::Check' => '0.22',
+ 'Package::Constants' => '0.01',
+ 'Term::UI' => '0.18', # option parsing
+ 'Test::Harness' => '2.62', # due to bug #19505
+ # only 2.58 and 2.60 are bad
+ 'Test::More' => '0.47', # to run our tests
+ 'Archive::Extract' => '0.16', # ./Dir bug fix
+ 'Archive::Tar' => '1.23',
+ 'IO::Zlib' => '1.04', # needed for Archive::Tar
+ 'Object::Accessor' => '0.34', # mk_aliases support
+ 'Module::CoreList' => '2.22', # deprecated core modules
+ 'Module::Pluggable' => '2.4',
+ 'Module::Loaded' => '0.01',
+ 'Parse::CPAN::Meta' => '0.02', # config_requires support
+ 'ExtUtils::Install' => '1.42', # uninstall outside @INC
+ },
+
+ features => {
+ # config_key_name => [
+ # sub { } to list module key/value pairs
+ # sub { } to check if feature is enabled
+ # ]
+ prefer_makefile => [
+ sub {
+ my $cb = shift;
+ $cb->configure_object->get_conf('prefer_makefile')
+ ? { }
+ : { 'CPANPLUS::Dist::Build' => '0.24' };
+ },
+ sub { return 1 }, # always enabled
+ ],
+ cpantest => [
+ { 'Test::Reporter' => '1.34',
+ 'Parse::CPAN::Meta' => '0.0'
+ },
+ sub {
+ my $cb = shift;
+ return $cb->configure_object->get_conf('cpantest');
+ },
+ ],
+ dist_type => [
+ sub {
+ my $cb = shift;
+ my $dist = $cb->configure_object->get_conf('dist_type');
+ return { $dist => '0.0' } if $dist;
+ return;
+ },
+ sub {
+ my $cb = shift;
+ return $cb->configure_object->get_conf('dist_type');
+ },
+ ],
+
+ md5 => [
+ {
+ 'Digest::MD5' => '0.0',
+ },
+ sub {
+ my $cb = shift;
+ return $cb->configure_object->get_conf('md5');
+ },
+ ],
+ shell => [
+ sub {
+ my $cb = shift;
+ my $dist = $cb->configure_object->get_conf('shell');
+
+ ### we bundle these shells, so don't bother having a dep
+ ### on them... If we don't do this, CPAN.pm actually detects
+ ### a recursive dependency and breaks (see #26077).
+ ### This is not an issue for CPANPLUS itself, it handles
+ ### it smartly.
+ return if $dist eq SHELL_DEFAULT or $dist eq SHELL_CLASSIC;
+ return { $dist => '0.0' } if $dist;
+ return;
+ },
+ sub { return 1 },
+ ],
+ signature => [
+ sub {
+ my $cb = shift;
+ return {
+ 'Module::Signature' => '0.06',
+ } if can_run('gpg');
+ ### leave this out -- Crypt::OpenPGP is fairly
+ ### painful to install, and broken on some platforms
+ ### so we'll just always fall back to gpg. It may
+ ### issue a warning or 2, but that's about it.
+ ### this change due to this ticket: #26914
+ # and $cb->configure_object->get_conf('prefer_bin');
+
+ return {
+ 'Crypt::OpenPGP' => '0.0',
+ 'Module::Signature' => '0.06',
+ };
+ },
+ sub {
+ my $cb = shift;
+ return $cb->configure_object->get_conf('signature');
+ },
+ ],
+ storable => [
+ { 'Storable' => '0.0' },
+ sub {
+ my $cb = shift;
+ return $cb->configure_object->get_conf('storable');
+ },
+ ],
+ sqlite_backend => [
+ { 'DBIx::Simple' => '0.0',
+ 'DBD::SQLite' => '0.0',
+ },
+ sub {
+ my $cb = shift;
+ my $conf = $cb->configure_object;
+ return $conf->get_conf('source_engine')
+ eq 'CPANPLUS::Internals::Source::SQLite'
+ },
+ ],
+ },
+ core => {
+ 'CPANPLUS' => '0.0',
+ },
+ };
+
+ sub _get_config { return $Modules }
+}
+
+=head1 METHODS
+
+=head2 $self = CPANPLUS::Selfupdate->new( $backend_object );
+
+Sets up a new selfupdate object. Called automatically when
+a new backend object is created.
+
+=cut
+
+sub new {
+ my $class = shift;
+ my $cb = shift or return;
+ return bless sub { $cb }, $class;
+}
+
+
+{ ### cache to find the relevant modules
+ my $cache = {
+ core
+ => sub { my $self = shift;
+ core => [ $self->list_core_modules ] },
+
+ dependencies
+ => sub { my $self = shift;
+ dependencies => [ $self->list_core_dependencies ] },
+
+ enabled_features
+ => sub { my $self = shift;
+ map { $_ => [ $self->modules_for_feature( $_ ) ] }
+ $self->list_enabled_features
+ },
+ features
+ => sub { my $self = shift;
+ map { $_ => [ $self->modules_for_feature( $_ ) ] }
+ $self->list_features
+ },
+ ### make sure to do 'core' first, in case
+ ### we are out of date ourselves
+ all => [ qw|core dependencies enabled_features| ],
+ };
+
+
+=head2 @cat = $self->list_categories
+
+Returns a list of categories that the C<selfupdate> method accepts.
+
+See C<selfupdate> for details.
+
+=cut
+
+ sub list_categories { return sort keys %$cache }
+
+=head2 %list = $self->list_modules_to_update( update => "core|dependencies|enabled_features|features|all", [latest => BOOL] )
+
+List which modules C<selfupdate> would upgrade. You can update either
+the core (CPANPLUS itself), the core dependencies, all features you have
+currently turned on, or all features available, or everything.
+
+The C<latest> option determines whether it should update to the latest
+version on CPAN, or if the minimal required version for CPANPLUS is
+good enough.
+
+Returns a hash of feature names and lists of module objects to be
+upgraded based on the category you provided. For example:
+
+ %list = $self->list_modules_to_update( update => 'core' );
+
+Would return:
+
+ ( core => [ $module_object_for_cpanplus ] );
+
+=cut
+
+ sub list_modules_to_update {
+ my $self = shift;
+ my $cb = $self->();
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my($type, $latest);
+ my $tmpl = {
+ update => { required => 1, store => \$type,
+ allow => [ keys %$cache ], },
+ latest => { default => 0, store => \$latest, allow => BOOLEANS },
+ };
+
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+ check( $tmpl, \%hash ) or return;
+ }
+
+ my $ref = $cache->{$type};
+
+ ### a list of ( feature1 => \@mods, feature2 => \@mods, etc )
+ my %list = UNIVERSAL::isa( $ref, 'ARRAY' )
+ ? map { $cache->{$_}->( $self ) } @$ref
+ : $ref->( $self );
+
+ ### filter based on whether we need the latest ones or not
+ for my $aref ( values %list ) {
+ $aref = [ $latest
+ ? grep { !$_->is_uptodate } @$aref
+ : grep { !$_->is_installed_version_sufficient } @$aref
+ ];
+ }
+
+ return %list;
+ }
+
+=head2 $bool = $self->selfupdate( update => "core|dependencies|enabled_features|features|all", [latest => BOOL, force => BOOL] )
+
+Selfupdate CPANPLUS. You can update either the core (CPANPLUS itself),
+the core dependencies, all features you have currently turned on, or
+all features available, or everything.
+
+The C<latest> option determines whether it should update to the latest
+version on CPAN, or if the minimal required version for CPANPLUS is
+good enough.
+
+Returns true on success, false on error.
+
+=cut
+
+ sub selfupdate {
+ my $self = shift;
+ my $cb = $self->();
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my $force;
+ my $tmpl = {
+ force => { default => $conf->get_conf('force'), store => \$force },
+ };
+
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+ check( $tmpl, \%hash ) or return;
+ }
+
+ my %list = $self->list_modules_to_update( %hash ) or return;
+
+ ### just the modules please
+ my @mods = map { @$_ } values %list;
+
+ my $flag;
+ for my $mod ( @mods ) {
+ unless( $mod->install( force => $force ) ) {
+ $flag++;
+ error(loc("Failed to update module '%1'", $mod->name));
+ }
+ }
+
+ return if $flag;
+ return 1;
+ }
+
+}
+
+=head2 @features = $self->list_features
+
+Returns a list of features that are supported by CPANPLUS.
+
+=cut
+
+sub list_features {
+ my $self = shift;
+ return keys %{ $self->_get_config->{'features'} };
+}
+
+=head2 @features = $self->list_enabled_features
+
+Returns a list of features that are enabled in your current
+CPANPLUS installation.
+
+=cut
+
+sub list_enabled_features {
+ my $self = shift;
+ my $cb = $self->();
+
+ my @enabled;
+ for my $feat ( $self->list_features ) {
+ my $ref = $self->_get_config->{'features'}->{$feat}->[1];
+ push @enabled, $feat if $ref->($cb);
+ }
+
+ return @enabled;
+}
+
+=head2 @mods = $self->modules_for_feature( FEATURE [,AS_HASH] )
+
+Returns a list of C<CPANPLUS::Selfupdate::Module> objects which
+represent the modules required to support this feature.
+
+For a list of features, call the C<list_features> method.
+
+If the C<AS_HASH> argument is provided, no module objects are
+returned, but a hashref where the keys are names of the modules,
+and values are their minimum versions.
+
+=cut
+
+sub modules_for_feature {
+ my $self = shift;
+ my $feature = shift or return;
+ my $as_hash = shift || 0;
+ my $cb = $self->();
+
+ unless( exists $self->_get_config->{'features'}->{$feature} ) {
+ error(loc("Unknown feature '%1'", $feature));
+ return;
+ }
+
+ my $ref = $self->_get_config->{'features'}->{$feature}->[0];
+
+ ### it's either a list of modules/versions or a subroutine that
+ ### returns a list of modules/versions
+ my $href = UNIVERSAL::isa( $ref, 'HASH' ) ? $ref : $ref->( $cb );
+
+ return unless $href; # nothing needed for the feature?
+
+ return $href if $as_hash;
+ return $self->_hashref_to_module( $href );
+}
+
+
+=head2 @mods = $self->list_core_dependencies( [AS_HASH] )
+
+Returns a list of C<CPANPLUS::Selfupdate::Module> objects which
+represent the modules that comprise the core dependencies of CPANPLUS.
+
+If the C<AS_HASH> argument is provided, no module objects are
+returned, but a hashref where the keys are names of the modules,
+and values are their minimum versions.
+
+=cut
+
+sub list_core_dependencies {
+ my $self = shift;
+ my $as_hash = shift || 0;
+ my $cb = $self->();
+ my $href = $self->_get_config->{'dependencies'};
+
+ return $href if $as_hash;
+ return $self->_hashref_to_module( $href );
+}
+
+=head2 @mods = $self->list_core_modules( [AS_HASH] )
+
+Returns a list of C<CPANPLUS::Selfupdate::Module> objects which
+represent the modules that comprise the core of CPANPLUS.
+
+If the C<AS_HASH> argument is provided, no module objects are
+returned, but a hashref where the keys are names of the modules,
+and values are their minimum versions.
+
+=cut
+
+sub list_core_modules {
+ my $self = shift;
+ my $as_hash = shift || 0;
+ my $cb = $self->();
+ my $href = $self->_get_config->{'core'};
+
+ return $href if $as_hash;
+ return $self->_hashref_to_module( $href );
+}
+
+sub _hashref_to_module {
+ my $self = shift;
+ my $cb = $self->();
+ my $href = shift or return;
+
+ return map {
+ CPANPLUS::Selfupdate::Module->new(
+ $cb->module_tree($_) => $href->{$_}
+ )
+ } keys %$href;
+}
+
+
+=head1 CPANPLUS::Selfupdate::Module
+
+C<CPANPLUS::Selfupdate::Module> extends C<CPANPLUS::Module> objects
+by providing accessors to aid in selfupdating CPANPLUS.
+
+These objects are returned by all methods of C<CPANPLUS::Selfupdate>
+that return module objects.
+
+=cut
+
+{ package CPANPLUS::Selfupdate::Module;
+ use base 'CPANPLUS::Module';
+
+ ### stores module name -> cpanplus required version
+ ### XXX only can deal with 1 pair!
+ my %Cache = ();
+ my $Acc = 'version_required';
+
+ sub new {
+ my $class = shift;
+ my $mod = shift or return;
+ my $ver = shift; return unless defined $ver;
+
+ my $obj = $mod->clone; # clone the module object
+ bless $obj, $class; # rebless it to our class
+
+ $obj->$Acc( $ver );
+
+ return $obj;
+ }
+
+=head2 $version = $mod->version_required
+
+Returns the version of this module required for CPANPLUS.
+
+=cut
+
+ sub version_required {
+ my $self = shift;
+ $Cache{ $self->name } = shift() if @_;
+ return $Cache{ $self->name };
+ }
+
+=head2 $bool = $mod->is_installed_version_sufficient
+
+Returns true if the installed version of this module is sufficient
+for CPANPLUS, or false if it is not.
+
+=cut
+
+
+ sub is_installed_version_sufficient {
+ my $self = shift;
+ return $self->is_uptodate( version => $self->$Acc );
+ }
+
+}
+
+1;
+
+=pod
+
+=head1 BUG REPORTS
+
+Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
+
+=head1 AUTHOR
+
+This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
+
+=head1 COPYRIGHT
+
+The CPAN++ interface (of which this module is a part of) is copyright (c)
+2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
+
+This library is free software; you may redistribute and/or modify it
+under the same terms as Perl itself.
+
+=cut
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Shell.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Shell.pm
new file mode 100644
index 00000000000..854d46b16a4
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Shell.pm
@@ -0,0 +1,341 @@
+package CPANPLUS::Shell;
+
+use strict;
+
+use CPANPLUS::Error;
+use CPANPLUS::Configure;
+use CPANPLUS::Internals::Constants;
+
+use Module::Load qw[load];
+use Params::Check qw[check];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+$Params::Check::VERBOSE = 1;
+
+use vars qw[@ISA $SHELL $DEFAULT];
+
+$DEFAULT = SHELL_DEFAULT;
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Shell
+
+=head1 SYNOPSIS
+
+ use CPANPLUS::Shell; # load the shell indicated by your
+ # config -- defaults to
+ # CPANPLUS::Shell::Default
+
+ use CPANPLUS::Shell qw[Classic] # load CPANPLUS::Shell::Classic;
+
+ my $ui = CPANPLUS::Shell->new();
+ my $name = $ui->which; # Find out what shell you loaded
+
+ $ui->shell; # run the ui shell
+
+
+=head1 DESCRIPTION
+
+This module is the generic loading (and base class) for all C<CPANPLUS>
+shells. Through this module you can load any installed C<CPANPLUS>
+shell.
+
+Just about all the functionality is provided by the shell that you have
+loaded, and not by this class (which merely functions as a generic
+loading class), so please consult the documentation of your shell of
+choice.
+
+=cut
+
+sub import {
+ my $class = shift;
+ my $option = shift;
+
+ ### find out what shell we're supposed to load ###
+ $SHELL = $option
+ ? $class . '::' . $option
+ : do { ### XXX this should offer to reconfigure
+ ### CPANPLUS, somehow. --rs
+ ### XXX load Configure only if we really have to
+ ### as that means any $Conf passed later on will
+ ### be ignored in favour of the one that was
+ ### retrieved via ->new --kane
+ my $conf = CPANPLUS::Configure->new() or
+ die loc("No configuration available -- aborting") . $/;
+ $conf->get_conf('shell') || $DEFAULT;
+ };
+
+ ### load the shell, fall back to the default if required
+ ### and die if even that doesn't work
+ EVAL: {
+ eval { load $SHELL };
+
+ if( $@ ) {
+ my $err = $@;
+
+ die loc("Your default shell '%1' is not available: %2",
+ $DEFAULT, $err) .
+ loc("Check your installation!") . "\n"
+ if $SHELL eq $DEFAULT;
+
+ warn loc("Failed to use '%1': %2", $SHELL, $err),
+ loc("Switching back to the default shell '%1'", $DEFAULT),
+ "\n";
+
+ $SHELL = $DEFAULT;
+ redo EVAL;
+ }
+ }
+ @ISA = ($SHELL);
+}
+
+sub which { return $SHELL }
+
+1;
+
+###########################################################################
+### abstracted out subroutines available to programmers of other shells ###
+###########################################################################
+
+package CPANPLUS::Shell::_Base::ReadLine;
+
+use strict;
+use vars qw($AUTOLOAD $TMPL);
+
+use FileHandle;
+use CPANPLUS::Error;
+use Params::Check qw[check];
+use Module::Load::Conditional qw[can_load];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+$Params::Check::VERBOSE = 1;
+
+
+$TMPL = {
+ brand => { default => '', strict_type => 1 },
+ prompt => { default => '> ', strict_type => 1 },
+ pager => { default => '' },
+ backend => { default => '' },
+ term => { default => '' },
+ format => { default => '' },
+ dist_format => { default => '' },
+ remote => { default => undef },
+ noninteractive => { default => '' },
+ cache => { default => [ ] },
+ settings => { default => { install_all_prereqs => undef },
+ no_override => 1 },
+ _old_sigpipe => { default => '', no_override => 1 },
+ _old_outfh => { default => '', no_override => 1 },
+ _signals => { default => { INT => { } }, no_override => 1 },
+};
+
+### autogenerate accessors ###
+for my $key ( keys %$TMPL ) {
+ no strict 'refs';
+ *{__PACKAGE__."::$key"} = sub {
+ my $self = shift;
+ $self->{$key} = $_[0] if @_;
+ return $self->{$key};
+ }
+}
+
+sub _init {
+ my $class = shift;
+ my %hash = @_;
+
+ my $self = check( $TMPL, \%hash ) or return;
+
+ bless $self, $class;
+
+ ### signal handler ###
+ $SIG{INT} = $self->_signals->{INT}->{handler} =
+ sub {
+ unless ( $self->_signals->{INT}->{count}++ ) {
+ warn loc("Caught SIGINT"), "\n";
+ } else {
+ warn loc("Got another SIGINT"), "\n"; die;
+ }
+ };
+ ### end sig handler ###
+
+ return $self;
+}
+
+### display shell's banner, takes the Backend object as argument
+sub _show_banner {
+ my $self = shift;
+ my $cpan = $self->backend;
+ my $term = $self->term;
+
+ ### Tries to probe for our ReadLine support status
+ # a) under an interactive shell?
+ my $rl_avail = (!$term->isa('CPANPLUS::Shell::_Faked'))
+ # b) do we have a tty terminal?
+ ? (-t STDIN)
+ # c) should we enable the term?
+ ? (!$self->__is_bad_terminal($term))
+ # d) external modules available?
+ ? ($term->ReadLine ne "Term::ReadLine::Stub")
+ # a+b+c+d => "Smart" terminal
+ ? loc("enabled")
+ # a+b+c => "Stub" terminal
+ : loc("available (try 'i Term::ReadLine::Perl')")
+ # a+b => "Bad" terminal
+ : loc("disabled")
+ # a => "Dumb" terminal
+ : loc("suppressed")
+ # none => "Faked" terminal
+ : loc("suppressed in batch mode");
+
+ $rl_avail = loc("ReadLine support %1.", $rl_avail);
+ $rl_avail = "\n*** $rl_avail" if (length($rl_avail) > 45);
+
+ $self->__print(
+ loc("%1 -- CPAN exploration and module installation (v%2)",
+ $self->which, $self->which->VERSION()), "\n",
+ loc("*** Please report bugs to <bug-cpanplus\@rt.cpan.org>."), "\n",
+ loc("*** Using CPANPLUS::Backend v%1. %2",
+ $cpan->VERSION, $rl_avail), "\n\n"
+ );
+}
+
+### checks whether the Term::ReadLine is broken and needs to fallback to Stub
+sub __is_bad_terminal {
+ my $self = shift;
+ my $term = $self->term;
+
+ return unless $^O eq 'MSWin32';
+
+ ### replace the term with the default (stub) one
+ return $self->term(Term::ReadLine::Stub->new( $self->brand ) );
+}
+
+### open a pager handle
+sub _pager_open {
+ my $self = shift;
+ my $cpan = $self->backend;
+ my $cmd = $cpan->configure_object->get_program('pager') or return;
+
+ $self->_old_sigpipe( $SIG{PIPE} );
+ $SIG{PIPE} = 'IGNORE';
+
+ my $fh = new FileHandle;
+ unless ( $fh->open("| $cmd") ) {
+ error(loc("could not pipe to %1: %2\n", $cmd, $!) );
+ return;
+ }
+
+ $fh->autoflush(1);
+
+ $self->pager( $fh );
+ $self->_old_outfh( select $fh );
+
+ return $fh;
+}
+
+### print to the current pager handle, or STDOUT if it's not opened
+sub _pager_close {
+ my $self = shift;
+ my $pager = $self->pager or return;
+
+ $pager->close if (ref($pager) and $pager->can('close'));
+
+ $self->pager( undef );
+
+ select $self->_old_outfh;
+ $SIG{PIPE} = $self->_old_sigpipe;
+
+ return 1;
+}
+
+
+
+{
+ my $win32_console;
+
+ ### determines row count of current terminal; defaults to 25.
+ ### used by the pager functions
+ sub _term_rowcount {
+ my $self = shift;
+ my $cpan = $self->backend;
+ my %hash = @_;
+
+ my $default;
+ my $tmpl = {
+ default => { default => 25, allow => qr/^\d$/,
+ store => \$default }
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ if ( $^O eq 'MSWin32' ) {
+ if ( can_load( modules => { 'Win32::Console' => '0.0' } ) ) {
+ $win32_console ||= Win32::Console->new();
+ my $rows = ($win32_console->Info)[-1];
+ return $rows;
+ }
+
+ } else {
+ local $Module::Load::Conditional::VERBOSE = 0;
+ if ( can_load(modules => {'Term::Size' => '0.0'}) ) {
+ my ($cols, $rows) = Term::Size::chars();
+ return $rows;
+ }
+ }
+ return $default;
+ }
+}
+
+### Custom print routines, mainly to be able to catch output
+### in test cases, or redirect it if need be
+{ sub __print {
+ my $self = shift;
+ print @_;
+ }
+
+ sub __printf {
+ my $self = shift;
+ my $fmt = shift;
+
+ ### MUST specify $fmt as a seperate param, and not as part
+ ### of @_, as it will then miss the $fmt and return the
+ ### number of elements in the list... =/ --kane
+ $self->__print( sprintf( $fmt, @_ ) );
+ }
+}
+
+1;
+
+=pod
+
+=head1 BUG REPORTS
+
+Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
+
+=head1 AUTHOR
+
+This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
+
+=head1 COPYRIGHT
+
+The CPAN++ interface (of which this module is a part of) is copyright (c)
+2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
+
+This library is free software; you may redistribute and/or modify it
+under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<CPANPLUS::Shell::Default>, L<CPANPLUS::Shell::Classic>, L<cpanp>
+
+=cut
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
+
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Classic.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Classic.pm
new file mode 100644
index 00000000000..08c03bcf383
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Classic.pm
@@ -0,0 +1,1236 @@
+##################################################
+### CPANPLUS/Shell/Classic.pm ###
+### Backwards compatible shell for CPAN++ ###
+### Written 08-04-2002 by Jos Boumans ###
+##################################################
+
+package CPANPLUS::Shell::Classic;
+
+use strict;
+
+
+use CPANPLUS::Error;
+use CPANPLUS::Backend;
+use CPANPLUS::Configure::Setup;
+use CPANPLUS::Internals::Constants;
+
+use Cwd;
+use IPC::Cmd;
+use Term::UI;
+use Data::Dumper;
+use Term::ReadLine;
+
+use Module::Load qw[load];
+use Params::Check qw[check];
+use Module::Load::Conditional qw[can_load];
+
+$Params::Check::VERBOSE = 1;
+$Params::Check::ALLOW_UNKNOWN = 1;
+
+BEGIN {
+ use vars qw[ $VERSION @ISA ];
+ @ISA = qw[ CPANPLUS::Shell::_Base::ReadLine ];
+ $VERSION = '0.0562';
+}
+
+load CPANPLUS::Shell;
+
+
+### our command set ###
+my $map = {
+ a => '_author',
+ b => '_bundle',
+ d => '_distribution',
+ 'm' => '_module',
+ i => '_find_all',
+ r => '_uptodate',
+ u => '_not_supported',
+ ls => '_ls',
+ get => '_fetch',
+ make => '_install',
+ test => '_install',
+ install => '_install',
+ clean => '_not_supported',
+ look => '_shell',
+ readme => '_readme',
+ h => '_help',
+ '?' => '_help',
+ o => '_set_conf',
+ reload => '_reload',
+ autobundle => '_autobundle',
+ '!' => '_bang',
+ #'q' => '_quit', # done it the loop itself
+};
+
+### the shell object, scoped to the file ###
+my $Shell;
+my $Brand = 'cpan';
+my $Prompt = $Brand . '> ';
+
+sub new {
+ my $class = shift;
+
+ my $cb = new CPANPLUS::Backend;
+ my $self = $class->SUPER::_init(
+ brand => $Brand,
+ term => Term::ReadLine->new( $Brand ),
+ prompt => $Prompt,
+ backend => $cb,
+ format => "%5s %-50s %8s %-10s\n",
+ );
+ ### make it available package wide ###
+ $Shell = $self;
+
+ ### enable verbose, it's the cpan.pm way
+ $cb->configure_object->set_conf( verbose => 1 );
+
+
+ ### register install callback ###
+ $cb->_register_callback(
+ name => 'install_prerequisite',
+ code => \&__ask_about_install,
+ );
+
+ ### register test report callback ###
+ $cb->_register_callback(
+ name => 'edit_test_report',
+ code => \&__ask_about_test_report,
+ );
+
+ return $self;
+}
+
+sub shell {
+ my $self = shift;
+ my $term = $self->term;
+
+ $self->_show_banner;
+ $self->_input_loop && print "\n";
+ $self->_quit;
+}
+
+sub _input_loop {
+ my $self = shift;
+ my $term = $self->term;
+ my $cb = $self->backend;
+
+ my $normal_quit = 0;
+ while (
+ defined (my $input = eval { $term->readline($self->prompt) } )
+ or $self->_signals->{INT}{count} == 1
+ ) {
+ ### re-initiate all signal handlers
+ while (my ($sig, $entry) = each %{$self->_signals} ) {
+ $SIG{$sig} = $entry->{handler} if exists($entry->{handler});
+ }
+
+ last if $self->_dispatch_on_input( input => $input );
+
+ ### flush the lib cache ###
+ $cb->_flush( list => [qw|lib load|] );
+
+ } continue {
+ $self->_signals->{INT}{count}--
+ if $self->_signals->{INT}{count}; # clear the sigint count
+ }
+
+ return 1;
+}
+
+sub _dispatch_on_input {
+ my $self = shift;
+ my $conf = $self->backend->configure_object();
+ my $term = $self->term;
+ my %hash = @_;
+
+ my $string;
+ my $tmpl = {
+ input => { required => 1, store => \$string }
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### the original force setting;
+ my $force_store = $conf->get_conf( 'force' );
+
+ ### parse the input: the first part before the space
+ ### is the command, followed by arguments.
+ ### see the usage below
+ my $key;
+ PARSE_INPUT: {
+ $string =~ s|^\s*([\w\?\!]+)\s*||;
+ chomp $string;
+ $key = lc($1);
+ }
+
+ ### you prefixed the input with 'force'
+ ### that means we set the force flag, and
+ ### reparse the input...
+ ### YAY goto block :)
+ if( $key eq 'force' ) {
+ $conf->set_conf( force => 1 );
+ goto PARSE_INPUT;
+ }
+
+ ### you want to quit
+ return 1 if $key =~ /^q/;
+
+ my $method = $map->{$key};
+ unless( $self->can( $method ) ) {
+ print "Unknown command '$key'. Type ? for help.\n";
+ return;
+ }
+
+ ### dispatch the method call
+ eval { $self->$method(
+ command => $key,
+ result => [ split /\s+/, $string ],
+ input => $string );
+ };
+ warn $@ if $@;
+
+ return;
+}
+
+### displays quit message
+sub _quit {
+
+ ### well, that's what CPAN.pm says...
+ print "Lockfile removed\n";
+}
+
+sub _not_supported {
+ my $self = shift;
+ my %hash = @_;
+
+ my $cmd;
+ my $tmpl = {
+ command => { required => 1, store => \$cmd }
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ print "Sorry, the command '$cmd' is not supported\n";
+
+ return;
+}
+
+sub _fetch {
+ my $self = shift;
+ my $cb = $self->backend;
+ my %hash = @_;
+
+ my($aref, $input);
+ my $tmpl = {
+ result => { store => \$aref, default => [] },
+ input => { default => 'all', store => \$input },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ for my $mod (@$aref) {
+ my $obj;
+
+ unless( $obj = $cb->module_tree($mod) ) {
+ print "Warning: Cannot get $input, don't know what it is\n";
+ print "Try the command\n\n";
+ print "\ti /$mod/\n\n";
+ print "to find objects with matching identifiers.\n";
+
+ next;
+ }
+
+ $obj->fetch && $obj->extract;
+ }
+
+ return $aref;
+}
+
+sub _install {
+ my $self = shift;
+ my $cb = $self->backend;
+ my %hash = @_;
+
+ my $mapping = {
+ make => { target => TARGET_CREATE, skiptest => 1 },
+ test => { target => TARGET_CREATE },
+ install => { target => TARGET_INSTALL },
+ };
+
+ my($aref,$cmd);
+ my $tmpl = {
+ result => { store => \$aref, default => [] },
+ command => { required => 1, store => \$cmd, allow => [keys %$mapping] },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ for my $mod (@$aref) {
+ my $obj = $cb->module_tree( $mod );
+
+ unless( $obj ) {
+ print "No such module '$mod'\n";
+ next;
+ }
+
+ my $opts = $mapping->{$cmd};
+ $obj->install( %$opts );
+ }
+
+ return $aref;
+}
+
+sub _shell {
+ my $self = shift;
+ my $cb = $self->backend;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my($aref, $cmd);
+ my $tmpl = {
+ result => { store => \$aref, default => [] },
+ command => { required => 1, store => \$cmd },
+
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+
+ my $shell = $conf->get_program('shell');
+ unless( $shell ) {
+ print "Your configuration does not define a value for subshells.\n".
+ qq[Please define it with "o conf shell <your shell>"\n];
+ return;
+ }
+
+ my $cwd = Cwd::cwd();
+
+ for my $mod (@$aref) {
+ print "Running $cmd for $mod\n";
+
+ my $obj = $cb->module_tree( $mod ) or next;
+ $obj->fetch or next;
+ $obj->extract or next;
+
+ $cb->_chdir( dir => $obj->status->extract ) or next;
+
+ #local $ENV{PERL5OPT} = CPANPLUS::inc->original_perl5opt;
+ if( system($shell) and $! ) {
+ print "Error executing your subshell '$shell': $!\n";
+ next;
+ }
+ }
+ $cb->_chdir( dir => $cwd );
+
+ return $aref;
+}
+
+sub _readme {
+ my $self = shift;
+ my $cb = $self->backend;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my($aref, $cmd);
+ my $tmpl = {
+ result => { store => \$aref, default => [] },
+ command => { required => 1, store => \$cmd },
+
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ for my $mod (@$aref) {
+ my $obj = $cb->module_tree( $mod ) or next;
+
+ if( my $readme = $obj->readme ) {
+
+ $self->_pager_open;
+ print $readme;
+ $self->_pager_close;
+ }
+ }
+
+ return 1;
+}
+
+sub _reload {
+ my $self = shift;
+ my $cb = $self->backend;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my($input, $cmd);
+ my $tmpl = {
+ input => { default => 'all', store => \$input },
+ command => { required => 1, store => \$cmd },
+
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ if ( $input =~ /cpan/i ) {
+ print qq[You want to reload the CPAN code\n];
+ print qq[Just type 'q' and then restart... ] .
+ qq[Trust me, it is MUCH safer\n];
+
+ } elsif ( $input =~ /index/i ) {
+ $cb->reload_indices(update_source => 1);
+
+ } else {
+ print qq[cpan re-evals the CPANPLUS.pm file\n];
+ print qq[index re-reads the index files\n];
+ }
+
+ return 1;
+}
+
+sub _autobundle {
+ my $self = shift;
+ my $cb = $self->backend;
+
+ print qq[Writing bundle file... This may take a while\n];
+
+ my $where = $cb->autobundle();
+
+ print $where
+ ? qq[\nWrote autobundle to $where\n]
+ : qq[\nCould not create autobundle\n];
+
+ return 1;
+}
+
+sub _set_conf {
+ my $self = shift;
+ my $cb = $self->backend;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my($aref, $input);
+ my $tmpl = {
+ result => { store => \$aref, default => [] },
+ input => { default => 'all', store => \$input },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ my $type = shift @$aref;
+
+ if( $type eq 'debug' ) {
+ print qq[Sorry you cannot set debug options through ] .
+ qq[this shell in CPANPLUS\n];
+ return;
+
+ } elsif ( $type eq 'conf' ) {
+
+ ### from CPAN.pm :o)
+ # CPAN::Shell::o and CPAN::Config::edit are closely related. 'o conf'
+ # should have been called set and 'o debug' maybe 'set debug'
+
+ # commit Commit changes to disk
+ # defaults Reload defaults from disk
+ # init Interactive setting of all options
+
+ my $name = shift @$aref;
+ my $value = "@$aref";
+
+ if( $name eq 'init' ) {
+ my $setup = CPANPLUS::Configure::Setup->new(
+ conf => $cb->configure_object,
+ term => $self->term,
+ backend => $cb,
+ );
+ return $setup->init;
+
+ } elsif ($name eq 'commit' ) {;
+ $cb->configure_object->save;
+ print "Your CPAN++ configuration info has been saved!\n\n";
+ return;
+
+ } elsif ($name eq 'defaults' ) {
+ print qq[Sorry, CPANPLUS cannot restore default for you.\n] .
+ qq[Perhaps you should run the interactive setup again.\n] .
+ qq[\ttry running 'o conf init'\n];
+ return;
+
+ ### we're just supplying things in the 'conf' section now,
+ ### not the program section.. it's a bit of a hassle to make that
+ ### work cleanly with the original CPAN.pm interface, so we'll fix
+ ### it when people start complaining, which is hopefully never.
+ } else {
+ unless( $name ) {
+ my @list = grep { $_ ne 'hosts' }
+ $conf->options( type => $type );
+
+ my $method = 'get_' . $type;
+
+ local $Data::Dumper::Indent = 0;
+ for my $name ( @list ) {
+ my $val = $conf->$method($name);
+ ($val) = ref($val)
+ ? (Data::Dumper::Dumper($val) =~ /= (.*);$/)
+ : "'$val'";
+ printf " %-25s %s\n", $name, $val;
+ }
+
+ } elsif ( $name eq 'hosts' ) {
+ print "Setting hosts is not trivial.\n" .
+ "It is suggested you edit the " .
+ "configuration file manually";
+
+ } else {
+ my $method = 'set_' . $type;
+ if( $conf->$method($name => defined $value ? $value : '') ) {
+ my $set_to = defined $value ? $value : 'EMPTY STRING';
+ print "Key '$name' was set to '$set_to'\n";
+ }
+ }
+ }
+ } else {
+ print qq[Known options:\n] .
+ qq[ conf set or get configuration variables\n] .
+ qq[ debug set or get debugging options\n];
+ }
+
+ return;
+}
+
+########################
+### search functions ###
+########################
+
+sub _author {
+ my $self = shift;
+ my $cb = $self->backend;
+ my %hash = @_;
+
+ my($aref, $short, $input, $class);
+ my $tmpl = {
+ result => { store => \$aref, default => ['/./'] },
+ short => { default => 0, store => \$short },
+ input => { default => 'all', store => \$input },
+ class => { default => 'Author', no_override => 1,
+ store => \$class },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ my @regexes = map { m|/(.+)/| ? qr/$1/ : $_ } @$aref;
+
+
+ my @rv;
+ for my $type (qw[author cpanid]) {
+ push @rv, $cb->search( type => $type, allow => \@regexes );
+ }
+
+ unless( @rv ) {
+ print "No object of type $class found for argument $input\n"
+ unless $short;
+ return;
+ }
+
+ return $self->_pp_author(
+ result => \@rv,
+ class => $class,
+ short => $short,
+ input => $input );
+
+}
+
+### find all modules matching a query ###
+sub _module {
+ my $self = shift;
+ my $cb = $self->backend;
+ my %hash = @_;
+
+ my($aref, $short, $input, $class);
+ my $tmpl = {
+ result => { store => \$aref, default => ['/./'] },
+ short => { default => 0, store => \$short },
+ input => { default => 'all', store => \$input },
+ class => { default => 'Module', no_override => 1,
+ store => \$class },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ my @rv;
+ for my $module (@$aref) {
+ if( $module =~ m|/(.+)/| ) {
+ push @rv, $cb->search( type => 'module',
+ allow => [qr/$1/i] );
+ } else {
+ my $obj = $cb->module_tree( $module ) or next;
+ push @rv, $obj;
+ }
+ }
+
+ return $self->_pp_module(
+ result => \@rv,
+ class => $class,
+ short => $short,
+ input => $input );
+}
+
+### find all bundles matching a query ###
+sub _bundle {
+ my $self = shift;
+ my $cb = $self->backend;
+ my %hash = @_;
+
+ my($aref, $short, $input, $class);
+ my $tmpl = {
+ result => { store => \$aref, default => ['/./'] },
+ short => { default => 0, store => \$short },
+ input => { default => 'all', store => \$input },
+ class => { default => 'Bundle', no_override => 1,
+ store => \$class },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ my @rv;
+ for my $bundle (@$aref) {
+ if( $bundle =~ m|/(.+)/| ) {
+ push @rv, $cb->search( type => 'module',
+ allow => [qr/Bundle::.*?$1/i] );
+ } else {
+ my $obj = $cb->module_tree( "Bundle::${bundle}" ) or next;
+ push @rv, $obj;
+ }
+ }
+
+ return $self->_pp_module(
+ result => \@rv,
+ class => $class,
+ short => $short,
+ input => $input );
+}
+
+sub _distribution {
+ my $self = shift;
+ my $cb = $self->backend;
+ my %hash = @_;
+
+ my($aref, $short, $input, $class);
+ my $tmpl = {
+ result => { store => \$aref, default => ['/./'] },
+ short => { default => 0, store => \$short },
+ input => { default => 'all', store => \$input },
+ class => { default => 'Distribution', no_override => 1,
+ store => \$class },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ my @rv;
+ for my $module (@$aref) {
+ ### if it's a regex... ###
+ if ( my ($match) = $module =~ m|^/(.+)/$|) {
+
+ ### something like /FOO/Bar.tar.gz/ was entered
+ if (my ($path,$package) = $match =~ m|^/?(.+)/(.+)$|) {
+ my $seen;
+
+ my @data = $cb->search( type => 'package',
+ allow => [qr/$package/i] );
+
+ my @list = $cb->search( type => 'path',
+ allow => [qr/$path/i],
+ data => \@data );
+
+ ### make sure we dont list the same dist twice
+ for my $val ( @list ) {
+ next if $seen->{$val->package}++;
+
+ push @rv, $val;
+ }
+
+ ### something like /FOO/ or /Bar.tgz/ was entered
+ ### so we look both in the path, as well as in the package name
+ } else {
+ my $seen;
+ { my @list = $cb->search( type => 'package',
+ allow => [qr/$match/i] );
+
+ ### make sure we dont list the same dist twice
+ for my $val ( @list ) {
+ next if $seen->{$val->package}++;
+
+ push @rv, $val;
+ }
+ }
+
+ { my @list = $cb->search( type => 'path',
+ allow => [qr/$match/i] );
+
+ ### make sure we dont list the same dist twice
+ for my $val ( @list ) {
+ next if $seen->{$val->package}++;
+
+ push @rv, $val;
+ }
+
+ }
+ }
+
+ } else {
+
+ ### user entered a full dist, like: R/RC/RCAPUTO/POE-0.19.tar.gz
+ if (my ($path,$package) = $module =~ m|^/?(.+)/(.+)$|) {
+ my @data = $cb->search( type => 'package',
+ allow => [qr/^$package$/] );
+ my @list = $cb->search( type => 'path',
+ allow => [qr/$path$/i],
+ data => \@data);
+
+ ### make sure we dont list the same dist twice
+ my $seen;
+ for my $val ( @list ) {
+ next if $seen->{$val->package}++;
+
+ push @rv, $val;
+ }
+ }
+ }
+ }
+
+ return $self->_pp_distribution(
+ result => \@rv,
+ class => $class,
+ short => $short,
+ input => $input );
+}
+
+sub _find_all {
+ my $self = shift;
+
+ my @rv;
+ for my $method (qw[_author _bundle _module _distribution]) {
+ my $aref = $self->$method( @_, short => 1 );
+
+ push @rv, @$aref if $aref;
+ }
+
+ print scalar(@rv). " items found\n"
+}
+
+sub _uptodate {
+ my $self = shift;
+ my $cb = $self->backend;
+ my %hash = @_;
+
+ my($aref, $short, $input, $class);
+ my $tmpl = {
+ result => { store => \$aref, default => ['/./'] },
+ short => { default => 0, store => \$short },
+ input => { default => 'all', store => \$input },
+ class => { default => 'Uptodate', no_override => 1,
+ store => \$class },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+
+ my @rv;
+ if( @$aref) {
+ for my $module (@$aref) {
+ if( $module =~ m|/(.+)/| ) {
+ my @list = $cb->search( type => 'module',
+ allow => [qr/$1/i] );
+
+ ### only add those that are installed and not core
+ push @rv, grep { not $_->package_is_perl_core }
+ grep { $_->installed_file }
+ @list;
+
+ } else {
+ my $obj = $cb->module_tree( $module ) or next;
+ push @rv, $obj;
+ }
+ }
+ } else {
+ @rv = @{$cb->_all_installed};
+ }
+
+ return $self->_pp_uptodate(
+ result => \@rv,
+ class => $class,
+ short => $short,
+ input => $input );
+}
+
+sub _ls {
+ my $self = shift;
+ my $cb = $self->backend;
+ my %hash = @_;
+
+ my($aref, $short, $input, $class);
+ my $tmpl = {
+ result => { store => \$aref, default => [] },
+ short => { default => 0, store => \$short },
+ input => { default => 'all', store => \$input },
+ class => { default => 'Uptodate', no_override => 1,
+ store => \$class },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ my @rv;
+ for my $name (@$aref) {
+ my $auth = $cb->author_tree( uc $name );
+
+ unless( $auth ) {
+ print qq[ls command rejects argument $name: not an author\n];
+ next;
+ }
+
+ push @rv, $auth->distributions;
+ }
+
+ return $self->_pp_ls(
+ result => \@rv,
+ class => $class,
+ short => $short,
+ input => $input );
+}
+
+############################
+### pretty printing subs ###
+############################
+
+
+sub _pp_author {
+ my $self = shift;
+ my %hash = @_;
+
+ my( $aref, $short, $class, $input );
+ my $tmpl = {
+ result => { required => 1, default => [], strict_type => 1,
+ store => \$aref },
+ short => { default => 0, store => \$short },
+ class => { required => 1, store => \$class },
+ input => { required => 1, store => \$input },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### no results
+ if( !@$aref ) {
+ print "No objects of type $class found for argument $input\n"
+ unless $short;
+
+ ### one result, long output desired;
+ } elsif( @$aref == 1 and !$short ) {
+
+ ### should look like this:
+ #cpan> a KANE
+ #Author id = KANE
+ # EMAIL boumans@frg.eur.nl
+ # FULLNAME Jos Boumans
+
+ my $obj = shift @$aref;
+
+ print "$class id = ", $obj->cpanid(), "\n";
+ printf " %-12s %s\n", 'EMAIL', $obj->email();
+ printf " %-12s %s%s\n", 'FULLNAME', $obj->author();
+
+ } else {
+
+ ### should look like this:
+ #Author KANE (Jos Boumans)
+ #Author LBROCARD (Leon Brocard)
+ #2 items found
+
+ for my $obj ( @$aref ) {
+ printf qq[%-15s %s ("%s" (%s))\n],
+ $class, $obj->cpanid, $obj->author, $obj->email;
+ }
+ print scalar(@$aref)." items found\n" unless $short;
+ }
+
+ return $aref;
+}
+
+sub _pp_module {
+ my $self = shift;
+ my %hash = @_;
+
+ my( $aref, $short, $class, $input );
+ my $tmpl = {
+ result => { required => 1, default => [], strict_type => 1,
+ store => \$aref },
+ short => { default => 0, store => \$short },
+ class => { required => 1, store => \$class },
+ input => { required => 1, store => \$input },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+
+ ### no results
+ if( !@$aref ) {
+ print "No objects of type $class found for argument $input\n"
+ unless $short;
+
+ ### one result, long output desired;
+ } elsif( @$aref == 1 and !$short ) {
+
+
+ ### should look like this:
+ #Module id = LWP
+ # DESCRIPTION Libwww-perl
+ # CPAN_USERID GAAS (Gisle Aas <gisle@ActiveState.com>)
+ # CPAN_VERSION 5.64
+ # CPAN_FILE G/GA/GAAS/libwww-perl-5.64.tar.gz
+ # DSLI_STATUS RmpO (released,mailing-list,perl,object-oriented)
+ # MANPAGE LWP - The World-Wide Web library for Perl
+ # INST_FILE C:\Perl\site\lib\LWP.pm
+ # INST_VERSION 5.62
+
+ my $obj = shift @$aref;
+ my $aut_obj = $obj->author;
+ my $format = " %-12s %s%s\n";
+
+ print "$class id = ", $obj->module(), "\n";
+ printf $format, 'DESCRIPTION', $obj->description()
+ if $obj->description();
+
+ printf $format, 'CPAN_USERID', $aut_obj->cpanid() . " (" .
+ $aut_obj->author() . " <" . $aut_obj->email() . ">)";
+
+ printf $format, 'CPAN_VERSION', $obj->version();
+ printf $format, 'CPAN_FILE', $obj->path() . '/' . $obj->package();
+
+ printf $format, 'DSLI_STATUS', $self->_pp_dslip($obj->dslip)
+ if $obj->dslip() =~ /\w/;
+
+ #printf $format, 'MANPAGE', $obj->foo();
+ ### this is for bundles... CPAN.pm downloads them,
+ #printf $format, 'CONATAINS,
+ # parses and goes from there...
+
+ printf $format, 'INST_FILE', $obj->installed_file ||
+ '(not installed)';
+ printf $format, 'INST_VERSION', $obj->installed_version;
+
+
+
+ } else {
+
+ ### should look like this:
+ #Module LWP (G/GA/GAAS/libwww-perl-5.64.tar.gz)
+ #Module POE (R/RC/RCAPUTO/POE-0.19.tar.gz)
+ #2 items found
+
+ for my $obj ( @$aref ) {
+ printf "%-15s %-15s (%s)\n", $class, $obj->module(),
+ $obj->path() .'/'. $obj->package();
+ }
+ print scalar(@$aref). " items found\n" unless $short;
+ }
+
+ return $aref;
+}
+
+sub _pp_dslip {
+ my $self = shift;
+ my $dslip = shift or return;
+
+ my (%_statusD, %_statusS, %_statusL, %_statusI);
+
+ @_statusD{qw(? i c a b R M S)} =
+ qw(unknown idea pre-alpha alpha beta released mature standard);
+
+ @_statusS{qw(? m d u n)} =
+ qw(unknown mailing-list developer comp.lang.perl.* none);
+
+ @_statusL{qw(? p c + o h)} = qw(unknown perl C C++ other hybrid);
+ @_statusI{qw(? f r O h)} =
+ qw(unknown functions references+ties object-oriented hybrid);
+
+ my @status = split("", $dslip);
+
+ my $results = sprintf( "%s (%s,%s,%s,%s)",
+ $dslip,
+ $_statusD{$status[0]},
+ $_statusS{$status[1]},
+ $_statusL{$status[2]},
+ $_statusI{$status[3]}
+ );
+
+ return $results;
+}
+
+sub _pp_distribution {
+ my $self = shift;
+ my $cb = $self->backend;
+ my %hash = @_;
+
+ my( $aref, $short, $class, $input );
+ my $tmpl = {
+ result => { required => 1, default => [], strict_type => 1,
+ store => \$aref },
+ short => { default => 0, store => \$short },
+ class => { required => 1, store => \$class },
+ input => { required => 1, store => \$input },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+
+ ### no results
+ if( !@$aref ) {
+ print "No objects of type $class found for argument $input\n"
+ unless $short;
+
+ ### one result, long output desired;
+ } elsif( @$aref == 1 and !$short ) {
+
+
+ ### should look like this:
+ #Distribution id = S/SA/SABECK/POE-Component-Client-POP3-0.02.tar.gz
+ # CPAN_USERID SABECK (Scott Beck <scott@gossamer-threads.com>)
+ # CONTAINSMODS POE::Component::Client::POP3
+
+ my $obj = shift @$aref;
+ my $aut_obj = $obj->author;
+ my $pkg = $obj->package;
+ my $format = " %-12s %s\n";
+
+ my @list = $cb->search( type => 'package',
+ allow => [qr/^$pkg$/] );
+
+
+ print "$class id = ", $obj->path(), '/', $obj->package(), "\n";
+ printf $format, 'CPAN_USERID',
+ $aut_obj->cpanid .' ('. $aut_obj->author .
+ ' '. $aut_obj->email .')';
+
+ ### yes i know it's ugly, but it's what cpan.pm does
+ printf $format, 'CONTAINSMODS', join (' ', map { $_->module } @list);
+
+ } else {
+
+ ### should look like this:
+ #Distribution LWP (G/GA/GAAS/libwww-perl-5.64.tar.gz)
+ #Distribution POE (R/RC/RCAPUTO/POE-0.19.tar.gz)
+ #2 items found
+
+ for my $obj ( @$aref ) {
+ printf "%-15s %s\n", $class, $obj->path() .'/'. $obj->package();
+ }
+
+ print scalar(@$aref). " items found\n" unless $short;
+ }
+
+ return $aref;
+}
+
+sub _pp_uptodate {
+ my $self = shift;
+ my $cb = $self->backend;
+ my %hash = @_;
+
+ my( $aref, $short, $class, $input );
+ my $tmpl = {
+ result => { required => 1, default => [], strict_type => 1,
+ store => \$aref },
+ short => { default => 0, store => \$short },
+ class => { required => 1, store => \$class },
+ input => { required => 1, store => \$input },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ my $format = "%-25s %9s %9s %s\n";
+
+ my @not_uptodate;
+ my $no_version;
+
+ my %seen;
+ for my $mod (@$aref) {
+ next if $mod->package_is_perl_core;
+ next if $seen{ $mod->package }++;
+
+
+ if( $mod->installed_file and not $mod->installed_version ) {
+ $no_version++;
+ next;
+ }
+
+ push @not_uptodate, $mod unless $mod->is_uptodate;
+ }
+
+ unless( @not_uptodate ) {
+ my $string = $input
+ ? "for $input"
+ : '';
+ print "All modules are up to date $string\n";
+ return;
+
+ } else {
+ printf $format, ( 'Package namespace',
+ 'installed',
+ 'latest',
+ 'in CPAN file'
+ );
+ }
+
+ for my $mod ( sort { $a->module cmp $b->module } @not_uptodate ) {
+ printf $format, ( $mod->module,
+ $mod->installed_version,
+ $mod->version,
+ $mod->path .'/'. $mod->package,
+ );
+ }
+
+ print "$no_version installed modules have no (parsable) version number\n"
+ if $no_version;
+
+ return \@not_uptodate;
+}
+
+sub _pp_ls {
+ my $self = shift;
+ my $cb = $self->backend;
+ my %hash = @_;
+
+ my( $aref, $short, $class, $input );
+ my $tmpl = {
+ result => { required => 1, default => [], strict_type => 1,
+ store => \$aref },
+ short => { default => 0, store => \$short },
+ class => { required => 1, store => \$class },
+ input => { required => 1, store => \$input },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### should look something like this:
+ #6272 2002-05-12 KANE/Acme-Comment-1.00.tar.gz
+ #8171 2002-08-13 KANE/Acme-Comment-1.01.zip
+ #7110 2002-09-04 KANE/Acme-Comment-1.02.tar.gz
+ #7571 2002-09-08 KANE/Acme-Intraweb-1.01.tar.gz
+ #6625 2001-08-23 KANE/Acme-POE-Knee-1.10.zip
+ #3058 2003-10-05 KANE/Acme-Test-0.02.tar.gz
+
+ ### don't know size or mtime
+ #my $format = "%8d %10s %s/%s\n";
+
+ for my $mod ( sort { $a->package cmp $b->package } @$aref ) {
+ print "\t" . $mod->package . "\n";
+ }
+
+ return $aref;
+}
+
+
+#############################
+### end pretty print subs ###
+#############################
+
+
+sub _bang {
+ my $self = shift;
+ my %hash = @_;
+
+ my( $input );
+ my $tmpl = {
+ input => { required => 1, store => \$input },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ eval $input;
+ warn $@ if $@;
+
+ print "\n";
+
+ return;
+}
+
+sub _help {
+ print qq[
+Display Information
+ a authors
+ b string display bundles
+ d or info distributions
+ m /regex/ about modules
+ i or anything of above
+ r none reinstall recommendations
+ u uninstalled distributions
+
+Download, Test, Make, Install...
+ get download
+ make make (implies get)
+ test modules, make test (implies make)
+ install dists, bundles make install (implies test)
+ clean make clean
+ look open subshell in these dists' directories
+ readme display these dists' README files
+
+Other
+ h,? display this menu ! perl-code eval a perl command
+ o conf [opt] set and query options q quit the cpan shell
+ reload cpan load CPAN.pm again reload index load newer indices
+ autobundle Snapshot force cmd unconditionally do cmd
+];
+
+}
+
+
+
+1;
+__END__
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Shell::Classic - CPAN.pm emulation for CPANPLUS
+
+=head1 DESCRIPTION
+
+The Classic shell is designed to provide the feel of the CPAN.pm shell
+using CPANPLUS underneath.
+
+For detailed documentation, refer to L<CPAN>.
+
+=head1 BUG REPORTS
+
+Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
+
+=head1 AUTHOR
+
+This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
+
+=head1 COPYRIGHT
+
+The CPAN++ interface (of which this module is a part of) is copyright (c)
+2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
+
+This library is free software; you may redistribute and/or modify it
+under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<CPANPLUS::Configure>, L<CPANPLUS::Module>, L<CPANPLUS::Module::Author>
+
+=cut
+
+
+=head1 SEE ALSO
+
+L<CPAN>
+
+=cut
+
+
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default.pm
new file mode 100644
index 00000000000..a9d51422f66
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default.pm
@@ -0,0 +1,1938 @@
+package CPANPLUS::Shell::Default;
+
+use strict;
+
+
+use CPANPLUS::Error;
+use CPANPLUS::Backend;
+use CPANPLUS::Configure::Setup;
+use CPANPLUS::Internals::Constants;
+use CPANPLUS::Internals::Constants::Report qw[GRADE_FAIL];
+
+use Cwd;
+use IPC::Cmd;
+use Term::UI;
+use Data::Dumper;
+use Term::ReadLine;
+
+use Module::Load qw[load];
+use Params::Check qw[check];
+use Module::Load::Conditional qw[can_load check_install];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+local $Params::Check::VERBOSE = 1;
+local $Data::Dumper::Indent = 1; # for dumpering from !
+
+BEGIN {
+ use vars qw[ $VERSION @ISA ];
+ @ISA = qw[ CPANPLUS::Shell::_Base::ReadLine ];
+ $VERSION = "0.90";
+}
+
+load CPANPLUS::Shell;
+
+
+my $map = {
+ 'm' => '_search_module',
+ 'a' => '_search_author',
+ '!' => '_bang',
+ '?' => '_help',
+ 'h' => '_help',
+ 'q' => '_quit',
+ 'r' => '_readme',
+ 'v' => '_show_banner',
+ 'w' => '__display_results',
+ 'd' => '_fetch',
+ 'z' => '_shell',
+ 'f' => '_distributions',
+ 'x' => '_reload_indices',
+ 'i' => '_install',
+ 't' => '_install',
+ 'l' => '_details',
+ 'p' => '_print',
+ 's' => '_set_conf',
+ 'o' => '_uptodate',
+ 'b' => '_autobundle',
+ 'u' => '_uninstall',
+ '/' => '_meta', # undocumented for now
+ 'c' => '_reports',
+};
+### free letters: e g j k n y ###
+
+
+### will be filled if you have a .default-shell.rc and
+### Config::Auto installed
+my $rc = {};
+
+### the shell object, scoped to the file ###
+my $Shell;
+my $Brand = loc('CPAN Terminal');
+my $Prompt = $Brand . '> ';
+
+=pod
+
+=head1 NAME
+
+CPANPLUS::Shell::Default
+
+=head1 SYNOPSIS
+
+ ### loading the shell:
+ $ cpanp # run 'cpanp' from the command line
+ $ perl -MCPANPLUS -eshell # load the shell from the command line
+
+
+ use CPANPLUS::Shell qw[Default]; # load this shell via the API
+ # always done via CPANPLUS::Shell
+
+ my $ui = CPANPLUS::Shell->new;
+ $ui->shell; # run the shell
+ $ui->dispatch_on_input( input => 'x'); # update the source using the
+ # dispatch method
+
+ ### when in the shell:
+ ### Note that all commands can also take options.
+ ### Look at their underlying CPANPLUS::Backend methods to see
+ ### what options those are.
+ cpanp> h # show help messages
+ cpanp> ? # show help messages
+
+ cpanp> m Acme # find acme modules, allows regexes
+ cpanp> a KANE # find modules by kane, allows regexes
+ cpanp> f Acme::Foo # get a list of all releases of Acme::Foo
+
+ cpanp> i Acme::Foo # install Acme::Foo
+ cpanp> i Acme-Foo-1.3 # install version 1.3 of Acme::Foo
+ cpanp> i <URI> # install from URI, like ftp://foo.com/X.tgz
+ cpanp> i <DIR> # install from an absolute or relative directory
+ cpanp> i 1 3..5 # install search results 1, 3, 4 and 5
+ cpanp> i * # install all search results
+ cpanp> a KANE; i *; # find modules by kane, install all results
+ cpanp> t Acme::Foo # test Acme::Foo, without installing it
+ cpanp> u Acme::Foo # uninstall Acme::Foo
+ cpanp> d Acme::Foo # download Acme::Foo
+ cpanp> z Acme::Foo # download & extract Acme::Foo, then open a
+ # shell in the extraction directory
+
+ cpanp> c Acme::Foo # get a list of test results for Acme::Foo
+ cpanp> l Acme::Foo # view details about the Acme::Foo package
+ cpanp> r Acme::Foo # view Acme::Foo's README file
+ cpanp> o # get a list of all installed modules that
+ # are out of date
+ cpanp> o 1..3 # list uptodateness from a previous search
+
+ cpanp> s conf # show config settings
+ cpanp> s conf md5 1 # enable md5 checks
+ cpanp> s program # show program settings
+ cpanp> s edit # edit config file
+ cpanp> s reconfigure # go through initial configuration again
+ cpanp> s selfupdate # update your CPANPLUS install
+ cpanp> s save # save config to disk
+ cpanp> s mirrors # show currently selected mirrors
+
+ cpanp> ! [PERL CODE] # execute the following perl code
+
+ cpanp> b # create an autobundle for this computers
+ # perl installation
+ cpanp> x # reload index files (purges cache)
+ cpanp> x --update_source # reload index files, get fresh source files
+ cpanp> p [FILE] # print error stack (to a file)
+ cpanp> v # show the banner
+ cpanp> w # show last search results again
+
+ cpanp> q # quit the shell
+
+ cpanp> /plugins # list avialable plugins
+ cpanp> /? PLUGIN # list help test of <PLUGIN>
+
+ ### common options:
+ cpanp> i ... --skiptest # skip tests
+ cpanp> i ... --force # force all operations
+ cpanp> i ... --verbose # run in verbose mode
+
+=head1 DESCRIPTION
+
+This module provides the default user interface to C<CPANPLUS>. You
+can start it via the C<cpanp> binary, or as detailed in the L<SYNOPSIS>.
+
+=cut
+
+sub new {
+ my $class = shift;
+
+ my $cb = CPANPLUS::Backend->new( @_ );
+ my $self = $class->SUPER::_init(
+ brand => $Brand,
+ term => Term::ReadLine->new( $Brand ),
+ prompt => $Prompt,
+ backend => $cb,
+ format => "%4s %-55s %8s %-10s\n",
+ dist_format => "%4s %-42s %-12s %8s %-10s\n",
+ );
+ ### make it available package wide ###
+ $Shell = $self;
+
+ my $rc_file = File::Spec->catfile(
+ $cb->configure_object->get_conf('base'),
+ DOT_SHELL_DEFAULT_RC,
+ );
+
+
+ if( -e $rc_file && -r _ ) {
+ $rc = $self->_read_configuration_from_rc( $rc_file );
+ }
+
+ ### register install callback ###
+ $cb->_register_callback(
+ name => 'install_prerequisite',
+ code => \&__ask_about_install,
+ );
+
+ ### execute any login commands specified ###
+ $self->dispatch_on_input( input => $rc->{'login'} )
+ if defined $rc->{'login'};
+
+ ### register test report callbacks ###
+ $cb->_register_callback(
+ name => 'edit_test_report',
+ code => \&__ask_about_edit_test_report,
+ );
+
+ $cb->_register_callback(
+ name => 'send_test_report',
+ code => \&__ask_about_send_test_report,
+ );
+
+ $cb->_register_callback(
+ name => 'proceed_on_test_failure',
+ code => \&__ask_about_test_failure,
+ );
+
+ ### load all the plugins
+ $self->_plugins_init;
+
+ return $self;
+}
+
+sub shell {
+ my $self = shift;
+ my $term = $self->term;
+ my $conf = $self->backend->configure_object;
+
+ $self->_show_banner;
+ $self->__print( "*** Type 'p' now to show start up log\n" ); # XXX add to banner?
+ $self->_show_random_tip if $conf->get_conf('show_startup_tip');
+ $self->_input_loop && $self->__print( "\n" );
+ $self->_quit;
+}
+
+sub _input_loop {
+ my $self = shift;
+ my $term = $self->term;
+ my $cb = $self->backend;
+
+ my $normal_quit = 0;
+ while (
+ defined (my $input = eval { $term->readline($self->prompt) } )
+ or $self->_signals->{INT}{count} == 1
+ ) {
+ ### re-initiate all signal handlers
+ while (my ($sig, $entry) = each %{$self->_signals} ) {
+ $SIG{$sig} = $entry->{handler} if exists($entry->{handler});
+ }
+
+ $self->__print( "\n" );
+ last if $self->dispatch_on_input( input => $input );
+
+ ### flush the lib cache ###
+ $cb->_flush( list => [qw|lib load|] );
+
+ } continue {
+ ### clear the sigint count
+ $self->_signals->{INT}{count}--
+ if $self->_signals->{INT}{count};
+
+ ### reset the 'install prereq?' cached answer
+ $self->settings->{'install_all_prereqs'} = undef;
+
+ }
+
+ return 1;
+}
+
+### return 1 to quit ###
+sub dispatch_on_input {
+ my $self = shift;
+ my $conf = $self->backend->configure_object();
+ my $term = $self->term;
+ my %hash = @_;
+
+ my($string, $noninteractive);
+ my $tmpl = {
+ input => { required => 1, store => \$string },
+ noninteractive => { required => 0, store => \$noninteractive },
+ };
+
+ check( $tmpl, \%hash ) or return;
+
+ ### indicates whether or not the user will receive a shell
+ ### prompt after the command has finished.
+ $self->noninteractive($noninteractive) if defined $noninteractive;
+
+ my $rv = 1;
+
+ my @cmds = split ';', $string;
+ while( my $input = shift @cmds ) {
+
+ ### to send over the socket ###
+ my $org_input = $input;
+
+ my $key; my $options;
+ { ### make whitespace not count when using special chars
+ { $input =~ s|^\s*([!?/])|$1 |; }
+
+ ### get the first letter of the input
+ $input =~ s|^\s*([\w\?\!/])\w*||;
+
+ chomp $input;
+ $key = lc($1);
+
+ ### we figured out what the command was...
+ ### if we have more input, that DOES NOT start with a white
+ ### space char, we misparsed.. like 'Test::Foo::Bar', which
+ ### would turn into 't', '::Foo::Bar'...
+ if( $input and $input !~ s/^\s+// ) {
+ $self->__print( loc("Could not understand command: %1\n".
+ "Possibly missing command before argument(s)?\n",
+ $org_input) );
+ return;
+ }
+
+ ### allow overrides from the config file ###
+ if( defined $rc->{$key} ) {
+ $input = $rc->{$key} . $input;
+ }
+
+ ### grab command line options like --no-force and --verbose ###
+ ($options,$input) = $term->parse_options($input)
+ unless $key eq '!';
+ }
+
+ ### emtpy line? ###
+ return unless $key;
+
+ ### time to quit ###
+ return 1 if $key eq 'q';
+
+ my $method = $map->{$key};
+
+ ### dispatch meta locally at all times ###
+ if( $key eq '/' ) {
+ ### keep track of failures
+ $rv *= length $self->$method(input => $input, options => $options);
+ next;
+ }
+
+ ### flush unless we're trying to print the stack
+ CPANPLUS::Error->flush unless $key eq 'p';
+
+ ### connected over a socket? ###
+ if( $self->remote ) {
+
+ ### unsupported commands ###
+ if( $key eq 'z' or
+ ($key eq 's' and $input =~ /^\s*edit/)
+ ) {
+ $self->__print( "\n",
+ loc( "Command '%1' not supported over remote connection",
+ join ' ', $key, $input
+ ), "\n\n" );
+
+ } else {
+ my($status,$buff) = $self->__send_remote_command($org_input);
+
+ $self->__print( "\n", loc("Command failed!"), "\n\n" )
+ unless $status;
+
+ ### keep track of failures
+ $rv *= length $status;
+
+ $self->_pager_open if $buff =~ tr/\n// > $self->_term_rowcount;
+ $self->__print( $buff );
+ $self->_pager_close;
+ }
+
+ ### or just a plain local shell? ###
+ } else {
+
+ unless( $self->can($method) ) {
+ $self->__print(loc("Unknown command '%1'. Usage:", $key), "\n");
+ $self->_help;
+
+ } else {
+
+ ### some methods don't need modules ###
+ my @mods;
+ @mods = $self->_select_modules($input)
+ unless grep {$key eq $_} qw[! m a v w x p s b / ? h];
+
+ ### keep track of failures
+ $rv *= defined eval { $self->$method(
+ modules => \@mods,
+ options => $options,
+ input => $input,
+ choice => $key )
+ };
+ error( $@ ) if $@;
+ }
+ }
+ }
+
+ ### outside the shell loop, we can return the actual return value;
+ return $rv if $self->noninteractive;
+
+ return;
+}
+
+sub _select_modules {
+ my $self = shift;
+ my $input = shift or return;
+ my $cache = $self->cache;
+ my $cb = $self->backend;
+
+ ### expand .. in $input
+ $input =~ s{\b(\d+)\s*\.\.\s*(\d+)\b}
+ {join(' ', ($1 < 1 ? 1 : $1) .. ($2 > $#{$cache} ? $#{$cache} : $2))}eg;
+
+ $input = join(' ', 1 .. $#{$cache}) if $input eq '*';
+ $input =~ s/'/::/g; # perl 4 convention
+
+ my @rv;
+ for my $mod (split /\s+/, $input) {
+
+ ### it's a cache look up ###
+ if( $mod =~ /^\d+/ and $mod > 0 ) {
+ unless( scalar @$cache ) {
+ $self->__print( loc("No search was done yet!"), "\n" );
+
+ } elsif ( my $obj = $cache->[$mod] ) {
+ push @rv, $obj;
+
+ } else {
+ $self->__print( loc("No such module: %1", $mod), "\n" );
+ }
+
+ } else {
+ my $obj = $cb->parse_module( module => $mod );
+
+ unless( $obj ) {
+ $self->__print( loc("No such module: %1", $mod), "\n" );
+
+ } else {
+ push @rv, $obj;
+ }
+ }
+ }
+
+ unless( scalar @rv ) {
+ $self->__print( loc("No modules found to operate on!\n") );
+ return;
+ } else {
+ return @rv;
+ }
+}
+
+sub _format_version {
+ my $self = shift;
+ my $version = shift || 0;
+
+ ### fudge $version into the 'optimal' format
+ $version = 0 if $version eq 'undef';
+ $version =~ s/_//g; # everything after gets stripped off otherwise
+
+ ### allow 6 digits after the dot, as that's how perl stringifies
+ ### x.y.z numbers.
+ $version = sprintf('%3.6f', $version);
+ $version = '' if $version == '0.00';
+ $version =~ s/(00{0,3})$/' ' x (length $1)/e;
+
+ return $version;
+}
+
+sub __display_results {
+ my $self = shift;
+ my $cache = $self->cache;
+
+ my @rv = @$cache;
+
+ if( scalar @rv ) {
+
+ $self->_pager_open if $#{$cache} >= $self->_term_rowcount;
+
+ my $i = 1;
+ for my $mod (@rv) {
+ next unless $mod; # first one is undef
+ # humans start counting at 1
+
+ ### for dists only -- we have checksum info
+ if( $mod->mtime ) {
+ $self->__printf(
+ $self->dist_format,
+ $i,
+ $mod->module,
+ $mod->mtime,
+ $self->_format_version( $mod->version ),
+ $mod->author->cpanid
+ );
+
+ } else {
+ $self->__printf(
+ $self->format,
+ $i,
+ $mod->module,
+ $self->_format_version( $mod->version ),
+ $mod->author->cpanid
+ );
+ }
+ $i++;
+ }
+
+ $self->_pager_close;
+
+ } else {
+ $self->__print( loc("No results to display"), "\n" );
+ }
+
+ return 1;
+}
+
+
+sub _quit {
+ my $self = shift;
+
+ $self->dispatch_on_input( input => $rc->{'logout'} )
+ if defined $rc->{'logout'};
+
+ $self->__print( loc("Exiting CPANPLUS shell"), "\n" );
+
+ return 1;
+}
+
+###########################
+### actual command subs ###
+###########################
+
+
+### print out the help message ###
+### perhaps, '?' should be a slightly different version ###
+{ my @help;
+ sub _help {
+ my $self = shift;
+ my %hash = @_;
+
+ my $input;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ input => { required => 0, store => \$input }
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+ }
+
+ @help = (
+loc('[General]' ),
+loc(' h | ? # display help' ),
+loc(' q # exit' ),
+loc(' v # version information' ),
+loc('[Search]' ),
+loc(' a AUTHOR ... # search by author(s)' ),
+loc(' m MODULE ... # search by module(s)' ),
+loc(' f MODULE ... # list all releases of a module' ),
+loc(" o [ MODULE ... ] # list installed module(s) that aren't up to date" ),
+loc(' w # display the result of your last search again' ),
+loc('[Operations]' ),
+loc(' i MODULE | NUMBER ... # install module(s), by name or by search number' ),
+loc(' i URI | ... # install module(s), by URI (ie http://foo.com/X.tgz)' ),
+loc(' i DIR | ... # install module(s), by path (ie ./Module-1.0)' ),
+loc(' t MODULE | NUMBER ... # test module(s), by name or by search number' ),
+loc(' u MODULE | NUMBER ... # uninstall module(s), by name or by search number' ),
+loc(' d MODULE | NUMBER ... # download module(s)' ),
+loc(' l MODULE | NUMBER ... # display detailed information about module(s)' ),
+loc(' r MODULE | NUMBER ... # display README files of module(s)' ),
+loc(' c MODULE | NUMBER ... # check for module report(s) from cpan-testers' ),
+loc(' z MODULE | NUMBER ... # extract module(s) and open command prompt in it' ),
+loc('[Local Administration]' ),
+loc(' b # write a bundle file for your configuration' ),
+loc(' s program [OPT VALUE] # set program locations for this session' ),
+loc(' s conf [OPT VALUE] # set config options for this session' ),
+loc(' s mirrors # show currently selected mirrors' ),
+loc(' s reconfigure # reconfigure settings ' ),
+loc(' s selfupdate # update your CPANPLUS install '),
+loc(' s save [user|system] # save settings for this user or systemwide' ),
+loc(' s edit [user|system] # open configuration file in editor and reload' ),
+loc(' ! EXPR # evaluate a perl statement' ),
+loc(' p [FILE] # print the error stack (optionally to a file)' ),
+loc(' x # reload CPAN indices (purges cache)' ),
+loc(' x --update_source # reload CPAN indices, get fresh source files' ),
+loc('[Common Options]' ),
+loc(' i ... --skiptest # skip tests' ),
+loc(' i ... --force # force all operations' ),
+loc(' i ... --verbose # run in verbose mode' ),
+loc('[Plugins]' ),
+loc(' /plugins # list available plugins' ),
+loc(' /? [PLUGIN NAME] # show usage for (a particular) plugin(s)' ),
+
+ ) unless @help;
+
+ $self->_pager_open if (@help >= $self->_term_rowcount);
+ ### XXX: functional placeholder for actual 'detailed' help.
+ $self->__print( "Detailed help for the command '$input' is " .
+ "not available.\n\n" ) if length $input;
+ $self->__print( map {"$_\n"} @help );
+ $self->__print( $/ );
+ $self->_pager_close;
+
+ return 1;
+ }
+}
+
+### eval some code ###
+sub _bang {
+ my $self = shift;
+ my $cb = $self->backend;
+ my %hash = @_;
+
+
+ my $input;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ input => { required => 1, store => \$input }
+ };
+
+ my $args = check( $tmpl, \%hash ) or return;
+ }
+
+ local $Data::Dumper::Indent = 1; # for dumpering from !
+ eval $input;
+ error( $@ ) if $@;
+ $self->__print( "\n" );
+
+ return if $@;
+ return 1;
+}
+
+sub _search_module {
+ my $self = shift;
+ my $cb = $self->backend;
+ my %hash = @_;
+
+ my $args;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ input => { required => 1, },
+ options => { default => { } },
+ };
+
+ $args = check( $tmpl, \%hash ) or return;
+ }
+
+ my @regexes = map { qr/$_/i } split /\s+/, $args->{'input'};
+
+ ### XXX this is rather slow, because (probably)
+ ### of the many method calls
+ ### XXX need to profile to speed it up =/
+
+ ### find the modules ###
+ my @rv = sort { $a->module cmp $b->module }
+ $cb->search(
+ %{$args->{'options'}},
+ type => 'module',
+ allow => \@regexes,
+ );
+
+ ### store the result in the cache ###
+ $self->cache([undef,@rv]);
+
+ $self->__display_results;
+
+ return 1;
+}
+
+sub _search_author {
+ my $self = shift;
+ my $cb = $self->backend;
+ my %hash = @_;
+
+ my $args;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ input => { required => 1, },
+ options => { default => { } },
+ };
+
+ $args = check( $tmpl, \%hash ) or return;
+ }
+
+ my @regexes = map { qr/$_/i } split /\s+/, $args->{'input'};
+
+ my @rv;
+ for my $type (qw[author cpanid]) {
+ push @rv, $cb->search(
+ %{$args->{'options'}},
+ type => $type,
+ allow => \@regexes,
+ );
+ }
+
+ my %seen;
+ my @list = sort { $a->module cmp $b->module }
+ grep { defined }
+ map { $_->modules }
+ grep { not $seen{$_}++ } @rv;
+
+ $self->cache([undef,@list]);
+
+ $self->__display_results;
+ return 1;
+}
+
+sub _readme {
+ my $self = shift;
+ my $cb = $self->backend;
+ my %hash = @_;
+
+ my $args; my $mods; my $opts;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ modules => { required => 1, store => \$mods },
+ options => { default => { }, store => \$opts },
+ };
+
+ $args = check( $tmpl, \%hash ) or return;
+ }
+
+ return unless scalar @$mods;
+
+ $self->_pager_open;
+ for my $mod ( @$mods ) {
+ $self->__print( $mod->readme( %$opts ) );
+ }
+
+ $self->_pager_close;
+
+ return 1;
+}
+
+sub _fetch {
+ my $self = shift;
+ my $cb = $self->backend;
+ my %hash = @_;
+
+ my $args; my $mods; my $opts;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ modules => { required => 1, store => \$mods },
+ options => { default => { }, store => \$opts },
+ };
+
+ $args = check( $tmpl, \%hash ) or return;
+ }
+
+ $self->_pager_open if @$mods >= $self->_term_rowcount;
+ my $rv = 1;
+ for my $mod (@$mods) {
+ my $where = $mod->fetch( %$opts );
+
+ $rv *= length $where;
+
+ $self->__print(
+ $where
+ ? loc("Successfully fetched '%1' to '%2'",
+ $mod->module, $where )
+ : loc("Failed to fetch '%1'", $mod->module)
+ );
+ $self->__print( "\n" );
+ }
+ $self->_pager_close;
+
+ return 1 if $rv;
+ return;
+}
+
+sub _shell {
+ my $self = shift;
+ my $cb = $self->backend;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my $shell = $conf->get_program('shell');
+ unless( $shell ) {
+ $self->__print(
+ loc("Your config does not specify a subshell!"), "\n",
+ loc("Perhaps you need to re-run your setup?"), "\n"
+ );
+ return;
+ }
+
+ my $args; my $mods; my $opts;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ modules => { required => 1, store => \$mods },
+ options => { default => { }, store => \$opts },
+ };
+
+ $args = check( $tmpl, \%hash ) or return;
+ }
+
+ my $cwd = Cwd::cwd();
+ for my $mod (@$mods) {
+ $mod->fetch( %$opts ) or next;
+ $mod->extract( %$opts ) or next;
+
+ $cb->_chdir( dir => $mod->status->extract() ) or next;
+
+ #local $ENV{PERL5OPT} = CPANPLUS::inc->original_perl5opt;
+
+ if( system($shell) and $! ) {
+ $self->__print(
+ loc("Error executing your subshell '%1': %2",
+ $shell, $!),"\n"
+ );
+ next;
+ }
+ }
+ $cb->_chdir( dir => $cwd );
+
+ return 1;
+}
+
+sub _distributions {
+ my $self = shift;
+ my $cb = $self->backend;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my $args; my $mods; my $opts;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ modules => { required => 1, store => \$mods },
+ options => { default => { }, store => \$opts },
+ };
+
+ $args = check( $tmpl, \%hash ) or return;
+ }
+
+ my @list;
+ for my $mod (@$mods) {
+ push @list, sort { $a->version <=> $b->version }
+ grep { defined } $mod->distributions( %$opts );
+ }
+
+ my @rv = sort { $a->module cmp $b->module } @list;
+
+ $self->cache([undef,@rv]);
+ $self->__display_results;
+
+ return 1;
+}
+
+sub _reload_indices {
+ my $self = shift;
+ my $cb = $self->backend;
+ my %hash = @_;
+
+ my $args; my $opts;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ options => { default => { }, store => \$opts },
+ };
+
+ $args = check( $tmpl, \%hash ) or return;
+ }
+
+ my $rv = $cb->reload_indices( %$opts );
+
+ ### so the update failed, but you didnt give it any options either
+ if( !$rv and !(keys %$opts) ) {
+ $self->__print(
+ "\nFailure may be due to corrupt source files\n" .
+ "Try this:\n\tx --update_source\n\n" );
+ }
+
+ return $rv;
+
+}
+
+sub _install {
+ my $self = shift;
+ my $cb = $self->backend;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my $args; my $mods; my $opts; my $choice;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ modules => { required => 1, store => \$mods },
+ options => { default => { }, store => \$opts },
+ choice => { required => 1, store => \$choice,
+ allow => [qw|i t|] },
+ };
+
+ $args = check( $tmpl, \%hash ) or return;
+ }
+
+ unless( scalar @$mods ) {
+ $self->__print( loc("Nothing done\n") );
+ return;
+ }
+
+ my $target = $choice eq 'i' ? TARGET_INSTALL : TARGET_CREATE;
+ my $prompt = $choice eq 'i' ? loc('Installing ') : loc('Testing ');
+ my $action = $choice eq 'i' ? 'install' : 'test';
+
+ my $status = {};
+ ### first loop over the mods to install them ###
+ for my $mod (@$mods) {
+ $self->__print( $prompt, $mod->module, " (".$mod->version.")", "\n" );
+
+ my $log_length = length CPANPLUS::Error->stack_as_string;
+
+ ### store the status for look up when we're done with all
+ ### install calls
+ $status->{$mod} = $mod->install( %$opts, target => $target );
+
+ ### would you like a log file of what happened?
+ if( $conf->get_conf('write_install_logs') ) {
+
+ if ( ON_WIN32 and !check_install(
+ module => 'IPC::Run', version => 0.55 )
+ ) {
+ error(loc("IPC::Run version '%1' is required on MSWin32"
+ . " in order to capture buffers."
+ . " The logfile generated may not contain"
+ . " any useful data, until it is installed", 0.55));
+ }
+
+ my $dir = File::Spec->catdir(
+ $conf->get_conf('base'),
+ $conf->_get_build('install_log_dir'),
+ );
+ ### create the dir if it doesn't exit yet
+ $cb->_mkdir( dir => $dir ) unless -d $dir;
+
+ my $file = File::Spec->catfile(
+ $dir,
+ INSTALL_LOG_FILE->( $mod )
+ );
+ if ( open my $fh, ">$file" ) {
+ my $stack = CPANPLUS::Error->stack_as_string;
+ ### remove everything in the log that was there *before*
+ ### we started this install
+ substr( $stack, 0, $log_length, '' );
+
+ print $fh $stack;
+ close $fh;
+
+ $self->__print(
+ loc("*** Install log written to:\n %1\n\n", $file)
+ );
+ } else {
+ warn "Could not open '$file': $!\n";
+ next;
+ }
+ }
+ }
+
+ my $flag;
+ ### then report whether all this went ok or not ###
+ for my $mod (@$mods) {
+ # if( $mod->status->installed ) {
+ if( $status->{$mod} ) {
+ $self->__print(
+ loc("Module '%1' %tense(%2,past) successfully\n",
+ $mod->module, $action)
+ );
+ } else {
+ $flag++;
+ $self->__print(
+ loc("Error %tense(%1,present) '%2'\n", $action, $mod->module)
+ );
+ }
+ }
+
+
+
+ if( !$flag ) {
+ $self->__print(
+ loc("No errors %tense(%1,present) all modules", $action), "\n"
+ );
+ } else {
+ $self->__print(
+ loc("Problem %tense(%1,present) one or more modules", $action)
+ );
+ $self->__print( "\n" );
+
+ $self->__print(
+ loc("*** You can view the complete error buffer by pressing ".
+ "'%1' ***\n", 'p')
+ ) unless $conf->get_conf('verbose') || $self->noninteractive;
+ }
+ $self->__print( "\n" );
+
+ return !$flag;
+}
+
+sub __ask_about_install {
+ my $mod = shift or return;
+ my $prereq = shift or return;
+ my $term = $Shell->term;
+
+ $Shell->__print( "\n" );
+ $Shell->__print( loc("Module '%1' requires '%2' to be installed",
+ $mod->module, $prereq->module ) );
+ $Shell->__print( "\n\n" );
+
+ ### previously cached answer?
+ return $Shell->settings->{'install_all_prereqs'}
+ if defined $Shell->settings->{'install_all_prereqs'};
+
+
+ $Shell->__print(
+ loc( "If you don't wish to see this question anymore\n".
+ "you can disable it by entering the following ".
+ "commands on the prompt:\n '%1'",
+ 's conf prereqs 1; s save' ) );
+ $Shell->__print("\n\n");
+
+ my $yes = loc("Yes");
+ my $no = loc("No");
+ my $all = loc("Yes to all (for this module)");
+ my $none = loc("No to all (for this module)");
+
+ my $reply = $term->get_reply(
+ prompt => loc("Should I install this module?"),
+ choices => [ $yes, $no, $all, $none ],
+ default => $yes,
+ );
+
+ ### if 'all' or 'none', save this, so we can apply it to
+ ### other prereqs in this chain.
+ $Shell->settings->{'install_all_prereqs'} =
+ $reply eq $all ? 1 :
+ $reply eq $none ? 0 :
+ undef;
+
+ ### if 'yes' or 'all', the user wants it installed
+ return $reply eq $all ? 1 :
+ $reply eq $yes ? 1 :
+ 0;
+}
+
+sub __ask_about_send_test_report {
+ my($mod, $grade) = @_;
+ return 1 unless $grade eq GRADE_FAIL;
+
+ my $term = $Shell->term;
+
+ $Shell->__print( "\n" );
+ $Shell->__print(
+ loc("Test report prepared for module '%1'.\n Would you like to ".
+ "send it? (You can edit it if you like)", $mod->module ) );
+ $Shell->__print( "\n\n" );
+ my $bool = $term->ask_yn(
+ prompt => loc("Would you like to send the test report?"),
+ default => 'n'
+ );
+
+ return $bool;
+}
+
+sub __ask_about_edit_test_report {
+ my($mod, $grade) = @_;
+ return 0 unless $grade eq GRADE_FAIL;
+
+ my $term = $Shell->term;
+
+ $Shell->__print( "\n" );
+ $Shell->__print(
+ loc("Test report prepared for module '%1'. You can edit this ".
+ "report if you would like", $mod->module ) );
+ $Shell->__print("\n\n");
+ my $bool = $term->ask_yn(
+ prompt => loc("Would you like to edit the test report?"),
+ default => 'y'
+ );
+
+ return $bool;
+}
+
+sub __ask_about_test_failure {
+ my $mod = shift;
+ my $captured = shift || '';
+ my $term = $Shell->term;
+
+ $Shell->__print( "\n" );
+ $Shell->__print(
+ loc( "The tests for '%1' failed. Would you like me to proceed ".
+ "anyway or should we abort?", $mod->module ) );
+ $Shell->__print( "\n\n" );
+
+ my $bool = $term->ask_yn(
+ prompt => loc("Proceed anyway?"),
+ default => 'n',
+ );
+
+ return $bool;
+}
+
+
+sub _details {
+ my $self = shift;
+ my $cb = $self->backend;
+ my $conf = $cb->configure_object;
+ my %hash = @_;
+
+ my $args; my $mods; my $opts;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ modules => { required => 1, store => \$mods },
+ options => { default => { }, store => \$opts },
+ };
+
+ $args = check( $tmpl, \%hash ) or return;
+ }
+
+ ### every module has about 10 lines of details
+ ### maybe more later with Module::CPANTS etc
+ $self->_pager_open if scalar @$mods * 10 > $self->_term_rowcount;
+
+
+ my $format = "%-24s %-45s\n";
+ my $cformat = "%-24s %-45s %-10s\n";
+ for my $mod (@$mods) {
+ my $href = $mod->details( %$opts );
+ my @list = sort { $a->module cmp $b->module } $mod->contains;
+
+ unless( $href ) {
+ $self->__print(
+ loc("No details for %1 - it might be outdated.",
+ $mod->module), "\n" );
+ next;
+
+ } else {
+ $self->__print( loc( "Details for '%1'\n", $mod->module ) );
+ for my $item ( sort keys %$href ) {
+ $self->__printf( $format, $item, $href->{$item} );
+ }
+
+ my $showed;
+ for my $item ( @list ) {
+ $self->__printf(
+ $cformat, ($showed ? '' : 'Contains:'),
+ $item->module, $item->version
+ );
+ $showed++;
+ }
+ $self->__print( "\n" );
+ }
+ }
+ $self->_pager_close;
+ $self->__print( "\n" );
+
+ return 1;
+}
+
+sub _print {
+ my $self = shift;
+ my %hash = @_;
+
+ my $args; my $opts; my $file;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ options => { default => { }, store => \$opts },
+ input => { default => '', store => \$file },
+ };
+
+ $args = check( $tmpl, \%hash ) or return;
+ }
+
+ my $old; my $fh;
+ if( $file ) {
+ $fh = FileHandle->new( ">$file" )
+ or( warn loc("Could not open '%1': '%2'", $file, $!),
+ return
+ );
+ $old = select $fh;
+ }
+
+
+ $self->_pager_open if !$file;
+
+ $self->__print( CPANPLUS::Error->stack_as_string );
+
+ $self->_pager_close;
+
+ select $old if $old;
+ $self->__print( "\n" );
+
+ return 1;
+}
+
+sub _set_conf {
+ my $self = shift;
+ my %hash = @_;
+ my $cb = $self->backend;
+ my $conf = $cb->configure_object;
+
+ ### possible options
+ ### XXX hard coded, not optimal :(
+ my %types = (
+ reconfigure => '',
+ save => q([user | system | boxed]),
+ edit => '',
+ program => q([key => val]),
+ conf => q([key => val]),
+ mirrors => '',
+ selfupdate => '', # XXX add all opts here?
+ );
+
+
+ my $args; my $opts; my $input;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ options => { default => { }, store => \$opts },
+ input => { default => '', store => \$input },
+ };
+
+ $args = check( $tmpl, \%hash ) or return;
+ }
+
+ my ($type,$key,$value) = $input =~ m/(\w+)\s*(\w*)\s*(.*?)$/;
+ $value =~ s/\s+$//g if $value;
+ $type = lc $type;
+
+ if( $type eq 'reconfigure' ) {
+ my $setup = CPANPLUS::Configure::Setup->new(
+ configure_object => $conf,
+ term => $self->term,
+ backend => $cb,
+ );
+ return $setup->init;
+
+ } elsif ( $type eq 'save' ) {
+ my $where = {
+ user => CONFIG_USER,
+ system => CONFIG_SYSTEM,
+ boxed => CONFIG_BOXED,
+ }->{ $key } || CONFIG_USER;
+
+ ### boxed is special, so let's get its value from %INC
+ ### so we can tell it where to save
+ ### XXX perhaps this logic should be generic for all
+ ### types, and put in the ->save() routine
+ my $dir;
+ if( $where eq CONFIG_BOXED ) {
+ my $file = join( '/', split( '::', CONFIG_BOXED ) ) . '.pm';
+ my $file_re = quotemeta($file);
+
+ my $path = $INC{$file} || '';
+ $path =~ s/$file_re$//;
+ $dir = $path;
+ }
+
+ my $rv = $cb->configure_object->save( $where => $dir );
+
+ $self->__print(
+ $rv
+ ? loc("Configuration successfully saved to %1\n (%2)\n",
+ $where, $rv)
+ : loc("Failed to save configuration\n" )
+ );
+ return $rv;
+
+ } elsif ( $type eq 'edit' ) {
+
+ my $editor = $conf->get_program('editor')
+ or( print(loc("No editor specified")), return );
+
+ my $where = {
+ user => CONFIG_USER,
+ system => CONFIG_SYSTEM,
+ }->{ $key } || CONFIG_USER;
+
+ my $file = $conf->_config_pm_to_file( $where );
+ system($editor,$file);
+
+ ### now reload it
+ ### disable warnings for this
+ { require Module::Loaded;
+ Module::Loaded::mark_as_unloaded( $where );
+
+ ### reinitialize the config
+ local $^W;
+ $conf->init;
+ }
+
+ return 1;
+
+ } elsif ( $type eq 'mirrors' ) {
+
+ $self->__print(
+ loc("Readonly list of mirrors (in order of preference):\n\n" ) );
+
+ my $i;
+ for my $host ( @{$conf->get_conf('hosts')} ) {
+ my $uri = $cb->_host_to_uri( %$host );
+
+ $i++;
+ $self->__print( "\t[$i] $uri\n" );
+ }
+
+ $self->__print(
+ loc("\nTo edit this list, please type: '%1'\n", 's edit') );
+
+ } elsif ( $type eq 'selfupdate' ) {
+ my %valid = map { $_ => $_ }
+ $cb->selfupdate_object->list_categories;
+
+ unless( $valid{$key} ) {
+ $self->__print(
+ loc( "To update your current CPANPLUS installation, ".
+ "choose one of the these options:\n%1",
+ ( join $/, map {
+ sprintf "\ts selfupdate %-17s " .
+ "[--latest=0] [--dryrun]", $_
+ } sort keys %valid )
+ )
+ );
+ } else {
+ my %update_args = (
+ update => $key,
+ latest => 1,
+ %$opts
+ );
+
+
+ my %list = $cb->selfupdate_object
+ ->list_modules_to_update( %update_args );
+
+ $self->__print(loc("The following updates will take place:"),$/.$/);
+
+ for my $feature ( sort keys %list ) {
+ my $aref = $list{$feature};
+
+ ### is it a 'feature' or a built in?
+ $self->__print(
+ $valid{$feature}
+ ? " " . ucfirst($feature) . ":\n"
+ : " Modules for '$feature' support:\n"
+ );
+
+ ### show what modules would be installed
+ $self->__print(
+ scalar @$aref
+ ? map { sprintf " %-42s %-6s -> %-6s \n",
+ $_->name, $_->installed_version, $_->version
+ } @$aref
+ : " No upgrades required\n"
+ );
+ $self->__print( $/ );
+ }
+
+
+ unless( $opts->{'dryrun'} ) {
+ $self->__print( loc("Updating your CPANPLUS installation\n") );
+ $cb->selfupdate_object->selfupdate( %update_args );
+ }
+ }
+
+ } else {
+
+ if ( $type eq 'program' or $type eq 'conf' ) {
+
+ my $format = {
+ conf => '%-25s %s',
+ program => '%-12s %s',
+ }->{ $type };
+
+ unless( $key ) {
+ my @list = grep { $_ ne 'hosts' }
+ $conf->options( type => $type );
+
+ my $method = 'get_' . $type;
+
+ local $Data::Dumper::Indent = 0;
+ for my $name ( @list ) {
+ my $val = $conf->$method($name) || '';
+ ($val) = ref($val)
+ ? (Data::Dumper::Dumper($val) =~ /= (.*);$/)
+ : "'$val'";
+
+ $self->__printf( " $format\n", $name, $val );
+ }
+
+ } elsif ( $key eq 'hosts' or $key eq 'lib' ) {
+ $self->__print(
+ loc( "Setting %1 is not trivial.\n" .
+ "It is suggested you use '%2' and edit the " .
+ "configuration file manually", $key, 's edit')
+ );
+ } else {
+ my $method = 'set_' . $type;
+ $conf->$method( $key => defined $value ? $value : '' )
+ and $self->__print( loc("Key '%1' was set to '%2'", $key,
+ defined $value ? $value : 'EMPTY STRING') );
+ }
+
+ } else {
+ $self->__print( loc("Unknown type '%1'",$type || 'EMPTY' ) );
+ $self->__print( $/ );
+ $self->__print( loc("Try one of the following:") );
+ $self->__print( $/, join $/,
+ map { sprintf "\t%-11s %s", $_, $types{$_} }
+ sort keys %types );
+ }
+ }
+ $self->__print( "\n" );
+ return 1;
+}
+
+sub _uptodate {
+ my $self = shift;
+ my %hash = @_;
+ my $cb = $self->backend;
+ my $conf = $cb->configure_object;
+
+ my $opts; my $mods;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ options => { default => { }, store => \$opts },
+ modules => { required => 1, store => \$mods },
+ };
+
+ check( $tmpl, \%hash ) or return;
+ }
+
+ ### long listing? short is default ###
+ my $long = $opts->{'long'} ? 1 : 0;
+
+ my @list = scalar @$mods ? @$mods : @{$cb->_all_installed};
+
+ my @rv; my %seen;
+ for my $mod (@list) {
+ ### skip this mod if it's up to date ###
+ next if $mod->is_uptodate;
+ ### skip this mod if it's core ###
+ next if $mod->package_is_perl_core;
+
+ if( $long or !$seen{$mod->package}++ ) {
+ push @rv, $mod;
+ }
+ }
+
+ @rv = sort { $a->module cmp $b->module } @rv;
+
+ $self->cache([undef,@rv]);
+
+ $self->_pager_open if scalar @rv >= $self->_term_rowcount;
+
+ my $format = "%5s %12s %12s %-36s %-10s\n";
+
+ my $i = 1;
+ for my $mod ( @rv ) {
+ $self->__printf(
+ $format,
+ $i,
+ $self->_format_version($mod->installed_version) || 'Unparsable',
+ $self->_format_version( $mod->version ),
+ $mod->module,
+ $mod->author->cpanid
+ );
+ $i++;
+ }
+ $self->_pager_close;
+
+ return 1;
+}
+
+sub _autobundle {
+ my $self = shift;
+ my %hash = @_;
+ my $cb = $self->backend;
+ my $conf = $cb->configure_object;
+
+ my $opts; my $input;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ options => { default => { }, store => \$opts },
+ input => { default => '', store => \$input },
+ };
+
+ check( $tmpl, \%hash ) or return;
+ }
+
+ $opts->{'path'} = $input if $input;
+
+ my $where = $cb->autobundle( %$opts );
+
+ $self->__print(
+ $where
+ ? loc("Wrote autobundle to '%1'", $where)
+ : loc("Could not create autobundle" )
+ );
+ $self->__print( "\n" );
+
+ return $where ? 1 : 0;
+}
+
+sub _uninstall {
+ my $self = shift;
+ my %hash = @_;
+ my $cb = $self->backend;
+ my $term = $self->term;
+ my $conf = $cb->configure_object;
+
+ my $opts; my $mods;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ options => { default => { }, store => \$opts },
+ modules => { default => [], store => \$mods },
+ };
+
+ check( $tmpl, \%hash ) or return;
+ }
+
+ my $force = $opts->{'force'} || $conf->get_conf('force');
+
+ unless( $force ) {
+ my $list = join "\n", map { ' ' . $_->module } @$mods;
+
+ $self->__print( loc("
+This will uninstall the following modules:
+%1
+
+Note that if you installed them via a package manager, you probably
+should use the same package manager to uninstall them
+
+", $list) );
+
+ return unless $term->ask_yn(
+ prompt => loc("Are you sure you want to continue?"),
+ default => 'n',
+ );
+ }
+
+ ### first loop over all the modules to uninstall them ###
+ for my $mod (@$mods) {
+ $self->__print( loc("Uninstalling '%1'", $mod->module), "\n" );
+
+ $mod->uninstall( %$opts );
+ }
+
+ my $flag;
+ ### then report whether all this went ok or not ###
+ for my $mod (@$mods) {
+ if( $mod->status->uninstall ) {
+ $self->__print(
+ loc("Module '%1' %tense(uninstall,past) successfully\n",
+ $mod->module ) );
+ } else {
+ $flag++;
+ $self->__print(
+ loc("Error %tense(uninstall,present) '%1'\n", $mod->module) );
+ }
+ }
+
+ if( !$flag ) {
+ $self->__print(
+ loc("All modules %tense(uninstall,past) successfully"), "\n" );
+ } else {
+ $self->__print(
+ loc("Problem %tense(uninstall,present) one or more modules" ),
+ "\n" );
+
+ $self->__print(
+ loc("*** You can view the complete error buffer by pressing '%1'".
+ "***\n", 'p') ) unless $conf->get_conf('verbose');
+ }
+ $self->__print( "\n" );
+
+ return !$flag;
+}
+
+sub _reports {
+ my $self = shift;
+ my %hash = @_;
+ my $cb = $self->backend;
+ my $term = $self->term;
+ my $conf = $cb->configure_object;
+
+ my $opts; my $mods;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ options => { default => { }, store => \$opts },
+ modules => { default => '', store => \$mods },
+ };
+
+ check( $tmpl, \%hash ) or return;
+ }
+
+ ### XXX might need to be conditional ###
+ $self->_pager_open;
+
+ for my $mod (@$mods) {
+ my @list = $mod->fetch_report( %$opts )
+ or( print(loc("No reports available for this distribution.")),
+ next
+ );
+
+ @list = reverse
+ map { $_->[0] }
+ sort { $a->[1] cmp $b->[1] }
+ map { [$_, $_->{'dist'}.':'.$_->{'platform'}] } @list;
+
+
+
+ ### XXX this may need to be sorted better somehow ###
+ my $url;
+ my $format = "%8s %s %s\n";
+
+ my %seen;
+ for my $href (@list ) {
+ $self->__print(
+ "[" . $mod->author->cpanid .'/'. $href->{'dist'} . "]\n"
+ ) unless $seen{ $href->{'dist'} }++;
+
+ $self->__printf(
+ $format,
+ $href->{'grade'},
+ $href->{'platform'},
+ ($href->{'details'} ? '(*)' : '')
+ );
+
+ $url ||= $href->{'details'};
+ }
+
+ $self->__print( "\n==> $url\n" ) if $url;
+ $self->__print( "\n" );
+ }
+ $self->_pager_close;
+
+ return 1;
+}
+
+### Load plugins
+{ my @PluginModules;
+ my %Dispatch = (
+ showtip => [ __PACKAGE__, '_show_random_tip'],
+ plugins => [ __PACKAGE__, '_list_plugins' ],
+ '?' => [ __PACKAGE__, '_plugins_usage' ],
+ );
+
+ sub plugin_modules { return @PluginModules }
+ sub plugin_table { return %Dispatch }
+
+ my $init_done;
+ sub _plugins_init {
+
+ ### only initialize once
+ return if $init_done++;
+
+ ### find all plugins first
+ if( check_install( module => 'Module::Pluggable', version => '2.4') ) {
+ require Module::Pluggable;
+
+ my $only_re = __PACKAGE__ . '::Plugins::\w+$';
+
+ Module::Pluggable->import(
+ sub_name => '_plugins',
+ search_path => __PACKAGE__,
+ only => qr/$only_re/,
+ #except => [ INSTALLER_MM, INSTALLER_SAMPLE ]
+ );
+
+ push @PluginModules, __PACKAGE__->_plugins;
+ }
+
+ ### now try to load them
+ for my $p ( __PACKAGE__->plugin_modules ) {
+ my %map = eval { load $p; $p->import; $p->plugins };
+ error(loc("Could not load plugin '$p': $@")), next if $@;
+
+ ### register each plugin
+ while( my($name, $func) = each %map ) {
+
+ if( not length $name or not length $func ) {
+ error(loc("Empty plugin name or dispatch function detected"));
+ next;
+ }
+
+ if( exists( $Dispatch{$name} ) ) {
+ error(loc("'%1' is already registered by '%2'",
+ $name, $Dispatch{$name}->[0]));
+ next;
+ }
+
+ ### register name, package and function
+ $Dispatch{$name} = [ $p, $func ];
+ }
+ }
+ }
+
+ ### dispatch a plugin command to its function
+ sub _meta {
+ my $self = shift;
+ my %hash = @_;
+ my $cb = $self->backend;
+ my $term = $self->term;
+ my $conf = $cb->configure_object;
+
+ my $opts; my $input;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ options => { default => { }, store => \$opts },
+ input => { default => '', store => \$input },
+ };
+
+ check( $tmpl, \%hash ) or return;
+ }
+
+ $input =~ s/\s*(\S+)\s*//;
+ my $cmd = $1;
+
+ ### look up the command, or go to the default
+ my $aref = $Dispatch{ $cmd } || [ __PACKAGE__, '_plugin_default' ];
+
+ my($pkg,$func) = @$aref;
+
+ my $rv = eval { $pkg->$func( $self, $cb, $cmd, $input, $opts ) };
+
+ error( $@ ) if $@;
+
+ ### return $rv instead, so input loop can be terminated?
+ return 1;
+ }
+
+ sub _plugin_default { error(loc("No such plugin command")) }
+}
+
+### plugin commands
+{ my $help_format = " /%-21s # %s\n";
+
+ sub _list_plugins {
+ my $self = shift;
+
+ $self->__print( loc("Available plugins:\n") );
+ $self->__print( loc(" List usage by using: /? PLUGIN_NAME\n" ) );
+ $self->__print( $/ );
+
+ my %table = __PACKAGE__->plugin_table;
+ for my $name( sort keys %table ) {
+ my $pkg = $table{$name}->[0];
+ my $this = __PACKAGE__;
+
+ my $who = $pkg eq $this
+ ? "Standard Plugin"
+ : do { my $v = $self->_format_version($pkg->VERSION) || '';
+ $pkg =~ s/^$this/../;
+ sprintf "Provided by: %-30s %-10s", $pkg, $v;
+ };
+
+ $self->__printf( $help_format, $name, $who );
+ }
+
+ $self->__print( $/.$/ );
+
+ $self->__print(
+ " Write your own plugins? Read the documentation of:\n" .
+ " CPANPLUS::Shell::Default::Plugins::HOWTO\n" );
+
+ $self->__print( $/ );
+ }
+
+ sub _list_plugins_help {
+ return sprintf $help_format, 'plugins', loc("lists available plugins");
+ }
+
+ ### registered as a plugin too
+ sub _show_random_tip_help {
+ return sprintf $help_format, 'showtip', loc("show usage tips" );
+ }
+
+ sub _plugins_usage {
+ my $self = shift;
+ my $shell = shift;
+ my $cb = shift;
+ my $cmd = shift;
+ my $input = shift;
+ my %table = $self->plugin_table;
+
+ my @list = length $input ? split /\s+/, $input : sort keys %table;
+
+ for my $name( @list ) {
+
+ ### no such plugin? skip
+ error(loc("No such plugin '$name'")), next unless $table{$name};
+
+ my $pkg = $table{$name}->[0];
+ my $func = $table{$name}->[1] . '_help';
+
+ if ( my $sub = $pkg->can( $func ) ) {
+ eval { $self->__print( $sub->() ) };
+ error( $@ ) if $@;
+
+ } else {
+ $self->__print(" No usage for '$name' -- try perldoc $pkg");
+ }
+
+ $self->__print( $/ );
+ }
+
+ $self->__print( $/.$/ );
+ }
+
+ sub _plugins_usage_help {
+ return sprintf $help_format, '? [NAME ...]',
+ loc("show usage for plugins");
+ }
+}
+
+### send a command to a remote host, retrieve the answer;
+sub __send_remote_command {
+ my $self = shift;
+ my $cmd = shift;
+ my $remote = $self->remote or return;
+ my $user = $remote->{'username'};
+ my $pass = $remote->{'password'};
+ my $conn = $remote->{'connection'};
+ my $end = "\015\012";
+ my $answer;
+
+ my $send = join "\0", $user, $pass, $cmd;
+
+ print $conn $send . $end;
+
+ ### XXX why doesn't something like this just work?
+ #1 while recv($conn, $answer, 1024, 0);
+ while(1) {
+ my $buff;
+ $conn->recv( $buff, 1024, 0 );
+ $answer .= $buff;
+ last if $buff =~ /$end$/;
+ }
+
+ my($status,$buffer) = split "\0", $answer;
+
+ return ($status, $buffer);
+}
+
+
+sub _read_configuration_from_rc {
+ my $self = shift;
+ my $rc_file = shift;
+
+ my $href;
+ if( can_load( modules => { 'Config::Auto' => '0.0' } ) ) {
+ $Config::Auto::DisablePerl = 1;
+
+ eval { $href = Config::Auto::parse( $rc_file, format => 'space' ) };
+
+ $self->__print(
+ loc( "Unable to read in config file '%1': %2", $rc_file, $@ )
+ ) if $@;
+ }
+
+ return $href || {};
+}
+
+{ my @tips = (
+ loc( "You can update CPANPLUS by running: '%1'", 's selfupdate' ),
+ loc( "You can install modules by URL using '%1'", 'i URL' ),
+ loc( "You can turn off these tips using '%1'",
+ 's conf show_startup_tip 0' ),
+ loc( "You can use wildcards like '%1' and '%2' on search results",
+ '*', '2..5' ) ,
+ loc( "You can use plugins. Type '%1' to list available plugins",
+ '/plugins' ),
+ loc( "You can show all your out of date modules using '%1'", 'o' ),
+ loc( "Many operations take options, like '%1', '%2' or '%3'",
+ '--verbose', '--force', '--skiptest' ),
+ loc( "The documentation in %1 and %2 is very useful",
+ "CPANPLUS::Module", "CPANPLUS::Backend" ),
+ loc( "You can type '%1' for help and '%2' to exit", 'h', 'q' ),
+ loc( "You can run an interactive setup using '%1'", 's reconfigure' ),
+ loc( "You can add custom sources to your index. See '%1' for details",
+ '/cs --help' ),
+ loc( "CPANPLUS now has an experimental SQLite backend. You can enable ".
+ "it via: '%1'. Update dependencies via '%2'",
+ 's conf source_engine CPANPLUS::Internals::Source::SQLite; s save',
+ 's selfupdate enabled_features ' ),
+ );
+
+ sub _show_random_tip {
+ my $self = shift;
+ $self->__print( $/, "Did you know...\n ",
+ $tips[ int rand scalar @tips ], $/ );
+ return 1;
+ }
+}
+
+1;
+
+__END__
+
+=pod
+
+=head1 BUG REPORTS
+
+Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
+
+=head1 AUTHOR
+
+This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
+
+=head1 COPYRIGHT
+
+The CPAN++ interface (of which this module is a part of) is copyright (c)
+2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
+
+This library is free software; you may redistribute and/or modify it
+under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<CPANPLUS::Shell::Classic>, L<CPANPLUS::Shell>, L<cpanp>
+
+=cut
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
+
+__END__
+
+TODO:
+ e => "_expand_inc", # scratch it, imho -- not used enough
+
+### free letters: g j k n y ###
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default/Plugins/CustomSource.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default/Plugins/CustomSource.pm
new file mode 100644
index 00000000000..ad4701a488c
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default/Plugins/CustomSource.pm
@@ -0,0 +1,201 @@
+package CPANPLUS::Shell::Default::Plugins::CustomSource;
+
+use strict;
+use CPANPLUS::Error qw[error msg];
+use CPANPLUS::Internals::Constants;
+
+use Data::Dumper;
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+=head1 NAME
+
+CPANPLUS::Shell::Default::Plugins::CustomSource
+
+=head1 SYNOPSIS
+
+ ### elaborate help text
+ CPAN Terminal> /? cs
+
+ ### add a new custom source
+ CPAN Terminal> /cs --add file:///path/to/releases
+
+ ### list all your custom sources by
+ CPAN Terminal> /cs --list
+
+ ### display the contents of a custom source by URI or ID
+ CPAN Terminal> /cs --contents file:///path/to/releases
+ CPAN Terminal> /cs --contents 1
+
+ ### Update a custom source by URI or ID
+ CPAN Terminal> /cs --update file:///path/to/releases
+ CPAN Terminal> /cs --update 1
+
+ ### Remove a custom source by URI or ID
+ CPAN Terminal> /cs --remove file:///path/to/releases
+ CPAN Terminal> /cs --remove 1
+
+ ### Write an index file for a custom source, to share
+ ### with 3rd parties or remote users
+ CPAN Terminal> /cs --write file:///path/to/releases
+
+ ### Make sure to save your sources when adding/removing
+ ### sources, so your changes are reflected in the cache:
+ CPAN Terminal> x
+
+=head1 DESCRIPTION
+
+This is a C<CPANPLUS::Shell::Default> plugin that can add
+custom sources to your CPANPLUS installation. This is a
+wrapper around the C<custom module sources> code as outlined
+in L<CPANPLUS::Backend/CUSTOM MODULE SOURCES>.
+
+This allows you to extend your index of available modules
+beyond what's available on C<CPAN> with your own local
+distributions, or ones offered by third parties.
+
+=cut
+
+
+sub plugins {
+ return ( cs => 'custom_source' )
+}
+
+my $Cb;
+my $Shell;
+my @Index = ();
+
+sub _uri_from_cache {
+ my $self = shift;
+ my $input = shift or return;
+
+ ### you gave us a search number
+ my $uri = $input =~ /^\d+$/
+ ? $Index[ $input - 1 ] # remember, off by 1!
+ : $input;
+
+ my %files = reverse $Cb->list_custom_sources;
+
+ ### it's an URI we know
+ ### VMS can lower case all files, so make sure we check that too
+ my $local = $files{ $uri };
+ $local = $files{ lc $uri } if !$local && ON_VMS;
+
+ if( $local ) {
+ return wantarray
+ ? ($uri, $local)
+ : $uri;
+ }
+
+ ### couldn't resolve the input
+ error(loc("Unknown URI/index: '%1'", $input));
+ return;
+}
+
+sub _list_custom_sources {
+ my $class = shift;
+
+ my %files = $Cb->list_custom_sources;
+
+ $Shell->__print( loc("Your remote sources:"), $/ ) if keys %files;
+
+ my $i = 0;
+ while(my($local,$remote) = each %files) {
+ $Shell->__printf( " [%2d] %s\n", ++$i, $remote );
+
+ ### remember, off by 1!
+ push @Index, $remote;
+ }
+
+ $Shell->__print( $/ );
+}
+
+sub _list_contents {
+ my $class = shift;
+ my $input = shift;
+
+ my ($uri,$local) = $class->_uri_from_cache( $input );
+ unless( $uri ) {
+ error(loc("--contents needs URI parameter"));
+ return;
+ }
+
+ my $fh = OPEN_FILE->( $local ) or return;
+
+ $Shell->__printf( " %s", $_ ) for sort <$fh>;
+ $Shell->__print( $/ );
+}
+
+sub custom_source {
+ my $class = shift;
+ my $shell = shift; $Shell = $shell; # available to all methods now
+ my $cb = shift; $Cb = $cb; # available to all methods now
+ my $cmd = shift;
+ my $input = shift || '';
+ my $opts = shift || {};
+
+ ### show a list
+ if( $opts->{'list'} ) {
+ $class->_list_custom_sources;
+
+ } elsif ( $opts->{'contents'} ) {
+ $class->_list_contents( $input );
+
+ } elsif ( $opts->{'add'} ) {
+ unless( $input ) {
+ error(loc("--add needs URI parameter"));
+ return;
+ }
+
+ $cb->add_custom_source( uri => $input )
+ and $shell->__print(loc("Added remote source '%1'", $input), $/);
+
+ $Shell->__print($/, loc("Remote source contains:"), $/, $/);
+ $class->_list_contents( $input );
+
+ } elsif ( $opts->{'remove'} ) {
+ my($uri,$local) = $class->_uri_from_cache( $input );
+ unless( $uri ) {
+ error(loc("--remove needs URI parameter"));
+ return;
+ }
+
+ 1 while unlink $local;
+
+ $shell->__print( loc("Removed remote source '%1'", $uri), $/ );
+
+ } elsif ( $opts->{'update'} ) {
+ ### did we get input? if so, it's a remote part
+ my $uri = $class->_uri_from_cache( $input );
+
+ $cb->update_custom_source( $uri ? ( remote => $uri ) : () )
+ and do { $shell->__print( loc("Updated remote sources"), $/ ) };
+
+ } elsif ( $opts->{'write'} ) {
+ $cb->write_custom_source_index( path => $input ) and
+ $shell->__print( loc("Wrote remote source index for '%1'", $input), $/);
+
+ } else {
+ error(loc("Unrecognized command, see '%1' for help", '/? cs'));
+ }
+
+ return;
+}
+
+sub custom_source_help {
+ return loc(
+ $/ .
+ ' # Plugin to manage custom sources from the default shell' . $/ .
+ " # See the 'CUSTOM MODULE SOURCES' section in the " . $/ .
+ ' # CPANPLUS::Backend documentation for details.' . $/ .
+ ' /cs --list # list available sources' . $/ .
+ ' /cs --add URI # add source' . $/ .
+ ' /cs --remove URI | INDEX # remove source' . $/ .
+ ' /cs --contents URI | INDEX # show packages from source'. $/ .
+ ' /cs --update [URI | INDEX] # update source index' . $/ .
+ ' /cs --write PATH # write source index' . $/
+ );
+
+}
+
+1;
+
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default/Plugins/HOWTO.pod b/Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default/Plugins/HOWTO.pod
new file mode 100644
index 00000000000..ca765f9e0ac
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default/Plugins/HOWTO.pod
@@ -0,0 +1,136 @@
+=head1 NAME
+
+CPANPLUS::Shell::Default::Plugins::HOWTO -- documentation on how to write your own plugins
+
+=head1 SYNOPSIS
+
+ package CPANPLUS::Shell::Default::Plugins::MyPlugin;
+
+ ### return command => method mapping
+ sub plugins { ( myplugin1 => 'mp1', myplugin2 => 'mp2' ) }
+
+ ### method called when the command '/myplugin1' is issued
+ sub mp1 { .... }
+
+ ### method called when the command '/? myplugin1' is issued
+ sub mp1_help { return "Help Text" }
+
+=head1 DESCRIPTION
+
+This pod text explains how to write your own plugins for
+C<CPANPLUS::Shell::Default>.
+
+=head1 HOWTO
+
+=head2 Registering Plugin Modules
+
+Plugins are detected by using C<Module::Pluggable>. Every module in
+the C<CPANPLUS::Shell::Default::Plugins::*> namespace is considered a
+plugin, and is attempted to be loaded.
+
+Therefor, any plugin must be declared in that namespace, in a corresponding
+C<.pm> file.
+
+=head2 Registering Plugin Commands
+
+To register any plugin commands, a list of key value pairs must be returned
+by a C<plugins> method in your package. The keys are the commands you wish
+to register, the values are the methods in the plugin package you wish to have
+called when the command is issued.
+
+For example, a simple 'Hello, World!' plugin:
+
+ package CPANPLUS::Shell::Default::Plugins::HW;
+
+ sub plugins { return ( helloworld => 'hw' ) };
+
+ sub hw { print "Hello, world!\n" }
+
+When the user in the default shell now issues the C</helloworld> command,
+this command will be dispatched to the plugin, and its C<hw> method will
+be called
+
+=head2 Registering Plugin Help
+
+To provide usage information for your plugin, the user of the default shell
+can type C</? PLUGIN_COMMAND>. In that case, the function C<PLUGIN_COMMAND_help>
+will be called in your plugin package.
+
+For example, extending the above example, when a user calls C</? helloworld>,
+the function C<hw_help> will be called, which might look like this:
+
+ sub hw_help { " /helloworld # prints "Hello, world!\n" }
+
+If you dont provide a corresponding _help function to your commands, the
+default shell will handle it gracefully, but the user will be stuck without
+usage information on your commands, so it's considered undesirable to omit
+the help functions.
+
+=head2 Arguments to Plugin Commands
+
+Any plugin function will receive the following arguments when called, which
+are all positional:
+
+=over 4
+
+=item Classname -- The name of your plugin class
+
+=item Shell -- The CPANPLUS::Shell::Default object
+
+=item Backend -- The CPANPLUS::Backend object
+
+=item Command -- The command issued by the user
+
+=item Input -- The input string from the user
+
+=item Options -- A hashref of options provided by the user
+
+=back
+
+For example, the following command:
+
+ /helloworld bob --nofoo --bar=2 joe
+
+Would yield the following arguments:
+
+ sub hw {
+ my $class = shift; # CPANPLUS::Shell::Default::Plugins::HW
+ my $shell = shift; # CPANPLUS::Shell::Default object
+ my $cb = shift; # CPANPLUS::Backend object
+ my $cmd = shift; # 'helloworld'
+ my $input = shift; # 'bob joe'
+ my $opts = shift; # { foo => 0, bar => 2 }
+
+ ....
+ }
+
+
+=head1 BUG REPORTS
+
+Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
+
+=head1 AUTHOR
+
+This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
+
+=head1 COPYRIGHT
+
+The CPAN++ interface (of which this module is a part of) is copyright (c)
+2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
+
+This library is free software; you may redistribute and/or modify it
+under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<CPANPLUS::Shell::Default>, L<CPANPLUS::Shell>, L<cpanp>
+
+=cut
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
+
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default/Plugins/Remote.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default/Plugins/Remote.pm
new file mode 100644
index 00000000000..d2b829abded
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default/Plugins/Remote.pm
@@ -0,0 +1,186 @@
+package CPANPLUS::Shell::Default::Plugins::Remote;
+
+use strict;
+
+use Module::Load;
+use Params::Check qw[check];
+use CPANPLUS::Error qw[error msg];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+=head1 NAME
+
+CPANPLUS::Shell::Default::Plugins::Remote
+
+=head1 SYNOPSIS
+
+ CPAN Terminal> /connect localhost 1337 --user=foo --pass=bar
+ ...
+ CPAN Terminal@localhost> /disconnect
+
+=head1 DESCRIPTION
+
+This is a C<CPANPLUS::Shell::Default> plugin that allows you to connect
+to a machine running an instance of C<CPANPLUS::Daemon>, allowing remote
+usage of the C<CPANPLUS Shell>.
+
+A sample session, updating all modules on a remote machine, might look
+like this:
+
+ CPAN Terminal> /connect --user=my_user --pass=secret localhost 1337
+
+ Connection accepted
+
+ Successfully connected to 'localhost' on port '11337'
+
+ Note that no output will appear until a command has completed
+ -- this may take a while
+
+
+ CPAN Terminal@localhost> o; i *
+
+ [....]
+
+ CPAN Terminal@localhost> /disconnect
+
+ CPAN Terminal>
+
+=cut
+
+### store the original prompt here, so we can restore it on disconnect
+my $Saved_Prompt;
+
+sub plugins { ( connect => 'connect', disconnect => 'disconnect' ) }
+
+sub connect {
+ my $class = shift;
+ my $shell = shift;
+ my $cb = shift;
+ my $cmd = shift;
+ my $input = shift || '';
+ my $opts = shift || {};
+ my $conf = $cb->configure_object;
+
+ my $user; my $pass;
+ { local $Params::Check::ALLOW_UNKNOWN = 1;
+
+ my $tmpl = {
+ user => { default => 'cpanpd', store => \$user },
+ pass => { required => 1, store => \$pass },
+ };
+
+ check( $tmpl, $opts ) or return;
+ }
+
+ my @parts = split /\s+/, $input;
+ my $host = shift @parts || 'localhost';
+ my $port = shift @parts || '1337';
+
+ load IO::Socket;
+
+ my $remote = IO::Socket::INET->new(
+ Proto => "tcp",
+ PeerAddr => $host,
+ PeerPort => $port,
+ ) or (
+ error( loc( "Cannot connect to port '%1' ".
+ "on host '%2'", $port, $host ) ),
+ return
+ );
+
+ my $con = {
+ connection => $remote,
+ username => $user,
+ password => $pass,
+ };
+
+ ### store the connection
+ $shell->remote( $con );
+
+ my($status,$buffer) = $shell->__send_remote_command(
+ "VERSION=$CPANPLUS::Shell::Default::VERSION");
+
+ if( $status ) {
+ print "\n$buffer\n\n";
+
+ print loc( "Successfully connected to '%1' on port '%2'",
+ $host, $port );
+ print "\n\n";
+ print loc( "Note that no output will appear until a command ".
+ "has completed\n-- this may take a while" );
+ print "\n\n";
+
+ ### save the original prompt
+ $Saved_Prompt = $shell->prompt;
+
+ $shell->prompt( $shell->brand .'@'. $host .':'. $port .'> ' );
+
+ } else {
+ print "\n$buffer\n\n";
+
+ print loc( "Failed to connect to '%1' on port '%2'",
+ $host, $port );
+ print "\n\n";
+
+ $shell->remote( undef );
+ }
+}
+
+sub disconnect {
+ my $class = shift;
+ my $shell = shift;
+
+ print "\n", ( $shell->remote
+ ? loc( "Disconnecting from remote host" )
+ : loc( "Not connected to remote host" )
+ ), "\n\n";
+
+ $shell->remote( undef );
+ $shell->prompt( $Saved_Prompt );
+}
+
+sub connect_help {
+ return loc(
+ " /connect [HOST PORT] # Connect to the remote machine,\n" .
+ " # defaults taken from your config\n" .
+ " --user=USER # Optional username\n" .
+ " --pass=PASS # Optional password" );
+}
+
+sub disconnect_help {
+ return loc(
+ " /disconnect # Disconnect from the remote server" );
+}
+
+1;
+
+=pod
+
+=head1 BUG REPORTS
+
+Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
+
+=head1 AUTHOR
+
+This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
+
+=head1 COPYRIGHT
+
+The CPAN++ interface (of which this module is a part of) is copyright (c)
+2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
+
+This library is free software; you may redistribute and/or modify it
+under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<CPANPLUS::Shell::Default>, L<CPANPLUS::Shell>, L<cpanp>
+
+=cut
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
+
diff --git a/Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default/Plugins/Source.pm b/Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default/Plugins/Source.pm
new file mode 100644
index 00000000000..889b3d3d9bd
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/CPANPLUS/Shell/Default/Plugins/Source.pm
@@ -0,0 +1,107 @@
+package CPANPLUS::Shell::Default::Plugins::Source;
+
+use strict;
+use CPANPLUS::Error qw[error msg];
+use Locale::Maketext::Simple Class => 'CPANPLUS', Style => 'gettext';
+
+=head1 NAME
+
+CPANPLUS::Shell::Default::Plugins::Source
+
+=head1 SYNOPSIS
+
+ CPAN Terminal> /source /tmp/list_of_commands /tmp/more_commands
+
+=head1 DESCRIPTION
+
+This is a C<CPANPLUS::Shell::Default> plugin that works just like
+your unix shells source(1) command; it reads in a file that has
+commands in it to execute, and then executes them.
+
+A sample file might look like this:
+
+ # first, update all the source files
+ x --update_source
+
+ # find all of my modules that are on the CPAN
+ # test them, and store the error log
+ a ^KANE$'
+ t *
+ p /home/kane/cpan-autotest/log
+
+ # and inform us we're good to go
+ ! print "Autotest complete, log stored; please enter your commands!"
+
+Note how empty lines, and lines starting with a '#' are being skipped
+in the execution.
+
+=cut
+
+
+sub plugins { return ( source => 'source' ) }
+
+sub source {
+ my $class = shift;
+ my $shell = shift;
+ my $cb = shift;
+ my $cmd = shift;
+ my $input = shift || '';
+ my $opts = shift || {};
+ my $verbose = $cb->configure_object->get_conf('verbose');
+
+ for my $file ( split /\s+/, $input ) {
+ my $fh = FileHandle->new("$file") or(
+ error(loc("Could not open file '%1': %2", $file, $!)),
+ next
+ );
+
+ while( my $line = <$fh> ) {
+ chomp $line;
+
+ next if $line !~ /\S+/; # skip empty/whitespace only lines
+ next if $line =~ /^#/; # skip comments
+
+ msg(loc("Dispatching '%1'", $line), $verbose);
+ return 1 if $shell->dispatch_on_input( input => $line );
+ }
+ }
+}
+
+sub source_help {
+ return loc(' /source FILE [FILE ..] '.
+ '# read in commands from the specified file' ),
+}
+
+1;
+
+=pod
+
+=head1 BUG REPORTS
+
+Please report bugs or other issues to E<lt>bug-cpanplus@rt.cpan.org<gt>.
+
+=head1 AUTHOR
+
+This module by Jos Boumans E<lt>kane@cpan.orgE<gt>.
+
+=head1 COPYRIGHT
+
+The CPAN++ interface (of which this module is a part of) is copyright (c)
+2001 - 2007, Jos Boumans E<lt>kane@cpan.orgE<gt>. All rights reserved.
+
+This library is free software; you may redistribute and/or modify it
+under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<CPANPLUS::Shell::Default>, L<CPANPLUS::Shell>, L<cpanp>
+
+=cut
+
+# Local variables:
+# c-indentation-style: bsd
+# c-basic-offset: 4
+# indent-tabs-mode: nil
+# End:
+# vim: expandtab shiftwidth=4:
+
diff --git a/Master/tlpkg/tlperl/lib/Encode/Alias.pm b/Master/tlpkg/tlperl/lib/Encode/Alias.pm
new file mode 100644
index 00000000000..f142403ca9c
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/Alias.pm
@@ -0,0 +1,377 @@
+package Encode::Alias;
+use strict;
+use warnings;
+no warnings 'redefine';
+our $VERSION = do { my @r = ( q$Revision: 2.12 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+sub DEBUG () { 0 }
+
+use base qw(Exporter);
+
+# Public, encouraged API is exported by default
+
+our @EXPORT =
+ qw (
+ define_alias
+ find_alias
+);
+
+our @Alias; # ordered matching list
+our %Alias; # cached known aliases
+
+sub find_alias {
+ require Encode;
+ my $class = shift;
+ my $find = shift;
+ unless ( exists $Alias{$find} ) {
+ $Alias{$find} = undef; # Recursion guard
+ for ( my $i = 0 ; $i < @Alias ; $i += 2 ) {
+ my $alias = $Alias[$i];
+ my $val = $Alias[ $i + 1 ];
+ my $new;
+ if ( ref($alias) eq 'Regexp' && $find =~ $alias ) {
+ DEBUG and warn "eval $val";
+ $new = eval $val;
+ DEBUG and $@ and warn "$val, $@";
+ }
+ elsif ( ref($alias) eq 'CODE' ) {
+ DEBUG and warn "$alias", "->", "($find)";
+ $new = $alias->($find);
+ }
+ elsif ( lc($find) eq lc($alias) ) {
+ $new = $val;
+ }
+ if ( defined($new) ) {
+ next if $new eq $find; # avoid (direct) recursion on bugs
+ DEBUG and warn "$alias, $new";
+ my $enc =
+ ( ref($new) ) ? $new : Encode::find_encoding($new);
+ if ($enc) {
+ $Alias{$find} = $enc;
+ last;
+ }
+ }
+ }
+
+ # case insensitive search when canonical is not in all lowercase
+ # RT ticket #7835
+ unless ( $Alias{$find} ) {
+ my $lcfind = lc($find);
+ for my $name ( keys %Encode::Encoding, keys %Encode::ExtModule )
+ {
+ $lcfind eq lc($name) or next;
+ $Alias{$find} = Encode::find_encoding($name);
+ DEBUG and warn "$find => $name";
+ }
+ }
+ }
+ if (DEBUG) {
+ my $name;
+ if ( my $e = $Alias{$find} ) {
+ $name = $e->name;
+ }
+ else {
+ $name = "";
+ }
+ warn "find_alias($class, $find)->name = $name";
+ }
+ return $Alias{$find};
+}
+
+sub define_alias {
+ while (@_) {
+ my ( $alias, $name ) = splice( @_, 0, 2 );
+ unshift( @Alias, $alias => $name ); # newer one has precedence
+ if ( ref($alias) ) {
+
+ # clear %Alias cache to allow overrides
+ my @a = keys %Alias;
+ for my $k (@a) {
+ if ( ref($alias) eq 'Regexp' && $k =~ $alias ) {
+ DEBUG and warn "delete \$Alias\{$k\}";
+ delete $Alias{$k};
+ }
+ elsif ( ref($alias) eq 'CODE' ) {
+ DEBUG and warn "delete \$Alias\{$k\}";
+ delete $Alias{ $alias->($name) };
+ }
+ }
+ }
+ else {
+ DEBUG and warn "delete \$Alias\{$alias\}";
+ delete $Alias{$alias};
+ }
+ }
+}
+
+# Allow latin-1 style names as well
+# 0 1 2 3 4 5 6 7 8 9 10
+our @Latin2iso = ( 0, 1, 2, 3, 4, 9, 10, 13, 14, 15, 16 );
+
+# Allow winlatin1 style names as well
+our %Winlatin2cp = (
+ 'latin1' => 1252,
+ 'latin2' => 1250,
+ 'cyrillic' => 1251,
+ 'greek' => 1253,
+ 'turkish' => 1254,
+ 'hebrew' => 1255,
+ 'arabic' => 1256,
+ 'baltic' => 1257,
+ 'vietnamese' => 1258,
+);
+
+init_aliases();
+
+sub undef_aliases {
+ @Alias = ();
+ %Alias = ();
+}
+
+sub init_aliases {
+ require Encode;
+ undef_aliases();
+
+ # Try all-lower-case version should all else fails
+ define_alias( qr/^(.*)$/ => '"\L$1"' );
+
+ # UTF/UCS stuff
+ define_alias( qr/^(unicode-1-1-)?UTF-?7$/i => '"UTF-7"' );
+ define_alias( qr/^UCS-?2-?LE$/i => '"UCS-2LE"' );
+ define_alias(
+ qr/^UCS-?2-?(BE)?$/i => '"UCS-2BE"',
+ qr/^UCS-?4-?(BE|LE)?$/i => 'uc("UTF-32$1")',
+ qr/^iso-10646-1$/i => '"UCS-2BE"'
+ );
+ define_alias(
+ qr/^UTF-?(16|32)-?BE$/i => '"UTF-$1BE"',
+ qr/^UTF-?(16|32)-?LE$/i => '"UTF-$1LE"',
+ qr/^UTF-?(16|32)$/i => '"UTF-$1"',
+ );
+
+ # ASCII
+ define_alias( qr/^(?:US-?)ascii$/i => '"ascii"' );
+ define_alias( 'C' => 'ascii' );
+ define_alias( qr/\b(?:ISO[-_]?)?646(?:[-_]?US)?$/i => '"ascii"' );
+
+ # Allow variants of iso-8859-1 etc.
+ define_alias( qr/\biso[-_]?(\d+)[-_](\d+)$/i => '"iso-$1-$2"' );
+
+ # At least HP-UX has these.
+ define_alias( qr/\biso8859(\d+)$/i => '"iso-8859-$1"' );
+
+ # More HP stuff.
+ define_alias(
+ qr/\b(?:hp-)?(arabic|greek|hebrew|kana|roman|thai|turkish)8$/i =>
+ '"${1}8"' );
+
+ # The Official name of ASCII.
+ define_alias( qr/\bANSI[-_]?X3\.4[-_]?1968$/i => '"ascii"' );
+
+ # This is a font issue, not an encoding issue.
+ # (The currency symbol of the Latin 1 upper half
+ # has been redefined as the euro symbol.)
+ define_alias( qr/^(.+)\@euro$/i => '"$1"' );
+
+ define_alias( qr/\b(?:iso[-_]?)?latin[-_]?(\d+)$/i =>
+'defined $Encode::Alias::Latin2iso[$1] ? "iso-8859-$Encode::Alias::Latin2iso[$1]" : undef'
+ );
+
+ define_alias(
+ qr/\bwin(latin[12]|cyrillic|baltic|greek|turkish|
+ hebrew|arabic|baltic|vietnamese)$/ix =>
+ '"cp" . $Encode::Alias::Winlatin2cp{lc($1)}'
+ );
+
+ # Common names for non-latin preferred MIME names
+ define_alias(
+ 'ascii' => 'US-ascii',
+ 'cyrillic' => 'iso-8859-5',
+ 'arabic' => 'iso-8859-6',
+ 'greek' => 'iso-8859-7',
+ 'hebrew' => 'iso-8859-8',
+ 'thai' => 'iso-8859-11',
+ );
+ # RT #20781
+ define_alias(qr/\btis-?620\b/i => '"iso-8859-11"');
+
+ # At least AIX has IBM-NNN (surprisingly...) instead of cpNNN.
+ # And Microsoft has their own naming (again, surprisingly).
+ # And windows-* is registered in IANA!
+ define_alias(
+ qr/\b(?:cp|ibm|ms|windows)[-_ ]?(\d{2,4})$/i => '"cp$1"' );
+
+ # Sometimes seen with a leading zero.
+ # define_alias( qr/\bcp037\b/i => '"cp37"');
+
+ # Mac Mappings
+ # predefined in *.ucm; unneeded
+ # define_alias( qr/\bmacIcelandic$/i => '"macIceland"');
+ define_alias( qr/^mac_(.*)$/i => '"mac$1"' );
+ # http://rt.cpan.org/Ticket/Display.html?id=36326
+ define_alias( qr/^macintosh$/i => '"MacRoman"' );
+
+ # Ououououou. gone. They are differente!
+ # define_alias( qr/\bmacRomanian$/i => '"macRumanian"');
+
+ # Standardize on the dashed versions.
+ define_alias( qr/\bkoi8[\s\-_]*([ru])$/i => '"koi8-$1"' );
+
+ unless ($Encode::ON_EBCDIC) {
+
+ # for Encode::CN
+ define_alias( qr/\beuc.*cn$/i => '"euc-cn"' );
+ define_alias( qr/\bcn.*euc$/i => '"euc-cn"' );
+
+ # define_alias( qr/\bGB[- ]?(\d+)$/i => '"euc-cn"' )
+ # CP936 doesn't have vendor-addon for GBK, so they're identical.
+ define_alias( qr/^gbk$/i => '"cp936"' );
+
+ # This fixes gb2312 vs. euc-cn confusion, practically
+ define_alias( qr/\bGB[-_ ]?2312(?!-?raw)/i => '"euc-cn"' );
+
+ # for Encode::JP
+ define_alias( qr/\bjis$/i => '"7bit-jis"' );
+ define_alias( qr/\beuc.*jp$/i => '"euc-jp"' );
+ define_alias( qr/\bjp.*euc$/i => '"euc-jp"' );
+ define_alias( qr/\bujis$/i => '"euc-jp"' );
+ define_alias( qr/\bshift.*jis$/i => '"shiftjis"' );
+ define_alias( qr/\bsjis$/i => '"shiftjis"' );
+ define_alias( qr/\bwindows-31j$/i => '"cp932"' );
+
+ # for Encode::KR
+ define_alias( qr/\beuc.*kr$/i => '"euc-kr"' );
+ define_alias( qr/\bkr.*euc$/i => '"euc-kr"' );
+
+ # This fixes ksc5601 vs. euc-kr confusion, practically
+ define_alias( qr/(?:x-)?uhc$/i => '"cp949"' );
+ define_alias( qr/(?:x-)?windows-949$/i => '"cp949"' );
+ define_alias( qr/\bks_c_5601-1987$/i => '"cp949"' );
+
+ # for Encode::TW
+ define_alias( qr/\bbig-?5$/i => '"big5-eten"' );
+ define_alias( qr/\bbig5-?et(?:en)?$/i => '"big5-eten"' );
+ define_alias( qr/\btca[-_]?big5$/i => '"big5-eten"' );
+ define_alias( qr/\bbig5-?hk(?:scs)?$/i => '"big5-hkscs"' );
+ define_alias( qr/\bhk(?:scs)?[-_]?big5$/i => '"big5-hkscs"' );
+ }
+
+ # utf8 is blessed :)
+ define_alias( qr/\bUTF-8$/i => '"utf-8-strict"' );
+
+ # At last, Map white space and _ to '-'
+ define_alias( qr/^(\S+)[\s_]+(.*)$/i => '"$1-$2"' );
+}
+
+1;
+__END__
+
+# TODO: HP-UX '8' encodings arabic8 greek8 hebrew8 kana8 thai8 turkish8
+# TODO: HP-UX '15' encodings japanese15 korean15 roi15
+# TODO: Cyrillic encoding ISO-IR-111 (useful?)
+# TODO: Armenian encoding ARMSCII-8
+# TODO: Hebrew encoding ISO-8859-8-1
+# TODO: Thai encoding TCVN
+# TODO: Vietnamese encodings VPS
+# TODO: Mac Asian+African encodings: Arabic Armenian Bengali Burmese
+# ChineseSimp ChineseTrad Devanagari Ethiopic ExtArabic
+# Farsi Georgian Gujarati Gurmukhi Hebrew Japanese
+# Kannada Khmer Korean Laotian Malayalam Mongolian
+# Oriya Sinhalese Symbol Tamil Telugu Tibetan Vietnamese
+
+=head1 NAME
+
+Encode::Alias - alias definitions to encodings
+
+=head1 SYNOPSIS
+
+ use Encode;
+ use Encode::Alias;
+ define_alias( newName => ENCODING);
+
+=head1 DESCRIPTION
+
+Allows newName to be used as an alias for ENCODING. ENCODING may be
+either the name of an encoding or an encoding object (as described
+in L<Encode>).
+
+Currently I<newName> can be specified in the following ways:
+
+=over 4
+
+=item As a simple string.
+
+=item As a qr// compiled regular expression, e.g.:
+
+ define_alias( qr/^iso8859-(\d+)$/i => '"iso-8859-$1"' );
+
+In this case, if I<ENCODING> is not a reference, it is C<eval>-ed
+in order to allow C<$1> etc. to be substituted. The example is one
+way to alias names as used in X11 fonts to the MIME names for the
+iso-8859-* family. Note the double quotes inside the single quotes.
+
+(or, you don't have to do this yourself because this example is predefined)
+
+If you are using a regex here, you have to use the quotes as shown or
+it won't work. Also note that regex handling is tricky even for the
+experienced. Use this feature with caution.
+
+=item As a code reference, e.g.:
+
+ define_alias( sub {shift =~ /^iso8859-(\d+)$/i ? "iso-8859-$1" : undef } );
+
+The same effect as the example above in a different way. The coderef
+takes the alias name as an argument and returns a canonical name on
+success or undef if not. Note the second argument is not required.
+Use this with even more caution than the regex version.
+
+=back
+
+=head3 Changes in code reference aliasing
+
+As of Encode 1.87, the older form
+
+ define_alias( sub { return /^iso8859-(\d+)$/i ? "iso-8859-$1" : undef } );
+
+no longer works.
+
+Encode up to 1.86 internally used "local $_" to implement ths older
+form. But consider the code below;
+
+ use Encode;
+ $_ = "eeeee" ;
+ while (/(e)/g) {
+ my $utf = decode('aliased-encoding-name', $1);
+ print "position:",pos,"\n";
+ }
+
+Prior to Encode 1.86 this fails because of "local $_".
+
+=head2 Alias overloading
+
+You can override predefined aliases by simply applying define_alias().
+The new alias is always evaluated first, and when necessary,
+define_alias() flushes the internal cache to make the new definition
+available.
+
+ # redirect SHIFT_JIS to MS/IBM Code Page 932, which is a
+ # superset of SHIFT_JIS
+
+ define_alias( qr/shift.*jis$/i => '"cp932"' );
+ define_alias( qr/sjis$/i => '"cp932"' );
+
+If you want to zap all predefined aliases, you can use
+
+ Encode::Alias->undef_aliases;
+
+to do so. And
+
+ Encode::Alias->init_aliases;
+
+gets the factory settings back.
+
+=head1 SEE ALSO
+
+L<Encode>, L<Encode::Supported>
+
+=cut
+
diff --git a/Master/tlpkg/tlperl/lib/Encode/Byte.pm b/Master/tlpkg/tlperl/lib/Encode/Byte.pm
new file mode 100644
index 00000000000..d105aa27cc8
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/Byte.pm
@@ -0,0 +1,120 @@
+package Encode::Byte;
+use strict;
+use warnings;
+use Encode;
+our $VERSION = do { my @r = ( q$Revision: 2.4 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+
+use XSLoader;
+XSLoader::load( __PACKAGE__, $VERSION );
+
+1;
+__END__
+
+=head1 NAME
+
+Encode::Byte - Single Byte Encodings
+
+=head1 SYNOPSIS
+
+ use Encode qw/encode decode/;
+ $greek = encode("iso-8859-7", $utf8); # loads Encode::Byte implicitly
+ $utf8 = decode("iso-8859-7", $greek); # ditto
+
+=head1 ABSTRACT
+
+This module implements various single byte encodings. For most cases it uses
+\x80-\xff (upper half) to map non-ASCII characters. Encodings
+supported are as follows.
+
+ Canonical Alias Description
+ --------------------------------------------------------------------
+ # ISO 8859 series
+ (iso-8859-1 is in built-in)
+ iso-8859-2 latin2 [ISO]
+ iso-8859-3 latin3 [ISO]
+ iso-8859-4 latin4 [ISO]
+ iso-8859-5 [ISO]
+ iso-8859-6 [ISO]
+ iso-8859-7 [ISO]
+ iso-8859-8 [ISO]
+ iso-8859-9 latin5 [ISO]
+ iso-8859-10 latin6 [ISO]
+ iso-8859-11
+ (iso-8859-12 is nonexistent)
+ iso-8859-13 latin7 [ISO]
+ iso-8859-14 latin8 [ISO]
+ iso-8859-15 latin9 [ISO]
+ iso-8859-16 latin10 [ISO]
+
+ # Cyrillic
+ koi8-f
+ koi8-r cp878 [RFC1489]
+ koi8-u [RFC2319]
+
+ # Vietnamese
+ viscii
+
+ # all cp* are also available as ibm-*, ms-*, and windows-*
+ # also see L<http://msdn.microsoft.com/en-us/library/aa752010%28VS.85%29.aspx>
+
+ cp424
+ cp437
+ cp737
+ cp775
+ cp850
+ cp852
+ cp855
+ cp856
+ cp857
+ cp860
+ cp861
+ cp862
+ cp863
+ cp864
+ cp865
+ cp866
+ cp869
+ cp874
+ cp1006
+ cp1250 WinLatin2
+ cp1251 WinCyrillic
+ cp1252 WinLatin1
+ cp1253 WinGreek
+ cp1254 WinTurkish
+ cp1255 WinHebrew
+ cp1256 WinArabic
+ cp1257 WinBaltic
+ cp1258 WinVietnamese
+
+ # Macintosh
+ # Also see L<http://developer.apple.com/technotes/tn/tn1150.html>
+ MacArabic
+ MacCentralEurRoman
+ MacCroatian
+ MacCyrillic
+ MacFarsi
+ MacGreek
+ MacHebrew
+ MacIcelandic
+ MacRoman
+ MacRomanian
+ MacRumanian
+ MacSami
+ MacThai
+ MacTurkish
+ MacUkrainian
+
+ # More vendor encodings
+ AdobeStandardEncoding
+ nextstep
+ hp-roman8
+
+=head1 DESCRIPTION
+
+To find how to use this module in detail, see L<Encode>.
+
+=head1 SEE ALSO
+
+L<Encode>
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/CJKConstants.pm b/Master/tlpkg/tlperl/lib/Encode/CJKConstants.pm
new file mode 100644
index 00000000000..43d20337544
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/CJKConstants.pm
@@ -0,0 +1,66 @@
+#
+# $Id: CJKConstants.pm,v 2.2 2006/06/03 20:28:48 dankogai Exp $
+#
+
+package Encode::CJKConstants;
+
+use strict;
+use warnings;
+our $RCSID = q$Id: CJKConstants.pm,v 2.2 2006/06/03 20:28:48 dankogai Exp $;
+our $VERSION = do { my @r = ( q$Revision: 2.2 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+
+use Carp;
+
+require Exporter;
+our @ISA = qw(Exporter);
+our @EXPORT = qw();
+our @EXPORT_OK = qw(%CHARCODE %ESC %RE);
+our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK, @EXPORT ] );
+
+my %_0208 = (
+ 1978 => '\e\$\@',
+ 1983 => '\e\$B',
+ 1990 => '\e&\@\e\$B',
+);
+
+our %CHARCODE = (
+ UNDEF_EUC => "\xa2\xae", # ¢® in EUC
+ UNDEF_SJIS => "\x81\xac", # ¢® in SJIS
+ UNDEF_JIS => "\xa2\xf7", # ¢÷ -- used in unicode
+ UNDEF_UNICODE => "\x20\x20", # ¢÷ -- used in unicode
+);
+
+our %ESC = (
+ GB_2312 => "\e\$A",
+ JIS_0208 => "\e\$B",
+ JIS_0212 => "\e\$(D",
+ KSC_5601 => "\e\$(C",
+ ASC => "\e\(B",
+ KANA => "\e\(I",
+ '2022_KR' => "\e\$)C",
+);
+
+our %RE = (
+ ASCII => '[\x00-\x7f]',
+ BIN => '[\x00-\x06\x7f\xff]',
+ EUC_0212 => '\x8f[\xa1-\xfe][\xa1-\xfe]',
+ EUC_C => '[\xa1-\xfe][\xa1-\xfe]',
+ EUC_KANA => '\x8e[\xa1-\xdf]',
+ JIS_0208 => "$_0208{1978}|$_0208{1983}|$_0208{1990}",
+ JIS_0212 => "\e" . '\$\(D',
+ ISO_ASC => "\e" . '\([BJ]',
+ JIS_KANA => "\e" . '\(I',
+ '2022_KR' => "\e" . '\$\)C',
+ SJIS_C => '[\x81-\x9f\xe0-\xfc][\x40-\x7e\x80-\xfc]',
+ SJIS_KANA => '[\xa1-\xdf]',
+ UTF8 => '[\xc0-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf][\x80-\xbf]'
+);
+
+1;
+
+=head1 NAME
+
+Encode::CJKConstants.pm -- Internally used by Encode::??::ISO_2022_*
+
+=cut
+
diff --git a/Master/tlpkg/tlperl/lib/Encode/CN.pm b/Master/tlpkg/tlperl/lib/Encode/CN.pm
new file mode 100644
index 00000000000..830f34507da
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/CN.pm
@@ -0,0 +1,74 @@
+package Encode::CN;
+BEGIN {
+ if ( ord("A") == 193 ) {
+ die "Encode::CN not supported on EBCDIC\n";
+ }
+}
+use strict;
+use warnings;
+use Encode;
+our $VERSION = do { my @r = ( q$Revision: 2.3 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+use XSLoader;
+XSLoader::load( __PACKAGE__, $VERSION );
+
+# Relocated from Encode.pm
+
+use Encode::CN::HZ;
+
+# use Encode::CN::2022_CN;
+
+1;
+__END__
+
+=head1 NAME
+
+Encode::CN - China-based Chinese Encodings
+
+=head1 SYNOPSIS
+
+ use Encode qw/encode decode/;
+ $euc_cn = encode("euc-cn", $utf8); # loads Encode::CN implicitly
+ $utf8 = decode("euc-cn", $euc_cn); # ditto
+
+=head1 DESCRIPTION
+
+This module implements China-based Chinese charset encodings.
+Encodings supported are as follows.
+
+ Canonical Alias Description
+ --------------------------------------------------------------------
+ euc-cn /\beuc.*cn$/i EUC (Extended Unix Character)
+ /\bcn.*euc$/i
+ /\bGB[-_ ]?2312(?:\D.*$|$)/i (see below)
+ gb2312-raw The raw (low-bit) GB2312 character map
+ gb12345-raw Traditional chinese counterpart to
+ GB2312 (raw)
+ iso-ir-165 GB2312 + GB6345 + GB8565 + additions
+ MacChineseSimp GB2312 + Apple Additions
+ cp936 Code Page 936, also known as GBK
+ (Extended GuoBiao)
+ hz 7-bit escaped GB2312 encoding
+ --------------------------------------------------------------------
+
+To find how to use this module in detail, see L<Encode>.
+
+=head1 NOTES
+
+Due to size concerns, C<GB 18030> (an extension to C<GBK>) is distributed
+separately on CPAN, under the name L<Encode::HanExtra>. That module
+also contains extra Taiwan-based encodings.
+
+=head1 BUGS
+
+When you see C<charset=gb2312> on mails and web pages, they really
+mean C<euc-cn> encodings. To fix that, C<gb2312> is aliased to C<euc-cn>.
+Use C<gb2312-raw> when you really mean it.
+
+The ASCII region (0x00-0x7f) is preserved for all encodings, even though
+this conflicts with mappings by the Unicode Consortium.
+
+=head1 SEE ALSO
+
+L<Encode>
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/CN/HZ.pm b/Master/tlpkg/tlperl/lib/Encode/CN/HZ.pm
new file mode 100644
index 00000000000..98c16a9053a
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/CN/HZ.pm
@@ -0,0 +1,198 @@
+package Encode::CN::HZ;
+
+use strict;
+use warnings;
+use utf8 ();
+
+use vars qw($VERSION);
+$VERSION = do { my @r = ( q$Revision: 2.5 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+
+use Encode qw(:fallbacks);
+
+use base qw(Encode::Encoding);
+__PACKAGE__->Define('hz');
+
+# HZ is a combination of ASCII and escaped GB, so we implement it
+# with the GB2312(raw) encoding here. Cf. RFCs 1842 & 1843.
+
+# not ported for EBCDIC. Which should be used, "~" or "\x7E"?
+
+sub needs_lines { 1 }
+
+sub decode ($$;$) {
+ my ( $obj, $str, $chk ) = @_;
+
+ my $GB = Encode::find_encoding('gb2312-raw');
+ my $ret = '';
+ my $in_ascii = 1; # default mode is ASCII.
+
+ while ( length $str ) {
+ if ($in_ascii) { # ASCII mode
+ if ( $str =~ s/^([\x00-\x7D\x7F]+)// ) { # no '~' => ASCII
+ $ret .= $1;
+
+ # EBCDIC should need ascii2native, but not ported.
+ }
+ elsif ( $str =~ s/^\x7E\x7E// ) { # escaped tilde
+ $ret .= '~';
+ }
+ elsif ( $str =~ s/^\x7E\cJ// ) { # '\cJ' == LF in ASCII
+ 1; # no-op
+ }
+ elsif ( $str =~ s/^\x7E\x7B// ) { # '~{'
+ $in_ascii = 0; # to GB
+ }
+ else { # encounters an invalid escape, \x80 or greater
+ last;
+ }
+ }
+ else { # GB mode; the byte ranges are as in RFC 1843.
+ no warnings 'uninitialized';
+ if ( $str =~ s/^((?:[\x21-\x77][\x21-\x7E])+)// ) {
+ $ret .= $GB->decode( $1, $chk );
+ }
+ elsif ( $str =~ s/^\x7E\x7D// ) { # '~}'
+ $in_ascii = 1;
+ }
+ else { # invalid
+ last;
+ }
+ }
+ }
+ $_[1] = '' if $chk; # needs_lines guarantees no partial character
+ return $ret;
+}
+
+sub cat_decode {
+ my ( $obj, undef, $src, $pos, $trm, $chk ) = @_;
+ my ( $rdst, $rsrc, $rpos ) = \@_[ 1 .. 3 ];
+
+ my $GB = Encode::find_encoding('gb2312-raw');
+ my $ret = '';
+ my $in_ascii = 1; # default mode is ASCII.
+
+ my $ini_pos = pos($$rsrc);
+
+ substr( $src, 0, $pos ) = '';
+
+ my $ini_len = bytes::length($src);
+
+ # $trm is the first of the pair '~~', then 2nd tilde is to be removed.
+ # XXX: Is better C<$src =~ s/^\x7E// or die if ...>?
+ $src =~ s/^\x7E// if $trm eq "\x7E";
+
+ while ( length $src ) {
+ my $now;
+ if ($in_ascii) { # ASCII mode
+ if ( $src =~ s/^([\x00-\x7D\x7F])// ) { # no '~' => ASCII
+ $now = $1;
+ }
+ elsif ( $src =~ s/^\x7E\x7E// ) { # escaped tilde
+ $now = '~';
+ }
+ elsif ( $src =~ s/^\x7E\cJ// ) { # '\cJ' == LF in ASCII
+ next;
+ }
+ elsif ( $src =~ s/^\x7E\x7B// ) { # '~{'
+ $in_ascii = 0; # to GB
+ next;
+ }
+ else { # encounters an invalid escape, \x80 or greater
+ last;
+ }
+ }
+ else { # GB mode; the byte ranges are as in RFC 1843.
+ if ( $src =~ s/^((?:[\x21-\x77][\x21-\x7F])+)// ) {
+ $now = $GB->decode( $1, $chk );
+ }
+ elsif ( $src =~ s/^\x7E\x7D// ) { # '~}'
+ $in_ascii = 1;
+ next;
+ }
+ else { # invalid
+ last;
+ }
+ }
+
+ next if !defined $now;
+
+ $ret .= $now;
+
+ if ( $now eq $trm ) {
+ $$rdst .= $ret;
+ $$rpos = $ini_pos + $pos + $ini_len - bytes::length($src);
+ pos($$rsrc) = $ini_pos;
+ return 1;
+ }
+ }
+
+ $$rdst .= $ret;
+ $$rpos = $ini_pos + $pos + $ini_len - bytes::length($src);
+ pos($$rsrc) = $ini_pos;
+ return ''; # terminator not found
+}
+
+sub encode($$;$) {
+ my ( $obj, $str, $chk ) = @_;
+
+ my $GB = Encode::find_encoding('gb2312-raw');
+ my $ret = '';
+ my $in_ascii = 1; # default mode is ASCII.
+
+ no warnings 'utf8'; # $str may be malformed UTF8 at the end of a chunk.
+
+ while ( length $str ) {
+ if ( $str =~ s/^([[:ascii:]]+)// ) {
+ my $tmp = $1;
+ $tmp =~ s/~/~~/g; # escapes tildes
+ if ( !$in_ascii ) {
+ $ret .= "\x7E\x7D"; # '~}'
+ $in_ascii = 1;
+ }
+ $ret .= pack 'a*', $tmp; # remove UTF8 flag.
+ }
+ elsif ( $str =~ s/(.)// ) {
+ my $s = $1;
+ my $tmp = $GB->encode( $s, $chk );
+ last if !defined $tmp;
+ if ( length $tmp == 2 ) { # maybe a valid GB char (XXX)
+ if ($in_ascii) {
+ $ret .= "\x7E\x7B"; # '~{'
+ $in_ascii = 0;
+ }
+ $ret .= $tmp;
+ }
+ elsif ( length $tmp ) { # maybe FALLBACK in ASCII (XXX)
+ if ( !$in_ascii ) {
+ $ret .= "\x7E\x7D"; # '~}'
+ $in_ascii = 1;
+ }
+ $ret .= $tmp;
+ }
+ }
+ else { # if $str is malformed UTF8 *and* if length $str != 0.
+ last;
+ }
+ }
+ $_[1] = $str if $chk;
+
+ # The state at the end of the chunk is discarded, even if in GB mode.
+ # That results in the combination of GB-OUT and GB-IN, i.e. "~}~{".
+ # Parhaps it is harmless, but further investigations may be required...
+
+ if ( !$in_ascii ) {
+ $ret .= "\x7E\x7D"; # '~}'
+ $in_ascii = 1;
+ }
+ utf8::encode($ret); # https://rt.cpan.org/Ticket/Display.html?id=35120
+ return $ret;
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Encode::CN::HZ -- internally used by Encode::CN
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/Changes.e2x b/Master/tlpkg/tlperl/lib/Encode/Changes.e2x
new file mode 100644
index 00000000000..5c67c55cb93
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/Changes.e2x
@@ -0,0 +1,7 @@
+#
+# $Id: Changes.e2x,v 2.0 2004/05/16 20:55:15 dankogai Exp $
+# Revision history for Perl extension Encode::$_Name_.
+#
+
+0.01 $_Now_
+ Autogenerated by enc2xs version $_Version_.
diff --git a/Master/tlpkg/tlperl/lib/Encode/Config.pm b/Master/tlpkg/tlperl/lib/Encode/Config.pm
new file mode 100644
index 00000000000..1286a479998
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/Config.pm
@@ -0,0 +1,170 @@
+#
+# Demand-load module list
+#
+package Encode::Config;
+our $VERSION = do { my @r = ( q$Revision: 2.5 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+
+use strict;
+use warnings;
+
+our %ExtModule = (
+
+ # Encode::Byte
+ #iso-8859-1 is in Encode.pm itself
+ 'iso-8859-2' => 'Encode::Byte',
+ 'iso-8859-3' => 'Encode::Byte',
+ 'iso-8859-4' => 'Encode::Byte',
+ 'iso-8859-5' => 'Encode::Byte',
+ 'iso-8859-6' => 'Encode::Byte',
+ 'iso-8859-7' => 'Encode::Byte',
+ 'iso-8859-8' => 'Encode::Byte',
+ 'iso-8859-9' => 'Encode::Byte',
+ 'iso-8859-10' => 'Encode::Byte',
+ 'iso-8859-11' => 'Encode::Byte',
+ 'iso-8859-13' => 'Encode::Byte',
+ 'iso-8859-14' => 'Encode::Byte',
+ 'iso-8859-15' => 'Encode::Byte',
+ 'iso-8859-16' => 'Encode::Byte',
+ 'koi8-f' => 'Encode::Byte',
+ 'koi8-r' => 'Encode::Byte',
+ 'koi8-u' => 'Encode::Byte',
+ 'viscii' => 'Encode::Byte',
+ 'cp424' => 'Encode::Byte',
+ 'cp437' => 'Encode::Byte',
+ 'cp737' => 'Encode::Byte',
+ 'cp775' => 'Encode::Byte',
+ 'cp850' => 'Encode::Byte',
+ 'cp852' => 'Encode::Byte',
+ 'cp855' => 'Encode::Byte',
+ 'cp856' => 'Encode::Byte',
+ 'cp857' => 'Encode::Byte',
+ 'cp858' => 'Encode::Byte',
+ 'cp860' => 'Encode::Byte',
+ 'cp861' => 'Encode::Byte',
+ 'cp862' => 'Encode::Byte',
+ 'cp863' => 'Encode::Byte',
+ 'cp864' => 'Encode::Byte',
+ 'cp865' => 'Encode::Byte',
+ 'cp866' => 'Encode::Byte',
+ 'cp869' => 'Encode::Byte',
+ 'cp874' => 'Encode::Byte',
+ 'cp1006' => 'Encode::Byte',
+ 'cp1250' => 'Encode::Byte',
+ 'cp1251' => 'Encode::Byte',
+ 'cp1252' => 'Encode::Byte',
+ 'cp1253' => 'Encode::Byte',
+ 'cp1254' => 'Encode::Byte',
+ 'cp1255' => 'Encode::Byte',
+ 'cp1256' => 'Encode::Byte',
+ 'cp1257' => 'Encode::Byte',
+ 'cp1258' => 'Encode::Byte',
+ 'AdobeStandardEncoding' => 'Encode::Byte',
+ 'MacArabic' => 'Encode::Byte',
+ 'MacCentralEurRoman' => 'Encode::Byte',
+ 'MacCroatian' => 'Encode::Byte',
+ 'MacCyrillic' => 'Encode::Byte',
+ 'MacFarsi' => 'Encode::Byte',
+ 'MacGreek' => 'Encode::Byte',
+ 'MacHebrew' => 'Encode::Byte',
+ 'MacIcelandic' => 'Encode::Byte',
+ 'MacRoman' => 'Encode::Byte',
+ 'MacRomanian' => 'Encode::Byte',
+ 'MacRumanian' => 'Encode::Byte',
+ 'MacSami' => 'Encode::Byte',
+ 'MacThai' => 'Encode::Byte',
+ 'MacTurkish' => 'Encode::Byte',
+ 'MacUkrainian' => 'Encode::Byte',
+ 'nextstep' => 'Encode::Byte',
+ 'hp-roman8' => 'Encode::Byte',
+ #'gsm0338' => 'Encode::Byte',
+ 'gsm0338' => 'Encode::GSM0338',
+
+ # Encode::EBCDIC
+ 'cp37' => 'Encode::EBCDIC',
+ 'cp500' => 'Encode::EBCDIC',
+ 'cp875' => 'Encode::EBCDIC',
+ 'cp1026' => 'Encode::EBCDIC',
+ 'cp1047' => 'Encode::EBCDIC',
+ 'posix-bc' => 'Encode::EBCDIC',
+
+ # Encode::Symbol
+ 'dingbats' => 'Encode::Symbol',
+ 'symbol' => 'Encode::Symbol',
+ 'AdobeSymbol' => 'Encode::Symbol',
+ 'AdobeZdingbat' => 'Encode::Symbol',
+ 'MacDingbats' => 'Encode::Symbol',
+ 'MacSymbol' => 'Encode::Symbol',
+
+ # Encode::Unicode
+ 'UCS-2BE' => 'Encode::Unicode',
+ 'UCS-2LE' => 'Encode::Unicode',
+ 'UTF-16' => 'Encode::Unicode',
+ 'UTF-16BE' => 'Encode::Unicode',
+ 'UTF-16LE' => 'Encode::Unicode',
+ 'UTF-32' => 'Encode::Unicode',
+ 'UTF-32BE' => 'Encode::Unicode',
+ 'UTF-32LE' => 'Encode::Unicode',
+ 'UTF-7' => 'Encode::Unicode::UTF7',
+);
+
+unless ( ord("A") == 193 ) {
+ %ExtModule = (
+ %ExtModule,
+ 'euc-cn' => 'Encode::CN',
+ 'gb12345-raw' => 'Encode::CN',
+ 'gb2312-raw' => 'Encode::CN',
+ 'hz' => 'Encode::CN',
+ 'iso-ir-165' => 'Encode::CN',
+ 'cp936' => 'Encode::CN',
+ 'MacChineseSimp' => 'Encode::CN',
+
+ '7bit-jis' => 'Encode::JP',
+ 'euc-jp' => 'Encode::JP',
+ 'iso-2022-jp' => 'Encode::JP',
+ 'iso-2022-jp-1' => 'Encode::JP',
+ 'jis0201-raw' => 'Encode::JP',
+ 'jis0208-raw' => 'Encode::JP',
+ 'jis0212-raw' => 'Encode::JP',
+ 'cp932' => 'Encode::JP',
+ 'MacJapanese' => 'Encode::JP',
+ 'shiftjis' => 'Encode::JP',
+
+ 'euc-kr' => 'Encode::KR',
+ 'iso-2022-kr' => 'Encode::KR',
+ 'johab' => 'Encode::KR',
+ 'ksc5601-raw' => 'Encode::KR',
+ 'cp949' => 'Encode::KR',
+ 'MacKorean' => 'Encode::KR',
+
+ 'big5-eten' => 'Encode::TW',
+ 'big5-hkscs' => 'Encode::TW',
+ 'cp950' => 'Encode::TW',
+ 'MacChineseTrad' => 'Encode::TW',
+
+ #'big5plus' => 'Encode::HanExtra',
+ #'euc-tw' => 'Encode::HanExtra',
+ #'gb18030' => 'Encode::HanExtra',
+
+ 'MIME-Header' => 'Encode::MIME::Header',
+ 'MIME-B' => 'Encode::MIME::Header',
+ 'MIME-Q' => 'Encode::MIME::Header',
+
+ 'MIME-Header-ISO_2022_JP' => 'Encode::MIME::Header::ISO_2022_JP',
+ );
+}
+
+#
+# Why not export ? to keep ConfigLocal Happy!
+#
+while ( my ( $enc, $mod ) = each %ExtModule ) {
+ $Encode::ExtModule{$enc} = $mod;
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Encode::Config -- internally used by Encode
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/ConfigLocal_PM.e2x b/Master/tlpkg/tlperl/lib/Encode/ConfigLocal_PM.e2x
new file mode 100644
index 00000000000..e203dfded50
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/ConfigLocal_PM.e2x
@@ -0,0 +1,13 @@
+#
+# Local demand-load module list
+#
+# You should not edit this file by hand! use "enc2xs -C"
+#
+package Encode::ConfigLocal;
+our $VERSION = $_LocalVer_;
+
+use strict;
+
+$_ModLines_
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Encode/EBCDIC.pm b/Master/tlpkg/tlperl/lib/Encode/EBCDIC.pm
new file mode 100644
index 00000000000..8024c130da1
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/EBCDIC.pm
@@ -0,0 +1,45 @@
+package Encode::EBCDIC;
+use strict;
+use warnings;
+use Encode;
+our $VERSION = do { my @r = ( q$Revision: 2.2 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+
+use XSLoader;
+XSLoader::load( __PACKAGE__, $VERSION );
+
+1;
+__END__
+
+=head1 NAME
+
+Encode::EBCDIC - EBCDIC Encodings
+
+=head1 SYNOPSIS
+
+ use Encode qw/encode decode/;
+ $posix_bc = encode("posix-bc", $utf8); # loads Encode::EBCDIC implicitly
+ $utf8 = decode("", $posix_bc); # ditto
+
+=head1 ABSTRACT
+
+This module implements various EBCDIC-Based encodings. Encodings
+supported are as follows.
+
+ Canonical Alias Description
+ --------------------------------------------------------------------
+ cp37
+ cp500
+ cp875
+ cp1026
+ cp1047
+ posix-bc
+
+=head1 DESCRIPTION
+
+To find how to use this module in detail, see L<Encode>.
+
+=head1 SEE ALSO
+
+L<Encode>, L<perlebcdic>
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/Encoder.pm b/Master/tlpkg/tlperl/lib/Encode/Encoder.pm
new file mode 100644
index 00000000000..f7194f81ac4
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/Encoder.pm
@@ -0,0 +1,253 @@
+#
+# $Id: Encoder.pm,v 2.1 2006/05/03 18:24:10 dankogai Exp $
+#
+package Encode::Encoder;
+use strict;
+use warnings;
+our $VERSION = do { my @r = ( q$Revision: 2.1 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+
+require Exporter;
+our @ISA = qw(Exporter);
+our @EXPORT_OK = qw ( encoder );
+
+our $AUTOLOAD;
+sub DEBUG () { 0 }
+use Encode qw(encode decode find_encoding from_to);
+use Carp;
+
+sub new {
+ my ( $class, $data, $encname ) = @_;
+ unless ($encname) {
+ $encname = Encode::is_utf8($data) ? 'utf8' : '';
+ }
+ else {
+ my $obj = find_encoding($encname)
+ or croak __PACKAGE__, ": unknown encoding: $encname";
+ $encname = $obj->name;
+ }
+ my $self = {
+ data => $data,
+ encoding => $encname,
+ };
+ bless $self => $class;
+}
+
+sub encoder { __PACKAGE__->new(@_) }
+
+sub data {
+ my ( $self, $data ) = @_;
+ if ( defined $data ) {
+ $self->{data} = $data;
+ return $data;
+ }
+ else {
+ return $self->{data};
+ }
+}
+
+sub encoding {
+ my ( $self, $encname ) = @_;
+ if ($encname) {
+ my $obj = find_encoding($encname)
+ or confess __PACKAGE__, ": unknown encoding: $encname";
+ $self->{encoding} = $obj->name;
+ return $self;
+ }
+ else {
+ return $self->{encoding};
+ }
+}
+
+sub bytes {
+ my ( $self, $encname ) = @_;
+ $encname ||= $self->{encoding};
+ my $obj = find_encoding($encname)
+ or confess __PACKAGE__, ": unknown encoding: $encname";
+ $self->{data} = $obj->decode( $self->{data}, 1 );
+ $self->{encoding} = '';
+ return $self;
+}
+
+sub DESTROY { # defined so it won't autoload.
+ DEBUG and warn shift;
+}
+
+sub AUTOLOAD {
+ my $self = shift;
+ my $type = ref($self)
+ or confess "$self is not an object";
+ my $myname = $AUTOLOAD;
+ $myname =~ s/.*://; # strip fully-qualified portion
+ my $obj = find_encoding($myname)
+ or confess __PACKAGE__, ": unknown encoding: $myname";
+ DEBUG and warn $self->{encoding}, " => ", $obj->name;
+ if ( $self->{encoding} ) {
+ from_to( $self->{data}, $self->{encoding}, $obj->name, 1 );
+ }
+ else {
+ $self->{data} = $obj->encode( $self->{data}, 1 );
+ }
+ $self->{encoding} = $obj->name;
+ return $self;
+}
+
+use overload
+ q("") => sub { $_[0]->{data} },
+ q(0+) => sub { use bytes(); bytes::length( $_[0]->{data} ) },
+ fallback => 1,
+ ;
+
+1;
+__END__
+
+=head1 NAME
+
+Encode::Encoder -- Object Oriented Encoder
+
+=head1 SYNOPSIS
+
+ use Encode::Encoder;
+ # Encode::encode("ISO-8859-1", $data);
+ Encode::Encoder->new($data)->iso_8859_1; # OOP way
+ # shortcut
+ use Encode::Encoder qw(encoder);
+ encoder($data)->iso_8859_1;
+ # you can stack them!
+ encoder($data)->iso_8859_1->base64; # provided base64() is defined
+ # you can use it as a decoder as well
+ encoder($base64)->bytes('base64')->latin1;
+ # stringified
+ print encoder($data)->utf8->latin1; # prints the string in latin1
+ # numified
+ encoder("\x{abcd}\x{ef}g")->utf8 == 6; # true. bytes::length($data)
+
+=head1 ABSTRACT
+
+B<Encode::Encoder> allows you to use Encode in an object-oriented
+style. This is not only more intuitive than a functional approach,
+but also handier when you want to stack encodings. Suppose you want
+your UTF-8 string converted to Latin1 then Base64: you can simply say
+
+ my $base64 = encoder($utf8)->latin1->base64;
+
+instead of
+
+ my $latin1 = encode("latin1", $utf8);
+ my $base64 = encode_base64($utf8);
+
+or the lazier and more convoluted
+
+ my $base64 = encode_base64(encode("latin1", $utf8));
+
+=head1 Description
+
+Here is how to use this module.
+
+=over 4
+
+=item *
+
+There are at least two instance variables stored in a hash reference,
+{data} and {encoding}.
+
+=item *
+
+When there is no method, it takes the method name as the name of the
+encoding and encodes the instance I<data> with I<encoding>. If successful,
+the instance I<encoding> is set accordingly.
+
+=item *
+
+You can retrieve the result via -E<gt>data but usually you don't have to
+because the stringify operator ("") is overridden to do exactly that.
+
+=back
+
+=head2 Predefined Methods
+
+This module predefines the methods below:
+
+=over 4
+
+=item $e = Encode::Encoder-E<gt>new([$data, $encoding]);
+
+returns an encoder object. Its data is initialized with $data if
+present, and its encoding is set to $encoding if present.
+
+When $encoding is omitted, it defaults to utf8 if $data is already in
+utf8 or "" (empty string) otherwise.
+
+=item encoder()
+
+is an alias of Encode::Encoder-E<gt>new(). This one is exported on demand.
+
+=item $e-E<gt>data([$data])
+
+When $data is present, sets the instance data to $data and returns the
+object itself. Otherwise, the current instance data is returned.
+
+=item $e-E<gt>encoding([$encoding])
+
+When $encoding is present, sets the instance encoding to $encoding and
+returns the object itself. Otherwise, the current instance encoding is
+returned.
+
+=item $e-E<gt>bytes([$encoding])
+
+decodes instance data from $encoding, or the instance encoding if
+omitted. If the conversion is successful, the instance encoding
+will be set to "".
+
+The name I<bytes> was deliberately picked to avoid namespace tainting
+-- this module may be used as a base class so method names that appear
+in Encode::Encoding are avoided.
+
+=back
+
+=head2 Example: base64 transcoder
+
+This module is designed to work with L<Encode::Encoding>.
+To make the Base64 transcoder example above really work, you could
+write a module like this:
+
+ package Encode::Base64;
+ use base 'Encode::Encoding';
+ __PACKAGE__->Define('base64');
+ use MIME::Base64;
+ sub encode{
+ my ($obj, $data) = @_;
+ return encode_base64($data);
+ }
+ sub decode{
+ my ($obj, $data) = @_;
+ return decode_base64($data);
+ }
+ 1;
+ __END__
+
+And your caller module would be something like this:
+
+ use Encode::Encoder;
+ use Encode::Base64;
+
+ # now you can really do the following
+
+ encoder($data)->iso_8859_1->base64;
+ encoder($base64)->bytes('base64')->latin1;
+
+=head2 Operator Overloading
+
+This module overloads two operators, stringify ("") and numify (0+).
+
+Stringify dumps the data inside the object.
+
+Numify returns the number of bytes in the instance data.
+
+They come in handy when you want to print or find the size of data.
+
+=head1 SEE ALSO
+
+L<Encode>,
+L<Encode::Encoding>
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/Encoding.pm b/Master/tlpkg/tlperl/lib/Encode/Encoding.pm
new file mode 100644
index 00000000000..768d6d126ac
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/Encoding.pm
@@ -0,0 +1,360 @@
+package Encode::Encoding;
+
+# Base class for classes which implement encodings
+use strict;
+use warnings;
+our $VERSION = do { my @r = ( q$Revision: 2.5 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+
+require Encode;
+
+sub DEBUG { 0 }
+
+sub Define {
+ my $obj = shift;
+ my $canonical = shift;
+ $obj = bless { Name => $canonical }, $obj unless ref $obj;
+
+ # warn "$canonical => $obj\n";
+ Encode::define_encoding( $obj, $canonical, @_ );
+}
+
+sub name { return shift->{'Name'} }
+
+sub mime_name{
+ require Encode::MIME::Name;
+ return Encode::MIME::Name::get_mime_name(shift->name);
+}
+
+# sub renew { return $_[0] }
+
+sub renew {
+ my $self = shift;
+ my $clone = bless {%$self} => ref($self);
+ $clone->{renewed}++; # so the caller can see it
+ DEBUG and warn $clone->{renewed};
+ return $clone;
+}
+
+sub renewed { return $_[0]->{renewed} || 0 }
+
+*new_sequence = \&renew;
+
+sub needs_lines { 0 }
+
+sub perlio_ok {
+ eval { require PerlIO::encoding };
+ return $@ ? 0 : 1;
+}
+
+# (Temporary|legacy) methods
+
+sub toUnicode { shift->decode(@_) }
+sub fromUnicode { shift->encode(@_) }
+
+#
+# Needs to be overloaded or just croak
+#
+
+sub encode {
+ require Carp;
+ my $obj = shift;
+ my $class = ref($obj) ? ref($obj) : $obj;
+ Carp::croak( $class . "->encode() not defined!" );
+}
+
+sub decode {
+ require Carp;
+ my $obj = shift;
+ my $class = ref($obj) ? ref($obj) : $obj;
+ Carp::croak( $class . "->encode() not defined!" );
+}
+
+sub DESTROY { }
+
+1;
+__END__
+
+=head1 NAME
+
+Encode::Encoding - Encode Implementation Base Class
+
+=head1 SYNOPSIS
+
+ package Encode::MyEncoding;
+ use base qw(Encode::Encoding);
+
+ __PACKAGE__->Define(qw(myCanonical myAlias));
+
+=head1 DESCRIPTION
+
+As mentioned in L<Encode>, encodings are (in the current
+implementation at least) defined as objects. The mapping of encoding
+name to object is via the C<%Encode::Encoding> hash. Though you can
+directly manipulate this hash, it is strongly encouraged to use this
+base class module and add encode() and decode() methods.
+
+=head2 Methods you should implement
+
+You are strongly encouraged to implement methods below, at least
+either encode() or decode().
+
+=over 4
+
+=item -E<gt>encode($string [,$check])
+
+MUST return the octet sequence representing I<$string>.
+
+=over 2
+
+=item *
+
+If I<$check> is true, it SHOULD modify I<$string> in place to remove
+the converted part (i.e. the whole string unless there is an error).
+If perlio_ok() is true, SHOULD becomes MUST.
+
+=item *
+
+If an error occurs, it SHOULD return the octet sequence for the
+fragment of string that has been converted and modify $string in-place
+to remove the converted part leaving it starting with the problem
+fragment. If perlio_ok() is true, SHOULD becomes MUST.
+
+=item *
+
+If I<$check> is is false then C<encode> MUST make a "best effort" to
+convert the string - for example, by using a replacement character.
+
+=back
+
+=item -E<gt>decode($octets [,$check])
+
+MUST return the string that I<$octets> represents.
+
+=over 2
+
+=item *
+
+If I<$check> is true, it SHOULD modify I<$octets> in place to remove
+the converted part (i.e. the whole sequence unless there is an
+error). If perlio_ok() is true, SHOULD becomes MUST.
+
+=item *
+
+If an error occurs, it SHOULD return the fragment of string that has
+been converted and modify $octets in-place to remove the converted
+part leaving it starting with the problem fragment. If perlio_ok() is
+true, SHOULD becomes MUST.
+
+=item *
+
+If I<$check> is false then C<decode> should make a "best effort" to
+convert the string - for example by using Unicode's "\x{FFFD}" as a
+replacement character.
+
+=back
+
+=back
+
+If you want your encoding to work with L<encoding> pragma, you should
+also implement the method below.
+
+=over 4
+
+=item -E<gt>cat_decode($destination, $octets, $offset, $terminator [,$check])
+
+MUST decode I<$octets> with I<$offset> and concatenate it to I<$destination>.
+Decoding will terminate when $terminator (a string) appears in output.
+I<$offset> will be modified to the last $octets position at end of decode.
+Returns true if $terminator appears output, else returns false.
+
+=back
+
+=head2 Other methods defined in Encode::Encodings
+
+You do not have to override methods shown below unless you have to.
+
+=over 4
+
+=item -E<gt>name
+
+Predefined As:
+
+ sub name { return shift->{'Name'} }
+
+MUST return the string representing the canonical name of the encoding.
+
+=item -E<gt>mime_name
+
+Predefined As:
+
+ sub mime_name{
+ require Encode::MIME::Name;
+ return Encode::MIME::Name::get_mime_name(shift->name);
+ }
+
+MUST return the string representing the IANA charset name of the encoding.
+
+=item -E<gt>renew
+
+Predefined As:
+
+ sub renew {
+ my $self = shift;
+ my $clone = bless { %$self } => ref($self);
+ $clone->{renewed}++;
+ return $clone;
+ }
+
+This method reconstructs the encoding object if necessary. If you need
+to store the state during encoding, this is where you clone your object.
+
+PerlIO ALWAYS calls this method to make sure it has its own private
+encoding object.
+
+=item -E<gt>renewed
+
+Predefined As:
+
+ sub renewed { $_[0]->{renewed} || 0 }
+
+Tells whether the object is renewed (and how many times). Some
+modules emit C<Use of uninitialized value in null operation> warning
+unless the value is numeric so return 0 for false.
+
+=item -E<gt>perlio_ok()
+
+Predefined As:
+
+ sub perlio_ok {
+ eval{ require PerlIO::encoding };
+ return $@ ? 0 : 1;
+ }
+
+If your encoding does not support PerlIO for some reasons, just;
+
+ sub perlio_ok { 0 }
+
+=item -E<gt>needs_lines()
+
+Predefined As:
+
+ sub needs_lines { 0 };
+
+If your encoding can work with PerlIO but needs line buffering, you
+MUST define this method so it returns true. 7bit ISO-2022 encodings
+are one example that needs this. When this method is missing, false
+is assumed.
+
+=back
+
+=head2 Example: Encode::ROT13
+
+ package Encode::ROT13;
+ use strict;
+ use base qw(Encode::Encoding);
+
+ __PACKAGE__->Define('rot13');
+
+ sub encode($$;$){
+ my ($obj, $str, $chk) = @_;
+ $str =~ tr/A-Za-z/N-ZA-Mn-za-m/;
+ $_[1] = '' if $chk; # this is what in-place edit means
+ return $str;
+ }
+
+ # Jr pna or ynml yvxr guvf;
+ *decode = \&encode;
+
+ 1;
+
+=head1 Why the heck Encode API is different?
+
+It should be noted that the I<$check> behaviour is different from the
+outer public API. The logic is that the "unchecked" case is useful
+when the encoding is part of a stream which may be reporting errors
+(e.g. STDERR). In such cases, it is desirable to get everything
+through somehow without causing additional errors which obscure the
+original one. Also, the encoding is best placed to know what the
+correct replacement character is, so if that is the desired behaviour
+then letting low level code do it is the most efficient.
+
+By contrast, if I<$check> is true, the scheme above allows the
+encoding to do as much as it can and tell the layer above how much
+that was. What is lacking at present is a mechanism to report what
+went wrong. The most likely interface will be an additional method
+call to the object, or perhaps (to avoid forcing per-stream objects
+on otherwise stateless encodings) an additional parameter.
+
+It is also highly desirable that encoding classes inherit from
+C<Encode::Encoding> as a base class. This allows that class to define
+additional behaviour for all encoding objects.
+
+ package Encode::MyEncoding;
+ use base qw(Encode::Encoding);
+
+ __PACKAGE__->Define(qw(myCanonical myAlias));
+
+to create an object with C<< bless {Name => ...}, $class >>, and call
+define_encoding. They inherit their C<name> method from
+C<Encode::Encoding>.
+
+=head2 Compiled Encodings
+
+For the sake of speed and efficiency, most of the encodings are now
+supported via a I<compiled form>: XS modules generated from UCM
+files. Encode provides the enc2xs tool to achieve that. Please see
+L<enc2xs> for more details.
+
+=head1 SEE ALSO
+
+L<perlmod>, L<enc2xs>
+
+=begin future
+
+=over 4
+
+=item Scheme 1
+
+The fixup routine gets passed the remaining fragment of string being
+processed. It modifies it in place to remove bytes/characters it can
+understand and returns a string used to represent them. For example:
+
+ sub fixup {
+ my $ch = substr($_[0],0,1,'');
+ return sprintf("\x{%02X}",ord($ch);
+ }
+
+This scheme is close to how the underlying C code for Encode works,
+but gives the fixup routine very little context.
+
+=item Scheme 2
+
+The fixup routine gets passed the original string, an index into
+it of the problem area, and the output string so far. It appends
+what it wants to the output string and returns a new index into the
+original string. For example:
+
+ sub fixup {
+ # my ($s,$i,$d) = @_;
+ my $ch = substr($_[0],$_[1],1);
+ $_[2] .= sprintf("\x{%02X}",ord($ch);
+ return $_[1]+1;
+ }
+
+This scheme gives maximal control to the fixup routine but is more
+complicated to code, and may require that the internals of Encode be tweaked to
+keep the original string intact.
+
+=item Other Schemes
+
+Hybrids of the above.
+
+Multiple return values rather than in-place modifications.
+
+Index into the string could be C<pos($str)> allowing C<s/\G...//>.
+
+=back
+
+=end future
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/GSM0338.pm b/Master/tlpkg/tlperl/lib/Encode/GSM0338.pm
new file mode 100644
index 00000000000..2ea71f2f77e
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/GSM0338.pm
@@ -0,0 +1,292 @@
+#
+# $Id: GSM0338.pm,v 2.1 2008/05/07 20:56:05 dankogai Exp $
+#
+package Encode::GSM0338;
+
+use strict;
+use warnings;
+use Carp;
+
+use vars qw($VERSION);
+$VERSION = do { my @r = ( q$Revision: 2.1 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+
+use Encode qw(:fallbacks);
+
+use base qw(Encode::Encoding);
+__PACKAGE__->Define('gsm0338');
+
+sub needs_lines { 1 }
+sub perlio_ok { 0 }
+
+use utf8;
+our %UNI2GSM = (
+ "\x{0040}" => "\x00", # COMMERCIAL AT
+ "\x{000A}" => "\x0A", # LINE FEED
+ "\x{000C}" => "\x1B\x0A", # FORM FEED
+ "\x{000D}" => "\x0D", # CARRIAGE RETURN
+ "\x{0020}" => "\x20", # SPACE
+ "\x{0021}" => "\x21", # EXCLAMATION MARK
+ "\x{0022}" => "\x22", # QUOTATION MARK
+ "\x{0023}" => "\x23", # NUMBER SIGN
+ "\x{0024}" => "\x02", # DOLLAR SIGN
+ "\x{0025}" => "\x25", # PERCENT SIGN
+ "\x{0026}" => "\x26", # AMPERSAND
+ "\x{0027}" => "\x27", # APOSTROPHE
+ "\x{0028}" => "\x28", # LEFT PARENTHESIS
+ "\x{0029}" => "\x29", # RIGHT PARENTHESIS
+ "\x{002A}" => "\x2A", # ASTERISK
+ "\x{002B}" => "\x2B", # PLUS SIGN
+ "\x{002C}" => "\x2C", # COMMA
+ "\x{002D}" => "\x2D", # HYPHEN-MINUS
+ "\x{002E}" => "\x2E", # FULL STOP
+ "\x{002F}" => "\x2F", # SOLIDUS
+ "\x{0030}" => "\x30", # DIGIT ZERO
+ "\x{0031}" => "\x31", # DIGIT ONE
+ "\x{0032}" => "\x32", # DIGIT TWO
+ "\x{0033}" => "\x33", # DIGIT THREE
+ "\x{0034}" => "\x34", # DIGIT FOUR
+ "\x{0035}" => "\x35", # DIGIT FIVE
+ "\x{0036}" => "\x36", # DIGIT SIX
+ "\x{0037}" => "\x37", # DIGIT SEVEN
+ "\x{0038}" => "\x38", # DIGIT EIGHT
+ "\x{0039}" => "\x39", # DIGIT NINE
+ "\x{003A}" => "\x3A", # COLON
+ "\x{003B}" => "\x3B", # SEMICOLON
+ "\x{003C}" => "\x3C", # LESS-THAN SIGN
+ "\x{003D}" => "\x3D", # EQUALS SIGN
+ "\x{003E}" => "\x3E", # GREATER-THAN SIGN
+ "\x{003F}" => "\x3F", # QUESTION MARK
+ "\x{0041}" => "\x41", # LATIN CAPITAL LETTER A
+ "\x{0042}" => "\x42", # LATIN CAPITAL LETTER B
+ "\x{0043}" => "\x43", # LATIN CAPITAL LETTER C
+ "\x{0044}" => "\x44", # LATIN CAPITAL LETTER D
+ "\x{0045}" => "\x45", # LATIN CAPITAL LETTER E
+ "\x{0046}" => "\x46", # LATIN CAPITAL LETTER F
+ "\x{0047}" => "\x47", # LATIN CAPITAL LETTER G
+ "\x{0048}" => "\x48", # LATIN CAPITAL LETTER H
+ "\x{0049}" => "\x49", # LATIN CAPITAL LETTER I
+ "\x{004A}" => "\x4A", # LATIN CAPITAL LETTER J
+ "\x{004B}" => "\x4B", # LATIN CAPITAL LETTER K
+ "\x{004C}" => "\x4C", # LATIN CAPITAL LETTER L
+ "\x{004D}" => "\x4D", # LATIN CAPITAL LETTER M
+ "\x{004E}" => "\x4E", # LATIN CAPITAL LETTER N
+ "\x{004F}" => "\x4F", # LATIN CAPITAL LETTER O
+ "\x{0050}" => "\x50", # LATIN CAPITAL LETTER P
+ "\x{0051}" => "\x51", # LATIN CAPITAL LETTER Q
+ "\x{0052}" => "\x52", # LATIN CAPITAL LETTER R
+ "\x{0053}" => "\x53", # LATIN CAPITAL LETTER S
+ "\x{0054}" => "\x54", # LATIN CAPITAL LETTER T
+ "\x{0055}" => "\x55", # LATIN CAPITAL LETTER U
+ "\x{0056}" => "\x56", # LATIN CAPITAL LETTER V
+ "\x{0057}" => "\x57", # LATIN CAPITAL LETTER W
+ "\x{0058}" => "\x58", # LATIN CAPITAL LETTER X
+ "\x{0059}" => "\x59", # LATIN CAPITAL LETTER Y
+ "\x{005A}" => "\x5A", # LATIN CAPITAL LETTER Z
+ "\x{005F}" => "\x11", # LOW LINE
+ "\x{0061}" => "\x61", # LATIN SMALL LETTER A
+ "\x{0062}" => "\x62", # LATIN SMALL LETTER B
+ "\x{0063}" => "\x63", # LATIN SMALL LETTER C
+ "\x{0064}" => "\x64", # LATIN SMALL LETTER D
+ "\x{0065}" => "\x65", # LATIN SMALL LETTER E
+ "\x{0066}" => "\x66", # LATIN SMALL LETTER F
+ "\x{0067}" => "\x67", # LATIN SMALL LETTER G
+ "\x{0068}" => "\x68", # LATIN SMALL LETTER H
+ "\x{0069}" => "\x69", # LATIN SMALL LETTER I
+ "\x{006A}" => "\x6A", # LATIN SMALL LETTER J
+ "\x{006B}" => "\x6B", # LATIN SMALL LETTER K
+ "\x{006C}" => "\x6C", # LATIN SMALL LETTER L
+ "\x{006D}" => "\x6D", # LATIN SMALL LETTER M
+ "\x{006E}" => "\x6E", # LATIN SMALL LETTER N
+ "\x{006F}" => "\x6F", # LATIN SMALL LETTER O
+ "\x{0070}" => "\x70", # LATIN SMALL LETTER P
+ "\x{0071}" => "\x71", # LATIN SMALL LETTER Q
+ "\x{0072}" => "\x72", # LATIN SMALL LETTER R
+ "\x{0073}" => "\x73", # LATIN SMALL LETTER S
+ "\x{0074}" => "\x74", # LATIN SMALL LETTER T
+ "\x{0075}" => "\x75", # LATIN SMALL LETTER U
+ "\x{0076}" => "\x76", # LATIN SMALL LETTER V
+ "\x{0077}" => "\x77", # LATIN SMALL LETTER W
+ "\x{0078}" => "\x78", # LATIN SMALL LETTER X
+ "\x{0079}" => "\x79", # LATIN SMALL LETTER Y
+ "\x{007A}" => "\x7A", # LATIN SMALL LETTER Z
+ "\x{000C}" => "\x1B\x0A", # FORM FEED
+ "\x{005B}" => "\x1B\x3C", # LEFT SQUARE BRACKET
+ "\x{005C}" => "\x1B\x2F", # REVERSE SOLIDUS
+ "\x{005D}" => "\x1B\x3E", # RIGHT SQUARE BRACKET
+ "\x{005E}" => "\x1B\x14", # CIRCUMFLEX ACCENT
+ "\x{007B}" => "\x1B\x28", # LEFT CURLY BRACKET
+ "\x{007C}" => "\x1B\x40", # VERTICAL LINE
+ "\x{007D}" => "\x1B\x29", # RIGHT CURLY BRACKET
+ "\x{007E}" => "\x1B\x3D", # TILDE
+ "\x{00A0}" => "\x1B", # NO-BREAK SPACE
+ "\x{00A1}" => "\x40", # INVERTED EXCLAMATION MARK
+ "\x{00A3}" => "\x01", # POUND SIGN
+ "\x{00A4}" => "\x24", # CURRENCY SIGN
+ "\x{00A5}" => "\x03", # YEN SIGN
+ "\x{00A7}" => "\x5F", # SECTION SIGN
+ "\x{00BF}" => "\x60", # INVERTED QUESTION MARK
+ "\x{00C4}" => "\x5B", # LATIN CAPITAL LETTER A WITH DIAERESIS
+ "\x{00C5}" => "\x0E", # LATIN CAPITAL LETTER A WITH RING ABOVE
+ "\x{00C6}" => "\x1C", # LATIN CAPITAL LETTER AE
+ "\x{00C9}" => "\x1F", # LATIN CAPITAL LETTER E WITH ACUTE
+ "\x{00D1}" => "\x5D", # LATIN CAPITAL LETTER N WITH TILDE
+ "\x{00D6}" => "\x5C", # LATIN CAPITAL LETTER O WITH DIAERESIS
+ "\x{00D8}" => "\x0B", # LATIN CAPITAL LETTER O WITH STROKE
+ "\x{00DC}" => "\x5E", # LATIN CAPITAL LETTER U WITH DIAERESIS
+ "\x{00DF}" => "\x1E", # LATIN SMALL LETTER SHARP S
+ "\x{00E0}" => "\x7F", # LATIN SMALL LETTER A WITH GRAVE
+ "\x{00E4}" => "\x7B", # LATIN SMALL LETTER A WITH DIAERESIS
+ "\x{00E5}" => "\x0F", # LATIN SMALL LETTER A WITH RING ABOVE
+ "\x{00E6}" => "\x1D", # LATIN SMALL LETTER AE
+ "\x{00E7}" => "\x09", # LATIN SMALL LETTER C WITH CEDILLA
+ "\x{00E8}" => "\x04", # LATIN SMALL LETTER E WITH GRAVE
+ "\x{00E9}" => "\x05", # LATIN SMALL LETTER E WITH ACUTE
+ "\x{00EC}" => "\x07", # LATIN SMALL LETTER I WITH GRAVE
+ "\x{00F1}" => "\x7D", # LATIN SMALL LETTER N WITH TILDE
+ "\x{00F2}" => "\x08", # LATIN SMALL LETTER O WITH GRAVE
+ "\x{00F6}" => "\x7C", # LATIN SMALL LETTER O WITH DIAERESIS
+ "\x{00F8}" => "\x0C", # LATIN SMALL LETTER O WITH STROKE
+ "\x{00F9}" => "\x06", # LATIN SMALL LETTER U WITH GRAVE
+ "\x{00FC}" => "\x7E", # LATIN SMALL LETTER U WITH DIAERESIS
+ "\x{0393}" => "\x13", # GREEK CAPITAL LETTER GAMMA
+ "\x{0394}" => "\x10", # GREEK CAPITAL LETTER DELTA
+ "\x{0398}" => "\x19", # GREEK CAPITAL LETTER THETA
+ "\x{039B}" => "\x14", # GREEK CAPITAL LETTER LAMDA
+ "\x{039E}" => "\x1A", # GREEK CAPITAL LETTER XI
+ "\x{03A0}" => "\x16", # GREEK CAPITAL LETTER PI
+ "\x{03A3}" => "\x18", # GREEK CAPITAL LETTER SIGMA
+ "\x{03A6}" => "\x12", # GREEK CAPITAL LETTER PHI
+ "\x{03A8}" => "\x17", # GREEK CAPITAL LETTER PSI
+ "\x{03A9}" => "\x15", # GREEK CAPITAL LETTER OMEGA
+ "\x{20AC}" => "\x1B\x65", # EURO SIGN
+);
+our %GSM2UNI = reverse %UNI2GSM;
+our $ESC = "\x1b";
+our $ATMARK = "\x40";
+our $FBCHAR = "\x3F";
+our $NBSP = "\x{00A0}";
+
+#define ERR_DECODE_NOMAP "%s \"\\x%02" UVXf "\" does not map to Unicode"
+
+sub decode ($$;$) {
+ my ( $obj, $bytes, $chk ) = @_;
+ my $str;
+ while ( length $bytes ) {
+ my $c = substr( $bytes, 0, 1, '' );
+ my $u;
+ if ( $c eq "\x00" ) {
+ my $c2 = substr( $bytes, 0, 1, '' );
+ $u =
+ !length $c2 ? $ATMARK
+ : $c2 eq "\x00" ? "\x{0000}"
+ : exists $GSM2UNI{$c2} ? $ATMARK . $GSM2UNI{$c2}
+ : $chk
+ ? croak sprintf( "\\x%02X\\x%02X does not map to Unicode",
+ ord($c), ord($c2) )
+ : $ATMARK . $FBCHAR;
+
+ }
+ elsif ( $c eq $ESC ) {
+ my $c2 = substr( $bytes, 0, 1, '' );
+ $u =
+ exists $GSM2UNI{ $c . $c2 } ? $GSM2UNI{ $c . $c2 }
+ : exists $GSM2UNI{$c2} ? $NBSP . $GSM2UNI{$c2}
+ : $chk
+ ? croak sprintf( "\\x%02X\\x%02X does not map to Unicode",
+ ord($c), ord($c2) )
+ : $NBSP . $FBCHAR;
+ }
+ else {
+ $u =
+ exists $GSM2UNI{$c}
+ ? $GSM2UNI{$c}
+ : $chk ? ref $chk eq 'CODE'
+ ? $chk->( ord $c )
+ : croak sprintf( "\\x%02X does not map to Unicode", ord($c) )
+ : $FBCHAR;
+ }
+ $str .= $u;
+ }
+ $_[1] = $bytes if $chk;
+ return $str;
+}
+
+#define ERR_ENCODE_NOMAP "\"\\x{%04" UVxf "}\" does not map to %s"
+
+sub encode($$;$) {
+ my ( $obj, $str, $chk ) = @_;
+ my $bytes;
+ while ( length $str ) {
+ my $u = substr( $str, 0, 1, '' );
+ my $c;
+ $bytes .=
+ exists $UNI2GSM{$u}
+ ? $UNI2GSM{$u}
+ : $chk ? ref $chk eq 'CODE'
+ ? $chk->( ord($u) )
+ : croak sprintf( "\\x{%04x} does not map to %s",
+ ord($u), $obj->name )
+ : $FBCHAR;
+ }
+ $_[1] = $str if $chk;
+ return $bytes;
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Encode::GSM0338 -- ESTI GSM 03.38 Encoding
+
+=head1 SYNOPSIS
+
+ use Encode qw/encode decode/;
+ $gsm0338 = encode("gsm0338", $utf8); # loads Encode::GSM0338 implicitly
+ $utf8 = decode("gsm0338", $gsm0338); # ditto
+
+=head1 DESCRIPTION
+
+GSM0338 is for GSM handsets. Though it shares alphanumerals with ASCII,
+control character ranges and other parts are mapped very differently,
+mainly to store Greek characters. There are also escape sequences
+(starting with 0x1B) to cover e.g. the Euro sign.
+
+This was once handled by L<Encode::Bytes> but because of all those
+unusual specifications, Encode 2.20 has relocated the support to
+this module.
+
+=head1 NOTES
+
+Unlike most other encodings, the following aways croaks on error
+for any $chk that evaluates to true.
+
+ $gsm0338 = encode("gsm0338", $utf8 $chk);
+ $utf8 = decode("gsm0338", $gsm0338, $chk);
+
+So if you want to check the validity of the encoding, surround the
+expression with C<eval {}> block as follows;
+
+ eval {
+ $utf8 = decode("gsm0338", $gsm0338, $chk);
+ };
+ if ($@){
+ # handle exception here
+ }
+
+=head1 BUGS
+
+ESTI GSM 03.38 Encoding itself.
+
+Mapping \x00 to '@' causes too much pain everywhere.
+
+Its use of \x1b (escape) is also very questionable.
+
+Because of those two, the code paging approach used use in ucm-based
+Encoding SOMETIMES fails so this module was written.
+
+=head1 SEE ALSO
+
+L<Encode>
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/Guess.pm b/Master/tlpkg/tlperl/lib/Encode/Guess.pm
new file mode 100644
index 00000000000..1ad7147e7f5
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/Guess.pm
@@ -0,0 +1,355 @@
+package Encode::Guess;
+use strict;
+use warnings;
+use Encode qw(:fallbacks find_encoding);
+our $VERSION = do { my @r = ( q$Revision: 2.3 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+
+my $Canon = 'Guess';
+sub DEBUG () { 0 }
+our %DEF_SUSPECTS = map { $_ => find_encoding($_) } qw(ascii utf8);
+$Encode::Encoding{$Canon} = bless {
+ Name => $Canon,
+ Suspects => {%DEF_SUSPECTS},
+} => __PACKAGE__;
+
+use base qw(Encode::Encoding);
+sub needs_lines { 1 }
+sub perlio_ok { 0 }
+
+our @EXPORT = qw(guess_encoding);
+our $NoUTFAutoGuess = 0;
+our $UTF8_BOM = pack( "C3", 0xef, 0xbb, 0xbf );
+
+sub import { # Exporter not used so we do it on our own
+ my $callpkg = caller;
+ for my $item (@EXPORT) {
+ no strict 'refs';
+ *{"$callpkg\::$item"} = \&{"$item"};
+ }
+ set_suspects(@_);
+}
+
+sub set_suspects {
+ my $class = shift;
+ my $self = ref($class) ? $class : $Encode::Encoding{$Canon};
+ $self->{Suspects} = {%DEF_SUSPECTS};
+ $self->add_suspects(@_);
+}
+
+sub add_suspects {
+ my $class = shift;
+ my $self = ref($class) ? $class : $Encode::Encoding{$Canon};
+ for my $c (@_) {
+ my $e = find_encoding($c) or die "Unknown encoding: $c";
+ $self->{Suspects}{ $e->name } = $e;
+ DEBUG and warn "Added: ", $e->name;
+ }
+}
+
+sub decode($$;$) {
+ my ( $obj, $octet, $chk ) = @_;
+ my $guessed = guess( $obj, $octet );
+ unless ( ref($guessed) ) {
+ require Carp;
+ Carp::croak($guessed);
+ }
+ my $utf8 = $guessed->decode( $octet, $chk );
+ $_[1] = $octet if $chk;
+ return $utf8;
+}
+
+sub guess_encoding {
+ guess( $Encode::Encoding{$Canon}, @_ );
+}
+
+sub guess {
+ my $class = shift;
+ my $obj = ref($class) ? $class : $Encode::Encoding{$Canon};
+ my $octet = shift;
+
+ # sanity check
+ return "Empty string, empty guess" unless defined $octet and length $octet;
+
+ # cheat 0: utf8 flag;
+ if ( Encode::is_utf8($octet) ) {
+ return find_encoding('utf8') unless $NoUTFAutoGuess;
+ Encode::_utf8_off($octet);
+ }
+
+ # cheat 1: BOM
+ use Encode::Unicode;
+ unless ($NoUTFAutoGuess) {
+ my $BOM = pack( 'C3', unpack( "C3", $octet ) );
+ return find_encoding('utf8')
+ if ( defined $BOM and $BOM eq $UTF8_BOM );
+ $BOM = unpack( 'N', $octet );
+ return find_encoding('UTF-32')
+ if ( defined $BOM and ( $BOM == 0xFeFF or $BOM == 0xFFFe0000 ) );
+ $BOM = unpack( 'n', $octet );
+ return find_encoding('UTF-16')
+ if ( defined $BOM and ( $BOM == 0xFeFF or $BOM == 0xFFFe ) );
+ if ( $octet =~ /\x00/o )
+ { # if \x00 found, we assume UTF-(16|32)(BE|LE)
+ my $utf;
+ my ( $be, $le ) = ( 0, 0 );
+ if ( $octet =~ /\x00\x00/o ) { # UTF-32(BE|LE) assumed
+ $utf = "UTF-32";
+ for my $char ( unpack( 'N*', $octet ) ) {
+ $char & 0x0000ffff and $be++;
+ $char & 0xffff0000 and $le++;
+ }
+ }
+ else { # UTF-16(BE|LE) assumed
+ $utf = "UTF-16";
+ for my $char ( unpack( 'n*', $octet ) ) {
+ $char & 0x00ff and $be++;
+ $char & 0xff00 and $le++;
+ }
+ }
+ DEBUG and warn "$utf, be == $be, le == $le";
+ $be == $le
+ and return
+ "Encodings ambiguous between $utf BE and LE ($be, $le)";
+ $utf .= ( $be > $le ) ? 'BE' : 'LE';
+ return find_encoding($utf);
+ }
+ }
+ my %try = %{ $obj->{Suspects} };
+ for my $c (@_) {
+ my $e = find_encoding($c) or die "Unknown encoding: $c";
+ $try{ $e->name } = $e;
+ DEBUG and warn "Added: ", $e->name;
+ }
+ my $nline = 1;
+ for my $line ( split /\r\n?|\n/, $octet ) {
+
+ # cheat 2 -- \e in the string
+ if ( $line =~ /\e/o ) {
+ my @keys = keys %try;
+ delete @try{qw/utf8 ascii/};
+ for my $k (@keys) {
+ ref( $try{$k} ) eq 'Encode::XS' and delete $try{$k};
+ }
+ }
+ my %ok = %try;
+
+ # warn join(",", keys %try);
+ for my $k ( keys %try ) {
+ my $scratch = $line;
+ $try{$k}->decode( $scratch, FB_QUIET );
+ if ( $scratch eq '' ) {
+ DEBUG and warn sprintf( "%4d:%-24s ok\n", $nline, $k );
+ }
+ else {
+ use bytes ();
+ DEBUG
+ and warn sprintf( "%4d:%-24s not ok; %d bytes left\n",
+ $nline, $k, bytes::length($scratch) );
+ delete $ok{$k};
+ }
+ }
+ %ok or return "No appropriate encodings found!";
+ if ( scalar( keys(%ok) ) == 1 ) {
+ my ($retval) = values(%ok);
+ return $retval;
+ }
+ %try = %ok;
+ $nline++;
+ }
+ $try{ascii}
+ or return "Encodings too ambiguous: ", join( " or ", keys %try );
+ return $try{ascii};
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Encode::Guess -- Guesses encoding from data
+
+=head1 SYNOPSIS
+
+ # if you are sure $data won't contain anything bogus
+
+ use Encode;
+ use Encode::Guess qw/euc-jp shiftjis 7bit-jis/;
+ my $utf8 = decode("Guess", $data);
+ my $data = encode("Guess", $utf8); # this doesn't work!
+
+ # more elaborate way
+ use Encode::Guess;
+ my $enc = guess_encoding($data, qw/euc-jp shiftjis 7bit-jis/);
+ ref($enc) or die "Can't guess: $enc"; # trap error this way
+ $utf8 = $enc->decode($data);
+ # or
+ $utf8 = decode($enc->name, $data)
+
+=head1 ABSTRACT
+
+Encode::Guess enables you to guess in what encoding a given data is
+encoded, or at least tries to.
+
+=head1 DESCRIPTION
+
+By default, it checks only ascii, utf8 and UTF-16/32 with BOM.
+
+ use Encode::Guess; # ascii/utf8/BOMed UTF
+
+To use it more practically, you have to give the names of encodings to
+check (I<suspects> as follows). The name of suspects can either be
+canonical names or aliases.
+
+CAVEAT: Unlike UTF-(16|32), BOM in utf8 is NOT AUTOMATICALLY STRIPPED.
+
+ # tries all major Japanese Encodings as well
+ use Encode::Guess qw/euc-jp shiftjis 7bit-jis/;
+
+If the C<$Encode::Guess::NoUTFAutoGuess> variable is set to a true
+value, no heuristics will be applied to UTF8/16/32, and the result
+will be limited to the suspects and C<ascii>.
+
+=over 4
+
+=item Encode::Guess->set_suspects
+
+You can also change the internal suspects list via C<set_suspects>
+method.
+
+ use Encode::Guess;
+ Encode::Guess->set_suspects(qw/euc-jp shiftjis 7bit-jis/);
+
+=item Encode::Guess->add_suspects
+
+Or you can use C<add_suspects> method. The difference is that
+C<set_suspects> flushes the current suspects list while
+C<add_suspects> adds.
+
+ use Encode::Guess;
+ Encode::Guess->add_suspects(qw/euc-jp shiftjis 7bit-jis/);
+ # now the suspects are euc-jp,shiftjis,7bit-jis, AND
+ # euc-kr,euc-cn, and big5-eten
+ Encode::Guess->add_suspects(qw/euc-kr euc-cn big5-eten/);
+
+=item Encode::decode("Guess" ...)
+
+When you are content with suspects list, you can now
+
+ my $utf8 = Encode::decode("Guess", $data);
+
+=item Encode::Guess->guess($data)
+
+But it will croak if:
+
+=over
+
+=item *
+
+Two or more suspects remain
+
+=item *
+
+No suspects left
+
+=back
+
+So you should instead try this;
+
+ my $decoder = Encode::Guess->guess($data);
+
+On success, $decoder is an object that is documented in
+L<Encode::Encoding>. So you can now do this;
+
+ my $utf8 = $decoder->decode($data);
+
+On failure, $decoder now contains an error message so the whole thing
+would be as follows;
+
+ my $decoder = Encode::Guess->guess($data);
+ die $decoder unless ref($decoder);
+ my $utf8 = $decoder->decode($data);
+
+=item guess_encoding($data, [, I<list of suspects>])
+
+You can also try C<guess_encoding> function which is exported by
+default. It takes $data to check and it also takes the list of
+suspects by option. The optional suspect list is I<not reflected> to
+the internal suspects list.
+
+ my $decoder = guess_encoding($data, qw/euc-jp euc-kr euc-cn/);
+ die $decoder unless ref($decoder);
+ my $utf8 = $decoder->decode($data);
+ # check only ascii and utf8
+ my $decoder = guess_encoding($data);
+
+=back
+
+=head1 CAVEATS
+
+=over 4
+
+=item *
+
+Because of the algorithm used, ISO-8859 series and other single-byte
+encodings do not work well unless either one of ISO-8859 is the only
+one suspect (besides ascii and utf8).
+
+ use Encode::Guess;
+ # perhaps ok
+ my $decoder = guess_encoding($data, 'latin1');
+ # definitely NOT ok
+ my $decoder = guess_encoding($data, qw/latin1 greek/);
+
+The reason is that Encode::Guess guesses encoding by trial and error.
+It first splits $data into lines and tries to decode the line for each
+suspect. It keeps it going until all but one encoding is eliminated
+out of suspects list. ISO-8859 series is just too successful for most
+cases (because it fills almost all code points in \x00-\xff).
+
+=item *
+
+Do not mix national standard encodings and the corresponding vendor
+encodings.
+
+ # a very bad idea
+ my $decoder
+ = guess_encoding($data, qw/shiftjis MacJapanese cp932/);
+
+The reason is that vendor encoding is usually a superset of national
+standard so it becomes too ambiguous for most cases.
+
+=item *
+
+On the other hand, mixing various national standard encodings
+automagically works unless $data is too short to allow for guessing.
+
+ # This is ok if $data is long enough
+ my $decoder =
+ guess_encoding($data, qw/euc-cn
+ euc-jp shiftjis 7bit-jis
+ euc-kr
+ big5-eten/);
+
+=item *
+
+DO NOT PUT TOO MANY SUSPECTS! Don't you try something like this!
+
+ my $decoder = guess_encoding($data,
+ Encode->encodings(":all"));
+
+=back
+
+It is, after all, just a guess. You should alway be explicit when it
+comes to encodings. But there are some, especially Japanese,
+environment that guess-coding is a must. Use this module with care.
+
+=head1 TO DO
+
+Encode::Guess does not work on EBCDIC platforms.
+
+=head1 SEE ALSO
+
+L<Encode>, L<Encode::Encoding>
+
+=cut
+
diff --git a/Master/tlpkg/tlperl/lib/Encode/JP.pm b/Master/tlpkg/tlperl/lib/Encode/JP.pm
new file mode 100644
index 00000000000..4251170c561
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/JP.pm
@@ -0,0 +1,95 @@
+package Encode::JP;
+BEGIN {
+ if ( ord("A") == 193 ) {
+ die "Encode::JP not supported on EBCDIC\n";
+ }
+}
+use strict;
+use warnings;
+use Encode;
+our $VERSION = do { my @r = ( q$Revision: 2.4 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+
+use XSLoader;
+XSLoader::load( __PACKAGE__, $VERSION );
+
+use Encode::JP::JIS7;
+
+1;
+__END__
+
+=head1 NAME
+
+Encode::JP - Japanese Encodings
+
+=head1 SYNOPSIS
+
+ use Encode qw/encode decode/;
+ $euc_jp = encode("euc-jp", $utf8); # loads Encode::JP implicitly
+ $utf8 = decode("euc-jp", $euc_jp); # ditto
+
+=head1 ABSTRACT
+
+This module implements Japanese charset encodings. Encodings
+supported are as follows.
+
+ Canonical Alias Description
+ --------------------------------------------------------------------
+ euc-jp /\beuc.*jp$/i EUC (Extended Unix Character)
+ /\bjp.*euc/i
+ /\bujis$/i
+ shiftjis /\bshift.*jis$/i Shift JIS (aka MS Kanji)
+ /\bsjis$/i
+ 7bit-jis /\bjis$/i 7bit JIS
+ iso-2022-jp ISO-2022-JP [RFC1468]
+ = 7bit JIS with all Halfwidth Kana
+ converted to Fullwidth
+ iso-2022-jp-1 ISO-2022-JP-1 [RFC2237]
+ = ISO-2022-JP with JIS X 0212-1990
+ support. See below
+ MacJapanese Shift JIS + Apple vendor mappings
+ cp932 /\bwindows-31j$/i Code Page 932
+ = Shift JIS + MS/IBM vendor mappings
+ jis0201-raw JIS0201, raw format
+ jis0208-raw JIS0201, raw format
+ jis0212-raw JIS0201, raw format
+ --------------------------------------------------------------------
+
+=head1 DESCRIPTION
+
+To find out how to use this module in detail, see L<Encode>.
+
+=head1 Note on ISO-2022-JP(-1)?
+
+ISO-2022-JP-1 (RFC2237) is a superset of ISO-2022-JP (RFC1468) which
+adds support for JIS X 0212-1990. That means you can use the same
+code to decode to utf8 but not vice versa.
+
+ $utf8 = decode('iso-2022-jp-1', $stream);
+
+and
+
+ $utf8 = decode('iso-2022-jp', $stream);
+
+yield the same result but
+
+ $with_0212 = encode('iso-2022-jp-1', $utf8);
+
+is now different from
+
+ $without_0212 = encode('iso-2022-jp', $utf8 );
+
+In the latter case, characters that map to 0212 are first converted
+to U+3013 (0xA2AE in EUC-JP; a white square also known as 'Tofu' or
+'geta mark') then fed to the decoding engine. U+FFFD is not used,
+in order to preserve text layout as much as possible.
+
+=head1 BUGS
+
+The ASCII region (0x00-0x7f) is preserved for all encodings, even
+though this conflicts with mappings by the Unicode Consortium.
+
+=head1 SEE ALSO
+
+L<Encode>
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/JP/H2Z.pm b/Master/tlpkg/tlperl/lib/Encode/JP/H2Z.pm
new file mode 100644
index 00000000000..f8e2230da11
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/JP/H2Z.pm
@@ -0,0 +1,176 @@
+#
+# $Id: H2Z.pm,v 2.2 2006/06/03 20:28:48 dankogai Exp $
+#
+
+package Encode::JP::H2Z;
+
+use strict;
+use warnings;
+
+our $RCSID = q$Id: H2Z.pm,v 2.2 2006/06/03 20:28:48 dankogai Exp $;
+our $VERSION = do { my @r = ( q$Revision: 2.2 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+
+use Encode::CJKConstants qw(:all);
+
+use vars qw(%_D2Z $_PAT_D2Z
+ %_Z2D $_PAT_Z2D
+ %_H2Z $_PAT_H2Z
+ %_Z2H $_PAT_Z2H);
+
+%_H2Z = (
+ "\x8e\xa1" => "\xa1\xa3", #¡£
+ "\x8e\xa2" => "\xa1\xd6", #¡Ö
+ "\x8e\xa3" => "\xa1\xd7", #¡×
+ "\x8e\xa4" => "\xa1\xa2", #¡¢
+ "\x8e\xa5" => "\xa1\xa6", #¡¦
+ "\x8e\xa6" => "\xa5\xf2", #¥ò
+ "\x8e\xa7" => "\xa5\xa1", #¥¡
+ "\x8e\xa8" => "\xa5\xa3", #¥£
+ "\x8e\xa9" => "\xa5\xa5", #¥¥
+ "\x8e\xaa" => "\xa5\xa7", #¥§
+ "\x8e\xab" => "\xa5\xa9", #¥©
+ "\x8e\xac" => "\xa5\xe3", #¥ã
+ "\x8e\xad" => "\xa5\xe5", #¥å
+ "\x8e\xae" => "\xa5\xe7", #¥ç
+ "\x8e\xaf" => "\xa5\xc3", #¥Ã
+ "\x8e\xb0" => "\xa1\xbc", #¡¼
+ "\x8e\xb1" => "\xa5\xa2", #¥¢
+ "\x8e\xb2" => "\xa5\xa4", #¥¤
+ "\x8e\xb3" => "\xa5\xa6", #¥¦
+ "\x8e\xb4" => "\xa5\xa8", #¥¨
+ "\x8e\xb5" => "\xa5\xaa", #¥ª
+ "\x8e\xb6" => "\xa5\xab", #¥«
+ "\x8e\xb7" => "\xa5\xad", #¥­
+ "\x8e\xb8" => "\xa5\xaf", #¥¯
+ "\x8e\xb9" => "\xa5\xb1", #¥±
+ "\x8e\xba" => "\xa5\xb3", #¥³
+ "\x8e\xbb" => "\xa5\xb5", #¥µ
+ "\x8e\xbc" => "\xa5\xb7", #¥·
+ "\x8e\xbd" => "\xa5\xb9", #¥¹
+ "\x8e\xbe" => "\xa5\xbb", #¥»
+ "\x8e\xbf" => "\xa5\xbd", #¥½
+ "\x8e\xc0" => "\xa5\xbf", #¥¿
+ "\x8e\xc1" => "\xa5\xc1", #¥Á
+ "\x8e\xc2" => "\xa5\xc4", #¥Ä
+ "\x8e\xc3" => "\xa5\xc6", #¥Æ
+ "\x8e\xc4" => "\xa5\xc8", #¥È
+ "\x8e\xc5" => "\xa5\xca", #¥Ê
+ "\x8e\xc6" => "\xa5\xcb", #¥Ë
+ "\x8e\xc7" => "\xa5\xcc", #¥Ì
+ "\x8e\xc8" => "\xa5\xcd", #¥Í
+ "\x8e\xc9" => "\xa5\xce", #¥Î
+ "\x8e\xca" => "\xa5\xcf", #¥Ï
+ "\x8e\xcb" => "\xa5\xd2", #¥Ò
+ "\x8e\xcc" => "\xa5\xd5", #¥Õ
+ "\x8e\xcd" => "\xa5\xd8", #¥Ø
+ "\x8e\xce" => "\xa5\xdb", #¥Û
+ "\x8e\xcf" => "\xa5\xde", #¥Þ
+ "\x8e\xd0" => "\xa5\xdf", #¥ß
+ "\x8e\xd1" => "\xa5\xe0", #¥à
+ "\x8e\xd2" => "\xa5\xe1", #¥á
+ "\x8e\xd3" => "\xa5\xe2", #¥â
+ "\x8e\xd4" => "\xa5\xe4", #¥ä
+ "\x8e\xd5" => "\xa5\xe6", #¥æ
+ "\x8e\xd6" => "\xa5\xe8", #¥è
+ "\x8e\xd7" => "\xa5\xe9", #¥é
+ "\x8e\xd8" => "\xa5\xea", #¥ê
+ "\x8e\xd9" => "\xa5\xeb", #¥ë
+ "\x8e\xda" => "\xa5\xec", #¥ì
+ "\x8e\xdb" => "\xa5\xed", #¥í
+ "\x8e\xdc" => "\xa5\xef", #¥ï
+ "\x8e\xdd" => "\xa5\xf3", #¥ó
+ "\x8e\xde" => "\xa1\xab", #¡«
+ "\x8e\xdf" => "\xa1\xac", #¡¬
+);
+
+%_D2Z = (
+ "\x8e\xb6\x8e\xde" => "\xa5\xac", #¥¬
+ "\x8e\xb7\x8e\xde" => "\xa5\xae", #¥®
+ "\x8e\xb8\x8e\xde" => "\xa5\xb0", #¥°
+ "\x8e\xb9\x8e\xde" => "\xa5\xb2", #¥²
+ "\x8e\xba\x8e\xde" => "\xa5\xb4", #¥´
+ "\x8e\xbb\x8e\xde" => "\xa5\xb6", #¥¶
+ "\x8e\xbc\x8e\xde" => "\xa5\xb8", #¥¸
+ "\x8e\xbd\x8e\xde" => "\xa5\xba", #¥º
+ "\x8e\xbe\x8e\xde" => "\xa5\xbc", #¥¼
+ "\x8e\xbf\x8e\xde" => "\xa5\xbe", #¥¾
+ "\x8e\xc0\x8e\xde" => "\xa5\xc0", #¥À
+ "\x8e\xc1\x8e\xde" => "\xa5\xc2", #¥Â
+ "\x8e\xc2\x8e\xde" => "\xa5\xc5", #¥Å
+ "\x8e\xc3\x8e\xde" => "\xa5\xc7", #¥Ç
+ "\x8e\xc4\x8e\xde" => "\xa5\xc9", #¥É
+ "\x8e\xca\x8e\xde" => "\xa5\xd0", #¥Ð
+ "\x8e\xcb\x8e\xde" => "\xa5\xd3", #¥Ó
+ "\x8e\xcc\x8e\xde" => "\xa5\xd6", #¥Ö
+ "\x8e\xcd\x8e\xde" => "\xa5\xd9", #¥Ù
+ "\x8e\xce\x8e\xde" => "\xa5\xdc", #¥Ü
+ "\x8e\xca\x8e\xdf" => "\xa5\xd1", #¥Ñ
+ "\x8e\xcb\x8e\xdf" => "\xa5\xd4", #¥Ô
+ "\x8e\xcc\x8e\xdf" => "\xa5\xd7", #¥×
+ "\x8e\xcd\x8e\xdf" => "\xa5\xda", #¥Ú
+ "\x8e\xce\x8e\xdf" => "\xa5\xdd", #¥Ý
+ "\x8e\xb3\x8e\xde" => "\xa5\xf4", #¥ô
+);
+
+# init only once;
+
+#$_PAT_D2Z = join("|", keys %_D2Z);
+#$_PAT_H2Z = join("|", keys %_H2Z);
+
+%_Z2H = reverse %_H2Z;
+%_Z2D = reverse %_D2Z;
+
+#$_PAT_Z2H = join("|", keys %_Z2H);
+#$_PAT_Z2D = join("|", keys %_Z2D);
+
+sub h2z {
+ no warnings qw(uninitialized);
+ my $r_str = shift;
+ my ($keep_dakuten) = @_;
+ my $n = 0;
+ unless ($keep_dakuten) {
+ $n = (
+ $$r_str =~ s(
+ ($RE{EUC_KANA}
+ (?:\x8e[\xde\xdf])?)
+ ){
+ my $str = $1;
+ $_D2Z{$str} || $_H2Z{$str} ||
+ # in case dakuten and handakuten are side-by-side!
+ $_H2Z{substr($str,0,2)} . $_H2Z{substr($str,2,2)};
+ }eogx
+ );
+ }
+ else {
+ $n = (
+ $$r_str =~ s(
+ ($RE{EUC_KANA})
+ ){
+ $_H2Z{$1};
+ }eogx
+ );
+ }
+ $n;
+}
+
+sub z2h {
+ my $r_str = shift;
+ my $n = (
+ $$r_str =~ s(
+ ($RE{EUC_C}|$RE{EUC_0212}|$RE{EUC_KANA})
+ ){
+ $_Z2D{$1} || $_Z2H{$1} || $1;
+ }eogx
+ );
+ $n;
+}
+
+1;
+__END__
+
+
+=head1 NAME
+
+Encode::JP::H2Z -- internally used by Encode::JP::2022_JP*
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/JP/JIS7.pm b/Master/tlpkg/tlperl/lib/Encode/JP/JIS7.pm
new file mode 100644
index 00000000000..3b5699c7fd0
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/JP/JIS7.pm
@@ -0,0 +1,165 @@
+package Encode::JP::JIS7;
+use strict;
+use warnings;
+our $VERSION = do { my @r = ( q$Revision: 2.4 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+
+use Encode qw(:fallbacks);
+
+for my $name ( '7bit-jis', 'iso-2022-jp', 'iso-2022-jp-1' ) {
+ my $h2z = ( $name eq '7bit-jis' ) ? 0 : 1;
+ my $jis0212 = ( $name eq 'iso-2022-jp' ) ? 0 : 1;
+
+ $Encode::Encoding{$name} = bless {
+ Name => $name,
+ h2z => $h2z,
+ jis0212 => $jis0212,
+ } => __PACKAGE__;
+}
+
+use base qw(Encode::Encoding);
+
+# we override this to 1 so PerlIO works
+sub needs_lines { 1 }
+
+use Encode::CJKConstants qw(:all);
+
+#
+# decode is identical for all 2022 variants
+#
+
+sub decode($$;$) {
+ my ( $obj, $str, $chk ) = @_;
+ my $residue = '';
+ if ($chk) {
+ $str =~ s/([^\x00-\x7f].*)$//so and $residue = $1;
+ }
+ $residue .= jis_euc( \$str );
+ $_[1] = $residue if $chk;
+ return Encode::decode( 'euc-jp', $str, FB_PERLQQ );
+}
+
+#
+# encode is different
+#
+
+sub encode($$;$) {
+ require Encode::JP::H2Z;
+ my ( $obj, $utf8, $chk ) = @_;
+
+ # empty the input string in the stack so perlio is ok
+ $_[1] = '' if $chk;
+ my ( $h2z, $jis0212 ) = @$obj{qw(h2z jis0212)};
+ my $octet = Encode::encode( 'euc-jp', $utf8, $chk );
+ $h2z and &Encode::JP::H2Z::h2z( \$octet );
+ euc_jis( \$octet, $jis0212 );
+ return $octet;
+}
+
+#
+# cat_decode
+#
+my $re_scan_jis_g = qr{
+ \G ( ($RE{JIS_0212}) | $RE{JIS_0208} |
+ ($RE{ISO_ASC}) | ($RE{JIS_KANA}) | )
+ ([^\e]*)
+}x;
+
+sub cat_decode { # ($obj, $dst, $src, $pos, $trm, $chk)
+ my ( $obj, undef, undef, $pos, $trm ) = @_; # currently ignores $chk
+ my ( $rdst, $rsrc, $rpos ) = \@_[ 1, 2, 3 ];
+ local ${^ENCODING};
+ use bytes;
+ my $opos = pos($$rsrc);
+ pos($$rsrc) = $pos;
+ while ( $$rsrc =~ /$re_scan_jis_g/gc ) {
+ my ( $esc, $esc_0212, $esc_asc, $esc_kana, $chunk ) =
+ ( $1, $2, $3, $4, $5 );
+
+ unless ($chunk) { $esc or last; next; }
+
+ if ( $esc && !$esc_asc ) {
+ $chunk =~ tr/\x21-\x7e/\xa1-\xfe/;
+ if ($esc_kana) {
+ $chunk =~ s/([\xa1-\xdf])/\x8e$1/og;
+ }
+ elsif ($esc_0212) {
+ $chunk =~ s/([\xa1-\xfe][\xa1-\xfe])/\x8f$1/og;
+ }
+ $chunk = Encode::decode( 'euc-jp', $chunk, 0 );
+ }
+ elsif ( ( my $npos = index( $chunk, $trm ) ) >= 0 ) {
+ $$rdst .= substr( $chunk, 0, $npos + length($trm) );
+ $$rpos += length($esc) + $npos + length($trm);
+ pos($$rsrc) = $opos;
+ return 1;
+ }
+ $$rdst .= $chunk;
+ $$rpos = pos($$rsrc);
+ }
+ $$rpos = pos($$rsrc);
+ pos($$rsrc) = $opos;
+ return '';
+}
+
+# JIS<->EUC
+my $re_scan_jis = qr{
+ (?:($RE{JIS_0212})|$RE{JIS_0208}|($RE{ISO_ASC})|($RE{JIS_KANA}))([^\e]*)
+}x;
+
+sub jis_euc {
+ local ${^ENCODING};
+ my $r_str = shift;
+ $$r_str =~ s($re_scan_jis)
+ {
+ my ($esc_0212, $esc_asc, $esc_kana, $chunk) =
+ ($1, $2, $3, $4);
+ if (!$esc_asc) {
+ $chunk =~ tr/\x21-\x7e/\xa1-\xfe/;
+ if ($esc_kana) {
+ $chunk =~ s/([\xa1-\xdf])/\x8e$1/og;
+ }
+ elsif ($esc_0212) {
+ $chunk =~ s/([\xa1-\xfe][\xa1-\xfe])/\x8f$1/og;
+ }
+ }
+ $chunk;
+ }geox;
+ my ($residue) = ( $$r_str =~ s/(\e.*)$//so );
+ return $residue;
+}
+
+sub euc_jis {
+ no warnings qw(uninitialized);
+ local ${^ENCODING};
+ my $r_str = shift;
+ my $jis0212 = shift;
+ $$r_str =~ s{
+ ((?:$RE{EUC_C})+|(?:$RE{EUC_KANA})+|(?:$RE{EUC_0212})+)
+ }{
+ my $chunk = $1;
+ my $esc =
+ ( $chunk =~ tr/\x8E//d ) ? $ESC{KANA} :
+ ( $chunk =~ tr/\x8F//d ) ? $ESC{JIS_0212} :
+ $ESC{JIS_0208};
+ if ($esc eq $ESC{JIS_0212} && !$jis0212){
+ # fallback to '?'
+ $chunk =~ tr/\xA1-\xFE/\x3F/;
+ }else{
+ $chunk =~ tr/\xA1-\xFE/\x21-\x7E/;
+ }
+ $esc . $chunk . $ESC{ASC};
+ }geox;
+ $$r_str =~ s/\Q$ESC{ASC}\E
+ (\Q$ESC{KANA}\E|\Q$ESC{JIS_0212}\E|\Q$ESC{JIS_0208}\E)/$1/gox;
+ $$r_str;
+}
+
+1;
+__END__
+
+
+=head1 NAME
+
+Encode::JP::JIS7 -- internally used by Encode::JP
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/KR.pm b/Master/tlpkg/tlperl/lib/Encode/KR.pm
new file mode 100644
index 00000000000..cf2c1174e4b
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/KR.pm
@@ -0,0 +1,69 @@
+package Encode::KR;
+BEGIN {
+ if ( ord("A") == 193 ) {
+ die "Encode::KR not supported on EBCDIC\n";
+ }
+}
+use strict;
+use warnings;
+use Encode;
+our $VERSION = do { my @r = ( q$Revision: 2.3 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+use XSLoader;
+XSLoader::load( __PACKAGE__, $VERSION );
+
+use Encode::KR::2022_KR;
+
+1;
+__END__
+
+=head1 NAME
+
+Encode::KR - Korean Encodings
+
+=head1 SYNOPSIS
+
+ use Encode qw/encode decode/;
+ $euc_kr = encode("euc-kr", $utf8); # loads Encode::KR implicitly
+ $utf8 = decode("euc-kr", $euc_kr); # ditto
+
+=head1 DESCRIPTION
+
+This module implements Korean charset encodings. Encodings supported
+are as follows.
+
+
+ Canonical Alias Description
+ --------------------------------------------------------------------
+ euc-kr /\beuc.*kr$/i EUC (Extended Unix Character)
+ /\bkr.*euc$/i
+ ksc5601-raw Korean standard code set (as is)
+ cp949 /(?:x-)?uhc$/i
+ /(?:x-)?windows-949$/i
+ /\bks_c_5601-1987$/i
+ Code Page 949 (EUC-KR + 8,822
+ (additional Hangul syllables)
+ MacKorean EUC-KR + Apple Vendor Mappings
+ johab JOHAB A supplementary encoding defined in
+ Annex 3 of KS X 1001:1998
+ iso-2022-kr iso-2022-kr [RFC1557]
+ --------------------------------------------------------------------
+
+To find how to use this module in detail, see L<Encode>.
+
+=head1 BUGS
+
+When you see C<charset=ks_c_5601-1987> on mails and web pages, they really
+mean "cp949" encodings. To fix that, the following aliases are set;
+
+ qr/(?:x-)?uhc$/i => '"cp949"'
+ qr/(?:x-)?windows-949$/i => '"cp949"'
+ qr/ks_c_5601-1987$/i => '"cp949"'
+
+The ASCII region (0x00-0x7f) is preserved for all encodings, even
+though this conflicts with mappings by the Unicode Consortium.
+
+=head1 SEE ALSO
+
+L<Encode>
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/KR/2022_KR.pm b/Master/tlpkg/tlperl/lib/Encode/KR/2022_KR.pm
new file mode 100644
index 00000000000..0218d971ee2
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/KR/2022_KR.pm
@@ -0,0 +1,81 @@
+package Encode::KR::2022_KR;
+use strict;
+use warnings;
+our $VERSION = do { my @r = ( q$Revision: 2.2 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+
+use Encode qw(:fallbacks);
+
+use base qw(Encode::Encoding);
+__PACKAGE__->Define('iso-2022-kr');
+
+sub needs_lines { 1 }
+
+sub perlio_ok {
+ return 0; # for the time being
+}
+
+sub decode {
+ my ( $obj, $str, $chk ) = @_;
+ my $res = $str;
+ my $residue = iso_euc( \$res );
+
+ # This is for PerlIO
+ $_[1] = $residue if $chk;
+ return Encode::decode( 'euc-kr', $res, FB_PERLQQ );
+}
+
+sub encode {
+ my ( $obj, $utf8, $chk ) = @_;
+
+ # empty the input string in the stack so perlio is ok
+ $_[1] = '' if $chk;
+ my $octet = Encode::encode( 'euc-kr', $utf8, FB_PERLQQ );
+ euc_iso( \$octet );
+ return $octet;
+}
+
+use Encode::CJKConstants qw(:all);
+
+# ISO<->EUC
+
+sub iso_euc {
+ my $r_str = shift;
+ $$r_str =~ s/$RE{'2022_KR'}//gox; # remove the designator
+ $$r_str =~ s{ # replace characters in GL
+ \x0e # between SO(\x0e) and SI(\x0f)
+ ([^\x0f]*) # with characters in GR
+ \x0f
+ }
+ {
+ my $out= $1;
+ $out =~ tr/\x21-\x7e/\xa1-\xfe/;
+ $out;
+ }geox;
+ my ($residue) = ( $$r_str =~ s/(\e.*)$//so );
+ return $residue;
+}
+
+sub euc_iso {
+ no warnings qw(uninitialized);
+ my $r_str = shift;
+ substr( $$r_str, 0, 0 ) =
+ $ESC{'2022_KR'}; # put the designator at the beg.
+ $$r_str =~
+ s{ # move KS X 1001 characters in GR to GL
+ ($RE{EUC_C}+) # and enclose them with SO and SI
+ }{
+ my $str = $1;
+ $str =~ tr/\xA1-\xFE/\x21-\x7E/;
+ "\x0e" . $str . "\x0f";
+ }geox;
+ $$r_str;
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Encode::KR::2022_KR -- internally used by Encode::KR
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/MIME/Header.pm b/Master/tlpkg/tlperl/lib/Encode/MIME/Header.pm
new file mode 100644
index 00000000000..9728dc32d89
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/MIME/Header.pm
@@ -0,0 +1,241 @@
+package Encode::MIME::Header;
+use strict;
+use warnings;
+no warnings 'redefine';
+
+our $VERSION = do { my @r = ( q$Revision: 2.11 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+use Encode qw(find_encoding encode_utf8 decode_utf8);
+use MIME::Base64;
+use Carp;
+
+my %seed = (
+ decode_b => '1', # decodes 'B' encoding ?
+ decode_q => '1', # decodes 'Q' encoding ?
+ encode => 'B', # encode with 'B' or 'Q' ?
+ bpl => 75, # bytes per line
+);
+
+$Encode::Encoding{'MIME-Header'} =
+ bless { %seed, Name => 'MIME-Header', } => __PACKAGE__;
+
+$Encode::Encoding{'MIME-B'} = bless {
+ %seed,
+ decode_q => 0,
+ Name => 'MIME-B',
+} => __PACKAGE__;
+
+$Encode::Encoding{'MIME-Q'} = bless {
+ %seed,
+ decode_q => 1,
+ encode => 'Q',
+ Name => 'MIME-Q',
+} => __PACKAGE__;
+
+use base qw(Encode::Encoding);
+
+sub needs_lines { 1 }
+sub perlio_ok { 0 }
+
+sub decode($$;$) {
+ use utf8;
+ my ( $obj, $str, $chk ) = @_;
+
+ # zap spaces between encoded words
+ $str =~ s/\?=\s+=\?/\?==\?/gos;
+
+ # multi-line header to single line
+ $str =~ s/(?:\r\n|[\r\n])[ \t]//gos;
+
+ 1 while ( $str =~
+ s/(=\?[-0-9A-Za-z_]+\?[Qq]\?)(.*?)\?=\1(.*?\?=)/$1$2$3/ )
+ ; # Concat consecutive QP encoded mime headers
+ # Fixes breaking inside multi-byte characters
+
+ $str =~ s{
+ =\? # begin encoded word
+ ([-0-9A-Za-z_]+) # charset (encoding)
+ (?:\*[A-Za-z]{1,8}(?:-[A-Za-z]{1,8})*)? # language (RFC 2231)
+ \?([QqBb])\? # delimiter
+ (.*?) # Base64-encodede contents
+ \?= # end encoded word
+ }{
+ if (uc($2) eq 'B'){
+ $obj->{decode_b} or croak qq(MIME "B" unsupported);
+ decode_b($1, $3, $chk);
+ } elsif (uc($2) eq 'Q'){
+ $obj->{decode_q} or croak qq(MIME "Q" unsupported);
+ decode_q($1, $3, $chk);
+ } else {
+ croak qq(MIME "$2" encoding is nonexistent!);
+ }
+ }egox;
+ $_[1] = $str if $chk;
+ return $str;
+}
+
+sub decode_b {
+ my $enc = shift;
+ my $d = find_encoding($enc) or croak qq(Unknown encoding "$enc");
+ my $db64 = decode_base64(shift);
+ my $chk = shift;
+ return $d->name eq 'utf8'
+ ? Encode::decode_utf8($db64)
+ : $d->decode( $db64, $chk || Encode::FB_PERLQQ );
+}
+
+sub decode_q {
+ my ( $enc, $q, $chk ) = @_;
+ my $d = find_encoding($enc) or croak qq(Unknown encoding "$enc");
+ $q =~ s/_/ /go;
+ $q =~ s/=([0-9A-Fa-f]{2})/pack("C", hex($1))/ego;
+ return $d->name eq 'utf8'
+ ? Encode::decode_utf8($q)
+ : $d->decode( $q, $chk || Encode::FB_PERLQQ );
+}
+
+my $especials =
+ join( '|' => map { quotemeta( chr($_) ) }
+ unpack( "C*", qq{()<>@,;:"'/[]?.=} ) );
+
+my $re_encoded_word = qr{
+ =\? # begin encoded word
+ (?:[-0-9A-Za-z_]+) # charset (encoding)
+ (?:\*[A-Za-z]{1,8}(?:-[A-Za-z]{1,8})*)? # language (RFC 2231)
+ \?(?:[QqBb])\? # delimiter
+ (?:.*?) # Base64-encodede contents
+ \?= # end encoded word
+}xo;
+
+my $re_especials = qr{$re_encoded_word|$especials}xo;
+
+sub encode($$;$) {
+ my ( $obj, $str, $chk ) = @_;
+ my @line = ();
+ for my $line ( split /\r\n|[\r\n]/o, $str ) {
+ my ( @word, @subline );
+ for my $word ( split /($re_especials)/o, $line ) {
+ if ( $word =~ /[^\x00-\x7f]/o
+ or $word =~ /^$re_encoded_word$/o )
+ {
+ push @word, $obj->_encode($word);
+ }
+ else {
+ push @word, $word;
+ }
+ }
+ my $subline = '';
+ for my $word (@word) {
+ use bytes ();
+ if ( bytes::length($subline) + bytes::length($word) >
+ $obj->{bpl} )
+ {
+ push @subline, $subline;
+ $subline = '';
+ }
+ $subline .= $word;
+ }
+ $subline and push @subline, $subline;
+ push @line, join( "\n " => @subline );
+ }
+ $_[1] = '' if $chk;
+ return join( "\n", @line );
+}
+
+use constant HEAD => '=?UTF-8?';
+use constant TAIL => '?=';
+use constant SINGLE => { B => \&_encode_b, Q => \&_encode_q, };
+
+sub _encode {
+ my ( $o, $str ) = @_;
+ my $enc = $o->{encode};
+ my $llen = ( $o->{bpl} - length(HEAD) - 2 - length(TAIL) );
+
+ # to coerce a floating-point arithmetics, the following contains
+ # .0 in numbers -- dankogai
+ $llen *= $enc eq 'B' ? 3.0 / 4.0 : 1.0 / 3.0;
+ my @result = ();
+ my $chunk = '';
+ while ( length( my $chr = substr( $str, 0, 1, '' ) ) ) {
+ use bytes ();
+ if ( bytes::length($chunk) + bytes::length($chr) > $llen ) {
+ push @result, SINGLE->{$enc}($chunk);
+ $chunk = '';
+ }
+ $chunk .= $chr;
+ }
+ length($chunk) and push @result, SINGLE->{$enc}($chunk);
+ return @result;
+}
+
+sub _encode_b {
+ HEAD . 'B?' . encode_base64( encode_utf8(shift), '' ) . TAIL;
+}
+
+sub _encode_q {
+ my $chunk = shift;
+ $chunk = encode_utf8($chunk);
+ $chunk =~ s{
+ ([^0-9A-Za-z])
+ }{
+ join("" => map {sprintf "=%02X", $_} unpack("C*", $1))
+ }egox;
+ return HEAD . 'Q?' . $chunk . TAIL;
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Encode::MIME::Header -- MIME 'B' and 'Q' header encoding
+
+=head1 SYNOPSIS
+
+ use Encode qw/encode decode/;
+ $utf8 = decode('MIME-Header', $header);
+ $header = encode('MIME-Header', $utf8);
+
+=head1 ABSTRACT
+
+This module implements RFC 2047 Mime Header Encoding. There are 3
+variant encoding names; C<MIME-Header>, C<MIME-B> and C<MIME-Q>. The
+difference is described below
+
+ decode() encode()
+ ----------------------------------------------
+ MIME-Header Both B and Q =?UTF-8?B?....?=
+ MIME-B B only; Q croaks =?UTF-8?B?....?=
+ MIME-Q Q only; B croaks =?UTF-8?Q?....?=
+
+=head1 DESCRIPTION
+
+When you decode(=?I<encoding>?I<X>?I<ENCODED WORD>?=), I<ENCODED WORD>
+is extracted and decoded for I<X> encoding (B for Base64, Q for
+Quoted-Printable). Then the decoded chunk is fed to
+decode(I<encoding>). So long as I<encoding> is supported by Encode,
+any source encoding is fine.
+
+When you encode, it just encodes UTF-8 string with I<X> encoding then
+quoted with =?UTF-8?I<X>?....?= . The parts that RFC 2047 forbids to
+encode are left as is and long lines are folded within 76 bytes per
+line.
+
+=head1 BUGS
+
+It would be nice to support encoding to non-UTF8, such as =?ISO-2022-JP?
+and =?ISO-8859-1?= but that makes the implementation too complicated.
+These days major mail agents all support =?UTF-8? so I think it is
+just good enough.
+
+Due to popular demand, 'MIME-Header-ISO_2022_JP' was introduced by
+Makamaka. Thre are still too many MUAs especially cellular phone
+handsets which does not grok UTF-8.
+
+=head1 SEE ALSO
+
+L<Encode>
+
+RFC 2047, L<http://www.faqs.org/rfcs/rfc2047.html> and many other
+locations.
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/MIME/Header/ISO_2022_JP.pm b/Master/tlpkg/tlperl/lib/Encode/MIME/Header/ISO_2022_JP.pm
new file mode 100644
index 00000000000..4abfbd05ef8
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/MIME/Header/ISO_2022_JP.pm
@@ -0,0 +1,131 @@
+package Encode::MIME::Header::ISO_2022_JP;
+
+use strict;
+use warnings;
+
+use base qw(Encode::MIME::Header);
+
+$Encode::Encoding{'MIME-Header-ISO_2022_JP'} =
+ bless { encode => 'B', bpl => 76, Name => 'MIME-Header-ISO_2022_JP' } =>
+ __PACKAGE__;
+
+use constant HEAD => '=?ISO-2022-JP?B?';
+use constant TAIL => '?=';
+
+use Encode::CJKConstants qw(%RE);
+
+our $VERSION = do { my @r = ( q$Revision: 1.3 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+
+# I owe the below codes totally to
+# Jcode by Dan Kogai & http://www.din.or.jp/~ohzaki/perl.htm#JP_Base64
+
+sub encode {
+ my $self = shift;
+ my $str = shift;
+
+ utf8::encode($str) if ( Encode::is_utf8($str) );
+ Encode::from_to( $str, 'utf8', 'euc-jp' );
+
+ my ($trailing_crlf) = ( $str =~ /(\n|\r|\x0d\x0a)$/o );
+
+ $str = _mime_unstructured_header( $str, $self->{bpl} );
+
+ not $trailing_crlf and $str =~ s/(\n|\r|\x0d\x0a)$//o;
+
+ return $str;
+}
+
+sub _mime_unstructured_header {
+ my ( $oldheader, $bpl ) = @_;
+ my $crlf = $oldheader =~ /\n$/;
+ my ( $header, @words, @wordstmp, $i ) = ('');
+
+ $oldheader =~ s/\s+$//;
+
+ @wordstmp = split /\s+/, $oldheader;
+
+ for ( $i = 0 ; $i < $#wordstmp ; $i++ ) {
+ if ( $wordstmp[$i] !~ /^[\x21-\x7E]+$/
+ and $wordstmp[ $i + 1 ] !~ /^[\x21-\x7E]+$/ )
+ {
+ $wordstmp[ $i + 1 ] = "$wordstmp[$i] $wordstmp[$i + 1]";
+ }
+ else {
+ push( @words, $wordstmp[$i] );
+ }
+ }
+
+ push( @words, $wordstmp[-1] );
+
+ for my $word (@words) {
+ if ( $word =~ /^[\x21-\x7E]+$/ ) {
+ $header =~ /(?:.*\n)*(.*)/;
+ if ( length($1) + length($word) > $bpl ) {
+ $header .= "\n $word";
+ }
+ else {
+ $header .= $word;
+ }
+ }
+ else {
+ $header = _add_encoded_word( $word, $header, $bpl );
+ }
+
+ $header =~ /(?:.*\n)*(.*)/;
+
+ if ( length($1) == $bpl ) {
+ $header .= "\n ";
+ }
+ else {
+ $header .= ' ';
+ }
+ }
+
+ $header =~ s/\n? $//mg;
+
+ $crlf ? "$header\n" : $header;
+}
+
+sub _add_encoded_word {
+ my ( $str, $line, $bpl ) = @_;
+ my $result = '';
+
+ while ( length($str) ) {
+ my $target = $str;
+ $str = '';
+
+ if (
+ length($line) + 22 +
+ ( $target =~ /^(?:$RE{EUC_0212}|$RE{EUC_C})/o ) * 8 > $bpl )
+ {
+ $line =~ s/[ \t\n\r]*$/\n/;
+ $result .= $line;
+ $line = ' ';
+ }
+
+ while (1) {
+ my $iso_2022_jp = $target;
+ Encode::from_to( $iso_2022_jp, 'euc-jp', 'iso-2022-jp' );
+
+ my $encoded =
+ HEAD . MIME::Base64::encode_base64( $iso_2022_jp, '' ) . TAIL;
+
+ if ( length($encoded) + length($line) > $bpl ) {
+ $target =~
+ s/($RE{EUC_0212}|$RE{EUC_KANA}|$RE{EUC_C}|$RE{ASCII})$//o;
+ $str = $1 . $str;
+ }
+ else {
+ $line .= $encoded;
+ last;
+ }
+ }
+
+ }
+
+ $result . $line;
+}
+
+1;
+__END__
+
diff --git a/Master/tlpkg/tlperl/lib/Encode/MIME/Name.pm b/Master/tlpkg/tlperl/lib/Encode/MIME/Name.pm
new file mode 100644
index 00000000000..10d86a746dc
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/MIME/Name.pm
@@ -0,0 +1,94 @@
+package Encode::MIME::Name;
+use strict;
+use warnings;
+our $VERSION = do { my @r = ( q$Revision: 1.1 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+
+our %MIME_NAME_OF = (
+ 'AdobeStandardEncoding' => 'Adobe-Standard-Encoding',
+ 'AdobeSymbol' => 'Adobe-Symbol-Encoding',
+ 'ascii' => 'US-ASCII',
+ 'big5-hkscs' => 'Big5-HKSCS',
+ 'cp1026' => 'IBM1026',
+ 'cp1047' => 'IBM1047',
+ 'cp1250' => 'windows-1250',
+ 'cp1251' => 'windows-1251',
+ 'cp1252' => 'windows-1252',
+ 'cp1253' => 'windows-1253',
+ 'cp1254' => 'windows-1254',
+ 'cp1255' => 'windows-1255',
+ 'cp1256' => 'windows-1256',
+ 'cp1257' => 'windows-1257',
+ 'cp1258' => 'windows-1258',
+ 'cp37' => 'IBM037',
+ 'cp424' => 'IBM424',
+ 'cp437' => 'IBM437',
+ 'cp500' => 'IBM500',
+ 'cp775' => 'IBM775',
+ 'cp850' => 'IBM850',
+ 'cp852' => 'IBM852',
+ 'cp855' => 'IBM855',
+ 'cp857' => 'IBM857',
+ 'cp860' => 'IBM860',
+ 'cp861' => 'IBM861',
+ 'cp862' => 'IBM862',
+ 'cp863' => 'IBM863',
+ 'cp864' => 'IBM864',
+ 'cp865' => 'IBM865',
+ 'cp866' => 'IBM866',
+ 'cp869' => 'IBM869',
+ 'cp936' => 'GBK',
+ 'euc-jp' => 'EUC-JP',
+ 'euc-kr' => 'EUC-KR',
+ #'gb2312-raw' => 'GB2312', # no, you're wrong, I18N::Charset
+ 'hp-roman8' => 'hp-roman8',
+ 'hz' => 'HZ-GB-2312',
+ 'iso-2022-jp' => 'ISO-2022-JP',
+ 'iso-2022-jp-1' => 'ISO-2022-JP',
+ 'iso-2022-kr' => 'ISO-2022-KR',
+ 'iso-8859-1' => 'ISO-8859-1',
+ 'iso-8859-10' => 'ISO-8859-10',
+ 'iso-8859-13' => 'ISO-8859-13',
+ 'iso-8859-14' => 'ISO-8859-14',
+ 'iso-8859-15' => 'ISO-8859-15',
+ 'iso-8859-16' => 'ISO-8859-16',
+ 'iso-8859-2' => 'ISO-8859-2',
+ 'iso-8859-3' => 'ISO-8859-3',
+ 'iso-8859-4' => 'ISO-8859-4',
+ 'iso-8859-5' => 'ISO-8859-5',
+ 'iso-8859-6' => 'ISO-8859-6',
+ 'iso-8859-7' => 'ISO-8859-7',
+ 'iso-8859-8' => 'ISO-8859-8',
+ 'iso-8859-9' => 'ISO-8859-9',
+ #'jis0201-raw' => 'JIS_X0201',
+ #'jis0208-raw' => 'JIS_C6226-1983',
+ #'jis0212-raw' => 'JIS_X0212-1990',
+ 'koi8-r' => 'KOI8-R',
+ 'koi8-u' => 'KOI8-U',
+ #'ksc5601-raw' => 'KS_C_5601-1987',
+ 'shiftjis' => 'Shift_JIS',
+ 'UTF-16' => 'UTF-16',
+ 'UTF-16BE' => 'UTF-16BE',
+ 'UTF-16LE' => 'UTF-16LE',
+ 'UTF-32' => 'UTF-32',
+ 'UTF-32BE' => 'UTF-32BE',
+ 'UTF-32LE' => 'UTF-32LE',
+ 'UTF-7' => 'UTF-7',
+ 'utf8' => 'UTF-8',
+ 'utf-8-strict' => 'UTF-8',
+ 'viscii' => 'VISCII',
+);
+
+sub get_mime_name($) { $MIME_NAME_OF{$_[0]} };
+
+1;
+__END__
+
+=head1 NAME
+
+Encode::MIME::NAME -- internally used by Encode
+
+=head1 SEE ALSO
+
+L<I18N::Charset>
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/Makefile_PL.e2x b/Master/tlpkg/tlperl/lib/Encode/Makefile_PL.e2x
new file mode 100644
index 00000000000..1d83a2fbda2
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/Makefile_PL.e2x
@@ -0,0 +1,180 @@
+#
+# This file is auto-generated by:
+# enc2xs version $_Version_
+# $_Now_
+#
+use 5.7.2;
+use strict;
+use ExtUtils::MakeMaker;
+use Config;
+
+# Please edit the following to the taste!
+my $name = '$_Name_';
+my %tables = (
+ $_Name__t => [ $_TableFiles_ ],
+ );
+
+#### DO NOT EDIT BEYOND THIS POINT!
+require File::Spec;
+my ($enc2xs, $encode_h) = ();
+PATHLOOP:
+for my $d (@Config{qw/bin sitebin vendorbin/},
+ (split /$Config{path_sep}/o, $ENV{PATH})){
+ for my $f (qw/enc2xs enc2xs5.7.3/){
+ my $path = File::Spec->catfile($d, $f);
+ -r $path and $enc2xs = $path and last PATHLOOP;
+ }
+}
+$enc2xs or die "enc2xs not found!";
+print "enc2xs is $enc2xs\n";
+my %encode_h = ();
+for my $d (@INC){
+ my $dir = File::Spec->catfile($d, "Encode");
+ my $file = File::Spec->catfile($dir, "encode.h");
+ -f $file and $encode_h{$dir} = -M $file;
+}
+%encode_h or die "encode.h not found!";
+# find the latest one
+($encode_h) = sort {$encode_h{$b} <=> $encode_h{$a}} keys %encode_h;
+print "encode.h is at $encode_h\n";
+
+WriteMakefile(
+ INC => "-I$encode_h",
+#### END_OF_HEADER -- DO NOT EDIT THIS LINE BY HAND! ####
+ NAME => 'Encode::'.$name,
+ VERSION_FROM => "$name.pm",
+ OBJECT => '$(O_FILES)',
+ 'dist' => {
+ COMPRESS => 'gzip -9f',
+ SUFFIX => 'gz',
+ DIST_DEFAULT => 'all tardist',
+ },
+ MAN3PODS => {},
+ PREREQ_PM => {
+ 'Encode' => "1.41",
+ },
+ # OS 390 winges about line numbers > 64K ???
+ XSOPT => '-nolinenumbers',
+ );
+
+package MY;
+
+sub post_initialize
+{
+ my ($self) = @_;
+ my %o;
+ my $x = $self->{'OBJ_EXT'};
+ # Add the table O_FILES
+ foreach my $e (keys %tables)
+ {
+ $o{$e.$x} = 1;
+ }
+ $o{"$name$x"} = 1;
+ $self->{'O_FILES'} = [sort keys %o];
+ my @files = ("$name.xs");
+ $self->{'C'} = ["$name.c"];
+ # The next two lines to make MacPerl Happy -- dankogai via pudge
+ $self->{SOURCE} .= " $name.c"
+ if $^O eq 'MacOS' && $self->{SOURCE} !~ /\b$name\.c\b/;
+ # $self->{'H'} = [$self->catfile($self->updir,'encode.h')];
+ my %xs;
+ foreach my $table (keys %tables) {
+ push (@{$self->{'C'}},"$table.c");
+ # Do NOT add $table.h etc. to H_FILES unless we own up as to how they
+ # get built.
+ foreach my $ext (qw($(OBJ_EXT) .c .h .exh .fnm)) {
+ push (@files,$table.$ext);
+ }
+ }
+ $self->{'XS'} = { "$name.xs" => "$name.c" };
+ $self->{'clean'}{'FILES'} .= join(' ',@files);
+ open(XS,">$name.xs") || die "Cannot open $name.xs:$!";
+ print XS <<'END';
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+#define U8 U8
+#include "encode.h"
+END
+ foreach my $table (keys %tables) {
+ print XS qq[#include "${table}.h"\n];
+ }
+ print XS <<"END";
+
+static void
+Encode_XSEncoding(pTHX_ encode_t *enc)
+{
+ dSP;
+ HV *stash = gv_stashpv("Encode::XS", TRUE);
+ SV *sv = sv_bless(newRV_noinc(newSViv(PTR2IV(enc))),stash);
+ int i = 0;
+ PUSHMARK(sp);
+ XPUSHs(sv);
+ while (enc->name[i])
+ {
+ const char *name = enc->name[i++];
+ XPUSHs(sv_2mortal(newSVpvn(name,strlen(name))));
+ }
+ PUTBACK;
+ call_pv("Encode::define_encoding",G_DISCARD);
+ SvREFCNT_dec(sv);
+}
+
+MODULE = Encode::$name PACKAGE = Encode::$name
+PROTOTYPES: DISABLE
+BOOT:
+{
+END
+ foreach my $table (keys %tables) {
+ print XS qq[#include "${table}.exh"\n];
+ }
+ print XS "}\n";
+ close(XS);
+ return "# Built $name.xs\n\n";
+}
+
+sub postamble
+{
+ my $self = shift;
+ my $dir = "."; # $self->catdir('Encode');
+ my $str = "# $name\$(OBJ_EXT) depends on .h and .exh files not .c files - but all written by enc2xs\n";
+ $str .= "$name.c : $name.xs ";
+ foreach my $table (keys %tables)
+ {
+ $str .= " $table.c";
+ }
+ $str .= "\n\n";
+ $str .= "$name\$(OBJ_EXT) : $name.c\n\n";
+
+ foreach my $table (keys %tables)
+ {
+ my $numlines = 1;
+ my $lengthsofar = length($str);
+ my $continuator = '';
+ $str .= "$table.c : Makefile.PL";
+ foreach my $file (@{$tables{$table}})
+ {
+ $str .= $continuator.' '.$self->catfile($dir,$file);
+ if ( length($str)-$lengthsofar > 128*$numlines )
+ {
+ $continuator .= " \\\n\t";
+ $numlines++;
+ } else {
+ $continuator = '';
+ }
+ }
+ my $plib = $self->{PERL_CORE} ? '"-I$(PERL_LIB)"' : '';
+ my $ucopts = '-"Q"';
+ $str .=
+ qq{\n\t\$(PERL) $plib $enc2xs $ucopts -o \$\@ -f $table.fnm\n\n};
+ open (FILELIST, ">$table.fnm")
+ || die "Could not open $table.fnm: $!";
+ foreach my $file (@{$tables{$table}})
+ {
+ print FILELIST $self->catfile($dir,$file) . "\n";
+ }
+ close(FILELIST);
+ }
+ return $str;
+}
+
diff --git a/Master/tlpkg/tlperl/lib/Encode/PerlIO.pod b/Master/tlpkg/tlperl/lib/Encode/PerlIO.pod
new file mode 100644
index 00000000000..1a9269a9b0c
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/PerlIO.pod
@@ -0,0 +1,167 @@
+=head1 NAME
+
+Encode::PerlIO -- a detailed document on Encode and PerlIO
+
+=head1 Overview
+
+It is very common to want to do encoding transformations when
+reading or writing files, network connections, pipes etc.
+If Perl is configured to use the new 'perlio' IO system then
+C<Encode> provides a "layer" (see L<PerlIO>) which can transform
+data as it is read or written.
+
+Here is how the blind poet would modernise the encoding:
+
+ use Encode;
+ open(my $iliad,'<:encoding(iso-8859-7)','iliad.greek');
+ open(my $utf8,'>:utf8','iliad.utf8');
+ my @epic = <$iliad>;
+ print $utf8 @epic;
+ close($utf8);
+ close($illiad);
+
+In addition, the new IO system can also be configured to read/write
+UTF-8 encoded characters (as noted above, this is efficient):
+
+ open(my $fh,'>:utf8','anything');
+ print $fh "Any \x{0021} string \N{SMILEY FACE}\n";
+
+Either of the above forms of "layer" specifications can be made the default
+for a lexical scope with the C<use open ...> pragma. See L<open>.
+
+Once a handle is open, its layers can be altered using C<binmode>.
+
+Without any such configuration, or if Perl itself is built using the
+system's own IO, then write operations assume that the file handle
+accepts only I<bytes> and will C<die> if a character larger than 255 is
+written to the handle. When reading, each octet from the handle becomes
+a byte-in-a-character. Note that this default is the same behaviour
+as bytes-only languages (including Perl before v5.6) would have,
+and is sufficient to handle native 8-bit encodings e.g. iso-8859-1,
+EBCDIC etc. and any legacy mechanisms for handling other encodings
+and binary data.
+
+In other cases, it is the program's responsibility to transform
+characters into bytes using the API above before doing writes, and to
+transform the bytes read from a handle into characters before doing
+"character operations" (e.g. C<lc>, C</\W+/>, ...).
+
+You can also use PerlIO to convert larger amounts of data you don't
+want to bring into memory. For example, to convert between ISO-8859-1
+(Latin 1) and UTF-8 (or UTF-EBCDIC in EBCDIC machines):
+
+ open(F, "<:encoding(iso-8859-1)", "data.txt") or die $!;
+ open(G, ">:utf8", "data.utf") or die $!;
+ while (<F>) { print G }
+
+ # Could also do "print G <F>" but that would pull
+ # the whole file into memory just to write it out again.
+
+More examples:
+
+ open(my $f, "<:encoding(cp1252)")
+ open(my $g, ">:encoding(iso-8859-2)")
+ open(my $h, ">:encoding(latin9)") # iso-8859-15
+
+See also L<encoding> for how to change the default encoding of the
+data in your script.
+
+=head1 How does it work?
+
+Here is a crude diagram of how filehandle, PerlIO, and Encode
+interact.
+
+ filehandle <-> PerlIO PerlIO <-> scalar (read/printed)
+ \ /
+ Encode
+
+When PerlIO receives data from either direction, it fills a buffer
+(currently with 1024 bytes) and passes the buffer to Encode.
+Encode tries to convert the valid part and passes it back to PerlIO,
+leaving invalid parts (usually a partial character) in the buffer.
+PerlIO then appends more data to the buffer, calls Encode again,
+and so on until the data stream ends.
+
+To do so, PerlIO always calls (de|en)code methods with CHECK set to 1.
+This ensures that the method stops at the right place when it
+encounters partial character. The following is what happens when
+PerlIO and Encode tries to encode (from utf8) more than 1024 bytes
+and the buffer boundary happens to be in the middle of a character.
+
+ A B C .... ~ \x{3000} ....
+ 41 42 43 .... 7E e3 80 80 ....
+ <- buffer --------------->
+ << encoded >>>>>>>>>>
+ <- next buffer ------
+
+Encode converts from the beginning to \x7E, leaving \xe3 in the buffer
+because it is invalid (partial character).
+
+Unfortunately, this scheme does not work well with escape-based
+encodings such as ISO-2022-JP.
+
+=head1 Line Buffering
+
+Now let's see what happens when you try to decode from ISO-2022-JP and
+the buffer ends in the middle of a character.
+
+ JIS208-ESC \x{5f3e}
+ A B C .... ~ \e $ B |DAN | ....
+ 41 42 43 .... 7E 1b 24 41 43 46 ....
+ <- buffer --------------------------->
+ << encoded >>>>>>>>>>>>>>>>>>>>>>>
+
+As you see, the next buffer begins with \x43. But \x43 is 'C' in
+ASCII, which is wrong in this case because we are now in JISX 0208
+area so it has to convert \x43\x46, not \x43. Unlike utf8 and EUC,
+in escape-based encodings you can't tell if a given octet is a whole
+character or just part of it.
+
+Fortunately PerlIO also supports line buffer if you tell PerlIO to use
+one instead of fixed buffer. Since ISO-2022-JP is guaranteed to revert to ASCII at the end of the line, partial
+character will never happen when line buffer is used.
+
+To tell PerlIO to use line buffer, implement -E<gt>needs_lines method
+for your encoding object. See L<Encode::Encoding> for details.
+
+Thanks to these efforts most encodings that come with Encode support
+PerlIO but that still leaves following encodings.
+
+ iso-2022-kr
+ MIME-B
+ MIME-Header
+ MIME-Q
+
+Fortunately iso-2022-kr is hardly used (according to Jungshik) and
+MIME-* are very unlikely to be fed to PerlIO because they are for mail
+headers. See L<Encode::MIME::Header> for details.
+
+=head2 How can I tell whether my encoding fully supports PerlIO ?
+
+As of this writing, any encoding whose class belongs to Encode::XS and
+Encode::Unicode works. The Encode module has a C<perlio_ok> method
+which you can use before applying PerlIO encoding to the filehandle.
+Here is an example:
+
+ my $use_perlio = perlio_ok($enc);
+ my $layer = $use_perlio ? "<:raw" : "<:encoding($enc)";
+ open my $fh, $layer, $file or die "$file : $!";
+ while(<$fh>){
+ $_ = decode($enc, $_) unless $use_perlio;
+ # ....
+ }
+
+=head1 SEE ALSO
+
+L<Encode::Encoding>,
+L<Encode::Supported>,
+L<Encode::PerlIO>,
+L<encoding>,
+L<perlebcdic>,
+L<perlfunc/open>,
+L<perlunicode>,
+L<utf8>,
+the Perl Unicode Mailing List E<lt>perl-unicode@perl.orgE<gt>
+
+=cut
+
diff --git a/Master/tlpkg/tlperl/lib/Encode/README.e2x b/Master/tlpkg/tlperl/lib/Encode/README.e2x
new file mode 100644
index 00000000000..28a31a655c2
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/README.e2x
@@ -0,0 +1,31 @@
+Encode::$_Name_ version 0.1
+========
+
+NAME
+ Encode::$_Name_ - <describe encoding>
+
+SYNOPSIS
+ use Encode::$_Name_;
+ #<put more words here>
+ABSTRACT
+ <fill this in>
+INSTALLATION
+
+To install this module type the following:
+
+ perl Makefile.PL
+ make
+ make test
+ make install
+
+DEPENDENCIES
+
+This module requires perl version 5.7.3 or later.
+
+COPYRIGHT AND LICENCE
+
+Copyright (C) 2002 Your Name <your@address.domain>
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
diff --git a/Master/tlpkg/tlperl/lib/Encode/Supported.pod b/Master/tlpkg/tlperl/lib/Encode/Supported.pod
new file mode 100644
index 00000000000..e84faafd9e2
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/Supported.pod
@@ -0,0 +1,901 @@
+=head1 NAME
+
+Encode::Supported -- Encodings supported by Encode
+
+=head1 DESCRIPTION
+
+=head2 Encoding Names
+
+Encoding names are case insensitive. White space in names
+is ignored. In addition, an encoding may have aliases.
+Each encoding has one "canonical" name. The "canonical"
+name is chosen from the names of the encoding by picking
+the first in the following sequence (with a few exceptions).
+
+=over 2
+
+=item *
+
+The name used by the Perl community. That includes 'utf8' and 'ascii'.
+Unlike aliases, canonical names directly reach the method so such
+frequently used words like 'utf8' don't need to do alias lookups.
+
+=item *
+
+The MIME name as defined in IETF RFCs. This includes all "iso-"s.
+
+=item *
+
+The name in the IANA registry.
+
+=item *
+
+The name used by the organization that defined it.
+
+=back
+
+In case I<de jure> canonical names differ from that of the Encode
+module, they are always aliased if it ever be implemented. So you can
+safely tell if a given encoding is implemented or not just by passing
+the canonical name.
+
+Because of all the alias issues, and because in the general case
+encodings have state, "Encode" uses an encoding object internally
+once an operation is in progress.
+
+=head1 Supported Encodings
+
+As of Perl 5.8.0, at least the following encodings are recognized.
+Note that unless otherwise specified, they are all case insensitive
+(via alias) and all occurrence of spaces are replaced with '-'.
+In other words, "ISO 8859 1" and "iso-8859-1" are identical.
+
+Encodings are categorized and implemented in several different modules
+but you don't have to C<use Encode::XX> to make them available for
+most cases. Encode.pm will automatically load those modules on demand.
+
+=head2 Built-in Encodings
+
+The following encodings are always available.
+
+ Canonical Aliases Comments & References
+ ----------------------------------------------------------------
+ ascii US-ascii ISO-646-US [ECMA]
+ ascii-ctrl Special Encoding
+ iso-8859-1 latin1 [ISO]
+ null Special Encoding
+ utf8 UTF-8 [RFC2279]
+ ----------------------------------------------------------------
+
+I<null> and I<ascii-ctrl> are special. "null" fails for all character
+so when you set fallback mode to PERLQQ, HTMLCREF or XMLCREF, ALL
+CHARACTERS will fall back to character references. Ditto for
+"ascii-ctrl" except for control characters. For fallback modes, see
+L<Encode>.
+
+=head2 Encode::Unicode -- other Unicode encodings
+
+Unicode coding schemes other than native utf8 are supported by
+Encode::Unicode, which will be autoloaded on demand.
+
+ ----------------------------------------------------------------
+ UCS-2BE UCS-2, iso-10646-1 [IANA, UC]
+ UCS-2LE [UC]
+ UTF-16 [UC]
+ UTF-16BE [UC]
+ UTF-16LE [UC]
+ UTF-32 [UC]
+ UTF-32BE UCS-4 [UC]
+ UTF-32LE [UC]
+ UTF-7 [RFC2152]
+ ----------------------------------------------------------------
+
+To find how (UCS-2|UTF-(16|32))(LE|BE)? differ from one another,
+see L<Encode::Unicode>.
+
+UTF-7 is a special encoding which "re-encodes" UTF-16BE into a 7-bit
+encoding. It is implemented seperately by Encode::Unicode::UTF7.
+
+=head2 Encode::Byte -- Extended ASCII
+
+Encode::Byte implements most single-byte encodings except for
+Symbols and EBCDIC. The following encodings are based on single-byte
+encodings implemented as extended ASCII. Most of them map
+\x80-\xff (upper half) to non-ASCII characters.
+
+=over 2
+
+=item ISO-8859 and corresponding vendor mappings
+
+Since there are so many, they are presented in table format with
+languages and corresponding encoding names by vendors. Note that
+the table is sorted in order of ISO-8859 and the corresponding vendor
+mappings are slightly different from that of ISO. See
+L<http://czyborra.com/charsets/iso8859.html> for details.
+
+ Lang/Regions ISO/Other Std. DOS Windows Macintosh Others
+ ----------------------------------------------------------------
+ N. America (ASCII) cp437 AdobeStandardEncoding
+ cp863 (DOSCanadaF)
+ W. Europe iso-8859-1 cp850 cp1252 MacRoman nextstep
+ hp-roman8
+ cp860 (DOSPortuguese)
+ Cntrl. Europe iso-8859-2 cp852 cp1250 MacCentralEurRoman
+ MacCroatian
+ MacRomanian
+ MacRumanian
+ Latin3[1] iso-8859-3
+ Latin4[2] iso-8859-4
+ Cyrillics iso-8859-5 cp855 cp1251 MacCyrillic
+ (See also next section) cp866 MacUkrainian
+ Arabic iso-8859-6 cp864 cp1256 MacArabic
+ cp1006 MacFarsi
+ Greek iso-8859-7 cp737 cp1253 MacGreek
+ cp869 (DOSGreek2)
+ Hebrew iso-8859-8 cp862 cp1255 MacHebrew
+ Turkish iso-8859-9 cp857 cp1254 MacTurkish
+ Nordics iso-8859-10 cp865
+ cp861 MacIcelandic
+ MacSami
+ Thai iso-8859-11[3] cp874 MacThai
+ (iso-8859-12 is nonexistent. Reserved for Indics?)
+ Baltics iso-8859-13 cp775 cp1257
+ Celtics iso-8859-14
+ Latin9 [4] iso-8859-15
+ Latin10 iso-8859-16
+ Vietnamese viscii cp1258 MacVietnamese
+ ----------------------------------------------------------------
+
+ [1] Esperanto, Maltese, and Turkish. Turkish is now on 8859-9.
+ [2] Baltics. Now on 8859-10, except for Latvian.
+ [3] TIS 620 + Non-Breaking Space (0xA0 / U+00A0)
+ [4] Nicknamed Latin0; the Euro sign as well as French and Finnish
+ letters that are missing from 8859-1 were added.
+
+All cp* are also available as ibm-*, ms-*, and windows-* . See also
+L<http://czyborra.com/charsets/codepages.html>.
+
+Macintosh encodings don't seem to be registered in such entities as
+IANA. "Canonical" names in Encode are based upon Apple's Tech Note
+1150. See L<http://developer.apple.com/technotes/tn/tn1150.html>
+for details.
+
+=item KOI8 - De Facto Standard for the Cyrillic world
+
+Though ISO-8859 does have ISO-8859-5, the KOI8 series is far more
+popular in the Net. L<Encode> comes with the following KOI charsets.
+For gory details, see L<http://czyborra.com/charsets/cyrillic.html>
+
+ ----------------------------------------------------------------
+ koi8-f
+ koi8-r cp878 [RFC1489]
+ koi8-u [RFC2319]
+ ----------------------------------------------------------------
+
+=back
+
+=head2 gsm0338 - Hentai Latin 1
+
+GSM0338 is for GSM handsets. Though it shares alphanumerals with
+ASCII, control character ranges and other parts are mapped very
+differently, mainly to store Greek characters. There are also escape
+sequences (starting with 0x1B) to cover e.g. the Euro sign.
+
+This was once handled by L<Encode::Bytes> but because of all those
+unusual specifications, Encode 2.20 has relocated the support to
+L<Encode::GSM0338>. See L<Encode::GSM0338> for details.
+
+=over 2
+
+=item gsm0338 support before 2.19
+
+Some special cases like a trailing 0x00 byte or a lone 0x1B byte are not
+well-defined and decode() will return an empty string for them.
+One possible workaround is
+
+ $gsm =~ s/\x00\z/\x00\x00/;
+ $uni = decode("gsm0338", $gsm);
+ $uni .= "\xA0" if $gsm =~ /\x1B\z/;
+
+Note that the Encode implementation of GSM0338 does not implement the
+reuse of Latin capital letters as Greek capital letters (for example,
+the 0x5A is U+005A (LATIN CAPITAL LETTER Z), not U+0396 (GREEK CAPITAL
+LETTER ZETA).
+
+The GSM0338 is also covered in Encode::Byte even though it is not
+an "extended ASCII" encoding.
+
+=back
+
+=head2 CJK: Chinese, Japanese, Korean (Multibyte)
+
+Note that Vietnamese is listed above. Also read "Encoding vs Charset"
+below. Also note that these are implemented in distinct modules by
+countries, due to the size concerns (simplified Chinese is mapped
+to 'CN', continental China, while traditional Chinese is mapped to
+'TW', Taiwan). Please refer to their respective documentation pages.
+
+=over 2
+
+=item Encode::CN -- Continental China
+
+ Standard DOS/Win Macintosh Comment/Reference
+ ----------------------------------------------------------------
+ euc-cn [1] MacChineseSimp
+ (gbk) cp936 [2]
+ gb12345-raw { GB12345 without CES }
+ gb2312-raw { GB2312 without CES }
+ hz
+ iso-ir-165
+ ----------------------------------------------------------------
+
+ [1] GB2312 is aliased to this. See L<Microsoft-related naming mess>
+ [2] gbk is aliased to this. See L<Microsoft-related naming mess>
+
+=item Encode::JP -- Japan
+
+ Standard DOS/Win Macintosh Comment/Reference
+ ----------------------------------------------------------------
+ euc-jp
+ shiftjis cp932 macJapanese
+ 7bit-jis
+ iso-2022-jp [RFC1468]
+ iso-2022-jp-1 [RFC2237]
+ jis0201-raw { JIS X 0201 (roman + halfwidth kana) without CES }
+ jis0208-raw { JIS X 0208 (Kanji + fullwidth kana) without CES }
+ jis0212-raw { JIS X 0212 (Extended Kanji) without CES }
+ ----------------------------------------------------------------
+
+=item Encode::KR -- Korea
+
+ Standard DOS/Win Macintosh Comment/Reference
+ ----------------------------------------------------------------
+ euc-kr MacKorean [RFC1557]
+ cp949 [1]
+ iso-2022-kr [RFC1557]
+ johab [KS X 1001:1998, Annex 3]
+ ksc5601-raw { KSC5601 without CES }
+ ----------------------------------------------------------------
+
+ [1] ks_c_5601-1987, (x-)?windows-949, and uhc are aliased to this.
+ See below.
+
+=item Encode::TW -- Taiwan
+
+ Standard DOS/Win Macintosh Comment/Reference
+ ----------------------------------------------------------------
+ big5-eten cp950 MacChineseTrad {big5 aliased to big5-eten}
+ big5-hkscs
+ ----------------------------------------------------------------
+
+=item Encode::HanExtra -- More Chinese via CPAN
+
+Due to the size concerns, additional Chinese encodings below are
+distributed separately on CPAN, under the name Encode::HanExtra.
+
+ Standard DOS/Win Macintosh Comment/Reference
+ ----------------------------------------------------------------
+ big5ext CMEX's Big5e Extension
+ big5plus CMEX's Big5+ Extension
+ cccii Chinese Character Code for Information Interchange
+ euc-tw EUC (Extended Unix Character)
+ gb18030 GBK with Traditional Characters
+ ----------------------------------------------------------------
+
+=item Encode::JIS2K -- JIS X 0213 encodings via CPAN
+
+Due to size concerns, additional Japanese encodings below are
+distributed separately on CPAN, under the name Encode::JIS2K.
+
+ Standard DOS/Win Macintosh Comment/Reference
+ ----------------------------------------------------------------
+ euc-jisx0213
+ shiftjisx0123
+ iso-2022-jp-3
+ jis0213-1-raw
+ jis0213-2-raw
+ ----------------------------------------------------------------
+
+=back
+
+=head2 Miscellaneous encodings
+
+=over 2
+
+=item Encode::EBCDIC
+
+See L<perlebcdic> for details.
+
+ ----------------------------------------------------------------
+ cp37
+ cp500
+ cp875
+ cp1026
+ cp1047
+ posix-bc
+ ----------------------------------------------------------------
+
+=item Encode::Symbols
+
+For symbols and dingbats.
+
+ ----------------------------------------------------------------
+ symbol
+ dingbats
+ MacDingbats
+ AdobeZdingbat
+ AdobeSymbol
+ ----------------------------------------------------------------
+
+=item Encode::MIME::Header
+
+Strictly speaking, MIME header encoding documented in RFC 2047 is more
+of encapsulation than encoding. However, their support in modern
+world is imperative so they are supported.
+
+ ----------------------------------------------------------------
+ MIME-Header [RFC2047]
+ MIME-B [RFC2047]
+ MIME-Q [RFC2047]
+ ----------------------------------------------------------------
+
+=item Encode::Guess
+
+This one is not a name of encoding but a utility that lets you pick up
+the most appropriate encoding for a data out of given I<suspects>. See
+L<Encode::Guess> for details.
+
+=back
+
+=head1 Unsupported encodings
+
+The following encodings are not supported as yet; some because they
+are rarely used, some because of technical difficulties. They may
+be supported by external modules via CPAN in the future, however.
+
+=over 2
+
+=item ISO-2022-JP-2 [RFC1554]
+
+Not very popular yet. Needs Unicode Database or equivalent to
+implement encode() (because it includes JIS X 0208/0212, KSC5601, and
+GB2312 simultaneously, whose code points in Unicode overlap. So you
+need to lookup the database to determine to what character set a given
+Unicode character should belong).
+
+=item ISO-2022-CN [RFC1922]
+
+Not very popular. Needs CNS 11643-1 and -2 which are not available in
+this module. CNS 11643 is supported (via euc-tw) in Encode::HanExtra.
+Autrijus Tang may add support for this encoding in his module in future.
+
+=item Various HP-UX encodings
+
+The following are unsupported due to the lack of mapping data.
+
+ '8' - arabic8, greek8, hebrew8, kana8, thai8, and turkish8
+ '15' - japanese15, korean15, and roi15
+
+=item Cyrillic encoding ISO-IR-111
+
+Anton Tagunov doubts its usefulness.
+
+=item ISO-8859-8-1 [Hebrew]
+
+None of the Encode team knows Hebrew enough (ISO-8859-8, cp1255 and
+MacHebrew are supported because and just because there were mappings
+available at L<http://www.unicode.org/>). Contributions welcome.
+
+=item ISIRI 3342, Iran System, ISIRI 2900 [Farsi]
+
+Ditto.
+
+=item Thai encoding TCVN
+
+Ditto.
+
+=item Vietnamese encodings VPS
+
+Though Jungshik Shin has reported that Mozilla supports this encoding,
+it was too late before 5.8.0 for us to add it. In the future, it
+may be available via a separate module. See
+L<http://lxr.mozilla.org/seamonkey/source/intl/uconv/ucvlatin/vps.uf>
+and
+L<http://lxr.mozilla.org/seamonkey/source/intl/uconv/ucvlatin/vps.ut>
+if you are interested in helping us.
+
+=item Various Mac encodings
+
+The following are unsupported due to the lack of mapping data.
+
+ MacArmenian, MacBengali, MacBurmese, MacEthiopic
+ MacExtArabic, MacGeorgian, MacKannada, MacKhmer
+ MacLaotian, MacMalayalam, MacMongolian, MacOriya
+ MacSinhalese, MacTamil, MacTelugu, MacTibetan
+ MacVietnamese
+
+The rest which are already available are based upon the vendor mappings
+at L<http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/> .
+
+=item (Mac) Indic encodings
+
+The maps for the following are available at L<http://www.unicode.org/>
+but remain unsupport because those encodings need algorithmical
+approach, currently unsupported by F<enc2xs>:
+
+ MacDevanagari
+ MacGurmukhi
+ MacGujarati
+
+For details, please see C<Unicode mapping issues and notes:> at
+L<http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/DEVANAGA.TXT> .
+
+I believe this issue is prevalent not only for Mac Indics but also in
+other Indic encodings, but the above were the only Indic encodings
+maps that I could find at L<http://www.unicode.org/> .
+
+=back
+
+=head1 Encoding vs. Charset -- terminology
+
+We are used to using the term (character) I<encoding> and I<character
+set> interchangeably. But just as confusing the terms byte and
+character is dangerous and the terms should be differentiated when
+needed, we need to differentiate I<encoding> and I<character set>.
+
+To understand that, here is a description of how we make computers
+grok our characters.
+
+=over 2
+
+=item *
+
+First we start with which characters to include. We call this
+collection of characters I<character repertoire>.
+
+=item *
+
+Then we have to give each character a unique ID so your computer can
+tell the difference between 'a' and 'A'. This itemized character
+repertoire is now a I<character set>.
+
+=item *
+
+If your computer can grow the character set without further
+processing, you can go ahead and use it. This is called a I<coded
+character set> (CCS) or I<raw character encoding>. ASCII is used this
+way for most cases.
+
+=item *
+
+But in many cases, especially multi-byte CJK encodings, you have to
+tweak a little more. Your network connection may not accept any data
+with the Most Significant Bit set, and your computer may not be able to
+tell if a given byte is a whole character or just half of it. So you
+have to I<encode> the character set to use it.
+
+A I<character encoding scheme> (CES) determines how to encode a given
+character set, or a set of multiple character sets. 7bit ISO-2022 is
+an example of a CES. You switch between character sets via I<escape
+sequences>.
+
+=back
+
+Technically, or mathematically, speaking, a character set encoded in
+such a CES that maps character by character may form a CCS. EUC is such
+an example. The CES of EUC is as follows:
+
+=over 2
+
+=item *
+
+Map ASCII unchanged.
+
+=item *
+
+Map such a character set that consists of 94 or 96 powered by N
+members by adding 0x80 to each byte.
+
+=item *
+
+You can also use 0x8e and 0x8f to indicate that the following sequence of
+characters belongs to yet another character set. To each following byte
+is added the value 0x80.
+
+=back
+
+By carefully looking at the encoded byte sequence, you can find that the
+byte sequence conforms a unique number. In that sense, EUC is a CCS
+generated by a CES above from up to four CCS (complicated?). UTF-8
+falls into this category. See L<perlUnicode/"UTF-8"> to find out how
+UTF-8 maps Unicode to a byte sequence.
+
+You may also have found out by now why 7bit ISO-2022 cannot comprise
+a CCS. If you look at a byte sequence \x21\x21, you can't tell if
+it is two !'s or IDEOGRAPHIC SPACE. EUC maps the latter to \xA1\xA1
+so you have no trouble differentiating between "!!". and S<" ">.
+
+=head1 Encoding Classification (by Anton Tagunov and Dan Kogai)
+
+This section tries to classify the supported encodings by their
+applicability for information exchange over the Internet and to
+choose the most suitable aliases to name them in the context of
+such communication.
+
+=over 2
+
+=item *
+
+To (en|de)code encodings marked by C<(**)>, you need
+C<Encode::HanExtra>, available from CPAN.
+
+=back
+
+Encoding names
+
+ US-ASCII UTF-8 ISO-8859-* KOI8-R
+ Shift_JIS EUC-JP ISO-2022-JP ISO-2022-JP-1
+ EUC-KR Big5 GB2312
+
+are registered with IANA as preferred MIME names and may
+be used over the Internet.
+
+C<Shift_JIS> has been officialized by JIS X 0208:1997.
+L<Microsoft-related naming mess> gives details.
+
+C<GB2312> is the IANA name for C<EUC-CN>.
+See L<Microsoft-related naming mess> for details.
+
+C<GB_2312-80> I<raw> encoding is available as C<gb2312-raw>
+with Encode. See L<Encode::CN> for details.
+
+ EUC-CN
+ KOI8-U [RFC2319]
+
+have not been registered with IANA (as of March 2002) but
+seem to be supported by major web browsers.
+The IANA name for C<EUC-CN> is C<GB2312>.
+
+ KS_C_5601-1987
+
+is heavily misused.
+See L<Microsoft-related naming mess> for details.
+
+C<KS_C_5601-1987> I<raw> encoding is available as C<kcs5601-raw>
+with Encode. See L<Encode::KR> for details.
+
+ UTF-16 UTF-16BE UTF-16LE
+
+are IANA-registered C<charset>s. See [RFC 2781] for details.
+Jungshik Shin reports that UTF-16 with a BOM is well accepted
+by MS IE 5/6 and NS 4/6. Beware however that
+
+=over 2
+
+=item *
+
+C<UTF-16> support in any software you're going to be
+using/interoperating with has probably been less tested
+then C<UTF-8> support
+
+=item *
+
+C<UTF-8> coded data seamlessly passes traditional
+command piping (C<cat>, C<more>, etc.) while C<UTF-16> coded
+data is likely to cause confusion (with its zero bytes,
+for example)
+
+=item *
+
+it is beyond the power of words to describe the way HTML browsers
+encode non-C<ASCII> form data. To get a general impression, visit
+L<http://www.alanflavell.org.uk/charset/form-i18n.html>.
+While encoding of form data has stabilized for C<UTF-8> encoded pages
+(at least IE 5/6, NS 6, and Opera 6 behave consistently), be sure to
+expect fun (and cross-browser discrepancies) with C<UTF-16> encoded
+pages!
+
+=back
+
+The rule of thumb is to use C<UTF-8> unless you know what
+you're doing and unless you really benefit from using C<UTF-16>.
+
+ ISO-IR-165 [RFC1345]
+ VISCII
+ GB 12345
+ GB 18030 (**) (see links bellow)
+ EUC-TW (**)
+
+are totally valid encodings but not registered at IANA.
+The names under which they are listed here are probably the
+most widely-known names for these encodings and are recommended
+names.
+
+ BIG5PLUS (**)
+
+is a proprietary name.
+
+=head2 Microsoft-related naming mess
+
+Microsoft products misuse the following names:
+
+=over 2
+
+=item KS_C_5601-1987
+
+Microsoft extension to C<EUC-KR>.
+
+Proper names: C<CP949>, C<UHC>, C<x-windows-949> (as used by Mozilla).
+
+See L<http://lists.w3.org/Archives/Public/ietf-charsets/2001AprJun/0033.html>
+for details.
+
+Encode aliases C<KS_C_5601-1987> to C<cp949> to reflect this common
+misusage. I<Raw> C<KS_C_5601-1987> encoding is available as
+C<kcs5601-raw>.
+
+See L<Encode::KR> for details.
+
+=item GB2312
+
+Microsoft extension to C<EUC-CN>.
+
+Proper names: C<CP936>, C<GBK>.
+
+C<GB2312> has been registered in the C<EUC-CN> meaning at
+IANA. This has partially repaired the situation: Microsoft's
+C<GB2312> has become a superset of the official C<GB2312>.
+
+Encode aliases C<GB2312> to C<euc-cn> in full agreement with
+IANA registration. C<cp936> is supported separately.
+I<Raw> C<GB_2312-80> encoding is available as C<gb2312-raw>.
+
+See L<Encode::CN> for details.
+
+=item Big5
+
+Microsoft extension to C<Big5>.
+
+Proper name: C<CP950>.
+
+Encode separately supports C<Big5> and C<cp950>.
+
+=item Shift_JIS
+
+Microsoft's understanding of C<Shift_JIS>.
+
+JIS has not endorsed the full Microsoft standard however.
+The official C<Shift_JIS> includes only JIS X 0201 and JIS X 0208
+character sets, while Microsoft has always used C<Shift_JIS>
+to encode a wider character repertoire. See C<IANA> registration for
+C<Windows-31J>.
+
+As a historical predecessor, Microsoft's variant
+probably has more rights for the name, though it may be objected
+that Microsoft shouldn't have used JIS as part of the name
+in the first place.
+
+Unambiguous name: C<CP932>. C<IANA> name (also used by Mozilla, and
+provided as an alias by Encode): C<Windows-31J>.
+
+Encode separately supports C<Shift_JIS> and C<cp932>.
+
+=back
+
+=head1 Glossary
+
+=over 2
+
+=item character repertoire
+
+A collection of unique characters. A I<character> set in the strictest
+sense. At this stage, characters are not numbered.
+
+=item coded character set (CCS)
+
+A character set that is mapped in a way computers can use directly.
+Many character encodings, including EUC, fall in this category.
+
+=item character encoding scheme (CES)
+
+An algorithm to map a character set to a byte sequence. You don't
+have to be able to tell which character set a given byte sequence
+belongs. 7-bit ISO-2022 is a CES but it cannot be a CCS. EUC is an
+example of being both a CCS and CES.
+
+=item charset (in MIME context)
+
+has long been used in the meaning of C<encoding>, CES.
+
+While the word combination C<character set> has lost this meaning
+in MIME context since [RFC 2130], the C<charset> abbreviation has
+retained it. This is how [RFC 2277] and [RFC 2278] bless C<charset>:
+
+ This document uses the term "charset" to mean a set of rules for
+ mapping from a sequence of octets to a sequence of characters, such
+ as the combination of a coded character set and a character encoding
+ scheme; this is also what is used as an identifier in MIME "charset="
+ parameters, and registered in the IANA charset registry ... (Note
+ that this is NOT a term used by other standards bodies, such as ISO).
+ [RFC 2277]
+
+=item EUC
+
+Extended Unix Character. See ISO-2022.
+
+=item ISO-2022
+
+A CES that was carefully designed to coexist with ASCII. There are a 7
+bit version and an 8 bit version.
+
+The 7 bit version switches character set via escape sequence so it
+cannot form a CCS. Since this is more difficult to handle in programs
+than the 8 bit version, the 7 bit version is not very popular except for
+iso-2022-jp, the I<de facto> standard CES for e-mails.
+
+The 8 bit version can form a CCS. EUC and ISO-8859 are two examples
+thereof. Pre-5.6 perl could use them as string literals.
+
+=item UCS
+
+Short for I<Universal Character Set>. When you say just UCS, it means
+I<Unicode>.
+
+=item UCS-2
+
+ISO/IEC 10646 encoding form: Universal Character Set coded in two
+octets.
+
+=item Unicode
+
+A character set that aims to include all character repertoires of the
+world. Many character sets in various national as well as industrial
+standards have become, in a way, just subsets of Unicode.
+
+=item UTF
+
+Short for I<Unicode Transformation Format>. Determines how to map a
+Unicode character into a byte sequence.
+
+=item UTF-16
+
+A UTF in 16-bit encoding. Can either be in big endian or little
+endian. The big endian version is called UTF-16BE (equal to UCS-2 +
+surrogate support) and the little endian version is called UTF-16LE.
+
+=back
+
+=head1 See Also
+
+L<Encode>,
+L<Encode::Byte>,
+L<Encode::CN>, L<Encode::JP>, L<Encode::KR>, L<Encode::TW>,
+L<Encode::EBCDIC>, L<Encode::Symbol>
+L<Encode::MIME::Header>, L<Encode::Guess>
+
+=head1 References
+
+=over 2
+
+=item ECMA
+
+European Computer Manufacturers Association
+L<http://www.ecma.ch>
+
+=over 2
+
+=item ECMA-035 (eq C<ISO-2022>)
+
+L<http://www.ecma.ch/ecma1/STAND/ECMA-035.HTM>
+
+The specification of ISO-2022 is available from the link above.
+
+=back
+
+=item IANA
+
+Internet Assigned Numbers Authority
+L<http://www.iana.org/>
+
+=over 2
+
+=item Assigned Charset Names by IANA
+
+L<http://www.iana.org/assignments/character-sets>
+
+Most of the C<canonical names> in Encode derive from this list
+so you can directly apply the string you have extracted from MIME
+header of mails and web pages.
+
+=back
+
+=item ISO
+
+International Organization for Standardization
+L<http://www.iso.ch/>
+
+=item RFC
+
+Request For Comments -- need I say more?
+L<http://www.rfc-editor.org/>, L<http://www.ietf.org/rfc.html>,
+L<http://www.faqs.org/rfcs/>
+
+=item UC
+
+Unicode Consortium
+L<http://www.unicode.org/>
+
+=over 2
+
+=item Unicode Glossary
+
+L<http://www.unicode.org/glossary/>
+
+The glossary of this document is based upon this site.
+
+=back
+
+=back
+
+=head2 Other Notable Sites
+
+=over 2
+
+=item czyborra.com
+
+L<http://czyborra.com/>
+
+Contains a lot of useful information, especially gory details of ISO
+vs. vendor mappings.
+
+=item CJK.inf
+
+L<http://examples.oreilly.com/cjkvinfo/doc/cjk.inf>
+
+Somewhat obsolete (last update in 1996), but still useful. Also try
+
+L<ftp://ftp.oreilly.com/pub/examples/nutshell/cjkv/pdf/GB18030_Summary.pdf>
+
+You will find brief info on C<EUC-CN>, C<GBK> and mostly on C<GB 18030>.
+
+=item Jungshik Shin's Hangul FAQ
+
+L<http://jshin.net/faq>
+
+And especially its subject 8.
+
+L<http://jshin.net/faq/qa8.html>
+
+A comprehensive overview of the Korean (C<KS *>) standards.
+
+=item debian.org: "Introduction to i18n"
+
+A brief description for most of the mentioned CJK encodings is
+contained in
+L<http://www.debian.org/doc/manuals/intro-i18n/ch-codes.en.html>
+
+=back
+
+=head2 Offline sources
+
+=over 2
+
+=item C<CJKV Information Processing> by Ken Lunde
+
+CJKV Information Processing
+1999 O'Reilly & Associates, ISBN : 1-56592-224-7
+
+The modern successor of C<CJK.inf>.
+
+Features a comprehensive coverage of CJKV character sets and
+encodings along with many other issues faced by anyone trying
+to better support CJKV languages/scripts in all the areas of
+information processing.
+
+To purchase this book, visit
+L<http://oreilly.com/catalog/9780596514471/>
+or your favourite bookstore.
+
+=back
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/Symbol.pm b/Master/tlpkg/tlperl/lib/Encode/Symbol.pm
new file mode 100644
index 00000000000..77031aad75c
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/Symbol.pm
@@ -0,0 +1,44 @@
+package Encode::Symbol;
+use strict;
+use warnings;
+use Encode;
+our $VERSION = do { my @r = ( q$Revision: 2.2 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+
+use XSLoader;
+XSLoader::load( __PACKAGE__, $VERSION );
+
+1;
+__END__
+
+=head1 NAME
+
+Encode::Symbol - Symbol Encodings
+
+=head1 SYNOPSIS
+
+ use Encode qw/encode decode/;
+ $symbol = encode("symbol", $utf8); # loads Encode::Symbol implicitly
+ $utf8 = decode("", $symbol); # ditto
+
+=head1 ABSTRACT
+
+This module implements symbol and dingbats encodings. Encodings
+supported are as follows.
+
+ Canonical Alias Description
+ --------------------------------------------------------------------
+ symbol
+ dingbats
+ AdobeZDingbat
+ AdobeSymbol
+ MacDingbats
+
+=head1 DESCRIPTION
+
+To find out how to use this module in detail, see L<Encode>.
+
+=head1 SEE ALSO
+
+L<Encode>
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/TW.pm b/Master/tlpkg/tlperl/lib/Encode/TW.pm
new file mode 100644
index 00000000000..c30499bee1e
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/TW.pm
@@ -0,0 +1,75 @@
+package Encode::TW;
+BEGIN {
+ if ( ord("A") == 193 ) {
+ die "Encode::TW not supported on EBCDIC\n";
+ }
+}
+use strict;
+use warnings;
+use Encode;
+our $VERSION = do { my @r = ( q$Revision: 2.3 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+use XSLoader;
+XSLoader::load( __PACKAGE__, $VERSION );
+
+1;
+__END__
+
+=head1 NAME
+
+Encode::TW - Taiwan-based Chinese Encodings
+
+=head1 SYNOPSIS
+
+ use Encode qw/encode decode/;
+ $big5 = encode("big5", $utf8); # loads Encode::TW implicitly
+ $utf8 = decode("big5", $big5); # ditto
+
+=head1 DESCRIPTION
+
+This module implements tradition Chinese charset encodings as used
+in Taiwan and Hong Kong.
+Encodings supported are as follows.
+
+ Canonical Alias Description
+ --------------------------------------------------------------------
+ big5-eten /\bbig-?5$/i Big5 encoding (with ETen extensions)
+ /\bbig5-?et(en)?$/i
+ /\btca-?big5$/i
+ big5-hkscs /\bbig5-?hk(scs)?$/i
+ /\bhk(scs)?-?big5$/i
+ Big5 + Cantonese characters in Hong Kong
+ MacChineseTrad Big5 + Apple Vendor Mappings
+ cp950 Code Page 950
+ = Big5 + Microsoft vendor mappings
+ --------------------------------------------------------------------
+
+To find out how to use this module in detail, see L<Encode>.
+
+=head1 NOTES
+
+Due to size concerns, C<EUC-TW> (Extended Unix Character), C<CCCII>
+(Chinese Character Code for Information Interchange), C<BIG5PLUS>
+(CMEX's Big5+) and C<BIG5EXT> (CMEX's Big5e) are distributed separately
+on CPAN, under the name L<Encode::HanExtra>. That module also contains
+extra China-based encodings.
+
+=head1 BUGS
+
+Since the original C<big5> encoding (1984) is not supported anywhere
+(glibc and DOS-based systems uses C<big5> to mean C<big5-eten>; Microsoft
+uses C<big5> to mean C<cp950>), a conscious decision was made to alias
+C<big5> to C<big5-eten>, which is the de facto superset of the original
+big5.
+
+The C<CNS11643> encoding files are not complete. For common C<CNS11643>
+manipulation, please use C<EUC-TW> in L<Encode::HanExtra>, which contains
+planes 1-7.
+
+The ASCII region (0x00-0x7f) is preserved for all encodings, even
+though this conflicts with mappings by the Unicode Consortium.
+
+=head1 SEE ALSO
+
+L<Encode>
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/Unicode.pm b/Master/tlpkg/tlperl/lib/Encode/Unicode.pm
new file mode 100644
index 00000000000..f71567c6196
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/Unicode.pm
@@ -0,0 +1,270 @@
+package Encode::Unicode;
+
+use strict;
+use warnings;
+no warnings 'redefine';
+
+our $VERSION = do { my @r = ( q$Revision: 2.7 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+
+use XSLoader;
+XSLoader::load( __PACKAGE__, $VERSION );
+
+#
+# Object Generator 8 transcoders all at once!
+#
+
+require Encode;
+
+our %BOM_Unknown = map { $_ => 1 } qw(UTF-16 UTF-32);
+
+for my $name (
+ qw(UTF-16 UTF-16BE UTF-16LE
+ UTF-32 UTF-32BE UTF-32LE
+ UCS-2BE UCS-2LE)
+ )
+{
+ my ( $size, $endian, $ucs2, $mask );
+ $name =~ /^(\w+)-(\d+)(\w*)$/o;
+ if ( $ucs2 = ( $1 eq 'UCS' ) ) {
+ $size = 2;
+ }
+ else {
+ $size = $2 / 8;
+ }
+ $endian = ( $3 eq 'BE' ) ? 'n' : ( $3 eq 'LE' ) ? 'v' : '';
+ $size == 4 and $endian = uc($endian);
+
+ $Encode::Encoding{$name} = bless {
+ Name => $name,
+ size => $size,
+ endian => $endian,
+ ucs2 => $ucs2,
+ } => __PACKAGE__;
+}
+
+use base qw(Encode::Encoding);
+
+sub renew {
+ my $self = shift;
+ $BOM_Unknown{ $self->name } or return $self;
+ my $clone = bless {%$self} => ref($self);
+ $clone->{renewed}++; # so the caller knows it is renewed.
+ return $clone;
+}
+
+# There used to be a perl implemntation of (en|de)code but with
+# XS version is ripe, perl version is zapped for optimal speed
+
+*decode = \&decode_xs;
+*encode = \&encode_xs;
+
+1;
+__END__
+
+=head1 NAME
+
+Encode::Unicode -- Various Unicode Transformation Formats
+
+=cut
+
+=head1 SYNOPSIS
+
+ use Encode qw/encode decode/;
+ $ucs2 = encode("UCS-2BE", $utf8);
+ $utf8 = decode("UCS-2BE", $ucs2);
+
+=head1 ABSTRACT
+
+This module implements all Character Encoding Schemes of Unicode that
+are officially documented by Unicode Consortium (except, of course,
+for UTF-8, which is a native format in perl).
+
+=over 4
+
+=item L<http://www.unicode.org/glossary/> says:
+
+I<Character Encoding Scheme> A character encoding form plus byte
+serialization. There are Seven character encoding schemes in Unicode:
+UTF-8, UTF-16, UTF-16BE, UTF-16LE, UTF-32 (UCS-4), UTF-32BE (UCS-4BE) and
+UTF-32LE (UCS-4LE), and UTF-7.
+
+Since UTF-7 is a 7-bit (re)encoded version of UTF-16BE, It is not part of
+Unicode's Character Encoding Scheme. It is separately implemented in
+Encode::Unicode::UTF7. For details see L<Encode::Unicode::UTF7>.
+
+=item Quick Reference
+
+ Decodes from ord(N) Encodes chr(N) to...
+ octet/char BOM S.P d800-dfff ord > 0xffff \x{1abcd} ==
+ ---------------+-----------------+------------------------------
+ UCS-2BE 2 N N is bogus Not Available
+ UCS-2LE 2 N N bogus Not Available
+ UTF-16 2/4 Y Y is S.P S.P BE/LE
+ UTF-16BE 2/4 N Y S.P S.P 0xd82a,0xdfcd
+ UTF-16LE 2/4 N Y S.P S.P 0x2ad8,0xcddf
+ UTF-32 4 Y - is bogus As is BE/LE
+ UTF-32BE 4 N - bogus As is 0x0001abcd
+ UTF-32LE 4 N - bogus As is 0xcdab0100
+ UTF-8 1-4 - - bogus >= 4 octets \xf0\x9a\af\8d
+ ---------------+-----------------+------------------------------
+
+=back
+
+=head1 Size, Endianness, and BOM
+
+You can categorize these CES by 3 criteria: size of each character,
+endianness, and Byte Order Mark.
+
+=head2 by size
+
+UCS-2 is a fixed-length encoding with each character taking 16 bits.
+It B<does not> support I<surrogate pairs>. When a surrogate pair
+is encountered during decode(), its place is filled with \x{FFFD}
+if I<CHECK> is 0, or the routine croaks if I<CHECK> is 1. When a
+character whose ord value is larger than 0xFFFF is encountered,
+its place is filled with \x{FFFD} if I<CHECK> is 0, or the routine
+croaks if I<CHECK> is 1.
+
+UTF-16 is almost the same as UCS-2 but it supports I<surrogate pairs>.
+When it encounters a high surrogate (0xD800-0xDBFF), it fetches the
+following low surrogate (0xDC00-0xDFFF) and C<desurrogate>s them to
+form a character. Bogus surrogates result in death. When \x{10000}
+or above is encountered during encode(), it C<ensurrogate>s them and
+pushes the surrogate pair to the output stream.
+
+UTF-32 (UCS-4) is a fixed-length encoding with each character taking 32 bits.
+Since it is 32-bit, there is no need for I<surrogate pairs>.
+
+=head2 by endianness
+
+The first (and now failed) goal of Unicode was to map all character
+repertoires into a fixed-length integer so that programmers are happy.
+Since each character is either a I<short> or I<long> in C, you have to
+pay attention to the endianness of each platform when you pass data
+to one another.
+
+Anything marked as BE is Big Endian (or network byte order) and LE is
+Little Endian (aka VAX byte order). For anything not marked either
+BE or LE, a character called Byte Order Mark (BOM) indicating the
+endianness is prepended to the string.
+
+CAVEAT: Though BOM in utf8 (\xEF\xBB\xBF) is valid, it is meaningless
+and as of this writing Encode suite just leave it as is (\x{FeFF}).
+
+=over 4
+
+=item BOM as integer when fetched in network byte order
+
+ 16 32 bits/char
+ -------------------------
+ BE 0xFeFF 0x0000FeFF
+ LE 0xFFFe 0xFFFe0000
+ -------------------------
+
+=back
+
+This modules handles the BOM as follows.
+
+=over 4
+
+=item *
+
+When BE or LE is explicitly stated as the name of encoding, BOM is
+simply treated as a normal character (ZERO WIDTH NO-BREAK SPACE).
+
+=item *
+
+When BE or LE is omitted during decode(), it checks if BOM is at the
+beginning of the string; if one is found, the endianness is set to
+what the BOM says. If no BOM is found, the routine dies.
+
+=item *
+
+When BE or LE is omitted during encode(), it returns a BE-encoded
+string with BOM prepended. So when you want to encode a whole text
+file, make sure you encode() the whole text at once, not line by line
+or each line, not file, will have a BOM prepended.
+
+=item *
+
+C<UCS-2> is an exception. Unlike others, this is an alias of UCS-2BE.
+UCS-2 is already registered by IANA and others that way.
+
+=back
+
+=head1 Surrogate Pairs
+
+To say the least, surrogate pairs were the biggest mistake of the
+Unicode Consortium. But according to the late Douglas Adams in I<The
+Hitchhiker's Guide to the Galaxy> Trilogy, C<In the beginning the
+Universe was created. This has made a lot of people very angry and
+been widely regarded as a bad move>. Their mistake was not of this
+magnitude so let's forgive them.
+
+(I don't dare make any comparison with Unicode Consortium and the
+Vogons here ;) Or, comparing Encode to Babel Fish is completely
+appropriate -- if you can only stick this into your ear :)
+
+Surrogate pairs were born when the Unicode Consortium finally
+admitted that 16 bits were not big enough to hold all the world's
+character repertoires. But they already made UCS-2 16-bit. What
+do we do?
+
+Back then, the range 0xD800-0xDFFF was not allocated. Let's split
+that range in half and use the first half to represent the C<upper
+half of a character> and the second half to represent the C<lower
+half of a character>. That way, you can represent 1024 * 1024 =
+1048576 more characters. Now we can store character ranges up to
+\x{10ffff} even with 16-bit encodings. This pair of half-character is
+now called a I<surrogate pair> and UTF-16 is the name of the encoding
+that embraces them.
+
+Here is a formula to ensurrogate a Unicode character \x{10000} and
+above;
+
+ $hi = ($uni - 0x10000) / 0x400 + 0xD800;
+ $lo = ($uni - 0x10000) % 0x400 + 0xDC00;
+
+And to desurrogate;
+
+ $uni = 0x10000 + ($hi - 0xD800) * 0x400 + ($lo - 0xDC00);
+
+Note this move has made \x{D800}-\x{DFFF} into a forbidden zone but
+perl does not prohibit the use of characters within this range. To perl,
+every one of \x{0000_0000} up to \x{ffff_ffff} (*) is I<a character>.
+
+ (*) or \x{ffff_ffff_ffff_ffff} if your perl is compiled with 64-bit
+ integer support!
+
+=head1 Error Checking
+
+Unlike most encodings which accept various ways to handle errors,
+Unicode encodings simply croaks.
+
+ % perl -MEncode -e'$_ = "\xfe\xff\xd8\xd9\xda\xdb\0\n"' \
+ -e'Encode::from_to($_, "utf16","shift_jis", 0); print'
+ UTF-16:Malformed LO surrogate d8d9 at /path/to/Encode.pm line 184.
+ % perl -MEncode -e'$a = "BOM missing"' \
+ -e' Encode::from_to($a, "utf16", "shift_jis", 0); print'
+ UTF-16:Unrecognised BOM 424f at /path/to/Encode.pm line 184.
+
+Unlike other encodings where mappings are not one-to-one against
+Unicode, UTFs are supposed to map 100% against one another. So Encode
+is more strict on UTFs.
+
+Consider that "division by zero" of Encode :)
+
+=head1 SEE ALSO
+
+L<Encode>, L<Encode::Unicode::UTF7>, L<http://www.unicode.org/glossary/>,
+L<http://www.unicode.org/unicode/faq/utf_bom.html>,
+
+RFC 2781 L<http://www.ietf.org/rfc/rfc2781.txt>,
+
+The whole Unicode standard L<http://www.unicode.org/unicode/uni2book/u2.html>
+
+Ch. 15, pp. 403 of C<Programming Perl (3rd Edition)>
+by Larry Wall, Tom Christiansen, Jon Orwant;
+O'Reilly & Associates; ISBN 0-596-00027-8
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/Unicode/UTF7.pm b/Master/tlpkg/tlperl/lib/Encode/Unicode/UTF7.pm
new file mode 100644
index 00000000000..6ee46195854
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/Unicode/UTF7.pm
@@ -0,0 +1,128 @@
+#
+# $Id: UTF7.pm,v 2.4 2006/06/03 20:28:48 dankogai Exp $
+#
+package Encode::Unicode::UTF7;
+use strict;
+use warnings;
+no warnings 'redefine';
+use base qw(Encode::Encoding);
+__PACKAGE__->Define('UTF-7');
+our $VERSION = do { my @r = ( q$Revision: 2.4 $ =~ /\d+/g ); sprintf "%d." . "%02d" x $#r, @r };
+use MIME::Base64;
+use Encode;
+
+#
+# Algorithms taken from Unicode::String by Gisle Aas
+#
+
+our $OPTIONAL_DIRECT_CHARS = 1;
+my $specials = quotemeta "\'(),-./:?";
+$OPTIONAL_DIRECT_CHARS
+ and $specials .= quotemeta "!\"#$%&*;<=>@[]^_`{|}";
+
+# \s will not work because it matches U+3000 DEOGRAPHIC SPACE
+# We use qr/[\n\r\t\ ] instead
+my $re_asis = qr/(?:[\n\r\t\ A-Za-z0-9$specials])/;
+my $re_encoded = qr/(?:[^\n\r\t\ A-Za-z0-9$specials])/;
+my $e_utf16 = find_encoding("UTF-16BE");
+
+sub needs_lines { 1 }
+
+sub encode($$;$) {
+ my ( $obj, $str, $chk ) = @_;
+ my $len = length($str);
+ pos($str) = 0;
+ my $bytes = '';
+ while ( pos($str) < $len ) {
+ if ( $str =~ /\G($re_asis+)/ogc ) {
+ $bytes .= $1;
+ }
+ elsif ( $str =~ /\G($re_encoded+)/ogsc ) {
+ if ( $1 eq "+" ) {
+ $bytes .= "+-";
+ }
+ else {
+ my $s = $1;
+ my $base64 = encode_base64( $e_utf16->encode($s), '' );
+ $base64 =~ s/=+$//;
+ $bytes .= "+$base64-";
+ }
+ }
+ else {
+ die "This should not happen! (pos=" . pos($str) . ")";
+ }
+ }
+ $_[1] = '' if $chk;
+ return $bytes;
+}
+
+sub decode($$;$) {
+ my ( $obj, $bytes, $chk ) = @_;
+ my $len = length($bytes);
+ my $str = "";
+ no warnings 'uninitialized';
+ while ( pos($bytes) < $len ) {
+ if ( $bytes =~ /\G([^+]+)/ogc ) {
+ $str .= $1;
+ }
+ elsif ( $bytes =~ /\G\+-/ogc ) {
+ $str .= "+";
+ }
+ elsif ( $bytes =~ /\G\+([A-Za-z0-9+\/]+)-?/ogsc ) {
+ my $base64 = $1;
+ my $pad = length($base64) % 4;
+ $base64 .= "=" x ( 4 - $pad ) if $pad;
+ $str .= $e_utf16->decode( decode_base64($base64) );
+ }
+ elsif ( $bytes =~ /\G\+/ogc ) {
+ $^W and warn "Bad UTF7 data escape";
+ $str .= "+";
+ }
+ else {
+ die "This should not happen " . pos($bytes);
+ }
+ }
+ $_[1] = '' if $chk;
+ return $str;
+}
+1;
+__END__
+
+=head1 NAME
+
+Encode::Unicode::UTF7 -- UTF-7 encoding
+
+=head1 SYNOPSIS
+
+ use Encode qw/encode decode/;
+ $utf7 = encode("UTF-7", $utf8);
+ $utf8 = decode("UTF-7", $ucs2);
+
+=head1 ABSTRACT
+
+This module implements UTF-7 encoding documented in RFC 2152. UTF-7,
+as its name suggests, is a 7-bit re-encoded version of UTF-16BE. It
+is designed to be MTA-safe and expected to be a standard way to
+exchange Unicoded mails via mails. But with the advent of UTF-8 and
+8-bit compliant MTAs, UTF-7 is hardly ever used.
+
+UTF-7 was not supported by Encode until version 1.95 because of that.
+But Unicode::String, a module by Gisle Aas which adds Unicode supports
+to non-utf8-savvy perl did support UTF-7, the UTF-7 support was added
+so Encode can supersede Unicode::String 100%.
+
+=head1 In Practice
+
+When you want to encode Unicode for mails and web pages, however, do
+not use UTF-7 unless you are sure your recipients and readers can
+handle it. Very few MUAs and WWW Browsers support these days (only
+Mozilla seems to support one). For general cases, use UTF-8 for
+message body and MIME-Header for header instead.
+
+=head1 SEE ALSO
+
+L<Encode>, L<Encode::Unicode>, L<Unicode::String>
+
+RFC 2781 L<http://www.ietf.org/rfc/rfc2152.txt>
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/_PM.e2x b/Master/tlpkg/tlperl/lib/Encode/_PM.e2x
new file mode 100644
index 00000000000..eb59cd1b520
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/_PM.e2x
@@ -0,0 +1,23 @@
+package Encode::$_Name_;
+our $VERSION = "0.01";
+
+use Encode;
+use XSLoader;
+XSLoader::load(__PACKAGE__,$VERSION);
+
+1;
+__END__
+
+=head1 NAME
+
+Encode::$_Name_ - New Encoding
+
+=head1 SYNOPSIS
+
+You got to fill this in!
+
+=head1 SEE ALSO
+
+L<Encode>
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Encode/_T.e2x b/Master/tlpkg/tlperl/lib/Encode/_T.e2x
new file mode 100644
index 00000000000..6cf5f293d54
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/_T.e2x
@@ -0,0 +1,7 @@
+use strict;
+# Adjust the number here!
+use Test::More tests => 2;
+
+use_ok('Encode');
+use_ok('Encode::$_Name_');
+# Add more test here!
diff --git a/Master/tlpkg/tlperl/lib/Encode/encode.h b/Master/tlpkg/tlperl/lib/Encode/encode.h
new file mode 100644
index 00000000000..0dcf83d32bc
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Encode/encode.h
@@ -0,0 +1,113 @@
+#ifndef ENCODE_H
+#define ENCODE_H
+
+#ifndef U8
+/*
+ A tad devious this:
+ perl normally has a #define for U8 - if that isn't present then we
+ typedef it - leaving it #ifndef so we can do data parts without
+ getting extern references to the code parts
+*/
+typedef unsigned char U8;
+#endif
+
+typedef struct encpage_s encpage_t;
+
+struct encpage_s
+{
+ /* fields ordered to pack nicely on 32-bit machines */
+ const U8 *const seq; /* Packed output sequences we generate
+ if we match */
+ const encpage_t *const next; /* Page to go to if we match */
+ const U8 min; /* Min value of octet to match this entry */
+ const U8 max; /* Max value of octet to match this entry */
+ const U8 dlen; /* destination length -
+ size of entries in seq */
+ const U8 slen; /* source length -
+ number of source octets needed */
+};
+
+/*
+ At any point in a translation there is a page pointer which points
+ at an array of the above structures.
+
+ Basic operation :
+ get octet from source stream.
+ if (octet >= min && octet < max) {
+ if slen is 0 then we cannot represent this character.
+ if we have less than slen octets (including this one) then
+ we have a partial character.
+ otherwise
+ copy dlen octets from seq + dlen*(octet-min) to output
+ (dlen may be zero if we don't know yet.)
+ load page pointer with next to continue.
+ (is slen is one this is end of a character)
+ get next octet.
+ }
+ else {
+ increment the page pointer to look at next slot in the array
+ }
+
+ arrays SHALL be constructed so there is an entry which matches
+ ..0xFF at the end, and either maps it or indicates no
+ representation.
+
+ if MSB of slen is set then mapping is an approximate "FALLBACK" entry.
+
+*/
+
+
+typedef struct encode_s encode_t;
+struct encode_s
+{
+ const encpage_t *const t_utf8; /* Starting table for translation from
+ the encoding to UTF-8 form */
+ const encpage_t *const f_utf8; /* Starting table for translation
+ from UTF-8 to the encoding */
+ const U8 *const rep; /* Replacement character in this
+ encoding e.g. "?" */
+ int replen; /* Number of octets in rep */
+ U8 min_el; /* Minimum octets to represent a
+ character */
+ U8 max_el; /* Maximum octets to represent a
+ character */
+ const char *const name[2]; /* name(s) of this encoding */
+};
+
+#ifdef U8
+/* See comment at top of file for deviousness */
+
+extern int do_encode(const encpage_t *enc, const U8 *src, STRLEN *slen,
+ U8 *dst, STRLEN dlen, STRLEN *dout, int approx,
+ const U8 *term, STRLEN tlen);
+
+extern void Encode_DefineEncoding(encode_t *enc);
+
+#endif /* U8 */
+
+#define ENCODE_NOSPACE 1
+#define ENCODE_PARTIAL 2
+#define ENCODE_NOREP 3
+#define ENCODE_FALLBACK 4
+#define ENCODE_FOUND_TERM 5
+
+#define FBCHAR_UTF8 "\xEF\xBF\xBD"
+
+#define ENCODE_DIE_ON_ERR 0x0001 /* croaks immediately */
+#define ENCODE_WARN_ON_ERR 0x0002 /* warn on error; may proceed */
+#define ENCODE_RETURN_ON_ERR 0x0004 /* immediately returns on NOREP */
+#define ENCODE_LEAVE_SRC 0x0008 /* $src updated unless set */
+#define ENCODE_PERLQQ 0x0100 /* perlqq fallback string */
+#define ENCODE_HTMLCREF 0x0200 /* HTML character ref. fb mode */
+#define ENCODE_XMLCREF 0x0400 /* XML character ref. fb mode */
+#define ENCODE_STOP_AT_PARTIAL 0x0800 /* stop at partial explicitly */
+
+#define ENCODE_FB_DEFAULT 0x0000
+#define ENCODE_FB_CROAK 0x0001
+#define ENCODE_FB_QUIET ENCODE_RETURN_ON_ERR
+#define ENCODE_FB_WARN (ENCODE_RETURN_ON_ERR|ENCODE_WARN_ON_ERR)
+#define ENCODE_FB_PERLQQ (ENCODE_PERLQQ|ENCODE_LEAVE_SRC)
+#define ENCODE_FB_HTMLCREF (ENCODE_HTMLCREF|ENCODE_LEAVE_SRC)
+#define ENCODE_FB_XMLCREF (ENCODE_XMLCREF|ENCODE_LEAVE_SRC)
+
+#endif /* ENCODE_H */
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder.pm b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder.pm
new file mode 100644
index 00000000000..7854e88dc94
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder.pm
@@ -0,0 +1,331 @@
+package ExtUtils::CBuilder;
+
+use File::Spec ();
+use File::Path ();
+use File::Basename ();
+
+use vars qw($VERSION @ISA);
+$VERSION = '0.27';
+$VERSION = eval $VERSION;
+
+# Okay, this is the brute-force method of finding out what kind of
+# platform we're on. I don't know of a systematic way. These values
+# came from the latest (bleadperl) perlport.pod.
+
+my %OSTYPES = qw(
+ aix Unix
+ bsdos Unix
+ dgux Unix
+ dynixptx Unix
+ freebsd Unix
+ linux Unix
+ hpux Unix
+ irix Unix
+ darwin Unix
+ machten Unix
+ next Unix
+ openbsd Unix
+ netbsd Unix
+ dec_osf Unix
+ svr4 Unix
+ svr5 Unix
+ sco_sv Unix
+ unicos Unix
+ unicosmk Unix
+ solaris Unix
+ sunos Unix
+ cygwin Unix
+ os2 Unix
+ gnu Unix
+ gnukfreebsd Unix
+ haiku Unix
+
+ dos Windows
+ MSWin32 Windows
+
+ os390 EBCDIC
+ os400 EBCDIC
+ posix-bc EBCDIC
+ vmesa EBCDIC
+
+ MacOS MacOS
+ VMS VMS
+ VOS VOS
+ riscos RiscOS
+ amigaos Amiga
+ mpeix MPEiX
+ );
+
+# We only use this once - don't waste a symbol table entry on it.
+# More importantly, don't make it an inheritable method.
+my $load = sub {
+ my $mod = shift;
+ eval "use $mod";
+ die $@ if $@;
+ @ISA = ($mod);
+};
+
+{
+ my @package = split /::/, __PACKAGE__;
+
+ if (grep {-e File::Spec->catfile($_, @package, 'Platform', $^O) . '.pm'} @INC) {
+ $load->(__PACKAGE__ . "::Platform::$^O");
+
+ } elsif (exists $OSTYPES{$^O} and
+ grep {-e File::Spec->catfile($_, @package, 'Platform', $OSTYPES{$^O}) . '.pm'} @INC) {
+ $load->(__PACKAGE__ . "::Platform::$OSTYPES{$^O}");
+
+ } else {
+ $load->(__PACKAGE__ . "::Base");
+ }
+}
+
+sub os_type { $OSTYPES{$^O} }
+
+1;
+__END__
+
+=head1 NAME
+
+ExtUtils::CBuilder - Compile and link C code for Perl modules
+
+=head1 SYNOPSIS
+
+ use ExtUtils::CBuilder;
+
+ my $b = ExtUtils::CBuilder->new(%options);
+ $obj_file = $b->compile(source => 'MyModule.c');
+ $lib_file = $b->link(objects => $obj_file);
+
+=head1 DESCRIPTION
+
+This module can build the C portions of Perl modules by invoking the
+appropriate compilers and linkers in a cross-platform manner. It was
+motivated by the C<Module::Build> project, but may be useful for other
+purposes as well. However, it is I<not> intended as a general
+cross-platform interface to all your C building needs. That would
+have been a much more ambitious goal!
+
+=head1 METHODS
+
+=over 4
+
+=item new
+
+Returns a new C<ExtUtils::CBuilder> object. A C<config> parameter
+lets you override C<Config.pm> settings for all operations performed
+by the object, as in the following example:
+
+ # Use a different compiler than Config.pm says
+ my $b = ExtUtils::CBuilder->new( config =>
+ { ld => 'gcc' } );
+
+A C<quiet> parameter tells C<CBuilder> to not print its C<system()>
+commands before executing them:
+
+ # Be quieter than normal
+ my $b = ExtUtils::CBuilder->new( quiet => 1 );
+
+=item have_compiler
+
+Returns true if the current system has a working C compiler and
+linker, false otherwise. To determine this, we actually compile and
+link a sample C library. The sample will be compiled in the system
+tempdir or, if that fails for some reason, in the current directory.
+
+=item have_cplusplus
+
+Just like have_compiler but for C++ instead of C.
+
+=item compile
+
+Compiles a C source file and produces an object file. The name of the
+object file is returned. The source file is specified in a C<source>
+parameter, which is required; the other parameters listed below are
+optional.
+
+=over 4
+
+=item C<object_file>
+
+Specifies the name of the output file to create. Otherwise the
+C<object_file()> method will be consulted, passing it the name of the
+C<source> file.
+
+=item C<include_dirs>
+
+Specifies any additional directories in which to search for header
+files. May be given as a string indicating a single directory, or as
+a list reference indicating multiple directories.
+
+=item C<extra_compiler_flags>
+
+Specifies any additional arguments to pass to the compiler. Should be
+given as a list reference containing the arguments individually, or if
+this is not possible, as a string containing all the arguments
+together.
+
+=item C<C++>
+
+Specifies that the source file is a C++ source file and sets appropriate
+compiler flags
+
+=back
+
+The operation of this method is also affected by the
+C<archlibexp>, C<cccdlflags>, C<ccflags>, C<optimize>, and C<cc>
+entries in C<Config.pm>.
+
+=item link
+
+Invokes the linker to produce a library file from object files. In
+scalar context, the name of the library file is returned. In list
+context, the library file and any temporary files created are
+returned. A required C<objects> parameter contains the name of the
+object files to process, either in a string (for one object file) or
+list reference (for one or more files). The following parameters are
+optional:
+
+
+=over 4
+
+=item lib_file
+
+Specifies the name of the output library file to create. Otherwise
+the C<lib_file()> method will be consulted, passing it the name of
+the first entry in C<objects>.
+
+=item module_name
+
+Specifies the name of the Perl module that will be created by linking.
+On platforms that need to do prelinking (Win32, OS/2, etc.) this is a
+required parameter.
+
+=item extra_linker_flags
+
+Any additional flags you wish to pass to the linker.
+
+=back
+
+On platforms where C<need_prelink()> returns true, C<prelink()>
+will be called automatically.
+
+The operation of this method is also affected by the C<lddlflags>,
+C<shrpenv>, and C<ld> entries in C<Config.pm>.
+
+=item link_executable
+
+Invokes the linker to produce an executable file from object files. In
+scalar context, the name of the executable file is returned. In list
+context, the executable file and any temporary files created are
+returned. A required C<objects> parameter contains the name of the
+object files to process, either in a string (for one object file) or
+list reference (for one or more files). The optional parameters are
+the same as C<link> with exception for
+
+
+=over 4
+
+=item exe_file
+
+Specifies the name of the output executable file to create. Otherwise
+the C<exe_file()> method will be consulted, passing it the name of the
+first entry in C<objects>.
+
+=back
+
+=item object_file
+
+ my $object_file = $b->object_file($source_file);
+
+Converts the name of a C source file to the most natural name of an
+output object file to create from it. For instance, on Unix the
+source file F<foo.c> would result in the object file F<foo.o>.
+
+=item lib_file
+
+ my $lib_file = $b->lib_file($object_file);
+
+Converts the name of an object file to the most natural name of a
+output library file to create from it. For instance, on Mac OS X the
+object file F<foo.o> would result in the library file F<foo.bundle>.
+
+=item exe_file
+
+ my $exe_file = $b->exe_file($object_file);
+
+Converts the name of an object file to the most natural name of an
+executable file to create from it. For instance, on Mac OS X the
+object file F<foo.o> would result in the executable file F<foo>, and
+on Windows it would result in F<foo.exe>.
+
+
+=item prelink
+
+On certain platforms like Win32, OS/2, VMS, and AIX, it is necessary
+to perform some actions before invoking the linker. The
+C<ExtUtils::Mksymlists> module does this, writing files used by the
+linker during the creation of shared libraries for dynamic extensions.
+The names of any files written will be returned as a list.
+
+Several parameters correspond to C<ExtUtils::Mksymlists::Mksymlists()>
+options, as follows:
+
+ Mksymlists() prelink() type
+ -------------|-------------------|-------------------
+ NAME | dl_name | string (required)
+ DLBASE | dl_base | string
+ FILE | dl_file | string
+ DL_VARS | dl_vars | array reference
+ DL_FUNCS | dl_funcs | hash reference
+ FUNCLIST | dl_func_list | array reference
+ IMPORTS | dl_imports | hash reference
+ VERSION | dl_version | string
+
+Please see the documentation for C<ExtUtils::Mksymlists> for the
+details of what these parameters do.
+
+=item need_prelink
+
+Returns true on platforms where C<prelink()> should be called
+during linking, and false otherwise.
+
+=item extra_link_args_after_prelink
+
+Returns list of extra arguments to give to the link command; the arguments
+are the same as for prelink(), with addition of array reference to the
+results of prelink(); this reference is indexed by key C<prelink_res>.
+
+=back
+
+=head1 TO DO
+
+Currently this has only been tested on Unix and doesn't contain any of
+the Windows-specific code from the C<Module::Build> project. I'll do
+that next.
+
+=head1 HISTORY
+
+This module is an outgrowth of the C<Module::Build> project, to which
+there have been many contributors. Notably, Randy W. Sims submitted
+lots of code to support 3 compilers on Windows and helped with various
+other platform-specific issues. Ilya Zakharevich has contributed
+fixes for OS/2; John E. Malmberg and Peter Prymmer have done likewise
+for VMS.
+
+=head1 AUTHOR
+
+Ken Williams, kwilliams@cpan.org
+
+=head1 COPYRIGHT
+
+Copyright (c) 2003-2005 Ken Williams. All rights reserved.
+
+This library is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+perl(1), Module::Build(3)
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Base.pm b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Base.pm
new file mode 100644
index 00000000000..28036c61bdc
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Base.pm
@@ -0,0 +1,307 @@
+package ExtUtils::CBuilder::Base;
+
+use strict;
+use File::Spec;
+use File::Basename;
+use Cwd ();
+use Config;
+use Text::ParseWords;
+use IO::File;
+
+use vars qw($VERSION);
+$VERSION = '0.27';
+
+sub new {
+ my $class = shift;
+ my $self = bless {@_}, $class;
+
+ $self->{properties}{perl} = $class->find_perl_interpreter
+ or warn "Warning: Can't locate your perl binary";
+
+ while (my ($k,$v) = each %Config) {
+ $self->{config}{$k} = $v unless exists $self->{config}{$k};
+ }
+ $self->{config}{cc} = $ENV{CC} if exists $ENV{CC};
+ return $self;
+}
+
+sub find_perl_interpreter {
+ my $perl;
+ File::Spec->file_name_is_absolute($perl = $^X)
+ or -f ($perl = $Config::Config{perlpath})
+ or ($perl = $^X);
+ return $perl;
+}
+
+sub add_to_cleanup {
+ my $self = shift;
+ foreach (@_) {
+ $self->{files_to_clean}{$_} = 1;
+ }
+}
+
+sub cleanup {
+ my $self = shift;
+ foreach my $file (keys %{$self->{files_to_clean}}) {
+ unlink $file;
+ }
+}
+
+sub object_file {
+ my ($self, $filename) = @_;
+
+ # File name, minus the suffix
+ (my $file_base = $filename) =~ s/\.[^.]+$//;
+ return "$file_base$self->{config}{obj_ext}";
+}
+
+sub arg_include_dirs {
+ my $self = shift;
+ return map {"-I$_"} @_;
+}
+
+sub arg_nolink { '-c' }
+
+sub arg_object_file {
+ my ($self, $file) = @_;
+ return ('-o', $file);
+}
+
+sub arg_share_object_file {
+ my ($self, $file) = @_;
+ return ($self->split_like_shell($self->{config}{lddlflags}), '-o', $file);
+}
+
+sub arg_exec_file {
+ my ($self, $file) = @_;
+ return ('-o', $file);
+}
+
+sub arg_defines {
+ my ($self, %args) = @_;
+ return map "-D$_=$args{$_}", keys %args;
+}
+
+sub compile {
+ my ($self, %args) = @_;
+ die "Missing 'source' argument to compile()" unless defined $args{source};
+
+ my $cf = $self->{config}; # For convenience
+
+ $args{object_file} ||= $self->object_file($args{source});
+
+ my @include_dirs = $self->arg_include_dirs
+ (@{$args{include_dirs} || []},
+ $self->perl_inc());
+
+ my @defines = $self->arg_defines( %{$args{defines} || {}} );
+
+ my @extra_compiler_flags = $self->split_like_shell($args{extra_compiler_flags});
+ my @cccdlflags = $self->split_like_shell($cf->{cccdlflags});
+ my @ccflags = $self->split_like_shell($cf->{ccflags});
+ push @ccflags, qw/-x c++/ if $args{'C++'};
+ my @optimize = $self->split_like_shell($cf->{optimize});
+ my @flags = (@include_dirs, @defines, @cccdlflags, @extra_compiler_flags,
+ $self->arg_nolink,
+ @ccflags, @optimize,
+ $self->arg_object_file($args{object_file}),
+ );
+
+ my @cc = $self->split_like_shell($cf->{cc});
+
+ $self->do_system(@cc, @flags, $args{source})
+ or die "error building $args{object_file} from '$args{source}'";
+
+ return $args{object_file};
+}
+
+sub have_compiler {
+ my ($self, $is_cplusplus) = @_;
+ return $self->{have_compiler} if defined $self->{have_compiler};
+
+ my $result;
+ my $attempts = 3;
+ # tmpdir has issues for some people so fall back to current dir
+ DIR: for my $dir ( File::Spec->tmpdir, '.' ) {
+
+ # don't clobber existing files (rare, but possible)
+ my $rand = int(rand(2**31));
+ my $tmpfile = File::Spec->catfile($dir, "compilet-$rand.c");
+ $tmpfile .= "c" if $is_cplusplus;
+ if ( -e $tmpfile ) {
+ redo DIR if $attempts--;
+ next DIR;
+ }
+
+ {
+ my $FH = IO::File->new("> $tmpfile") or die "Can't create $tmpfile: $!";
+ if ( $is_cplusplus ) {
+ print $FH "class Bogus { public: int boot_compilet() { return 1; } };\n";
+ }
+ else {
+ print $FH "int boot_compilet() { return 1; }\n";
+ }
+ }
+
+ my ($obj_file, @lib_files);
+ eval {
+ local $^W = 0;
+ local $self->{quiet} = 1;
+ $obj_file = $self->compile('C++' => $is_cplusplus, source => $tmpfile);
+ @lib_files = $self->link(objects => $obj_file, module_name => 'compilet');
+ };
+ $result = $@ ? 0 : 1;
+
+ foreach (grep defined, $tmpfile, $obj_file, @lib_files) {
+ 1 while unlink;
+ }
+ last DIR if $result;
+ }
+
+ return $self->{have_compiler} = $result;
+}
+
+sub have_cplusplus {
+ push @_, 1;
+ goto &have_compiler;
+}
+
+sub lib_file {
+ my ($self, $dl_file) = @_;
+ $dl_file =~ s/\.[^.]+$//;
+ $dl_file =~ tr/"//d;
+ return "$dl_file.$self->{config}{dlext}";
+}
+
+
+sub exe_file {
+ my ($self, $dl_file) = @_;
+ $dl_file =~ s/\.[^.]+$//;
+ $dl_file =~ tr/"//d;
+ return "$dl_file$self->{config}{_exe}";
+}
+
+sub need_prelink { 0 }
+
+sub extra_link_args_after_prelink { return }
+
+sub prelink {
+ my ($self, %args) = @_;
+
+ ($args{dl_file} = $args{dl_name}) =~ s/.*::// unless $args{dl_file};
+
+ require ExtUtils::Mksymlists;
+ ExtUtils::Mksymlists::Mksymlists( # dl. abbrev for dynamic library
+ DL_VARS => $args{dl_vars} || [],
+ DL_FUNCS => $args{dl_funcs} || {},
+ FUNCLIST => $args{dl_func_list} || [],
+ IMPORTS => $args{dl_imports} || {},
+ NAME => $args{dl_name}, # Name of the Perl module
+ DLBASE => $args{dl_base}, # Basename of DLL file
+ FILE => $args{dl_file}, # Dir + Basename of symlist file
+ VERSION => (defined $args{dl_version} ? $args{dl_version} : '0.0'),
+ );
+
+ # Mksymlists will create one of these files
+ return grep -e, map "$args{dl_file}.$_", qw(ext def opt);
+}
+
+sub link {
+ my ($self, %args) = @_;
+ return $self->_do_link('lib_file', lddl => 1, %args);
+}
+
+sub link_executable {
+ my ($self, %args) = @_;
+ return $self->_do_link('exe_file', lddl => 0, %args);
+}
+
+sub _do_link {
+ my ($self, $type, %args) = @_;
+
+ my $cf = $self->{config}; # For convenience
+
+ my $objects = delete $args{objects};
+ $objects = [$objects] unless ref $objects;
+ my $out = $args{$type} || $self->$type($objects->[0]);
+
+ my @temp_files;
+ @temp_files =
+ $self->prelink(%args,
+ dl_name => $args{module_name}) if $args{lddl} && $self->need_prelink;
+
+ my @linker_flags = ($self->split_like_shell($args{extra_linker_flags}),
+ $self->extra_link_args_after_prelink(%args, dl_name => $args{module_name},
+ prelink_res => \@temp_files));
+
+ my @output = $args{lddl} ? $self->arg_share_object_file($out) : $self->arg_exec_file($out);
+ my @shrp = $self->split_like_shell($cf->{shrpenv});
+ my @ld = $self->split_like_shell($cf->{ld});
+
+ $self->do_system(@shrp, @ld, @output, @$objects, @linker_flags)
+ or die "error building $out from @$objects";
+
+ return wantarray ? ($out, @temp_files) : $out;
+}
+
+
+sub do_system {
+ my ($self, @cmd) = @_;
+ print "@cmd\n" if !$self->{quiet};
+ return !system(@cmd);
+}
+
+sub split_like_shell {
+ my ($self, $string) = @_;
+
+ return () unless defined($string);
+ return @$string if UNIVERSAL::isa($string, 'ARRAY');
+ $string =~ s/^\s+|\s+$//g;
+ return () unless length($string);
+
+ return Text::ParseWords::shellwords($string);
+}
+
+# if building perl, perl's main source directory
+sub perl_src {
+ # N.B. makemaker actually searches regardless of PERL_CORE, but
+ # only squawks at not finding it if PERL_CORE is set
+
+ return unless $ENV{PERL_CORE};
+
+ my $Updir = File::Spec->updir;
+ my $dir = File::Spec->curdir;
+
+ # Try up to 5 levels upwards
+ for (0..10) {
+ if (
+ -f File::Spec->catfile($dir,"config_h.SH")
+ &&
+ -f File::Spec->catfile($dir,"perl.h")
+ &&
+ -f File::Spec->catfile($dir,"lib","Exporter.pm")
+ ) {
+ return Cwd::realpath( $dir );
+ }
+
+ $dir = File::Spec->catdir($dir, $Updir);
+ }
+
+ warn "PERL_CORE is set but I can't find your perl source!\n";
+ return ''; # return empty string if $ENV{PERL_CORE} but can't find dir ???
+}
+
+# directory of perl's include files
+sub perl_inc {
+ my $self = shift;
+
+ $self->perl_src() || File::Spec->catdir($self->{config}{archlibexp},"CORE");
+}
+
+sub DESTROY {
+ my $self = shift;
+ local($., $@, $!, $^E, $?);
+ $self->cleanup();
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Unix.pm b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Unix.pm
new file mode 100644
index 00000000000..78ff244b5ba
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Unix.pm
@@ -0,0 +1,40 @@
+package ExtUtils::CBuilder::Platform::Unix;
+
+use strict;
+use ExtUtils::CBuilder::Base;
+
+use vars qw($VERSION @ISA);
+$VERSION = '0.27';
+@ISA = qw(ExtUtils::CBuilder::Base);
+
+sub link_executable {
+ my $self = shift;
+
+ # On some platforms (which ones??) $Config{cc} seems to be a better
+ # bet for linking executables than $Config{ld}. Cygwin is a notable
+ # exception.
+ local $self->{config}{ld} =
+ $self->{config}{cc} . " " . $self->{config}{ldflags};
+ return $self->SUPER::link_executable(@_);
+}
+
+sub link {
+ my $self = shift;
+ my $cf = $self->{config};
+
+ # Some platforms (notably Mac OS X 10.3, but some others too) expect
+ # the syntax "FOO=BAR /bin/command arg arg" to work in %Config
+ # (notably $Config{ld}). It usually works in system(SCALAR), but we
+ # use system(LIST). We fix it up here with 'env'.
+
+ local $cf->{ld} = $cf->{ld};
+ if (ref $cf->{ld}) {
+ unshift @{$cf->{ld}}, 'env' if $cf->{ld}[0] =~ /^\s*\w+=/;
+ } else {
+ $cf->{ld} =~ s/^(\s*\w+=)/env $1/;
+ }
+
+ return $self->SUPER::link(@_);
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/VMS.pm b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/VMS.pm
new file mode 100644
index 00000000000..35a2eba550b
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/VMS.pm
@@ -0,0 +1,294 @@
+package ExtUtils::CBuilder::Platform::VMS;
+
+use strict;
+use ExtUtils::CBuilder::Base;
+
+use vars qw($VERSION @ISA);
+$VERSION = '0.27';
+@ISA = qw(ExtUtils::CBuilder::Base);
+
+use File::Spec::Functions qw(catfile catdir);
+
+# We do prelink, but don't want the parent to redo it.
+
+sub need_prelink { 0 }
+
+sub arg_defines {
+ my ($self, %args) = @_;
+
+ s/"/""/g foreach values %args;
+
+ my @config_defines;
+
+ # VMS can only have one define qualifier; add the one from config, if any.
+ if ($self->{config}{ccflags} =~ s{/ def[^=]+ =+ \(? ([^\/\)]*) } {}ix) {
+ push @config_defines, $1;
+ }
+
+ return '' unless keys(%args) || @config_defines;
+
+ return ('/define=('
+ . join(',',
+ @config_defines,
+ map "\"$_" . ( length($args{$_}) ? "=$args{$_}" : '') . "\"",
+ keys %args)
+ . ')');
+}
+
+sub arg_include_dirs {
+ my ($self, @dirs) = @_;
+
+ # VMS can only have one include list, add the one from config.
+ if ($self->{config}{ccflags} =~ s{/inc[^=]+(?:=)+(?:\()?([^\/\)]*)} {}i) {
+ unshift @dirs, $1;
+ }
+ return unless @dirs;
+
+ return ('/include=(' . join(',', @dirs) . ')');
+}
+
+sub _do_link {
+ my ($self, $type, %args) = @_;
+
+ my $objects = delete $args{objects};
+ $objects = [$objects] unless ref $objects;
+
+ if ($args{lddl}) {
+
+ # prelink will call Mksymlists, which creates the extension-specific
+ # linker options file and populates it with the boot symbol.
+
+ my @temp_files = $self->prelink(%args, dl_name => $args{module_name});
+
+ # We now add the rest of what we need to the linker options file. We
+ # should replicate the functionality of C<ExtUtils::MM_VMS::dlsyms>,
+ # but there is as yet no infrastructure for handling object libraries,
+ # so for now we depend on object files being listed individually on the
+ # command line, which should work for simple cases. We do bring in our
+ # own version of C<ExtUtils::Liblist::Kid::ext> so that any additional
+ # libraries (including PERLSHR) can be added to the options file.
+
+ my @optlibs = $self->_liblist_ext( $args{'libs'} );
+
+ my $optfile = 'sys$disk:[]' . $temp_files[0];
+ open my $opt_fh, '>>', $optfile
+ or die "_do_link: Unable to open $optfile: $!";
+ for my $lib (@optlibs) {print $opt_fh "$lib\n" if length $lib }
+ close $opt_fh;
+
+ $objects->[-1] .= ',';
+ push @$objects, $optfile . '/OPTIONS,';
+
+ # This one not needed for DEC C, but leave for completeness.
+ push @$objects, $self->perl_inc() . 'perlshr_attr.opt/OPTIONS';
+ }
+
+ return $self->SUPER::_do_link($type, %args, objects => $objects);
+}
+
+sub arg_nolink { return; }
+
+sub arg_object_file {
+ my ($self, $file) = @_;
+ return "/obj=$file";
+}
+
+sub arg_exec_file {
+ my ($self, $file) = @_;
+ return ("/exe=$file");
+}
+
+sub arg_share_object_file {
+ my ($self, $file) = @_;
+ return ("$self->{config}{lddlflags}=$file");
+}
+
+
+sub lib_file {
+ my ($self, $dl_file) = @_;
+ $dl_file =~ s/\.[^.]+$//;
+ $dl_file =~ tr/"//d;
+ $dl_file = $dl_file .= '.' . $self->{config}{dlext};
+
+ # Need to create with the same name as DynaLoader will load with.
+ if (defined &DynaLoader::mod2fname) {
+ my ($dev,$dir,$file) = File::Spec->splitpath($dl_file);
+ $file = DynaLoader::mod2fname([$file]);
+ $dl_file = File::Spec->catpath($dev,$dir,$file);
+ }
+ return $dl_file;
+}
+
+# The following is reproduced almost verbatim from ExtUtils::Liblist::Kid::_vms_ext.
+# We can't just call that because it's tied up with the MakeMaker object hierarchy.
+
+sub _liblist_ext {
+ my($self, $potential_libs,$verbose,$give_libs) = @_;
+ $verbose ||= 0;
+
+ my(@crtls,$crtlstr);
+ @crtls = ( ($self->{'config'}{'ldflags'} =~ m-/Debug-i ? $self->{'config'}{'dbgprefix'} : '')
+ . 'PerlShr/Share' );
+ push(@crtls, grep { not /\(/ } split /\s+/, $self->{'config'}{'perllibs'});
+ push(@crtls, grep { not /\(/ } split /\s+/, $self->{'config'}{'libc'});
+ # In general, we pass through the basic libraries from %Config unchanged.
+ # The one exception is that if we're building in the Perl source tree, and
+ # a library spec could be resolved via a logical name, we go to some trouble
+ # to ensure that the copy in the local tree is used, rather than one to
+ # which a system-wide logical may point.
+ if ($self->perl_src) {
+ my($lib,$locspec,$type);
+ foreach $lib (@crtls) {
+ if (($locspec,$type) = $lib =~ m{^([\w\$-]+)(/\w+)?} and $locspec =~ /perl/i) {
+ if (lc $type eq '/share') { $locspec .= $self->{'config'}{'exe_ext'}; }
+ elsif (lc $type eq '/library') { $locspec .= $self->{'config'}{'lib_ext'}; }
+ else { $locspec .= $self->{'config'}{'obj_ext'}; }
+ $locspec = catfile($self->perl_src, $locspec);
+ $lib = "$locspec$type" if -e $locspec;
+ }
+ }
+ }
+ $crtlstr = @crtls ? join(' ',@crtls) : '';
+
+ unless ($potential_libs) {
+ warn "Result:\n\tEXTRALIBS: \n\tLDLOADLIBS: $crtlstr\n" if $verbose;
+ return ('', '', $crtlstr, '', ($give_libs ? [] : ()));
+ }
+
+ my(@dirs,@libs,$dir,$lib,%found,@fndlibs,$ldlib);
+ my $cwd = cwd();
+ my($so,$lib_ext,$obj_ext) = @{$self->{'config'}}{'so','lib_ext','obj_ext'};
+ # List of common Unix library names and their VMS equivalents
+ # (VMS equivalent of '' indicates that the library is automatically
+ # searched by the linker, and should be skipped here.)
+ my(@flibs, %libs_seen);
+ my %libmap = ( 'm' => '', 'f77' => '', 'F77' => '', 'V77' => '', 'c' => '',
+ 'malloc' => '', 'crypt' => '', 'resolv' => '', 'c_s' => '',
+ 'socket' => '', 'X11' => 'DECW$XLIBSHR',
+ 'Xt' => 'DECW$XTSHR', 'Xm' => 'DECW$XMLIBSHR',
+ 'Xmu' => 'DECW$XMULIBSHR');
+ if ($self->{'config'}{'vms_cc_type'} ne 'decc') { $libmap{'curses'} = 'VAXCCURSE'; }
+
+ warn "Potential libraries are '$potential_libs'\n" if $verbose;
+
+ # First, sort out directories and library names in the input
+ foreach $lib (split ' ',$potential_libs) {
+ push(@dirs,$1), next if $lib =~ /^-L(.*)/;
+ push(@dirs,$lib), next if $lib =~ /[:>\]]$/;
+ push(@dirs,$lib), next if -d $lib;
+ push(@libs,$1), next if $lib =~ /^-l(.*)/;
+ push(@libs,$lib);
+ }
+ push(@dirs,split(' ',$self->{'config'}{'libpth'}));
+
+ # Now make sure we've got VMS-syntax absolute directory specs
+ # (We don't, however, check whether someone's hidden a relative
+ # path in a logical name.)
+ foreach $dir (@dirs) {
+ unless (-d $dir) {
+ warn "Skipping nonexistent Directory $dir\n" if $verbose > 1;
+ $dir = '';
+ next;
+ }
+ warn "Resolving directory $dir\n" if $verbose;
+ if (!File::Spec->file_name_is_absolute($dir)) {
+ $dir = catdir($cwd,$dir);
+ }
+ }
+ @dirs = grep { length($_) } @dirs;
+ unshift(@dirs,''); # Check each $lib without additions first
+
+ LIB: foreach $lib (@libs) {
+ if (exists $libmap{$lib}) {
+ next unless length $libmap{$lib};
+ $lib = $libmap{$lib};
+ }
+
+ my(@variants,$variant,$cand);
+ my($ctype) = '';
+
+ # If we don't have a file type, consider it a possibly abbreviated name and
+ # check for common variants. We try these first to grab libraries before
+ # a like-named executable image (e.g. -lperl resolves to perlshr.exe
+ # before perl.exe).
+ if ($lib !~ /\.[^:>\]]*$/) {
+ push(@variants,"${lib}shr","${lib}rtl","${lib}lib");
+ push(@variants,"lib$lib") if $lib !~ /[:>\]]/;
+ }
+ push(@variants,$lib);
+ warn "Looking for $lib\n" if $verbose;
+ foreach $variant (@variants) {
+ my($fullname, $name);
+
+ foreach $dir (@dirs) {
+ my($type);
+
+ $name = "$dir$variant";
+ warn "\tChecking $name\n" if $verbose > 2;
+ $fullname = VMS::Filespec::rmsexpand($name);
+ if (defined $fullname and -f $fullname) {
+ # It's got its own suffix, so we'll have to figure out the type
+ if ($fullname =~ /(?:$so|exe)$/i) { $type = 'SHR'; }
+ elsif ($fullname =~ /(?:$lib_ext|olb)$/i) { $type = 'OLB'; }
+ elsif ($fullname =~ /(?:$obj_ext|obj)$/i) {
+ warn "Note (probably harmless): "
+ ."Plain object file $fullname found in library list\n";
+ $type = 'OBJ';
+ }
+ else {
+ warn "Note (probably harmless): "
+ ."Unknown library type for $fullname; assuming shared\n";
+ $type = 'SHR';
+ }
+ }
+ elsif (-f ($fullname = VMS::Filespec::rmsexpand($name,$so)) or
+ -f ($fullname = VMS::Filespec::rmsexpand($name,'.exe'))) {
+ $type = 'SHR';
+ $name = $fullname unless $fullname =~ /exe;?\d*$/i;
+ }
+ elsif (not length($ctype) and # If we've got a lib already,
+ # don't bother
+ ( -f ($fullname = VMS::Filespec::rmsexpand($name,$lib_ext)) or
+ -f ($fullname = VMS::Filespec::rmsexpand($name,'.olb')))) {
+ $type = 'OLB';
+ $name = $fullname unless $fullname =~ /olb;?\d*$/i;
+ }
+ elsif (not length($ctype) and # If we've got a lib already,
+ # don't bother
+ ( -f ($fullname = VMS::Filespec::rmsexpand($name,$obj_ext)) or
+ -f ($fullname = VMS::Filespec::rmsexpand($name,'.obj')))) {
+ warn "Note (probably harmless): "
+ ."Plain object file $fullname found in library list\n";
+ $type = 'OBJ';
+ $name = $fullname unless $fullname =~ /obj;?\d*$/i;
+ }
+ if (defined $type) {
+ $ctype = $type; $cand = $name;
+ last if $ctype eq 'SHR';
+ }
+ }
+ if ($ctype) {
+ # This has to precede any other CRTLs, so just make it first
+ if ($cand eq 'VAXCCURSE') { unshift @{$found{$ctype}}, $cand; }
+ else { push @{$found{$ctype}}, $cand; }
+ warn "\tFound as $cand (really $fullname), type $ctype\n"
+ if $verbose > 1;
+ push @flibs, $name unless $libs_seen{$fullname}++;
+ next LIB;
+ }
+ }
+ warn "Note (probably harmless): "
+ ."No library found for $lib\n";
+ }
+
+ push @fndlibs, @{$found{OBJ}} if exists $found{OBJ};
+ push @fndlibs, map { "$_/Library" } @{$found{OLB}} if exists $found{OLB};
+ push @fndlibs, map { "$_/Share" } @{$found{SHR}} if exists $found{SHR};
+ $lib = join(' ',@fndlibs);
+
+ $ldlib = $crtlstr ? "$lib $crtlstr" : $lib;
+ warn "Result:\n\tEXTRALIBS: $lib\n\tLDLOADLIBS: $ldlib\n" if $verbose;
+ wantarray ? ($lib, '', $ldlib, '', ($give_libs ? \@flibs : ())) : $lib;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Windows.pm b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Windows.pm
new file mode 100644
index 00000000000..f0b98dbaa30
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Windows.pm
@@ -0,0 +1,288 @@
+package ExtUtils::CBuilder::Platform::Windows;
+
+use strict;
+use warnings;
+
+use File::Basename;
+use File::Spec;
+
+use ExtUtils::CBuilder::Base;
+use IO::File;
+
+use vars qw($VERSION @ISA);
+$VERSION = '0.27';
+@ISA = qw(ExtUtils::CBuilder::Base);
+
+=begin comment
+
+The compiler-specific packages implement functions for generating properly
+formatted commandlines for the compiler being used. Each package
+defines two primary functions 'format_linker_cmd()' &
+'format_compiler_cmd()' that accepts a list of named arguments (a
+hash) and returns a list of formatted options suitable for invoking the
+compiler. By default, if the compiler supports scripting of its
+operation then a script file is built containing the options while
+those options are removed from the commandline, and a reference to the
+script is pushed onto the commandline in their place. Scripting the
+compiler in this way helps to avoid the problems associated with long
+commandlines under some shells.
+
+=end comment
+
+=cut
+
+sub new {
+ my $class = shift;
+ my $self = $class->SUPER::new(@_);
+ my $cf = $self->{config};
+
+ # Inherit from an appropriate compiler driver class
+ my $driver = "ExtUtils::CBuilder::Platform::Windows::" . $self->_compiler_type;
+ eval "require $driver" or die "Could not load compiler driver: $@";
+ unshift @ISA, $driver;
+
+ return $self;
+}
+
+sub _compiler_type {
+ my $self = shift;
+ my $cc = $self->{config}{cc};
+
+ return ( $cc =~ /cl(\.exe)?$/ ? 'MSVC'
+ : $cc =~ /bcc32(\.exe)?$/ ? 'BCC'
+ : 'GCC');
+}
+
+sub split_like_shell {
+ # Since Windows will pass the whole command string (not an argument
+ # array) to the target program and make the program parse it itself,
+ # we don't actually need to do any processing here.
+ (my $self, local $_) = @_;
+
+ return @$_ if defined() && UNIVERSAL::isa($_, 'ARRAY');
+ return unless defined() && length();
+ return ($_);
+}
+
+sub do_system {
+ # See above
+ my $self = shift;
+ my $cmd = join(" ",
+ grep length,
+ map {$a=$_;$a=~s/\t/ /g;$a=~s/^\s+|\s+$//;$a}
+ grep defined, @_);
+ return $self->SUPER::do_system($cmd);
+}
+
+sub arg_defines {
+ my ($self, %args) = @_;
+ s/"/\\"/g foreach values %args;
+ return map qq{"-D$_=$args{$_}"}, keys %args;
+}
+
+sub compile {
+ my ($self, %args) = @_;
+ my $cf = $self->{config};
+
+ die "Missing 'source' argument to compile()" unless defined $args{source};
+
+ my ($basename, $srcdir) =
+ ( File::Basename::fileparse($args{source}, '\.[^.]+$') )[0,1];
+
+ $srcdir ||= File::Spec->curdir();
+
+ my @defines = $self->arg_defines( %{ $args{defines} || {} } );
+
+ my %spec = (
+ srcdir => $srcdir,
+ builddir => $srcdir,
+ basename => $basename,
+ source => $args{source},
+ output => File::Spec->catfile($srcdir, $basename) . $cf->{obj_ext},
+ cc => $cf->{cc},
+ cflags => [
+ $self->split_like_shell($cf->{ccflags}),
+ $self->split_like_shell($cf->{cccdlflags}),
+ $self->split_like_shell($args{extra_compiler_flags}),
+ ],
+ optimize => [ $self->split_like_shell($cf->{optimize}) ],
+ defines => \@defines,
+ includes => [ @{$args{include_dirs} || []} ],
+ perlinc => [
+ $self->perl_inc(),
+ $self->split_like_shell($cf->{incpath}),
+ ],
+ use_scripts => 1, # XXX provide user option to change this???
+ );
+
+ $self->normalize_filespecs(
+ \$spec{source},
+ \$spec{output},
+ $spec{includes},
+ $spec{perlinc},
+ );
+
+ my @cmds = $self->format_compiler_cmd(%spec);
+ while ( my $cmd = shift @cmds ) {
+ $self->do_system( @$cmd )
+ or die "error building $cf->{dlext} file from '$args{source}'";
+ }
+
+ (my $out = $spec{output}) =~ tr/'"//d;
+ return $out;
+}
+
+sub need_prelink { 1 }
+
+sub link {
+ my ($self, %args) = @_;
+ my $cf = $self->{config};
+
+ my @objects = ( ref $args{objects} eq 'ARRAY' ? @{$args{objects}} : $args{objects} );
+ my $to = join '', (File::Spec->splitpath($objects[0]))[0,1];
+ $to ||= File::Spec->curdir();
+
+ (my $file_base = $args{module_name}) =~ s/.*:://;
+ my $output = $args{lib_file} ||
+ File::Spec->catfile($to, "$file_base.$cf->{dlext}");
+
+ # if running in perl source tree, look for libs there, not installed
+ my $lddlflags = $cf->{lddlflags};
+ my $perl_src = $self->perl_src();
+ $lddlflags =~ s/\Q$cf->{archlibexp}\E[\\\/]CORE/$perl_src/ if $perl_src;
+
+ my %spec = (
+ srcdir => $to,
+ builddir => $to,
+ startup => [ ],
+ objects => \@objects,
+ libs => [ ],
+ output => $output,
+ ld => $cf->{ld},
+ libperl => $cf->{libperl},
+ perllibs => [ $self->split_like_shell($cf->{perllibs}) ],
+ libpath => [ $self->split_like_shell($cf->{libpth}) ],
+ lddlflags => [ $self->split_like_shell($lddlflags) ],
+ other_ldflags => [ $self->split_like_shell($args{extra_linker_flags} || '') ],
+ use_scripts => 1, # XXX provide user option to change this???
+ );
+
+ unless ( $spec{basename} ) {
+ ($spec{basename} = $args{module_name}) =~ s/.*:://;
+ }
+
+ $spec{srcdir} = File::Spec->canonpath( $spec{srcdir} );
+ $spec{builddir} = File::Spec->canonpath( $spec{builddir} );
+
+ $spec{output} ||= File::Spec->catfile( $spec{builddir},
+ $spec{basename} . '.'.$cf->{dlext} );
+ $spec{manifest} ||= File::Spec->catfile( $spec{builddir},
+ $spec{basename} . '.'.$cf->{dlext}.'.manifest');
+ $spec{implib} ||= File::Spec->catfile( $spec{builddir},
+ $spec{basename} . $cf->{lib_ext} );
+ $spec{explib} ||= File::Spec->catfile( $spec{builddir},
+ $spec{basename} . '.exp' );
+ if ($cf->{cc} eq 'cl') {
+ $spec{dbg_file} ||= File::Spec->catfile( $spec{builddir},
+ $spec{basename} . '.pdb' );
+ }
+ elsif ($cf->{cc} eq 'bcc32') {
+ $spec{dbg_file} ||= File::Spec->catfile( $spec{builddir},
+ $spec{basename} . '.tds' );
+ }
+ $spec{def_file} ||= File::Spec->catfile( $spec{srcdir} ,
+ $spec{basename} . '.def' );
+ $spec{base_file} ||= File::Spec->catfile( $spec{srcdir} ,
+ $spec{basename} . '.base' );
+
+ $self->add_to_cleanup(
+ grep defined,
+ @{[ @spec{qw(manifest implib explib dbg_file def_file base_file map_file)} ]}
+ );
+
+ foreach my $opt ( qw(output manifest implib explib dbg_file def_file map_file base_file) ) {
+ $self->normalize_filespecs( \$spec{$opt} );
+ }
+
+ foreach my $opt ( qw(libpath startup objects) ) {
+ $self->normalize_filespecs( $spec{$opt} );
+ }
+
+ (my $def_base = $spec{def_file}) =~ tr/'"//d;
+ $def_base =~ s/\.def$//;
+ $self->prelink( dl_name => $args{module_name},
+ dl_file => $def_base,
+ dl_base => $spec{basename} );
+
+ my @cmds = $self->format_linker_cmd(%spec);
+ while ( my $cmd = shift @cmds ) {
+ $self->do_system( @$cmd );
+ }
+
+ $spec{output} =~ tr/'"//d;
+ return wantarray
+ ? grep defined, @spec{qw[output manifest implib explib dbg_file def_file map_file base_file]}
+ : $spec{output};
+}
+
+# canonize & quote paths
+sub normalize_filespecs {
+ my ($self, @specs) = @_;
+ foreach my $spec ( grep defined, @specs ) {
+ if ( ref $spec eq 'ARRAY') {
+ $self->normalize_filespecs( map {\$_} grep defined, @$spec )
+ } elsif ( ref $spec eq 'SCALAR' ) {
+ $$spec =~ tr/"//d if $$spec;
+ next unless $$spec;
+ $$spec = '"' . File::Spec->canonpath($$spec) . '"';
+ } elsif ( ref $spec eq '' ) {
+ $spec = '"' . File::Spec->canonpath($spec) . '"';
+ } else {
+ die "Don't know how to normalize " . (ref $spec || $spec) . "\n";
+ }
+ }
+}
+
+# directory of perl's include files
+sub perl_inc {
+ my $self = shift;
+
+ my $perl_src = $self->perl_src();
+
+ if ($perl_src) {
+ File::Spec->catdir($perl_src, "lib", "CORE");
+ } else {
+ File::Spec->catdir($self->{config}{archlibexp},"CORE");
+ }
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+ExtUtils::CBuilder::Platform::Windows - Builder class for Windows platforms
+
+=head1 DESCRIPTION
+
+This module implements the Windows-specific parts of ExtUtils::CBuilder.
+Most of the Windows-specific stuff has to do with compiling and
+linking C code. Currently we support the 3 compilers perl itself
+supports: MSVC, BCC, and GCC.
+
+This module inherits from C<ExtUtils::CBuilder::Base>, so any functionality
+not implemented here will be implemented there. The interfaces are
+defined by the L<ExtUtils::CBuilder> documentation.
+
+=head1 AUTHOR
+
+Ken Williams <ken@mathforum.org>
+
+Most of the code here was written by Randy W. Sims <RandyS@ThePierianSpring.org>.
+
+=head1 SEE ALSO
+
+perl(1), ExtUtils::CBuilder(3), ExtUtils::MakeMaker(3)
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Windows/BCC.pm b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Windows/BCC.pm
new file mode 100644
index 00000000000..ee65c91a159
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Windows/BCC.pm
@@ -0,0 +1,130 @@
+package ExtUtils::CBuilder::Platform::Windows::BCC;
+
+use vars qw($VERSION);
+$VERSION = '0.27';
+
+sub format_compiler_cmd {
+ my ($self, %spec) = @_;
+
+ foreach my $path ( @{ $spec{includes} || [] },
+ @{ $spec{perlinc} || [] } ) {
+ $path = '-I' . $path;
+ }
+
+ %spec = $self->write_compiler_script(%spec)
+ if $spec{use_scripts};
+
+ return [ grep {defined && length} (
+ $spec{cc}, '-c' ,
+ @{$spec{includes}} ,
+ @{$spec{cflags}} ,
+ @{$spec{optimize}} ,
+ @{$spec{defines}} ,
+ @{$spec{perlinc}} ,
+ "-o$spec{output}" ,
+ $spec{source} ,
+ ) ];
+}
+
+sub write_compiler_script {
+ my ($self, %spec) = @_;
+
+ my $script = File::Spec->catfile( $spec{srcdir},
+ $spec{basename} . '.ccs' );
+
+ $self->add_to_cleanup($script);
+
+ print "Generating script '$script'\n" if !$self->{quiet};
+
+ my $SCRIPT = IO::File->new( ">$script" )
+ or die( "Could not create script '$script': $!" );
+
+ # XXX Borland "response files" seem to be unable to accept macro
+ # definitions containing quoted strings. Escaping strings with
+ # backslash doesn't work, and any level of quotes are stripped. The
+ # result is is a floating point number in the source file where a
+ # string is expected. So we leave the macros on the command line.
+ print $SCRIPT join( "\n",
+ map { ref $_ ? @{$_} : $_ }
+ grep defined,
+ delete(
+ @spec{ qw(includes cflags optimize perlinc) } )
+ );
+
+ push @{$spec{includes}}, '@"' . $script . '"';
+
+ return %spec;
+}
+
+sub format_linker_cmd {
+ my ($self, %spec) = @_;
+
+ foreach my $path ( @{$spec{libpath}} ) {
+ $path = "-L$path";
+ }
+
+ push( @{$spec{startup}}, 'c0d32.obj' )
+ unless ( $spec{starup} && @{$spec{startup}} );
+
+ %spec = $self->write_linker_script(%spec)
+ if $spec{use_scripts};
+
+ return [ grep {defined && length} (
+ $spec{ld} ,
+ @{$spec{lddlflags}} ,
+ @{$spec{libpath}} ,
+ @{$spec{other_ldflags}} ,
+ @{$spec{startup}} ,
+ @{$spec{objects}} , ',',
+ $spec{output} , ',',
+ $spec{map_file} , ',',
+ $spec{libperl} ,
+ @{$spec{perllibs}} , ',',
+ $spec{def_file}
+ ) ];
+}
+
+sub write_linker_script {
+ my ($self, %spec) = @_;
+
+ # To work around Borlands "unique" commandline syntax,
+ # two scripts are used:
+
+ my $ld_script = File::Spec->catfile( $spec{srcdir},
+ $spec{basename} . '.lds' );
+ my $ld_libs = File::Spec->catfile( $spec{srcdir},
+ $spec{basename} . '.lbs' );
+
+ $self->add_to_cleanup($ld_script, $ld_libs);
+
+ print "Generating scripts '$ld_script' and '$ld_libs'.\n" if !$self->{quiet};
+
+ # Script 1: contains options & names of object files.
+ my $LD_SCRIPT = IO::File->new( ">$ld_script" )
+ or die( "Could not create linker script '$ld_script': $!" );
+
+ print $LD_SCRIPT join( " +\n",
+ map { @{$_} }
+ grep defined,
+ delete(
+ @spec{ qw(lddlflags libpath other_ldflags startup objects) } )
+ );
+
+ # Script 2: contains name of libs to link against.
+ my $LD_LIBS = IO::File->new( ">$ld_libs" )
+ or die( "Could not create linker script '$ld_libs': $!" );
+
+ print $LD_LIBS join( " +\n",
+ (delete $spec{libperl} || ''),
+ @{delete $spec{perllibs} || []},
+ );
+
+ push @{$spec{lddlflags}}, '@"' . $ld_script . '"';
+ push @{$spec{perllibs}}, '@"' . $ld_libs . '"';
+
+ return %spec;
+}
+
+1;
+
+
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Windows/GCC.pm b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Windows/GCC.pm
new file mode 100644
index 00000000000..132bf842bdb
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Windows/GCC.pm
@@ -0,0 +1,151 @@
+package ExtUtils::CBuilder::Platform::Windows::GCC;
+
+use vars qw($VERSION);
+$VERSION = '0.27';
+
+sub format_compiler_cmd {
+ my ($self, %spec) = @_;
+
+ foreach my $path ( @{ $spec{includes} || [] },
+ @{ $spec{perlinc} || [] } ) {
+ $path = '-I' . $path;
+ }
+
+ # split off any -arguments included in cc
+ my @cc = split / (?=-)/, $spec{cc};
+
+ return [ grep {defined && length} (
+ @cc, '-c' ,
+ @{$spec{includes}} ,
+ @{$spec{cflags}} ,
+ @{$spec{optimize}} ,
+ @{$spec{defines}} ,
+ @{$spec{perlinc}} ,
+ '-o', $spec{output} ,
+ $spec{source} ,
+ ) ];
+}
+
+sub format_linker_cmd {
+ my ($self, %spec) = @_;
+ my $cf = $self->{config};
+
+ # The Config.pm variable 'libperl' is hardcoded to the full name
+ # of the perl import library (i.e. 'libperl56.a'). GCC will not
+ # find it unless the 'lib' prefix & the extension are stripped.
+ $spec{libperl} =~ s/^(?:lib)?([^.]+).*$/-l$1/;
+
+ unshift( @{$spec{other_ldflags}}, '-nostartfiles' )
+ if ( $spec{startup} && @{$spec{startup}} );
+
+ # From ExtUtils::MM_Win32:
+ #
+ ## one thing for GCC/Mingw32:
+ ## we try to overcome non-relocateable-DLL problems by generating
+ ## a (hopefully unique) image-base from the dll's name
+ ## -- BKS, 10-19-1999
+ File::Basename::basename( $spec{output} ) =~ /(....)(.{0,4})/;
+ $spec{image_base} = sprintf( "0x%x0000", unpack('n', $1 ^ $2) );
+
+ %spec = $self->write_linker_script(%spec)
+ if $spec{use_scripts};
+
+ foreach my $path ( @{$spec{libpath}} ) {
+ $path = "-L$path";
+ }
+
+ my @cmds; # Stores the series of commands needed to build the module.
+
+ my $DLLTOOL = $cf->{dlltool} || 'dlltool';
+
+ push @cmds, [
+ $DLLTOOL, '--def' , $spec{def_file},
+ '--output-exp' , $spec{explib}
+ ];
+
+ # split off any -arguments included in ld
+ my @ld = split / (?=-)/, $spec{ld};
+
+ push @cmds, [ grep {defined && length} (
+ @ld ,
+ '-o', $spec{output} ,
+ "-Wl,--base-file,$spec{base_file}" ,
+ "-Wl,--image-base,$spec{image_base}" ,
+ @{$spec{lddlflags}} ,
+ @{$spec{libpath}} ,
+ @{$spec{startup}} ,
+ @{$spec{objects}} ,
+ @{$spec{other_ldflags}} ,
+ $spec{libperl} ,
+ @{$spec{perllibs}} ,
+ $spec{explib} ,
+ $spec{map_file} ? ('-Map', $spec{map_file}) : ''
+ ) ];
+
+ push @cmds, [
+ $DLLTOOL, '--def' , $spec{def_file},
+ '--output-exp' , $spec{explib},
+ '--base-file' , $spec{base_file}
+ ];
+
+ push @cmds, [ grep {defined && length} (
+ @ld ,
+ '-o', $spec{output} ,
+ "-Wl,--image-base,$spec{image_base}" ,
+ @{$spec{lddlflags}} ,
+ @{$spec{libpath}} ,
+ @{$spec{startup}} ,
+ @{$spec{objects}} ,
+ @{$spec{other_ldflags}} ,
+ $spec{libperl} ,
+ @{$spec{perllibs}} ,
+ $spec{explib} ,
+ $spec{map_file} ? ('-Map', $spec{map_file}) : ''
+ ) ];
+
+ return @cmds;
+}
+
+sub write_linker_script {
+ my ($self, %spec) = @_;
+
+ my $script = File::Spec->catfile( $spec{srcdir},
+ $spec{basename} . '.lds' );
+
+ $self->add_to_cleanup($script);
+
+ print "Generating script '$script'\n" if !$self->{quiet};
+
+ my $SCRIPT = IO::File->new( ">$script" )
+ or die( "Could not create script '$script': $!" );
+
+ print $SCRIPT ( 'SEARCH_DIR(' . $_ . ")\n" )
+ for @{delete $spec{libpath} || []};
+
+ # gcc takes only one startup file, so the first object in startup is
+ # specified as the startup file and any others are shifted into the
+ # beginning of the list of objects.
+ if ( $spec{startup} && @{$spec{startup}} ) {
+ print $SCRIPT 'STARTUP(' . shift( @{$spec{startup}} ) . ")\n";
+ unshift @{$spec{objects}},
+ @{delete $spec{startup} || []};
+ }
+
+ print $SCRIPT 'INPUT(' . join( ',',
+ @{delete $spec{objects} || []}
+ ) . ")\n";
+
+ print $SCRIPT 'INPUT(' . join( ' ',
+ (delete $spec{libperl} || ''),
+ @{delete $spec{perllibs} || []},
+ ) . ")\n";
+
+ #it is important to keep the order 1.linker_script - 2.other_ldflags
+ unshift @{$spec{other_ldflags}}, '"' . $script . '"';
+
+ return %spec;
+}
+
+1;
+
+
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Windows/MSVC.pm b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Windows/MSVC.pm
new file mode 100644
index 00000000000..7da1c9b4c12
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/Windows/MSVC.pm
@@ -0,0 +1,131 @@
+package ExtUtils::CBuilder::Platform::Windows::MSVC;
+
+use vars qw($VERSION);
+$VERSION = '0.27';
+
+sub arg_exec_file {
+ my ($self, $file) = @_;
+ return "/OUT:$file";
+}
+
+sub format_compiler_cmd {
+ my ($self, %spec) = @_;
+
+ foreach my $path ( @{ $spec{includes} || [] },
+ @{ $spec{perlinc} || [] } ) {
+ $path = '-I' . $path;
+ }
+
+ %spec = $self->write_compiler_script(%spec)
+ if $spec{use_scripts};
+
+ return [ grep {defined && length} (
+ $spec{cc},'-nologo','-c',
+ @{$spec{includes}} ,
+ @{$spec{cflags}} ,
+ @{$spec{optimize}} ,
+ @{$spec{defines}} ,
+ @{$spec{perlinc}} ,
+ "-Fo$spec{output}" ,
+ $spec{source} ,
+ ) ];
+}
+
+sub write_compiler_script {
+ my ($self, %spec) = @_;
+
+ my $script = File::Spec->catfile( $spec{srcdir},
+ $spec{basename} . '.ccs' );
+
+ $self->add_to_cleanup($script);
+ print "Generating script '$script'\n" if !$self->{quiet};
+
+ my $SCRIPT = IO::File->new( ">$script" )
+ or die( "Could not create script '$script': $!" );
+
+ print $SCRIPT join( "\n",
+ map { ref $_ ? @{$_} : $_ }
+ grep defined,
+ delete(
+ @spec{ qw(includes cflags optimize defines perlinc) } )
+ );
+
+ push @{$spec{includes}}, '@"' . $script . '"';
+
+ return %spec;
+}
+
+sub format_linker_cmd {
+ my ($self, %spec) = @_;
+ my $cf = $self->{config};
+
+ foreach my $path ( @{$spec{libpath}} ) {
+ $path = "-libpath:$path";
+ }
+
+ my $output = $spec{output};
+
+ $spec{def_file} &&= '-def:' . $spec{def_file};
+ $spec{output} &&= '-out:' . $spec{output};
+ $spec{manifest} &&= '-manifest ' . $spec{manifest};
+ $spec{implib} &&= '-implib:' . $spec{implib};
+ $spec{map_file} &&= '-map:' . $spec{map_file};
+
+ %spec = $self->write_linker_script(%spec)
+ if $spec{use_scripts};
+
+ my @cmds; # Stores the series of commands needed to build the module.
+
+ push @cmds, [ grep {defined && length} (
+ $spec{ld} ,
+ @{$spec{lddlflags}} ,
+ @{$spec{libpath}} ,
+ @{$spec{other_ldflags}} ,
+ @{$spec{startup}} ,
+ @{$spec{objects}} ,
+ $spec{map_file} ,
+ $spec{libperl} ,
+ @{$spec{perllibs}} ,
+ $spec{def_file} ,
+ $spec{implib} ,
+ $spec{output} ,
+ ) ];
+
+ # Embed the manifest file if it exists
+ push @cmds, [
+ 'if', 'exist', $spec{manifest}, 'mt', '-nologo', $spec{manifest}, '-outputresource:' . "$output;2"
+ ];
+
+ return @cmds;
+}
+
+sub write_linker_script {
+ my ($self, %spec) = @_;
+
+ my $script = File::Spec->catfile( $spec{srcdir},
+ $spec{basename} . '.lds' );
+
+ $self->add_to_cleanup($script);
+
+ print "Generating script '$script'\n" if !$self->{quiet};
+
+ my $SCRIPT = IO::File->new( ">$script" )
+ or die( "Could not create script '$script': $!" );
+
+ print $SCRIPT join( "\n",
+ map { ref $_ ? @{$_} : $_ }
+ grep defined,
+ delete(
+ @spec{ qw(lddlflags libpath other_ldflags
+ startup objects libperl perllibs
+ def_file implib map_file) } )
+ );
+
+ push @{$spec{lddlflags}}, '@"' . $script . '"';
+
+ return %spec;
+}
+
+1;
+
+
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/aix.pm b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/aix.pm
new file mode 100644
index 00000000000..656e0dc67ff
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/aix.pm
@@ -0,0 +1,31 @@
+package ExtUtils::CBuilder::Platform::aix;
+
+use strict;
+use ExtUtils::CBuilder::Platform::Unix;
+use File::Spec;
+
+use vars qw($VERSION @ISA);
+$VERSION = '0.27';
+@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
+
+sub need_prelink { 1 }
+
+sub link {
+ my ($self, %args) = @_;
+ my $cf = $self->{config};
+
+ (my $baseext = $args{module_name}) =~ s/.*:://;
+ my $perl_inc = $self->perl_inc();
+
+ # Massage some very naughty bits in %Config
+ local $cf->{lddlflags} = $cf->{lddlflags};
+ for ($cf->{lddlflags}) {
+ s/\Q$(BASEEXT)\E/$baseext/;
+ s/\Q$(PERL_INC)\E/$perl_inc/;
+ }
+
+ return $self->SUPER::link(%args);
+}
+
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/cygwin.pm b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/cygwin.pm
new file mode 100644
index 00000000000..f8650978ec4
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/cygwin.pm
@@ -0,0 +1,33 @@
+package ExtUtils::CBuilder::Platform::cygwin;
+
+use strict;
+use File::Spec;
+use ExtUtils::CBuilder::Platform::Unix;
+
+use vars qw($VERSION @ISA);
+$VERSION = '0.27';
+@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
+
+# TODO: If a specific exe_file name is requested, if the exe created
+# doesn't have that name, we might want to rename it. Apparently asking
+# for an exe of "foo" might result in "foo.exe". Alternatively, we should
+# make sure the return value is correctly "foo.exe".
+# C.f http://rt.cpan.org/Public/Bug/Display.html?id=41003
+sub link_executable {
+ my $self = shift;
+ return $self->SUPER::link_executable(@_);
+}
+
+sub link {
+ my ($self, %args) = @_;
+
+ my $lib = $self->{config}{useshrplib} ? 'libperl.dll.a' : 'libperl.a';
+ $args{extra_linker_flags} = [
+ File::Spec->catfile($self->perl_inc(), $lib),
+ $self->split_like_shell($args{extra_linker_flags})
+ ];
+
+ return $self->SUPER::link(%args);
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/darwin.pm b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/darwin.pm
new file mode 100644
index 00000000000..efc79347708
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/darwin.pm
@@ -0,0 +1,22 @@
+package ExtUtils::CBuilder::Platform::darwin;
+
+use strict;
+use ExtUtils::CBuilder::Platform::Unix;
+
+use vars qw($VERSION @ISA);
+$VERSION = '0.27';
+@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
+
+sub compile {
+ my $self = shift;
+ my $cf = $self->{config};
+
+ # -flat_namespace isn't a compile flag, it's a linker flag. But
+ # it's mistakenly in Config.pm as both. Make the correction here.
+ local $cf->{ccflags} = $cf->{ccflags};
+ $cf->{ccflags} =~ s/-flat_namespace//;
+ $self->SUPER::compile(@_);
+}
+
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/dec_osf.pm b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/dec_osf.pm
new file mode 100644
index 00000000000..d07b71f6d65
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/dec_osf.pm
@@ -0,0 +1,18 @@
+package ExtUtils::CBuilder::Platform::dec_osf;
+
+use strict;
+use ExtUtils::CBuilder::Platform::Unix;
+use File::Spec;
+
+use vars qw($VERSION @ISA);
+@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
+$VERSION = '0.27';
+
+sub link_executable {
+ my $self = shift;
+ # $Config{ld} is 'ld' but that won't work: use the cc instead.
+ local $self->{config}{ld} = $self->{config}{cc};
+ return $self->SUPER::link_executable(@_);
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/os2.pm b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/os2.pm
new file mode 100644
index 00000000000..2815d587d7f
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/CBuilder/Platform/os2.pm
@@ -0,0 +1,80 @@
+package ExtUtils::CBuilder::Platform::os2;
+
+use strict;
+use ExtUtils::CBuilder::Platform::Unix;
+
+use vars qw($VERSION @ISA);
+$VERSION = '0.27';
+@ISA = qw(ExtUtils::CBuilder::Platform::Unix);
+
+sub need_prelink { 1 }
+
+sub prelink {
+ # Generate import libraries (XXXX currently near .DEF; should be near DLL!)
+ my $self = shift;
+ my %args = @_;
+
+ my @res = $self->SUPER::prelink(%args);
+ die "Unexpected number of DEF files" unless @res == 1;
+ die "Can't find DEF file in the output"
+ unless $res[0] =~ m,^(.*)\.def$,si;
+ my $libname = "$1$self->{config}{lib_ext}"; # Put .LIB file near .DEF file
+ $self->do_system('emximp', '-o', $libname, $res[0]) or die "emxexp: res=$?";
+ return (@res, $libname);
+}
+
+sub _do_link {
+ my $self = shift;
+ my ($how, %args) = @_;
+ if ($how eq 'lib_file'
+ and (defined $args{module_name} and length $args{module_name})) {
+
+ # DynaLoader::mod2fname() is a builtin func
+ my $lib = DynaLoader::mod2fname([split /::/, $args{module_name}]);
+
+ # Now know the basename, find directory parts via lib_file, or objects
+ my $objs = ( (ref $args{objects}) ? $args{objects} : [$args{objects}] );
+ my $near_obj = $self->lib_file(@$objs);
+ my $ref_file = ( defined $args{lib_file} ? $args{lib_file} : $near_obj );
+ my $lib_dir = ($ref_file =~ m,(.*)[/\\],s ? "$1/" : '' );
+ my $exp_dir = ($near_obj =~ m,(.*)[/\\],s ? "$1/" : '' );
+
+ $args{dl_file} = $1 if $near_obj =~ m,(.*)\.,s; # put ExportList near OBJ
+ $args{lib_file} = "$lib_dir$lib.$self->{config}{dlext}"; # DLL file
+
+ # XXX _do_link does not have place to put libraries?
+ push @$objs, $self->perl_inc() . "/libperl$self->{config}{lib_ext}";
+ $args{objects} = $objs;
+ }
+ # Some 'env' do exec(), thus return too early when run from ksh;
+ # To avoid 'env', remove (useless) shrpenv
+ local $self->{config}{shrpenv} = '';
+ return $self->SUPER::_do_link($how, %args);
+}
+
+sub extra_link_args_after_prelink {
+ # Add .DEF file to the link line
+ my ($self, %args) = @_;
+
+ my @DEF = grep /\.def$/i, @{$args{prelink_res}};
+ die "More than one .def files created by `prelink' stage" if @DEF > 1;
+ # XXXX No "$how" argument here, so how to test for dynamic link?
+ die "No .def file created by `prelink' stage"
+ unless @DEF or not @{$args{prelink_res}};
+
+ my @after_libs = ($OS2::is_aout ? ()
+ : $self->perl_inc() . "/libperl_override$self->{config}{lib_ext}");
+ # , "-L", "-lperl"
+ (@after_libs, @DEF);
+}
+
+sub link_executable {
+ # ldflags is not expecting .exe extension given on command line; remove -Zexe
+ my $self = shift;
+ local $self->{config}{ldflags} = $self->{config}{ldflags};
+ $self->{config}{ldflags} =~ s/(?<!\S)-Zexe(?!\S)//;
+ return $self->SUPER::link_executable(@_);
+}
+
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/Command.pm b/Master/tlpkg/tlperl/lib/ExtUtils/Command.pm
new file mode 100644
index 00000000000..b5632ff06d6
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/Command.pm
@@ -0,0 +1,369 @@
+package ExtUtils::Command;
+
+use 5.00503;
+use strict;
+use Carp;
+use File::Copy;
+use File::Compare;
+use File::Basename;
+use File::Path qw(rmtree);
+require Exporter;
+use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION);
+@ISA = qw(Exporter);
+@EXPORT = qw(cp rm_f rm_rf mv cat eqtime mkpath touch test_f test_d chmod
+ dos2unix);
+$VERSION = '1.16';
+
+my $Is_VMS = $^O eq 'VMS';
+my $Is_VMS_mode = $Is_VMS;
+my $Is_VMS_noefs = $Is_VMS;
+my $Is_Win32 = $^O eq 'MSWin32';
+
+if( $Is_VMS ) {
+ my $vms_unix_rpt;
+ my $vms_efs;
+ my $vms_case;
+
+ if (eval { local $SIG{__DIE__}; require VMS::Feature; }) {
+ $vms_unix_rpt = VMS::Feature::current("filename_unix_report");
+ $vms_efs = VMS::Feature::current("efs_charset");
+ $vms_case = VMS::Feature::current("efs_case_preserve");
+ } else {
+ my $unix_rpt = $ENV{'DECC$FILENAME_UNIX_REPORT'} || '';
+ my $efs_charset = $ENV{'DECC$EFS_CHARSET'} || '';
+ my $efs_case = $ENV{'DECC$EFS_CASE_PRESERVE'} || '';
+ $vms_unix_rpt = $unix_rpt =~ /^[ET1]/i;
+ $vms_efs = $efs_charset =~ /^[ET1]/i;
+ $vms_case = $efs_case =~ /^[ET1]/i;
+ }
+ $Is_VMS_mode = 0 if $vms_unix_rpt;
+ $Is_VMS_noefs = 0 if ($vms_efs);
+}
+
+
+=head1 NAME
+
+ExtUtils::Command - utilities to replace common UNIX commands in Makefiles etc.
+
+=head1 SYNOPSIS
+
+ perl -MExtUtils::Command -e cat files... > destination
+ perl -MExtUtils::Command -e mv source... destination
+ perl -MExtUtils::Command -e cp source... destination
+ perl -MExtUtils::Command -e touch files...
+ perl -MExtUtils::Command -e rm_f files...
+ perl -MExtUtils::Command -e rm_rf directories...
+ perl -MExtUtils::Command -e mkpath directories...
+ perl -MExtUtils::Command -e eqtime source destination
+ perl -MExtUtils::Command -e test_f file
+ perl -MExtUtils::Command -e test_d directory
+ perl -MExtUtils::Command -e chmod mode files...
+ ...
+
+=head1 DESCRIPTION
+
+The module is used to replace common UNIX commands. In all cases the
+functions work from @ARGV rather than taking arguments. This makes
+them easier to deal with in Makefiles. Call them like this:
+
+ perl -MExtUtils::Command -e some_command some files to work on
+
+and I<NOT> like this:
+
+ perl -MExtUtils::Command -e 'some_command qw(some files to work on)'
+
+For that use L<Shell::Command>.
+
+Filenames with * and ? will be glob expanded.
+
+
+=head2 FUNCTIONS
+
+=over 4
+
+=cut
+
+# VMS uses % instead of ? to mean "one character"
+my $wild_regex = $Is_VMS ? '*%' : '*?';
+sub expand_wildcards
+{
+ @ARGV = map(/[$wild_regex]/o ? glob($_) : $_,@ARGV);
+}
+
+
+=item cat
+
+ cat file ...
+
+Concatenates all files mentioned on command line to STDOUT.
+
+=cut
+
+sub cat ()
+{
+ expand_wildcards();
+ print while (<>);
+}
+
+=item eqtime
+
+ eqtime source destination
+
+Sets modified time of destination to that of source.
+
+=cut
+
+sub eqtime
+{
+ my ($src,$dst) = @ARGV;
+ local @ARGV = ($dst); touch(); # in case $dst doesn't exist
+ utime((stat($src))[8,9],$dst);
+}
+
+=item rm_rf
+
+ rm_rf files or directories ...
+
+Removes files and directories - recursively (even if readonly)
+
+=cut
+
+sub rm_rf
+{
+ expand_wildcards();
+ rmtree([grep -e $_,@ARGV],0,0);
+}
+
+=item rm_f
+
+ rm_f file ...
+
+Removes files (even if readonly)
+
+=cut
+
+sub rm_f {
+ expand_wildcards();
+
+ foreach my $file (@ARGV) {
+ next unless -f $file;
+
+ next if _unlink($file);
+
+ chmod(0777, $file);
+
+ next if _unlink($file);
+
+ carp "Cannot delete $file: $!";
+ }
+}
+
+sub _unlink {
+ my $files_unlinked = 0;
+ foreach my $file (@_) {
+ my $delete_count = 0;
+ $delete_count++ while unlink $file;
+ $files_unlinked++ if $delete_count;
+ }
+ return $files_unlinked;
+}
+
+
+=item touch
+
+ touch file ...
+
+Makes files exist, with current timestamp
+
+=cut
+
+sub touch {
+ my $t = time;
+ expand_wildcards();
+ foreach my $file (@ARGV) {
+ open(FILE,">>$file") || die "Cannot write $file:$!";
+ close(FILE);
+ utime($t,$t,$file);
+ }
+}
+
+=item mv
+
+ mv source_file destination_file
+ mv source_file source_file destination_dir
+
+Moves source to destination. Multiple sources are allowed if
+destination is an existing directory.
+
+Returns true if all moves succeeded, false otherwise.
+
+=cut
+
+sub mv {
+ expand_wildcards();
+ my @src = @ARGV;
+ my $dst = pop @src;
+
+ croak("Too many arguments") if (@src > 1 && ! -d $dst);
+
+ my $nok = 0;
+ foreach my $src (@src) {
+ $nok ||= !move($src,$dst);
+ }
+ return !$nok;
+}
+
+=item cp
+
+ cp source_file destination_file
+ cp source_file source_file destination_dir
+
+Copies sources to the destination. Multiple sources are allowed if
+destination is an existing directory.
+
+Returns true if all copies succeeded, false otherwise.
+
+=cut
+
+sub cp {
+ expand_wildcards();
+ my @src = @ARGV;
+ my $dst = pop @src;
+
+ croak("Too many arguments") if (@src > 1 && ! -d $dst);
+
+ my $nok = 0;
+ foreach my $src (@src) {
+ $nok ||= !copy($src,$dst);
+
+ # Win32 does not update the mod time of a copied file, just the
+ # created time which make does not look at.
+ utime(time, time, $dst) if $Is_Win32;
+ }
+ return $nok;
+}
+
+=item chmod
+
+ chmod mode files ...
+
+Sets UNIX like permissions 'mode' on all the files. e.g. 0666
+
+=cut
+
+sub chmod {
+ local @ARGV = @ARGV;
+ my $mode = shift(@ARGV);
+ expand_wildcards();
+
+ if( $Is_VMS_mode && $Is_VMS_noefs) {
+ foreach my $idx (0..$#ARGV) {
+ my $path = $ARGV[$idx];
+ next unless -d $path;
+
+ # chmod 0777, [.foo.bar] doesn't work on VMS, you have to do
+ # chmod 0777, [.foo]bar.dir
+ my @dirs = File::Spec->splitdir( $path );
+ $dirs[-1] .= '.dir';
+ $path = File::Spec->catfile(@dirs);
+
+ $ARGV[$idx] = $path;
+ }
+ }
+
+ chmod(oct $mode,@ARGV) || die "Cannot chmod ".join(' ',$mode,@ARGV).":$!";
+}
+
+=item mkpath
+
+ mkpath directory ...
+
+Creates directories, including any parent directories.
+
+=cut
+
+sub mkpath
+{
+ expand_wildcards();
+ File::Path::mkpath([@ARGV],0,0777);
+}
+
+=item test_f
+
+ test_f file
+
+Tests if a file exists. I<Exits> with 0 if it does, 1 if it does not (ie.
+shell's idea of true and false).
+
+=cut
+
+sub test_f
+{
+ exit(-f $ARGV[0] ? 0 : 1);
+}
+
+=item test_d
+
+ test_d directory
+
+Tests if a directory exists. I<Exits> with 0 if it does, 1 if it does
+not (ie. shell's idea of true and false).
+
+=cut
+
+sub test_d
+{
+ exit(-d $ARGV[0] ? 0 : 1);
+}
+
+=item dos2unix
+
+ dos2unix files or dirs ...
+
+Converts DOS and OS/2 linefeeds to Unix style recursively.
+
+=cut
+
+sub dos2unix {
+ require File::Find;
+ File::Find::find(sub {
+ return if -d;
+ return unless -w _;
+ return unless -r _;
+ return if -B _;
+
+ local $\;
+
+ my $orig = $_;
+ my $temp = '.dos2unix_tmp';
+ open ORIG, $_ or do { warn "dos2unix can't open $_: $!"; return };
+ open TEMP, ">$temp" or
+ do { warn "dos2unix can't create .dos2unix_tmp: $!"; return };
+ while (my $line = <ORIG>) {
+ $line =~ s/\015\012/\012/g;
+ print TEMP $line;
+ }
+ close ORIG;
+ close TEMP;
+ rename $temp, $orig;
+
+ }, @ARGV);
+}
+
+=back
+
+=head1 SEE ALSO
+
+Shell::Command which is these same functions but take arguments normally.
+
+
+=head1 AUTHOR
+
+Nick Ing-Simmons C<ni-s@cpan.org>
+
+Maintained by Michael G Schwern C<schwern@pobox.com> within the
+ExtUtils-MakeMaker package and, as a separate CPAN package, by
+Randy Kobes C<r.kobes@uwinnipeg.ca>.
+
+=cut
+
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/Command/MM.pm b/Master/tlpkg/tlperl/lib/ExtUtils/Command/MM.pm
new file mode 100644
index 00000000000..f9b474de16f
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/Command/MM.pm
@@ -0,0 +1,275 @@
+package ExtUtils::Command::MM;
+
+require 5.006;
+
+use strict;
+use warnings;
+
+require Exporter;
+our @ISA = qw(Exporter);
+
+our @EXPORT = qw(test_harness pod2man perllocal_install uninstall
+ warn_if_old_packlist);
+our $VERSION = '6.56';
+
+my $Is_VMS = $^O eq 'VMS';
+
+
+=head1 NAME
+
+ExtUtils::Command::MM - Commands for the MM's to use in Makefiles
+
+=head1 SYNOPSIS
+
+ perl "-MExtUtils::Command::MM" -e "function" "--" arguments...
+
+
+=head1 DESCRIPTION
+
+B<FOR INTERNAL USE ONLY!> The interface is not stable.
+
+ExtUtils::Command::MM encapsulates code which would otherwise have to
+be done with large "one" liners.
+
+Any $(FOO) used in the examples are make variables, not Perl.
+
+=over 4
+
+=item B<test_harness>
+
+ test_harness($verbose, @test_libs);
+
+Runs the tests on @ARGV via Test::Harness passing through the $verbose
+flag. Any @test_libs will be unshifted onto the test's @INC.
+
+@test_libs are run in alphabetical order.
+
+=cut
+
+sub test_harness {
+ require Test::Harness;
+ require File::Spec;
+
+ $Test::Harness::verbose = shift;
+
+ # Because Windows doesn't do this for us and listing all the *.t files
+ # out on the command line can blow over its exec limit.
+ require ExtUtils::Command;
+ my @argv = ExtUtils::Command::expand_wildcards(@ARGV);
+
+ local @INC = @INC;
+ unshift @INC, map { File::Spec->rel2abs($_) } @_;
+ Test::Harness::runtests(sort { lc $a cmp lc $b } @argv);
+}
+
+
+
+=item B<pod2man>
+
+ pod2man( '--option=value',
+ $podfile1 => $manpage1,
+ $podfile2 => $manpage2,
+ ...
+ );
+
+ # or args on @ARGV
+
+pod2man() is a function performing most of the duties of the pod2man
+program. Its arguments are exactly the same as pod2man as of 5.8.0
+with the addition of:
+
+ --perm_rw octal permission to set the resulting manpage to
+
+And the removal of:
+
+ --verbose/-v
+ --help/-h
+
+If no arguments are given to pod2man it will read from @ARGV.
+
+If Pod::Man is unavailable, this function will warn and return undef.
+
+=cut
+
+sub pod2man {
+ local @ARGV = @_ ? @_ : @ARGV;
+
+ {
+ local $@;
+ if( !eval { require Pod::Man } ) {
+ warn "Pod::Man is not available: $@".
+ "Man pages will not be generated during this install.\n";
+ return undef;
+ }
+ }
+ require Getopt::Long;
+
+ # We will cheat and just use Getopt::Long. We fool it by putting
+ # our arguments into @ARGV. Should be safe.
+ my %options = ();
+ Getopt::Long::config ('bundling_override');
+ Getopt::Long::GetOptions (\%options,
+ 'section|s=s', 'release|r=s', 'center|c=s',
+ 'date|d=s', 'fixed=s', 'fixedbold=s', 'fixeditalic=s',
+ 'fixedbolditalic=s', 'official|o', 'quotes|q=s', 'lax|l',
+ 'name|n=s', 'perm_rw=i'
+ );
+
+ # If there's no files, don't bother going further.
+ return 0 unless @ARGV;
+
+ # Official sets --center, but don't override things explicitly set.
+ if ($options{official} && !defined $options{center}) {
+ $options{center} = q[Perl Programmer's Reference Guide];
+ }
+
+ # This isn't a valid Pod::Man option and is only accepted for backwards
+ # compatibility.
+ delete $options{lax};
+
+ do {{ # so 'next' works
+ my ($pod, $man) = splice(@ARGV, 0, 2);
+
+ next if ((-e $man) &&
+ (-M $man < -M $pod) &&
+ (-M $man < -M "Makefile"));
+
+ print "Manifying $man\n";
+
+ my $parser = Pod::Man->new(%options);
+ $parser->parse_from_file($pod, $man)
+ or do { warn("Could not install $man\n"); next };
+
+ if (exists $options{perm_rw}) {
+ chmod(oct($options{perm_rw}), $man)
+ or do { warn("chmod $options{perm_rw} $man: $!\n"); next };
+ }
+ }} while @ARGV;
+
+ return 1;
+}
+
+
+=item B<warn_if_old_packlist>
+
+ perl "-MExtUtils::Command::MM" -e warn_if_old_packlist <somefile>
+
+Displays a warning that an old packlist file was found. Reads the
+filename from @ARGV.
+
+=cut
+
+sub warn_if_old_packlist {
+ my $packlist = $ARGV[0];
+
+ return unless -f $packlist;
+ print <<"PACKLIST_WARNING";
+WARNING: I have found an old package in
+ $packlist.
+Please make sure the two installations are not conflicting
+PACKLIST_WARNING
+
+}
+
+
+=item B<perllocal_install>
+
+ perl "-MExtUtils::Command::MM" -e perllocal_install
+ <type> <module name> <key> <value> ...
+
+ # VMS only, key|value pairs come on STDIN
+ perl "-MExtUtils::Command::MM" -e perllocal_install
+ <type> <module name> < <key>|<value> ...
+
+Prints a fragment of POD suitable for appending to perllocal.pod.
+Arguments are read from @ARGV.
+
+'type' is the type of what you're installing. Usually 'Module'.
+
+'module name' is simply the name of your module. (Foo::Bar)
+
+Key/value pairs are extra information about the module. Fields include:
+
+ installed into which directory your module was out into
+ LINKTYPE dynamic or static linking
+ VERSION module version number
+ EXE_FILES any executables installed in a space seperated
+ list
+
+=cut
+
+sub perllocal_install {
+ my($type, $name) = splice(@ARGV, 0, 2);
+
+ # VMS feeds args as a piped file on STDIN since it usually can't
+ # fit all the args on a single command line.
+ my @mod_info = $Is_VMS ? split /\|/, <STDIN>
+ : @ARGV;
+
+ my $pod;
+ $pod = sprintf <<POD, scalar localtime;
+ =head2 %s: C<$type> L<$name|$name>
+
+ =over 4
+
+POD
+
+ do {
+ my($key, $val) = splice(@mod_info, 0, 2);
+
+ $pod .= <<POD
+ =item *
+
+ C<$key: $val>
+
+POD
+
+ } while(@mod_info);
+
+ $pod .= "=back\n\n";
+ $pod =~ s/^ //mg;
+ print $pod;
+
+ return 1;
+}
+
+=item B<uninstall>
+
+ perl "-MExtUtils::Command::MM" -e uninstall <packlist>
+
+A wrapper around ExtUtils::Install::uninstall(). Warns that
+uninstallation is deprecated and doesn't actually perform the
+uninstallation.
+
+=cut
+
+sub uninstall {
+ my($packlist) = shift @ARGV;
+
+ require ExtUtils::Install;
+
+ print <<'WARNING';
+
+Uninstall is unsafe and deprecated, the uninstallation was not performed.
+We will show what would have been done.
+
+WARNING
+
+ ExtUtils::Install::uninstall($packlist, 1, 1);
+
+ print <<'WARNING';
+
+Uninstall is unsafe and deprecated, the uninstallation was not performed.
+Please check the list above carefully, there may be errors.
+Remove the appropriate files manually.
+Sorry for the inconvenience.
+
+WARNING
+
+}
+
+=back
+
+=cut
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/Constant.pm b/Master/tlpkg/tlperl/lib/ExtUtils/Constant.pm
new file mode 100644
index 00000000000..0a20b89b792
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/Constant.pm
@@ -0,0 +1,565 @@
+package ExtUtils::Constant;
+use vars qw (@ISA $VERSION @EXPORT_OK %EXPORT_TAGS);
+$VERSION = 0.22;
+
+=head1 NAME
+
+ExtUtils::Constant - generate XS code to import C header constants
+
+=head1 SYNOPSIS
+
+ use ExtUtils::Constant qw (WriteConstants);
+ WriteConstants(
+ NAME => 'Foo',
+ NAMES => [qw(FOO BAR BAZ)],
+ );
+ # Generates wrapper code to make the values of the constants FOO BAR BAZ
+ # available to perl
+
+=head1 DESCRIPTION
+
+ExtUtils::Constant facilitates generating C and XS wrapper code to allow
+perl modules to AUTOLOAD constants defined in C library header files.
+It is principally used by the C<h2xs> utility, on which this code is based.
+It doesn't contain the routines to scan header files to extract these
+constants.
+
+=head1 USAGE
+
+Generally one only needs to call the C<WriteConstants> function, and then
+
+ #include "const-c.inc"
+
+in the C section of C<Foo.xs>
+
+ INCLUDE: const-xs.inc
+
+in the XS section of C<Foo.xs>.
+
+For greater flexibility use C<constant_types()>, C<C_constant> and
+C<XS_constant>, with which C<WriteConstants> is implemented.
+
+Currently this module understands the following types. h2xs may only know
+a subset. The sizes of the numeric types are chosen by the C<Configure>
+script at compile time.
+
+=over 4
+
+=item IV
+
+signed integer, at least 32 bits.
+
+=item UV
+
+unsigned integer, the same size as I<IV>
+
+=item NV
+
+floating point type, probably C<double>, possibly C<long double>
+
+=item PV
+
+NUL terminated string, length will be determined with C<strlen>
+
+=item PVN
+
+A fixed length thing, given as a [pointer, length] pair. If you know the
+length of a string at compile time you may use this instead of I<PV>
+
+=item SV
+
+A B<mortal> SV.
+
+=item YES
+
+Truth. (C<PL_sv_yes>) The value is not needed (and ignored).
+
+=item NO
+
+Defined Falsehood. (C<PL_sv_no>) The value is not needed (and ignored).
+
+=item UNDEF
+
+C<undef>. The value of the macro is not needed.
+
+=back
+
+=head1 FUNCTIONS
+
+=over 4
+
+=cut
+
+if ($] >= 5.006) {
+ eval "use warnings; 1" or die $@;
+}
+use strict;
+use Carp qw(croak cluck);
+
+use Exporter;
+use ExtUtils::Constant::Utils qw(C_stringify);
+use ExtUtils::Constant::XS qw(%XS_Constant %XS_TypeSet);
+
+@ISA = 'Exporter';
+
+%EXPORT_TAGS = ( 'all' => [ qw(
+ XS_constant constant_types return_clause memEQ_clause C_stringify
+ C_constant autoload WriteConstants WriteMakefileSnippet
+) ] );
+
+@EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
+
+=item constant_types
+
+A function returning a single scalar with C<#define> definitions for the
+constants used internally between the generated C and XS functions.
+
+=cut
+
+sub constant_types {
+ ExtUtils::Constant::XS->header();
+}
+
+sub memEQ_clause {
+ cluck "ExtUtils::Constant::memEQ_clause is deprecated";
+ ExtUtils::Constant::XS->memEQ_clause({name=>$_[0], checked_at=>$_[1],
+ indent=>$_[2]});
+}
+
+sub return_clause ($$) {
+ cluck "ExtUtils::Constant::return_clause is deprecated";
+ my $indent = shift;
+ ExtUtils::Constant::XS->return_clause({indent=>$indent}, @_);
+}
+
+sub switch_clause {
+ cluck "ExtUtils::Constant::switch_clause is deprecated";
+ my $indent = shift;
+ my $comment = shift;
+ ExtUtils::Constant::XS->switch_clause({indent=>$indent, comment=>$comment},
+ @_);
+}
+
+sub C_constant {
+ my ($package, $subname, $default_type, $what, $indent, $breakout, @items)
+ = @_;
+ ExtUtils::Constant::XS->C_constant({package => $package, subname => $subname,
+ default_type => $default_type,
+ types => $what, indent => $indent,
+ breakout => $breakout}, @items);
+}
+
+=item XS_constant PACKAGE, TYPES, XS_SUBNAME, C_SUBNAME
+
+A function to generate the XS code to implement the perl subroutine
+I<PACKAGE>::constant used by I<PACKAGE>::AUTOLOAD to load constants.
+This XS code is a wrapper around a C subroutine usually generated by
+C<C_constant>, and usually named C<constant>.
+
+I<TYPES> should be given either as a comma separated list of types that the
+C subroutine C<constant> will generate or as a reference to a hash. It should
+be the same list of types as C<C_constant> was given.
+[Otherwise C<XS_constant> and C<C_constant> may have different ideas about
+the number of parameters passed to the C function C<constant>]
+
+You can call the perl visible subroutine something other than C<constant> if
+you give the parameter I<XS_SUBNAME>. The C subroutine it calls defaults to
+the name of the perl visible subroutine, unless you give the parameter
+I<C_SUBNAME>.
+
+=cut
+
+sub XS_constant {
+ my $package = shift;
+ my $what = shift;
+ my $XS_subname = shift;
+ my $C_subname = shift;
+ $XS_subname ||= 'constant';
+ $C_subname ||= $XS_subname;
+
+ if (!ref $what) {
+ # Convert line of the form IV,UV,NV to hash
+ $what = {map {$_ => 1} split /,\s*/, ($what)};
+ }
+ my $params = ExtUtils::Constant::XS->params ($what);
+ my $type;
+
+ my $xs = <<"EOT";
+void
+$XS_subname(sv)
+ PREINIT:
+#ifdef dXSTARG
+ dXSTARG; /* Faster if we have it. */
+#else
+ dTARGET;
+#endif
+ STRLEN len;
+ int type;
+EOT
+
+ if ($params->{IV}) {
+ $xs .= " IV iv;\n";
+ } else {
+ $xs .= " /* IV\t\tiv;\tUncomment this if you need to return IVs */\n";
+ }
+ if ($params->{NV}) {
+ $xs .= " NV nv;\n";
+ } else {
+ $xs .= " /* NV\t\tnv;\tUncomment this if you need to return NVs */\n";
+ }
+ if ($params->{PV}) {
+ $xs .= " const char *pv;\n";
+ } else {
+ $xs .=
+ " /* const char\t*pv;\tUncomment this if you need to return PVs */\n";
+ }
+
+ $xs .= << 'EOT';
+ INPUT:
+ SV * sv;
+ const char * s = SvPV(sv, len);
+EOT
+ if ($params->{''}) {
+ $xs .= << 'EOT';
+ INPUT:
+ int utf8 = SvUTF8(sv);
+EOT
+ }
+ $xs .= << 'EOT';
+ PPCODE:
+EOT
+
+ if ($params->{IV} xor $params->{NV}) {
+ $xs .= << "EOT";
+ /* Change this to $C_subname(aTHX_ s, len, &iv, &nv);
+ if you need to return both NVs and IVs */
+EOT
+ }
+ $xs .= " type = $C_subname(aTHX_ s, len";
+ $xs .= ', utf8' if $params->{''};
+ $xs .= ', &iv' if $params->{IV};
+ $xs .= ', &nv' if $params->{NV};
+ $xs .= ', &pv' if $params->{PV};
+ $xs .= ', &sv' if $params->{SV};
+ $xs .= ");\n";
+
+ # If anyone is insane enough to suggest a package name containing %
+ my $package_sprintf_safe = $package;
+ $package_sprintf_safe =~ s/%/%%/g;
+
+ $xs .= << "EOT";
+ /* Return 1 or 2 items. First is error message, or undef if no error.
+ Second, if present, is found value */
+ switch (type) {
+ case PERL_constant_NOTFOUND:
+ sv =
+ sv_2mortal(newSVpvf("%s is not a valid $package_sprintf_safe macro", s));
+ PUSHs(sv);
+ break;
+ case PERL_constant_NOTDEF:
+ sv = sv_2mortal(newSVpvf(
+ "Your vendor has not defined $package_sprintf_safe macro %s, used",
+ s));
+ PUSHs(sv);
+ break;
+EOT
+
+ foreach $type (sort keys %XS_Constant) {
+ # '' marks utf8 flag needed.
+ next if $type eq '';
+ $xs .= "\t/* Uncomment this if you need to return ${type}s\n"
+ unless $what->{$type};
+ $xs .= " case PERL_constant_IS$type:\n";
+ if (length $XS_Constant{$type}) {
+ $xs .= << "EOT";
+ EXTEND(SP, 1);
+ PUSHs(&PL_sv_undef);
+ $XS_Constant{$type};
+EOT
+ } else {
+ # Do nothing. return (), which will be correctly interpreted as
+ # (undef, undef)
+ }
+ $xs .= " break;\n";
+ unless ($what->{$type}) {
+ chop $xs; # Yes, another need for chop not chomp.
+ $xs .= " */\n";
+ }
+ }
+ $xs .= << "EOT";
+ default:
+ sv = sv_2mortal(newSVpvf(
+ "Unexpected return type %d while processing $package_sprintf_safe macro %s, used",
+ type, s));
+ PUSHs(sv);
+ }
+EOT
+
+ return $xs;
+}
+
+
+=item autoload PACKAGE, VERSION, AUTOLOADER
+
+A function to generate the AUTOLOAD subroutine for the module I<PACKAGE>
+I<VERSION> is the perl version the code should be backwards compatible with.
+It defaults to the version of perl running the subroutine. If I<AUTOLOADER>
+is true, the AUTOLOAD subroutine falls back on AutoLoader::AUTOLOAD for all
+names that the constant() routine doesn't recognise.
+
+=cut
+
+# ' # Grr. syntax highlighters that don't grok pod.
+
+sub autoload {
+ my ($module, $compat_version, $autoloader) = @_;
+ $compat_version ||= $];
+ croak "Can't maintain compatibility back as far as version $compat_version"
+ if $compat_version < 5;
+ my $func = "sub AUTOLOAD {\n"
+ . " # This AUTOLOAD is used to 'autoload' constants from the constant()\n"
+ . " # XS function.";
+ $func .= " If a constant is not found then control is passed\n"
+ . " # to the AUTOLOAD in AutoLoader." if $autoloader;
+
+
+ $func .= "\n\n"
+ . " my \$constname;\n";
+ $func .=
+ " our \$AUTOLOAD;\n" if ($compat_version >= 5.006);
+
+ $func .= <<"EOT";
+ (\$constname = \$AUTOLOAD) =~ s/.*:://;
+ croak "&${module}::constant not defined" if \$constname eq 'constant';
+ my (\$error, \$val) = constant(\$constname);
+EOT
+
+ if ($autoloader) {
+ $func .= <<'EOT';
+ if ($error) {
+ if ($error =~ /is not a valid/) {
+ $AutoLoader::AUTOLOAD = $AUTOLOAD;
+ goto &AutoLoader::AUTOLOAD;
+ } else {
+ croak $error;
+ }
+ }
+EOT
+ } else {
+ $func .=
+ " if (\$error) { croak \$error; }\n";
+ }
+
+ $func .= <<'END';
+ {
+ no strict 'refs';
+ # Fixed between 5.005_53 and 5.005_61
+#XXX if ($] >= 5.00561) {
+#XXX *$AUTOLOAD = sub () { $val };
+#XXX }
+#XXX else {
+ *$AUTOLOAD = sub { $val };
+#XXX }
+ }
+ goto &$AUTOLOAD;
+}
+
+END
+
+ return $func;
+}
+
+
+=item WriteMakefileSnippet
+
+WriteMakefileSnippet ATTRIBUTE =E<gt> VALUE [, ...]
+
+A function to generate perl code for Makefile.PL that will regenerate
+the constant subroutines. Parameters are named as passed to C<WriteConstants>,
+with the addition of C<INDENT> to specify the number of leading spaces
+(default 2).
+
+Currently only C<INDENT>, C<NAME>, C<DEFAULT_TYPE>, C<NAMES>, C<C_FILE> and
+C<XS_FILE> are recognised.
+
+=cut
+
+sub WriteMakefileSnippet {
+ my %args = @_;
+ my $indent = $args{INDENT} || 2;
+
+ my $result = <<"EOT";
+ExtUtils::Constant::WriteConstants(
+ NAME => '$args{NAME}',
+ NAMES => \\\@names,
+ DEFAULT_TYPE => '$args{DEFAULT_TYPE}',
+EOT
+ foreach (qw (C_FILE XS_FILE)) {
+ next unless exists $args{$_};
+ $result .= sprintf " %-12s => '%s',\n",
+ $_, $args{$_};
+ }
+ $result .= <<'EOT';
+ );
+EOT
+
+ $result =~ s/^/' 'x$indent/gem;
+ return ExtUtils::Constant::XS->dump_names({default_type=>$args{DEFAULT_TYPE},
+ indent=>$indent,},
+ @{$args{NAMES}})
+ . $result;
+}
+
+=item WriteConstants ATTRIBUTE =E<gt> VALUE [, ...]
+
+Writes a file of C code and a file of XS code which you should C<#include>
+and C<INCLUDE> in the C and XS sections respectively of your module's XS
+code. You probably want to do this in your C<Makefile.PL>, so that you can
+easily edit the list of constants without touching the rest of your module.
+The attributes supported are
+
+=over 4
+
+=item NAME
+
+Name of the module. This must be specified
+
+=item DEFAULT_TYPE
+
+The default type for the constants. If not specified C<IV> is assumed.
+
+=item BREAKOUT_AT
+
+The names of the constants are grouped by length. Generate child subroutines
+for each group with this number or more names in.
+
+=item NAMES
+
+An array of constants' names, either scalars containing names, or hashrefs
+as detailed in L<"C_constant">.
+
+=item PROXYSUBS
+
+If true, uses proxy subs. See L<ExtUtils::Constant::ProxySubs>.
+
+=item C_FH
+
+A filehandle to write the C code to. If not given, then I<C_FILE> is opened
+for writing.
+
+=item C_FILE
+
+The name of the file to write containing the C code. The default is
+C<const-c.inc>. The C<-> in the name ensures that the file can't be
+mistaken for anything related to a legitimate perl package name, and
+not naming the file C<.c> avoids having to override Makefile.PL's
+C<.xs> to C<.c> rules.
+
+=item XS_FH
+
+A filehandle to write the XS code to. If not given, then I<XS_FILE> is opened
+for writing.
+
+=item XS_FILE
+
+The name of the file to write containing the XS code. The default is
+C<const-xs.inc>.
+
+=item XS_SUBNAME
+
+The perl visible name of the XS subroutine generated which will return the
+constants. The default is C<constant>.
+
+=item C_SUBNAME
+
+The name of the C subroutine generated which will return the constants.
+The default is I<XS_SUBNAME>. Child subroutines have C<_> and the name
+length appended, so constants with 10 character names would be in
+C<constant_10> with the default I<XS_SUBNAME>.
+
+=back
+
+=cut
+
+sub WriteConstants {
+ my %ARGS =
+ ( # defaults
+ C_FILE => 'const-c.inc',
+ XS_FILE => 'const-xs.inc',
+ XS_SUBNAME => 'constant',
+ DEFAULT_TYPE => 'IV',
+ @_);
+
+ $ARGS{C_SUBNAME} ||= $ARGS{XS_SUBNAME}; # No-one sane will have C_SUBNAME eq '0'
+
+ croak "Module name not specified" unless length $ARGS{NAME};
+
+ my $c_fh = $ARGS{C_FH};
+ if (!$c_fh) {
+ if ($] <= 5.008) {
+ # We need these little games, rather than doing things
+ # unconditionally, because we're used in core Makefile.PLs before
+ # IO is available (needed by filehandle), but also we want to work on
+ # older perls where undefined scalars do not automatically turn into
+ # anonymous file handles.
+ require FileHandle;
+ $c_fh = FileHandle->new();
+ }
+ open $c_fh, ">$ARGS{C_FILE}" or die "Can't open $ARGS{C_FILE}: $!";
+ }
+
+ my $xs_fh = $ARGS{XS_FH};
+ if (!$xs_fh) {
+ if ($] <= 5.008) {
+ require FileHandle;
+ $xs_fh = FileHandle->new();
+ }
+ open $xs_fh, ">$ARGS{XS_FILE}" or die "Can't open $ARGS{XS_FILE}: $!";
+ }
+
+ # As this subroutine is intended to make code that isn't edited, there's no
+ # need for the user to specify any types that aren't found in the list of
+ # names.
+
+ if ($ARGS{PROXYSUBS}) {
+ require ExtUtils::Constant::ProxySubs;
+ $ARGS{C_FH} = $c_fh;
+ $ARGS{XS_FH} = $xs_fh;
+ ExtUtils::Constant::ProxySubs->WriteConstants(%ARGS);
+ } else {
+ my $types = {};
+
+ print $c_fh constant_types(); # macro defs
+ print $c_fh "\n";
+
+ # indent is still undef. Until anyone implements indent style rules with
+ # it.
+ foreach (ExtUtils::Constant::XS->C_constant({package => $ARGS{NAME},
+ subname => $ARGS{C_SUBNAME},
+ default_type =>
+ $ARGS{DEFAULT_TYPE},
+ types => $types,
+ breakout =>
+ $ARGS{BREAKOUT_AT}},
+ @{$ARGS{NAMES}})) {
+ print $c_fh $_, "\n"; # C constant subs
+ }
+ print $xs_fh XS_constant ($ARGS{NAME}, $types, $ARGS{XS_SUBNAME},
+ $ARGS{C_SUBNAME});
+ }
+
+ close $c_fh or warn "Error closing $ARGS{C_FILE}: $!" unless $ARGS{C_FH};
+ close $xs_fh or warn "Error closing $ARGS{XS_FILE}: $!" unless $ARGS{XS_FH};
+}
+
+1;
+__END__
+
+=back
+
+=head1 AUTHOR
+
+Nicholas Clark <nick@ccl4.org> based on the code in C<h2xs> by Larry Wall and
+others
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/Constant/Base.pm b/Master/tlpkg/tlperl/lib/ExtUtils/Constant/Base.pm
new file mode 100644
index 00000000000..b5b79af1ea7
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/Constant/Base.pm
@@ -0,0 +1,1006 @@
+package ExtUtils::Constant::Base;
+
+use strict;
+use vars qw($VERSION);
+use Carp;
+use Text::Wrap;
+use ExtUtils::Constant::Utils qw(C_stringify perl_stringify);
+$VERSION = '0.04';
+
+use constant is_perl56 => ($] < 5.007 && $] > 5.005_50);
+
+
+=head1 NAME
+
+ExtUtils::Constant::Base - base class for ExtUtils::Constant objects
+
+=head1 SYNOPSIS
+
+ require ExtUtils::Constant::Base;
+ @ISA = 'ExtUtils::Constant::Base';
+
+=head1 DESCRIPTION
+
+ExtUtils::Constant::Base provides a base implementation of methods to
+generate C code to give fast constant value lookup by named string. Currently
+it's mostly used ExtUtils::Constant::XS, which generates the lookup code
+for the constant() subroutine found in many XS modules.
+
+=head1 USAGE
+
+ExtUtils::Constant::Base exports no subroutines. The following methods are
+available
+
+=over 4
+
+=cut
+
+sub valid_type {
+ # Default to assuming that you don't need different types of return data.
+ 1;
+}
+sub default_type {
+ '';
+}
+
+=item header
+
+A method returning a scalar containing definitions needed, typically for a
+C header file.
+
+=cut
+
+sub header {
+ ''
+}
+
+# This might actually be a return statement. Note that you are responsible
+# for any space you might need before your value, as it lets to perform
+# "tricks" such as "return KEY_" and have strings appended.
+sub assignment_clause_for_type;
+# In which case this might be an empty string
+sub return_statement_for_type {undef};
+sub return_statement_for_notdef;
+sub return_statement_for_notfound;
+
+# "#if 1" is true to a C pre-processor
+sub macro_from_name {
+ 1;
+}
+
+sub macro_from_item {
+ 1;
+}
+
+sub macro_to_ifdef {
+ my ($self, $macro) = @_;
+ if (ref $macro) {
+ return $macro->[0];
+ }
+ if (defined $macro && $macro ne "" && $macro ne "1") {
+ return $macro ? "#ifdef $macro\n" : "#if 0\n";
+ }
+ return "";
+}
+
+sub macro_to_endif {
+ my ($self, $macro) = @_;
+
+ if (ref $macro) {
+ return $macro->[1];
+ }
+ if (defined $macro && $macro ne "" && $macro ne "1") {
+ return "#endif\n";
+ }
+ return "";
+}
+
+sub name_param {
+ 'name';
+}
+
+# This is possibly buggy, in that it's not mandatory (below, in the main
+# C_constant parameters, but is expected to exist here, if it's needed)
+# Buggy because if you're definitely pure 8 bit only, and will never be
+# presented with your constants in utf8, the default form of C_constant can't
+# be told not to do the utf8 version.
+
+sub is_utf8_param {
+ 'utf8';
+}
+
+sub memEQ {
+ "!memcmp";
+}
+
+=item memEQ_clause args_hashref
+
+A method to return a suitable C C<if> statement to check whether I<name>
+is equal to the C variable C<name>. If I<checked_at> is defined, then it
+is used to avoid C<memEQ> for short names, or to generate a comment to
+highlight the position of the character in the C<switch> statement.
+
+If i<checked_at> is a reference to a scalar, then instead it gives
+the characters pre-checked at the beginning, (and the number of chars by
+which the C variable name has been advanced. These need to be chopped from
+the front of I<name>).
+
+=cut
+
+sub memEQ_clause {
+# if (memEQ(name, "thingy", 6)) {
+ # Which could actually be a character comparison or even ""
+ my ($self, $args) = @_;
+ my ($name, $checked_at, $indent) = @{$args}{qw(name checked_at indent)};
+ $indent = ' ' x ($indent || 4);
+ my $front_chop;
+ if (ref $checked_at) {
+ # regexp won't work on 5.6.1 without use utf8; in turn that won't work
+ # on 5.005_03.
+ substr ($name, 0, length $$checked_at,) = '';
+ $front_chop = C_stringify ($$checked_at);
+ undef $checked_at;
+ }
+ my $len = length $name;
+
+ if ($len < 2) {
+ return $indent . "{\n"
+ if (defined $checked_at and $checked_at == 0) or $len == 0;
+ # We didn't switch, drop through to the code for the 2 character string
+ $checked_at = 1;
+ }
+
+ my $name_param = $self->name_param;
+
+ if ($len < 3 and defined $checked_at) {
+ my $check;
+ if ($checked_at == 1) {
+ $check = 0;
+ } elsif ($checked_at == 0) {
+ $check = 1;
+ }
+ if (defined $check) {
+ my $char = C_stringify (substr $name, $check, 1);
+ # Placate 5.005 with a break in the string. I can't see a good way of
+ # getting it to not take [ as introducing an array lookup, even with
+ # ${name_param}[$check]
+ return $indent . "if ($name_param" . "[$check] == '$char') {\n";
+ }
+ }
+ if (($len == 2 and !defined $checked_at)
+ or ($len == 3 and defined ($checked_at) and $checked_at == 2)) {
+ my $char1 = C_stringify (substr $name, 0, 1);
+ my $char2 = C_stringify (substr $name, 1, 1);
+ return $indent .
+ "if ($name_param" . "[0] == '$char1' && $name_param" . "[1] == '$char2') {\n";
+ }
+ if (($len == 3 and defined ($checked_at) and $checked_at == 1)) {
+ my $char1 = C_stringify (substr $name, 0, 1);
+ my $char2 = C_stringify (substr $name, 2, 1);
+ return $indent .
+ "if ($name_param" . "[0] == '$char1' && $name_param" . "[2] == '$char2') {\n";
+ }
+
+ my $pointer = '^';
+ my $have_checked_last = defined ($checked_at) && $len == $checked_at + 1;
+ if ($have_checked_last) {
+ # Checked at the last character, so no need to memEQ it.
+ $pointer = C_stringify (chop $name);
+ $len--;
+ }
+
+ $name = C_stringify ($name);
+ my $memEQ = $self->memEQ();
+ my $body = $indent . "if ($memEQ($name_param, \"$name\", $len)) {\n";
+ # Put a little ^ under the letter we checked at
+ # Screws up for non printable and non-7 bit stuff, but that's too hard to
+ # get right.
+ if (defined $checked_at) {
+ $body .= $indent . "/* " . (' ' x length $memEQ)
+ . (' ' x length $name_param)
+ . (' ' x $checked_at) . $pointer
+ . (' ' x ($len - $checked_at + length $len)) . " */\n";
+ } elsif (defined $front_chop) {
+ $body .= $indent . "/* $front_chop"
+ . (' ' x ($len + 1 + length $len)) . " */\n";
+ }
+ return $body;
+}
+
+=item dump_names arg_hashref, ITEM...
+
+An internal function to generate the embedded perl code that will regenerate
+the constant subroutines. I<default_type>, I<types> and I<ITEM>s are the
+same as for C_constant. I<indent> is treated as number of spaces to indent
+by. If C<declare_types> is true a C<$types> is always declared in the perl
+code generated, if defined and false never declared, and if undefined C<$types>
+is only declared if the values in I<types> as passed in cannot be inferred from
+I<default_types> and the I<ITEM>s.
+
+=cut
+
+sub dump_names {
+ my ($self, $args, @items) = @_;
+ my ($default_type, $what, $indent, $declare_types)
+ = @{$args}{qw(default_type what indent declare_types)};
+ $indent = ' ' x ($indent || 0);
+
+ my $result;
+ my (@simple, @complex, %used_types);
+ foreach (@items) {
+ my $type;
+ if (ref $_) {
+ $type = $_->{type} || $default_type;
+ if ($_->{utf8}) {
+ # For simplicity always skip the bytes case, and reconstitute this entry
+ # from its utf8 twin.
+ next if $_->{utf8} eq 'no';
+ # Copy the hashref, as we don't want to mess with the caller's hashref.
+ $_ = {%$_};
+ unless (is_perl56) {
+ utf8::decode ($_->{name});
+ } else {
+ $_->{name} = pack 'U*', unpack 'U0U*', $_->{name};
+ }
+ delete $_->{utf8};
+ }
+ } else {
+ $_ = {name=>$_};
+ $type = $default_type;
+ }
+ $used_types{$type}++;
+ if ($type eq $default_type
+ # grr 5.6.1
+ and length $_->{name}
+ and length $_->{name} == ($_->{name} =~ tr/A-Za-z0-9_//)
+ and !defined ($_->{macro}) and !defined ($_->{value})
+ and !defined ($_->{default}) and !defined ($_->{pre})
+ and !defined ($_->{post}) and !defined ($_->{def_pre})
+ and !defined ($_->{def_post}) and !defined ($_->{weight})) {
+ # It's the default type, and the name consists only of A-Za-z0-9_
+ push @simple, $_->{name};
+ } else {
+ push @complex, $_;
+ }
+ }
+
+ if (!defined $declare_types) {
+ # Do they pass in any types we weren't already using?
+ foreach (keys %$what) {
+ next if $used_types{$_};
+ $declare_types++; # Found one in $what that wasn't used.
+ last; # And one is enough to terminate this loop
+ }
+ }
+ if ($declare_types) {
+ $result = $indent . 'my $types = {map {($_, 1)} qw('
+ . join (" ", sort keys %$what) . ")};\n";
+ }
+ local $Text::Wrap::huge = 'overflow';
+ local $Text::Wrap::columns = 80;
+ $result .= wrap ($indent . "my \@names = (qw(",
+ $indent . " ", join (" ", sort @simple) . ")");
+ if (@complex) {
+ foreach my $item (sort {$a->{name} cmp $b->{name}} @complex) {
+ my $name = perl_stringify $item->{name};
+ my $line = ",\n$indent {name=>\"$name\"";
+ $line .= ", type=>\"$item->{type}\"" if defined $item->{type};
+ foreach my $thing (qw (macro value default pre post def_pre def_post)) {
+ my $value = $item->{$thing};
+ if (defined $value) {
+ if (ref $value) {
+ $line .= ", $thing=>[\""
+ . join ('", "', map {perl_stringify $_} @$value) . '"]';
+ } else {
+ $line .= ", $thing=>\"" . perl_stringify($value) . "\"";
+ }
+ }
+ }
+ $line .= "}";
+ # Ensure that the enclosing C comment doesn't end
+ # by turning */ into *" . "/
+ $line =~ s!\*\/!\*" . "/!gs;
+ # gcc -Wall doesn't like finding /* inside a comment
+ $line =~ s!\/\*!/" . "\*!gs;
+ $result .= $line;
+ }
+ }
+ $result .= ");\n";
+
+ $result;
+}
+
+=item assign arg_hashref, VALUE...
+
+A method to return a suitable assignment clause. If I<type> is aggregate
+(eg I<PVN> expects both pointer and length) then there should be multiple
+I<VALUE>s for the components. I<pre> and I<post> if defined give snippets
+of C code to proceed and follow the assignment. I<pre> will be at the start
+of a block, so variables may be defined in it.
+
+=cut
+# Hmm. value undef to to NOTDEF? value () to do NOTFOUND?
+
+sub assign {
+ my $self = shift;
+ my $args = shift;
+ my ($indent, $type, $pre, $post, $item)
+ = @{$args}{qw(indent type pre post item)};
+ $post ||= '';
+ my $clause;
+ my $close;
+ if ($pre) {
+ chomp $pre;
+ $close = "$indent}\n";
+ $clause = $indent . "{\n";
+ $indent .= " ";
+ $clause .= "$indent$pre";
+ $clause .= ";" unless $pre =~ /;$/;
+ $clause .= "\n";
+ }
+ confess "undef \$type" unless defined $type;
+ confess "Can't generate code for type $type"
+ unless $self->valid_type($type);
+
+ $clause .= join '', map {"$indent$_\n"}
+ $self->assignment_clause_for_type({type=>$type,item=>$item}, @_);
+ chomp $post;
+ if (length $post) {
+ $clause .= "$post";
+ $clause .= ";" unless $post =~ /;$/;
+ $clause .= "\n";
+ }
+ my $return = $self->return_statement_for_type($type);
+ $clause .= "$indent$return\n" if defined $return;
+ $clause .= $close if $close;
+ return $clause;
+}
+
+=item return_clause arg_hashref, ITEM
+
+A method to return a suitable C<#ifdef> clause. I<ITEM> is a hashref
+(as passed to C<C_constant> and C<match_clause>. I<indent> is the number
+of spaces to indent, defaulting to 6.
+
+=cut
+
+sub return_clause {
+
+##ifdef thingy
+# *iv_return = thingy;
+# return PERL_constant_ISIV;
+##else
+# return PERL_constant_NOTDEF;
+##endif
+ my ($self, $args, $item) = @_;
+ my $indent = $args->{indent};
+
+ my ($name, $value, $default, $pre, $post, $def_pre, $def_post, $type)
+ = @$item{qw (name value default pre post def_pre def_post type)};
+ $value = $name unless defined $value;
+ my $macro = $self->macro_from_item($item);
+ $indent = ' ' x ($indent || 6);
+ unless (defined $type) {
+ # use Data::Dumper; print STDERR Dumper ($item);
+ confess "undef \$type";
+ }
+
+ ##ifdef thingy
+ my $clause = $self->macro_to_ifdef($macro);
+
+ # *iv_return = thingy;
+ # return PERL_constant_ISIV;
+ $clause
+ .= $self->assign ({indent=>$indent, type=>$type, pre=>$pre, post=>$post,
+ item=>$item}, ref $value ? @$value : $value);
+
+ if (defined $macro && $macro ne "" && $macro ne "1") {
+ ##else
+ $clause .= "#else\n";
+
+ # return PERL_constant_NOTDEF;
+ if (!defined $default) {
+ my $notdef = $self->return_statement_for_notdef();
+ $clause .= "$indent$notdef\n" if defined $notdef;
+ } else {
+ my @default = ref $default ? @$default : $default;
+ $type = shift @default;
+ $clause .= $self->assign ({indent=>$indent, type=>$type, pre=>$pre,
+ post=>$post, item=>$item}, @default);
+ }
+ }
+ ##endif
+ $clause .= $self->macro_to_endif($macro);
+
+ return $clause;
+}
+
+sub match_clause {
+ # $offset defined if we have checked an offset.
+ my ($self, $args, $item) = @_;
+ my ($offset, $indent) = @{$args}{qw(checked_at indent)};
+ $indent = ' ' x ($indent || 4);
+ my $body = '';
+ my ($no, $yes, $either, $name, $inner_indent);
+ if (ref $item eq 'ARRAY') {
+ ($yes, $no) = @$item;
+ $either = $yes || $no;
+ confess "$item is $either expecting hashref in [0] || [1]"
+ unless ref $either eq 'HASH';
+ $name = $either->{name};
+ } else {
+ confess "$item->{name} has utf8 flag '$item->{utf8}', should be false"
+ if $item->{utf8};
+ $name = $item->{name};
+ $inner_indent = $indent;
+ }
+
+ $body .= $self->memEQ_clause ({name => $name, checked_at => $offset,
+ indent => length $indent});
+ # If we've been presented with an arrayref for $item, then the user string
+ # contains in the range 128-255, and we need to check whether it was utf8
+ # (or not).
+ # In the worst case we have two named constants, where one's name happens
+ # encoded in UTF8 happens to be the same byte sequence as the second's
+ # encoded in (say) ISO-8859-1.
+ # In this case, $yes and $no both have item hashrefs.
+ if ($yes) {
+ $body .= $indent . " if (" . $self->is_utf8_param . ") {\n";
+ } elsif ($no) {
+ $body .= $indent . " if (!" . $self->is_utf8_param . ") {\n";
+ }
+ if ($either) {
+ $body .= $self->return_clause ({indent=>4 + length $indent}, $either);
+ if ($yes and $no) {
+ $body .= $indent . " } else {\n";
+ $body .= $self->return_clause ({indent=>4 + length $indent}, $no);
+ }
+ $body .= $indent . " }\n";
+ } else {
+ $body .= $self->return_clause ({indent=>2 + length $indent}, $item);
+ }
+ $body .= $indent . "}\n";
+}
+
+
+=item switch_clause arg_hashref, NAMELEN, ITEMHASH, ITEM...
+
+An internal method to generate a suitable C<switch> clause, called by
+C<C_constant> I<ITEM>s are in the hash ref format as given in the description
+of C<C_constant>, and must all have the names of the same length, given by
+I<NAMELEN>. I<ITEMHASH> is a reference to a hash, keyed by name, values being
+the hashrefs in the I<ITEM> list. (No parameters are modified, and there can
+be keys in the I<ITEMHASH> that are not in the list of I<ITEM>s without
+causing problems - the hash is passed in to save generating it afresh for
+each call).
+
+=cut
+
+sub switch_clause {
+ my ($self, $args, $namelen, $items, @items) = @_;
+ my ($indent, $comment) = @{$args}{qw(indent comment)};
+ $indent = ' ' x ($indent || 2);
+
+ local $Text::Wrap::huge = 'overflow';
+ local $Text::Wrap::columns = 80;
+
+ my @names = sort map {$_->{name}} @items;
+ my $leader = $indent . '/* ';
+ my $follower = ' ' x length $leader;
+ my $body = $indent . "/* Names all of length $namelen. */\n";
+ if (defined $comment) {
+ $body = wrap ($leader, $follower, $comment) . "\n";
+ $leader = $follower;
+ }
+ my @safe_names = @names;
+ foreach (@safe_names) {
+ confess sprintf "Name '$_' is length %d, not $namelen", length
+ unless length == $namelen;
+ # Argh. 5.6.1
+ # next unless tr/A-Za-z0-9_//c;
+ next if tr/A-Za-z0-9_// == length;
+ $_ = '"' . perl_stringify ($_) . '"';
+ # Ensure that the enclosing C comment doesn't end
+ # by turning */ into *" . "/
+ s!\*\/!\*"."/!gs;
+ # gcc -Wall doesn't like finding /* inside a comment
+ s!\/\*!/"."\*!gs;
+ }
+ $body .= wrap ($leader, $follower, join (" ", @safe_names) . " */") . "\n";
+ # Figure out what to switch on.
+ # (RMS, Spread of jump table, Position, Hashref)
+ my @best = (1e38, ~0);
+ # Prefer the last character over the others. (As it lets us shorten the
+ # memEQ clause at no cost).
+ foreach my $i ($namelen - 1, 0 .. ($namelen - 2)) {
+ my ($min, $max) = (~0, 0);
+ my %spread;
+ if (is_perl56) {
+ # Need proper Unicode preserving hash keys for bytes in range 128-255
+ # here too, for some reason. grr 5.6.1 yet again.
+ tie %spread, 'ExtUtils::Constant::Aaargh56Hash';
+ }
+ foreach (@names) {
+ my $char = substr $_, $i, 1;
+ my $ord = ord $char;
+ confess "char $ord is out of range" if $ord > 255;
+ $max = $ord if $ord > $max;
+ $min = $ord if $ord < $min;
+ push @{$spread{$char}}, $_;
+ # warn "$_ $char";
+ }
+ # I'm going to pick the character to split on that minimises the root
+ # mean square of the number of names in each case. Normally this should
+ # be the one with the most keys, but it may pick a 7 where the 8 has
+ # one long linear search. I'm not sure if RMS or just sum of squares is
+ # actually better.
+ # $max and $min are for the tie-breaker if the root mean squares match.
+ # Assuming that the compiler may be building a jump table for the
+ # switch() then try to minimise the size of that jump table.
+ # Finally use < not <= so that if it still ties the earliest part of
+ # the string wins. Because if that passes but the memEQ fails, it may
+ # only need the start of the string to bin the choice.
+ # I think. But I'm micro-optimising. :-)
+ # OK. Trump that. Now favour the last character of the string, before the
+ # rest.
+ my $ss;
+ $ss += @$_ * @$_ foreach values %spread;
+ my $rms = sqrt ($ss / keys %spread);
+ if ($rms < $best[0] || ($rms == $best[0] && ($max - $min) < $best[1])) {
+ @best = ($rms, $max - $min, $i, \%spread);
+ }
+ }
+ confess "Internal error. Failed to pick a switch point for @names"
+ unless defined $best[2];
+ # use Data::Dumper; print Dumper (@best);
+ my ($offset, $best) = @best[2,3];
+ $body .= $indent . "/* Offset $offset gives the best switch position. */\n";
+
+ my $do_front_chop = $offset == 0 && $namelen > 2;
+ if ($do_front_chop) {
+ $body .= $indent . "switch (*" . $self->name_param() . "++) {\n";
+ } else {
+ $body .= $indent . "switch (" . $self->name_param() . "[$offset]) {\n";
+ }
+ foreach my $char (sort keys %$best) {
+ confess sprintf "'$char' is %d bytes long, not 1", length $char
+ if length ($char) != 1;
+ confess sprintf "char %#X is out of range", ord $char if ord ($char) > 255;
+ $body .= $indent . "case '" . C_stringify ($char) . "':\n";
+ foreach my $thisone (sort {
+ # Deal with the case of an item actually being an array ref to 1 or 2
+ # hashrefs. Don't assign to $a or $b, as they're aliases to the orignal
+ my $l = ref $a eq 'ARRAY' ? ($a->[0] || $->[1]) : $a;
+ my $r = ref $b eq 'ARRAY' ? ($b->[0] || $->[1]) : $b;
+ # Sort by weight first
+ ($r->{weight} || 0) <=> ($l->{weight} || 0)
+ # Sort equal weights by name
+ or $l->{name} cmp $r->{name}}
+ # If this looks evil, maybe it is. $items is a
+ # hashref, and we're doing a hash slice on it
+ @{$items}{@{$best->{$char}}}) {
+ # warn "You are here";
+ if ($do_front_chop) {
+ $body .= $self->match_clause ({indent => 2 + length $indent,
+ checked_at => \$char}, $thisone);
+ } else {
+ $body .= $self->match_clause ({indent => 2 + length $indent,
+ checked_at => $offset}, $thisone);
+ }
+ }
+ $body .= $indent . " break;\n";
+ }
+ $body .= $indent . "}\n";
+ return $body;
+}
+
+sub C_constant_return_type {
+ "static int";
+}
+
+sub C_constant_prefix_param {
+ '';
+}
+
+sub C_constant_prefix_param_defintion {
+ '';
+}
+
+sub name_param_definition {
+ "const char *" . $_[0]->name_param;
+}
+
+sub namelen_param {
+ 'len';
+}
+
+sub namelen_param_definition {
+ 'size_t ' . $_[0]->namelen_param;
+}
+
+sub C_constant_other_params {
+ '';
+}
+
+sub C_constant_other_params_defintion {
+ '';
+}
+
+=item params WHAT
+
+An "internal" method, subject to change, currently called to allow an
+overriding class to cache information that will then be passed into all
+the C<*param*> calls. (Yes, having to read the source to make sense of this is
+considered a known bug). I<WHAT> is be a hashref of types the constant
+function will return. In ExtUtils::Constant::XS this method is used to
+returns a hashref keyed IV NV PV SV to show which combination of pointers will
+be needed in the C argument list generated by
+C_constant_other_params_definition and C_constant_other_params
+
+=cut
+
+sub params {
+ '';
+}
+
+
+=item dogfood arg_hashref, ITEM...
+
+An internal function to generate the embedded perl code that will regenerate
+the constant subroutines. Parameters are the same as for C_constant.
+
+Currently the base class does nothing and returns an empty string.
+
+=cut
+
+sub dogfood {
+ ''
+}
+
+=item normalise_items args, default_type, seen_types, seen_items, ITEM...
+
+Convert the items to a normalised form. For 8 bit and Unicode values converts
+the item to an array of 1 or 2 items, both 8 bit and UTF-8 encoded.
+
+=cut
+
+sub normalise_items
+{
+ my $self = shift;
+ my $args = shift;
+ my $default_type = shift;
+ my $what = shift;
+ my $items = shift;
+ my @new_items;
+ foreach my $orig (@_) {
+ my ($name, $item);
+ if (ref $orig) {
+ # Make a copy which is a normalised version of the ref passed in.
+ $name = $orig->{name};
+ my ($type, $macro, $value) = @$orig{qw (type macro value)};
+ $type ||= $default_type;
+ $what->{$type} = 1;
+ $item = {name=>$name, type=>$type};
+
+ undef $macro if defined $macro and $macro eq $name;
+ $item->{macro} = $macro if defined $macro;
+ undef $value if defined $value and $value eq $name;
+ $item->{value} = $value if defined $value;
+ foreach my $key (qw(default pre post def_pre def_post weight
+ not_constant)) {
+ my $value = $orig->{$key};
+ $item->{$key} = $value if defined $value;
+ # warn "$key $value";
+ }
+ } else {
+ $name = $orig;
+ $item = {name=>$name, type=>$default_type};
+ $what->{$default_type} = 1;
+ }
+ warn +(ref ($self) || $self)
+ . "doesn't know how to handle values of type $_ used in macro $name"
+ unless $self->valid_type ($item->{type});
+ # tr///c is broken on 5.6.1 for utf8, so my original tr/\0-\177//c
+ # doesn't work. Upgrade to 5.8
+ # if ($name !~ tr/\0-\177//c || $] < 5.005_50) {
+ if ($name =~ tr/\0-\177// == length $name || $] < 5.005_50
+ || $args->{disable_utf8_duplication}) {
+ # No characters outside 7 bit ASCII.
+ if (exists $items->{$name}) {
+ die "Multiple definitions for macro $name";
+ }
+ $items->{$name} = $item;
+ } else {
+ # No characters outside 8 bit. This is hardest.
+ if (exists $items->{$name} and ref $items->{$name} ne 'ARRAY') {
+ confess "Unexpected ASCII definition for macro $name";
+ }
+ # Again, 5.6.1 tr broken, so s/5\.6.*/5\.8\.0/;
+ # if ($name !~ tr/\0-\377//c) {
+ if ($name =~ tr/\0-\377// == length $name) {
+# if ($] < 5.007) {
+# $name = pack "C*", unpack "U*", $name;
+# }
+ $item->{utf8} = 'no';
+ $items->{$name}[1] = $item;
+ push @new_items, $item;
+ # Copy item, to create the utf8 variant.
+ $item = {%$item};
+ }
+ # Encode the name as utf8 bytes.
+ unless (is_perl56) {
+ utf8::encode($name);
+ } else {
+# warn "Was >$name< " . length ${name};
+ $name = pack 'C*', unpack 'C*', $name . pack 'U*';
+# warn "Now '${name}' " . length ${name};
+ }
+ if ($items->{$name}[0]) {
+ die "Multiple definitions for macro $name";
+ }
+ $item->{utf8} = 'yes';
+ $item->{name} = $name;
+ $items->{$name}[0] = $item;
+ # We have need for the utf8 flag.
+ $what->{''} = 1;
+ }
+ push @new_items, $item;
+ }
+ @new_items;
+}
+
+=item C_constant arg_hashref, ITEM...
+
+A function that returns a B<list> of C subroutine definitions that return
+the value and type of constants when passed the name by the XS wrapper.
+I<ITEM...> gives a list of constant names. Each can either be a string,
+which is taken as a C macro name, or a reference to a hash with the following
+keys
+
+=over 8
+
+=item name
+
+The name of the constant, as seen by the perl code.
+
+=item type
+
+The type of the constant (I<IV>, I<NV> etc)
+
+=item value
+
+A C expression for the value of the constant, or a list of C expressions if
+the type is aggregate. This defaults to the I<name> if not given.
+
+=item macro
+
+The C pre-processor macro to use in the C<#ifdef>. This defaults to the
+I<name>, and is mainly used if I<value> is an C<enum>. If a reference an
+array is passed then the first element is used in place of the C<#ifdef>
+line, and the second element in place of the C<#endif>. This allows
+pre-processor constructions such as
+
+ #if defined (foo)
+ #if !defined (bar)
+ ...
+ #endif
+ #endif
+
+to be used to determine if a constant is to be defined.
+
+A "macro" 1 signals that the constant is always defined, so the C<#if>/C<#endif>
+test is omitted.
+
+=item default
+
+Default value to use (instead of C<croak>ing with "your vendor has not
+defined...") to return if the macro isn't defined. Specify a reference to
+an array with type followed by value(s).
+
+=item pre
+
+C code to use before the assignment of the value of the constant. This allows
+you to use temporary variables to extract a value from part of a C<struct>
+and return this as I<value>. This C code is places at the start of a block,
+so you can declare variables in it.
+
+=item post
+
+C code to place between the assignment of value (to a temporary) and the
+return from the function. This allows you to clear up anything in I<pre>.
+Rarely needed.
+
+=item def_pre
+
+=item def_post
+
+Equivalents of I<pre> and I<post> for the default value.
+
+=item utf8
+
+Generated internally. Is zero or undefined if name is 7 bit ASCII,
+"no" if the name is 8 bit (and so should only match if SvUTF8() is false),
+"yes" if the name is utf8 encoded.
+
+The internals automatically clone any name with characters 128-255 but none
+256+ (ie one that could be either in bytes or utf8) into a second entry
+which is utf8 encoded.
+
+=item weight
+
+Optional sorting weight for names, to determine the order of
+linear testing when multiple names fall in the same case of a switch clause.
+Higher comes earlier, undefined defaults to zero.
+
+=back
+
+In the argument hashref, I<package> is the name of the package, and is only
+used in comments inside the generated C code. I<subname> defaults to
+C<constant> if undefined.
+
+I<default_type> is the type returned by C<ITEM>s that don't specify their
+type. It defaults to the value of C<default_type()>. I<types> should be given
+either as a comma separated list of types that the C subroutine I<subname>
+will generate or as a reference to a hash. I<default_type> will be added to
+the list if not present, as will any types given in the list of I<ITEM>s. The
+resultant list should be the same list of types that C<XS_constant> is
+given. [Otherwise C<XS_constant> and C<C_constant> may differ in the number of
+parameters to the constant function. I<indent> is currently unused and
+ignored. In future it may be used to pass in information used to change the C
+indentation style used.] The best way to maintain consistency is to pass in a
+hash reference and let this function update it.
+
+I<breakout> governs when child functions of I<subname> are generated. If there
+are I<breakout> or more I<ITEM>s with the same length of name, then the code
+to switch between them is placed into a function named I<subname>_I<len>, for
+example C<constant_5> for names 5 characters long. The default I<breakout> is
+3. A single C<ITEM> is always inlined.
+
+=cut
+
+# The parameter now BREAKOUT was previously documented as:
+#
+# I<NAMELEN> if defined signals that all the I<name>s of the I<ITEM>s are of
+# this length, and that the constant name passed in by perl is checked and
+# also of this length. It is used during recursion, and should be C<undef>
+# unless the caller has checked all the lengths during code generation, and
+# the generated subroutine is only to be called with a name of this length.
+#
+# As you can see it now performs this function during recursion by being a
+# scalar reference.
+
+sub C_constant {
+ my ($self, $args, @items) = @_;
+ my ($package, $subname, $default_type, $what, $indent, $breakout) =
+ @{$args}{qw(package subname default_type types indent breakout)};
+ $package ||= 'Foo';
+ $subname ||= 'constant';
+ # I'm not using this. But a hashref could be used for full formatting without
+ # breaking this API
+ # $indent ||= 0;
+
+ my ($namelen, $items);
+ if (ref $breakout) {
+ # We are called recursively. We trust @items to be normalised, $what to
+ # be a hashref, and pinch %$items from our parent to save recalculation.
+ ($namelen, $items) = @$breakout;
+ } else {
+ $items = {};
+ if (is_perl56) {
+ # Need proper Unicode preserving hash keys.
+ require ExtUtils::Constant::Aaargh56Hash;
+ tie %$items, 'ExtUtils::Constant::Aaargh56Hash';
+ }
+ $breakout ||= 3;
+ $default_type ||= $self->default_type();
+ if (!ref $what) {
+ # Convert line of the form IV,UV,NV to hash
+ $what = {map {$_ => 1} split /,\s*/, ($what || '')};
+ # Figure out what types we're dealing with, and assign all unknowns to the
+ # default type
+ }
+ @items = $self->normalise_items ({}, $default_type, $what, $items, @items);
+ # use Data::Dumper; print Dumper @items;
+ }
+ my $params = $self->params ($what);
+
+ # Probably "static int"
+ my ($body, @subs);
+ $body = $self->C_constant_return_type($params) . "\n$subname ("
+ # Eg "pTHX_ "
+ . $self->C_constant_prefix_param_defintion($params)
+ # Probably "const char *name"
+ . $self->name_param_definition($params);
+ # Something like ", STRLEN len"
+ $body .= ", " . $self->namelen_param_definition($params)
+ unless defined $namelen;
+ $body .= $self->C_constant_other_params_defintion($params);
+ $body .= ") {\n";
+
+ if (defined $namelen) {
+ # We are a child subroutine. Print the simple description
+ my $comment = 'When generated this function returned values for the list'
+ . ' of names given here. However, subsequent manual editing may have'
+ . ' added or removed some.';
+ $body .= $self->switch_clause ({indent=>2, comment=>$comment},
+ $namelen, $items, @items);
+ } else {
+ # We are the top level.
+ $body .= " /* Initially switch on the length of the name. */\n";
+ $body .= $self->dogfood ({package => $package, subname => $subname,
+ default_type => $default_type, what => $what,
+ indent => $indent, breakout => $breakout},
+ @items);
+ $body .= ' switch ('.$self->namelen_param().") {\n";
+ # Need to group names of the same length
+ my @by_length;
+ foreach (@items) {
+ push @{$by_length[length $_->{name}]}, $_;
+ }
+ foreach my $i (0 .. $#by_length) {
+ next unless $by_length[$i]; # None of this length
+ $body .= " case $i:\n";
+ if (@{$by_length[$i]} == 1) {
+ my $only_thing = $by_length[$i]->[0];
+ if ($only_thing->{utf8}) {
+ if ($only_thing->{utf8} eq 'yes') {
+ # With utf8 on flag item is passed in element 0
+ $body .= $self->match_clause (undef, [$only_thing]);
+ } else {
+ # With utf8 off flag item is passed in element 1
+ $body .= $self->match_clause (undef, [undef, $only_thing]);
+ }
+ } else {
+ $body .= $self->match_clause (undef, $only_thing);
+ }
+ } elsif (@{$by_length[$i]} < $breakout) {
+ $body .= $self->switch_clause ({indent=>4},
+ $i, $items, @{$by_length[$i]});
+ } else {
+ # Only use the minimal set of parameters actually needed by the types
+ # of the names of this length.
+ my $what = {};
+ foreach (@{$by_length[$i]}) {
+ $what->{$_->{type}} = 1;
+ $what->{''} = 1 if $_->{utf8};
+ }
+ $params = $self->params ($what);
+ push @subs, $self->C_constant ({package=>$package,
+ subname=>"${subname}_$i",
+ default_type => $default_type,
+ types => $what, indent => $indent,
+ breakout => [$i, $items]},
+ @{$by_length[$i]});
+ $body .= " return ${subname}_$i ("
+ # Eg "aTHX_ "
+ . $self->C_constant_prefix_param($params)
+ # Probably "name"
+ . $self->name_param($params);
+ $body .= $self->C_constant_other_params($params);
+ $body .= ");\n";
+ }
+ $body .= " break;\n";
+ }
+ $body .= " }\n";
+ }
+ my $notfound = $self->return_statement_for_notfound();
+ $body .= " $notfound\n" if $notfound;
+ $body .= "}\n";
+ return (@subs, $body);
+}
+
+1;
+__END__
+
+=back
+
+=head1 BUGS
+
+Not everything is documented yet.
+
+Probably others.
+
+=head1 AUTHOR
+
+Nicholas Clark <nick@ccl4.org> based on the code in C<h2xs> by Larry Wall and
+others
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/Constant/ProxySubs.pm b/Master/tlpkg/tlperl/lib/ExtUtils/Constant/ProxySubs.pm
new file mode 100644
index 00000000000..c3fe8ed3c56
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/Constant/ProxySubs.pm
@@ -0,0 +1,549 @@
+package ExtUtils::Constant::ProxySubs;
+
+use strict;
+use vars qw($VERSION @ISA %type_to_struct %type_from_struct %type_to_sv
+ %type_to_C_value %type_is_a_problem %type_num_args
+ %type_temporary);
+use Carp;
+require ExtUtils::Constant::XS;
+use ExtUtils::Constant::Utils qw(C_stringify);
+use ExtUtils::Constant::XS qw(%XS_TypeSet);
+
+$VERSION = '0.06';
+@ISA = 'ExtUtils::Constant::XS';
+
+%type_to_struct =
+ (
+ IV => '{const char *name; I32 namelen; IV value;}',
+ NV => '{const char *name; I32 namelen; NV value;}',
+ UV => '{const char *name; I32 namelen; UV value;}',
+ PV => '{const char *name; I32 namelen; const char *value;}',
+ PVN => '{const char *name; I32 namelen; const char *value; STRLEN len;}',
+ YES => '{const char *name; I32 namelen;}',
+ NO => '{const char *name; I32 namelen;}',
+ UNDEF => '{const char *name; I32 namelen;}',
+ '' => '{const char *name; I32 namelen;} ',
+ );
+
+%type_from_struct =
+ (
+ IV => sub { $_[0] . '->value' },
+ NV => sub { $_[0] . '->value' },
+ UV => sub { $_[0] . '->value' },
+ PV => sub { $_[0] . '->value' },
+ PVN => sub { $_[0] . '->value', $_[0] . '->len' },
+ YES => sub {},
+ NO => sub {},
+ UNDEF => sub {},
+ '' => sub {},
+ );
+
+%type_to_sv =
+ (
+ IV => sub { "newSViv($_[0])" },
+ NV => sub { "newSVnv($_[0])" },
+ UV => sub { "newSVuv($_[0])" },
+ PV => sub { "newSVpv($_[0], 0)" },
+ PVN => sub { "newSVpvn($_[0], $_[1])" },
+ YES => sub { '&PL_sv_yes' },
+ NO => sub { '&PL_sv_no' },
+ UNDEF => sub { '&PL_sv_undef' },
+ '' => sub { '&PL_sv_yes' },
+ SV => sub {"SvREFCNT_inc($_[0])"},
+ );
+
+%type_to_C_value =
+ (
+ YES => sub {},
+ NO => sub {},
+ UNDEF => sub {},
+ '' => sub {},
+ );
+
+sub type_to_C_value {
+ my ($self, $type) = @_;
+ return $type_to_C_value{$type} || sub {return map {ref $_ ? @$_ : $_} @_};
+}
+
+# TODO - figure out if there is a clean way for the type_to_sv code to
+# attempt s/sv_2mortal// and if it succeeds tell type_to_sv not to add
+# SvREFCNT_inc
+%type_is_a_problem =
+ (
+ # The documentation says *mortal SV*, but we now need a non-mortal copy.
+ SV => 1,
+ );
+
+%type_temporary =
+ (
+ SV => ['SV *'],
+ PV => ['const char *'],
+ PVN => ['const char *', 'STRLEN'],
+ );
+$type_temporary{$_} = [$_] foreach qw(IV UV NV);
+
+while (my ($type, $value) = each %XS_TypeSet) {
+ $type_num_args{$type}
+ = defined $value ? ref $value ? scalar @$value : 1 : 0;
+}
+$type_num_args{''} = 0;
+
+sub partition_names {
+ my ($self, $default_type, @items) = @_;
+ my (%found, @notfound, @trouble);
+
+ while (my $item = shift @items) {
+ my $default = delete $item->{default};
+ if ($default) {
+ # If we find a default value, convert it into a regular item and
+ # append it to the queue of items to process
+ my $default_item = {%$item};
+ $default_item->{invert_macro} = 1;
+ $default_item->{pre} = delete $item->{def_pre};
+ $default_item->{post} = delete $item->{def_post};
+ $default_item->{type} = shift @$default;
+ $default_item->{value} = $default;
+ push @items, $default_item;
+ } else {
+ # It can be "not found" unless it's the default (invert the macro)
+ # or the "macro" is an empty string (ie no macro)
+ push @notfound, $item unless $item->{invert_macro}
+ or !$self->macro_to_ifdef($self->macro_from_item($item));
+ }
+
+ if ($item->{pre} or $item->{post} or $item->{not_constant}
+ or $type_is_a_problem{$item->{type}}) {
+ push @trouble, $item;
+ } else {
+ push @{$found{$item->{type}}}, $item;
+ }
+ }
+ # use Data::Dumper; print Dumper \%found;
+ (\%found, \@notfound, \@trouble);
+}
+
+sub boottime_iterator {
+ my ($self, $type, $iterator, $hash, $subname) = @_;
+ my $extractor = $type_from_struct{$type};
+ die "Can't find extractor code for type $type"
+ unless defined $extractor;
+ my $generator = $type_to_sv{$type};
+ die "Can't find generator code for type $type"
+ unless defined $generator;
+
+ my $athx = $self->C_constant_prefix_param();
+
+ return sprintf <<"EOBOOT", &$generator(&$extractor($iterator));
+ while ($iterator->name) {
+ $subname($athx $hash, $iterator->name,
+ $iterator->namelen, %s);
+ ++$iterator;
+ }
+EOBOOT
+}
+
+sub name_len_value_macro {
+ my ($self, $item) = @_;
+ my $name = $item->{name};
+ my $value = $item->{value};
+ $value = $item->{name} unless defined $value;
+
+ my $namelen = length $name;
+ if ($name =~ tr/\0-\377// != $namelen) {
+ # the hash API signals UTF-8 by passing the length negated.
+ utf8::encode($name);
+ $namelen = -length $name;
+ }
+ $name = C_stringify($name);
+
+ my $macro = $self->macro_from_item($item);
+ ($name, $namelen, $value, $macro);
+}
+
+sub WriteConstants {
+ my $self = shift;
+ my $ARGS = {@_};
+
+ my ($c_fh, $xs_fh, $c_subname, $xs_subname, $default_type, $package)
+ = @{$ARGS}{qw(C_FH XS_FH C_SUBNAME XS_SUBNAME DEFAULT_TYPE NAME)};
+
+ my $options = $ARGS->{PROXYSUBS};
+ $options = {} unless ref $options;
+ my $explosives = $options->{croak_on_read};
+
+ $xs_subname ||= 'constant';
+
+ # If anyone is insane enough to suggest a package name containing %
+ my $package_sprintf_safe = $package;
+ $package_sprintf_safe =~ s/%/%%/g;
+
+ # All the types we see
+ my $what = {};
+ # A hash to lookup items with.
+ my $items = {};
+
+ my @items = $self->normalise_items ({disable_utf8_duplication => 1},
+ $default_type, $what, $items,
+ @{$ARGS->{NAMES}});
+
+ # Partition the values by type. Also include any defaults in here
+ # Everything that doesn't have a default needs alternative code for
+ # "I'm missing"
+ # And everything that has pre or post code ends up in a private block
+ my ($found, $notfound, $trouble)
+ = $self->partition_names($default_type, @items);
+
+ my $pthx = $self->C_constant_prefix_param_defintion();
+ my $athx = $self->C_constant_prefix_param();
+ my $symbol_table = C_stringify($package) . '::';
+
+ my $can_do_pcs = $] >= 5.009;
+ my $cast_CONSTSUB = $] < 5.010 ? '(char *)' : '';
+
+ print $c_fh $self->header(), <<"EOADD";
+static void
+${c_subname}_add_symbol($pthx HV *hash, const char *name, I32 namelen, SV *value) {
+EOADD
+ if (!$can_do_pcs) {
+ print $c_fh <<'EO_NOPCS';
+ if (namelen == namelen) {
+EO_NOPCS
+ } else {
+ print $c_fh <<"EO_PCS";
+ SV **sv = hv_fetch(hash, name, namelen, TRUE);
+ if (!sv) {
+ Perl_croak($athx "Couldn't add key '%s' to %%$package_sprintf_safe\::",
+ name);
+ }
+ if (SvOK(*sv) || SvTYPE(*sv) == SVt_PVGV) {
+ /* Someone has been here before us - have to make a real sub. */
+EO_PCS
+ }
+ # This piece of code is common to both
+ print $c_fh <<"EOADD";
+ newCONSTSUB(hash, ${cast_CONSTSUB}name, value);
+EOADD
+ if ($can_do_pcs) {
+ print $c_fh <<'EO_PCS';
+ } else {
+ SvUPGRADE(*sv, SVt_RV);
+ SvRV_set(*sv, value);
+ SvROK_on(*sv);
+ SvREADONLY_on(value);
+ }
+EO_PCS
+ } else {
+ print $c_fh <<'EO_NOPCS';
+ }
+EO_NOPCS
+ }
+ print $c_fh <<'EOADD';
+}
+
+EOADD
+
+ print $c_fh $explosives ? <<"EXPLODE" : "\n";
+
+static int
+Im_sorry_Dave(pTHX_ SV *sv, MAGIC *mg)
+{
+ PERL_UNUSED_ARG(mg);
+ Perl_croak(aTHX_
+ "Your vendor has not defined $package_sprintf_safe macro %"SVf
+ " used", sv);
+ NORETURN_FUNCTION_END;
+}
+
+static MGVTBL not_defined_vtbl = {
+ Im_sorry_Dave, /* get - I'm afraid I can't do that */
+ Im_sorry_Dave, /* set */
+ 0, /* len */
+ 0, /* clear */
+ 0, /* free */
+ 0, /* copy */
+ 0, /* dup */
+};
+
+EXPLODE
+
+{
+ my $key = $symbol_table;
+ # Just seems tidier (and slightly more space efficient) not to have keys
+ # such as Fcntl::
+ $key =~ s/::$//;
+ my $key_len = length $key;
+
+ print $c_fh <<"MISSING";
+
+#ifndef SYMBIAN
+
+/* Store a hash of all symbols missing from the package. To avoid trampling on
+ the package namespace (uninvited) put each package's hash in our namespace.
+ To avoid creating lots of typeblogs and symbol tables for sub-packages, put
+ each package's hash into one hash in our namespace. */
+
+static HV *
+get_missing_hash(pTHX) {
+ HV *const parent
+ = get_hv("ExtUtils::Constant::ProxySubs::Missing", GVf_MULTI);
+ /* We could make a hash of hashes directly, but this would confuse anything
+ at Perl space that looks at us, and as we're visible in Perl space,
+ best to play nice. */
+ SV *const *const ref
+ = hv_fetch(parent, "$key", $key_len, TRUE);
+ HV *new_hv;
+
+ if (!ref)
+ return NULL;
+
+ if (SvROK(*ref))
+ return (HV*) SvRV(*ref);
+
+ new_hv = newHV();
+ SvUPGRADE(*ref, SVt_RV);
+ SvRV_set(*ref, (SV *)new_hv);
+ SvROK_on(*ref);
+ return new_hv;
+}
+
+#endif
+
+MISSING
+
+}
+
+ print $xs_fh <<"EOBOOT";
+BOOT:
+ {
+#ifdef dTHX
+ dTHX;
+#endif
+ HV *symbol_table = get_hv("$symbol_table", GV_ADD);
+#ifndef SYMBIAN
+ HV *${c_subname}_missing;
+#endif
+EOBOOT
+
+ my %iterator;
+
+ $found->{''}
+ = [map {{%$_, type=>'', invert_macro => 1}} @$notfound];
+
+ foreach my $type (sort keys %$found) {
+ my $struct = $type_to_struct{$type};
+ my $type_to_value = $self->type_to_C_value($type);
+ my $number_of_args = $type_num_args{$type};
+ die "Can't find structure definition for type $type"
+ unless defined $struct;
+
+ my $struct_type = $type ? lc($type) . '_s' : 'notfound_s';
+ print $c_fh "struct $struct_type $struct;\n";
+
+ my $array_name = 'values_for_' . ($type ? lc $type : 'notfound');
+ print $xs_fh <<"EOBOOT";
+
+ static const struct $struct_type $array_name\[] =
+ {
+EOBOOT
+
+
+ foreach my $item (@{$found->{$type}}) {
+ my ($name, $namelen, $value, $macro)
+ = $self->name_len_value_macro($item);
+
+ my $ifdef = $self->macro_to_ifdef($macro);
+ if (!$ifdef && $item->{invert_macro}) {
+ carp("Attempting to supply a default for '$name' which has no conditional macro");
+ next;
+ }
+ print $xs_fh $ifdef;
+ if ($item->{invert_macro}) {
+ print $xs_fh
+ " /* This is the default value: */\n" if $type;
+ print $xs_fh "#else\n";
+ }
+ print $xs_fh " { ", join (', ', "\"$name\"", $namelen,
+ &$type_to_value($value)), " },\n",
+ $self->macro_to_endif($macro);
+ }
+
+
+ # Terminate the list with a NULL
+ print $xs_fh " { NULL, 0", (", 0" x $number_of_args), " } };\n";
+
+ $iterator{$type} = "value_for_" . ($type ? lc $type : 'notfound');
+
+ print $xs_fh <<"EOBOOT";
+ const struct $struct_type *$iterator{$type} = $array_name;
+EOBOOT
+ }
+
+ delete $found->{''};
+
+ print $xs_fh <<"EOBOOT";
+#ifndef SYMBIAN
+ ${c_subname}_missing = get_missing_hash(aTHX);
+#endif
+EOBOOT
+
+ my $add_symbol_subname = $c_subname . '_add_symbol';
+ foreach my $type (sort keys %$found) {
+ print $xs_fh $self->boottime_iterator($type, $iterator{$type},
+ 'symbol_table',
+ $add_symbol_subname);
+ }
+
+ print $xs_fh <<"EOBOOT";
+ while (value_for_notfound->name) {
+EOBOOT
+
+ print $xs_fh $explosives ? <<"EXPLODE" : << "DONT";
+ SV *tripwire = newSV(0);
+
+ sv_magicext(tripwire, 0, PERL_MAGIC_ext, &not_defined_vtbl, 0, 0);
+ SvPV_set(tripwire, (char *)value_for_notfound->name);
+ if(value_for_notfound->namelen >= 0) {
+ SvCUR_set(tripwire, value_for_notfound->namelen);
+ } else {
+ SvCUR_set(tripwire, -value_for_notfound->namelen);
+ SvUTF8_on(tripwire);
+ }
+ SvPOKp_on(tripwire);
+ SvREADONLY_on(tripwire);
+ assert(SvLEN(tripwire) == 0);
+
+ $add_symbol_subname($athx symbol_table, value_for_notfound->name,
+ value_for_notfound->namelen, tripwire);
+EXPLODE
+
+ /* Need to add prototypes, else parsing will vary by platform. */
+ SV **sv = hv_fetch(symbol_table, value_for_notfound->name,
+ value_for_notfound->namelen, TRUE);
+ if (!sv) {
+ Perl_croak($athx
+ "Couldn't add key '%s' to %%$package_sprintf_safe\::",
+ value_for_notfound->name);
+ }
+ if (!SvOK(*sv) && SvTYPE(*sv) != SVt_PVGV) {
+ /* Nothing was here before, so mark a prototype of "" */
+ sv_setpvn(*sv, "", 0);
+ } else if (SvPOK(*sv) && SvCUR(*sv) == 0) {
+ /* There is already a prototype of "" - do nothing */
+ } else {
+ /* Someone has been here before us - have to make a real
+ typeglob. */
+ /* It turns out to be incredibly hard to deal with all the
+ corner cases of sub foo (); and reporting errors correctly,
+ so lets cheat a bit. Start with a constant subroutine */
+ CV *cv = newCONSTSUB(symbol_table,
+ ${cast_CONSTSUB}value_for_notfound->name,
+ &PL_sv_yes);
+ /* and then turn it into a non constant declaration only. */
+ SvREFCNT_dec(CvXSUBANY(cv).any_ptr);
+ CvCONST_off(cv);
+ CvXSUB(cv) = NULL;
+ CvXSUBANY(cv).any_ptr = NULL;
+ }
+#ifndef SYMBIAN
+ if (!hv_store(${c_subname}_missing, value_for_notfound->name,
+ value_for_notfound->namelen, &PL_sv_yes, 0))
+ Perl_croak($athx "Couldn't add key '%s' to missing_hash",
+ value_for_notfound->name);
+#endif
+DONT
+
+ print $xs_fh <<"EOBOOT";
+
+ ++value_for_notfound;
+ }
+EOBOOT
+
+ foreach my $item (@$trouble) {
+ my ($name, $namelen, $value, $macro)
+ = $self->name_len_value_macro($item);
+ my $ifdef = $self->macro_to_ifdef($macro);
+ my $type = $item->{type};
+ my $type_to_value = $self->type_to_C_value($type);
+
+ print $xs_fh $ifdef;
+ if ($item->{invert_macro}) {
+ print $xs_fh
+ " /* This is the default value: */\n" if $type;
+ print $xs_fh "#else\n";
+ }
+ my $generator = $type_to_sv{$type};
+ die "Can't find generator code for type $type"
+ unless defined $generator;
+
+ print $xs_fh " {\n";
+ # We need to use a temporary value because some really troublesome
+ # items use C pre processor directives in their values, and in turn
+ # these don't fit nicely in the macro-ised generator functions
+ my $counter = 0;
+ printf $xs_fh " %s temp%d;\n", $_, $counter++
+ foreach @{$type_temporary{$type}};
+
+ print $xs_fh " $item->{pre}\n" if $item->{pre};
+
+ # And because the code in pre might be both declarations and
+ # statements, we can't declare and assign to the temporaries in one.
+ $counter = 0;
+ printf $xs_fh " temp%d = %s;\n", $counter++, $_
+ foreach &$type_to_value($value);
+
+ my @tempvarnames = map {sprintf 'temp%d', $_} 0 .. $counter - 1;
+ printf $xs_fh <<"EOBOOT", $name, &$generator(@tempvarnames);
+ ${c_subname}_add_symbol($athx symbol_table, "%s",
+ $namelen, %s);
+EOBOOT
+ print $xs_fh " $item->{post}\n" if $item->{post};
+ print $xs_fh " }\n";
+
+ print $xs_fh $self->macro_to_endif($macro);
+ }
+
+ print $xs_fh <<EOBOOT;
+ /* As we've been creating subroutines, we better invalidate any cached
+ methods */
+ ++PL_sub_generation;
+ }
+EOBOOT
+
+ print $xs_fh $explosives ? <<"EXPLODE" : <<"DONT";
+
+void
+$xs_subname(sv)
+ INPUT:
+ SV * sv;
+ PPCODE:
+ sv = newSVpvf("Your vendor has not defined $package_sprintf_safe macro %" SVf
+ ", used", sv);
+ PUSHs(sv_2mortal(sv));
+EXPLODE
+
+void
+$xs_subname(sv)
+ PREINIT:
+ STRLEN len;
+ INPUT:
+ SV * sv;
+ const char * s = SvPV(sv, len);
+ PPCODE:
+#ifdef SYMBIAN
+ sv = newSVpvf("%"SVf" is not a valid $package_sprintf_safe macro", sv);
+#else
+ HV *${c_subname}_missing = get_missing_hash(aTHX);
+ if (hv_exists(${c_subname}_missing, s, SvUTF8(sv) ? -(I32)len : (I32)len)) {
+ sv = newSVpvf("Your vendor has not defined $package_sprintf_safe macro %" SVf
+ ", used", sv);
+ } else {
+ sv = newSVpvf("%"SVf" is not a valid $package_sprintf_safe macro",
+ sv);
+ }
+#endif
+ PUSHs(sv_2mortal(sv));
+DONT
+
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/Constant/Utils.pm b/Master/tlpkg/tlperl/lib/ExtUtils/Constant/Utils.pm
new file mode 100644
index 00000000000..016507c72a6
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/Constant/Utils.pm
@@ -0,0 +1,131 @@
+package ExtUtils::Constant::Utils;
+
+use strict;
+use vars qw($VERSION @EXPORT_OK @ISA $is_perl56);
+use Carp;
+
+@ISA = 'Exporter';
+@EXPORT_OK = qw(C_stringify perl_stringify);
+$VERSION = '0.02';
+
+$is_perl56 = ($] < 5.007 && $] > 5.005_50);
+
+=head1 NAME
+
+ExtUtils::Constant::Utils - helper functions for ExtUtils::Constant
+
+=head1 SYNOPSIS
+
+ use ExtUtils::Constant::Utils qw (C_stringify);
+ $C_code = C_stringify $stuff;
+
+=head1 DESCRIPTION
+
+ExtUtils::Constant::Utils packages up utility subroutines used by
+ExtUtils::Constant, ExtUtils::Constant::Base and derived classes. All its
+functions are explicitly exportable.
+
+=head1 USAGE
+
+=over 4
+
+=item C_stringify NAME
+
+A function which returns a 7 bit ASCII correctly \ escaped version of the
+string passed suitable for C's "" or ''. It will die if passed Unicode
+characters.
+
+=cut
+
+# Hopefully make a happy C identifier.
+sub C_stringify {
+ local $_ = shift;
+ return unless defined $_;
+ # grr 5.6.1
+ confess "Wide character in '$_' intended as a C identifier"
+ if tr/\0-\377// != length;
+ # grr 5.6.1 moreso because its regexps will break on data that happens to
+ # be utf8, which includes my 8 bit test cases.
+ $_ = pack 'C*', unpack 'U*', $_ . pack 'U*' if $is_perl56;
+ s/\\/\\\\/g;
+ s/([\"\'])/\\$1/g; # Grr. fix perl mode.
+ s/\n/\\n/g; # Ensure newlines don't end up in octal
+ s/\r/\\r/g;
+ s/\t/\\t/g;
+ s/\f/\\f/g;
+ s/\a/\\a/g;
+ if (ord('A') == 193) { # EBCDIC has no ^\0-\177 workalike.
+ s/([[:^print:]])/sprintf "\\%03o", ord $1/ge;
+ } else {
+ s/([^\0-\177])/sprintf "\\%03o", ord $1/ge;
+ }
+ unless ($] < 5.006) {
+ # This will elicit a warning on 5.005_03 about [: :] being reserved unless
+ # I cheat
+ my $cheat = '([[:^print:]])';
+ s/$cheat/sprintf "\\%03o", ord $1/ge;
+ } else {
+ require POSIX;
+ s/([^A-Za-z0-9_])/POSIX::isprint($1) ? $1 : sprintf "\\%03o", ord $1/ge;
+ }
+ $_;
+}
+
+=item perl_stringify NAME
+
+A function which returns a 7 bit ASCII correctly \ escaped version of the
+string passed suitable for a perl "" string.
+
+=cut
+
+# Hopefully make a happy perl identifier.
+sub perl_stringify {
+ local $_ = shift;
+ return unless defined $_;
+ s/\\/\\\\/g;
+ s/([\"\'])/\\$1/g; # Grr. fix perl mode.
+ s/\n/\\n/g; # Ensure newlines don't end up in octal
+ s/\r/\\r/g;
+ s/\t/\\t/g;
+ s/\f/\\f/g;
+ s/\a/\\a/g;
+ unless ($] < 5.006) {
+ if ($] > 5.007) {
+ if (ord('A') == 193) { # EBCDIC has no ^\0-\177 workalike.
+ s/([[:^print:]])/sprintf "\\x{%X}", ord $1/ge;
+ } else {
+ s/([^\0-\177])/sprintf "\\x{%X}", ord $1/ge;
+ }
+ } else {
+ # Grr 5.6.1. And I don't think I can use utf8; to force the regexp
+ # because 5.005_03 will fail.
+ # This is grim, but I also can't split on //
+ my $copy;
+ foreach my $index (0 .. length ($_) - 1) {
+ my $char = substr ($_, $index, 1);
+ $copy .= ($char le "\177") ? $char : sprintf "\\x{%X}", ord $char;
+ }
+ $_ = $copy;
+ }
+ # This will elicit a warning on 5.005_03 about [: :] being reserved unless
+ # I cheat
+ my $cheat = '([[:^print:]])';
+ s/$cheat/sprintf "\\%03o", ord $1/ge;
+ } else {
+ # Turns out "\x{}" notation only arrived with 5.6
+ s/([^\0-\177])/sprintf "\\x%02X", ord $1/ge;
+ require POSIX;
+ s/([^A-Za-z0-9_])/POSIX::isprint($1) ? $1 : sprintf "\\%03o", ord $1/ge;
+ }
+ $_;
+}
+
+1;
+__END__
+
+=back
+
+=head1 AUTHOR
+
+Nicholas Clark <nick@ccl4.org> based on the code in C<h2xs> by Larry Wall and
+others
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/Constant/XS.pm b/Master/tlpkg/tlperl/lib/ExtUtils/Constant/XS.pm
new file mode 100644
index 00000000000..14eb8097146
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/Constant/XS.pm
@@ -0,0 +1,259 @@
+package ExtUtils::Constant::XS;
+
+use strict;
+use vars qw($VERSION %XS_Constant %XS_TypeSet @ISA @EXPORT_OK $is_perl56);
+use Carp;
+use ExtUtils::Constant::Utils 'perl_stringify';
+require ExtUtils::Constant::Base;
+
+
+@ISA = qw(ExtUtils::Constant::Base Exporter);
+@EXPORT_OK = qw(%XS_Constant %XS_TypeSet);
+
+$VERSION = '0.03';
+
+$is_perl56 = ($] < 5.007 && $] > 5.005_50);
+
+=head1 NAME
+
+ExtUtils::Constant::XS - generate C code for XS modules' constants.
+
+=head1 SYNOPSIS
+
+ require ExtUtils::Constant::XS;
+
+=head1 DESCRIPTION
+
+ExtUtils::Constant::XS overrides ExtUtils::Constant::Base to generate C
+code for XS modules' constants.
+
+=head1 BUGS
+
+Nothing is documented.
+
+Probably others.
+
+=head1 AUTHOR
+
+Nicholas Clark <nick@ccl4.org> based on the code in C<h2xs> by Larry Wall and
+others
+
+=cut
+
+# '' is used as a flag to indicate non-ascii macro names, and hence the need
+# to pass in the utf8 on/off flag.
+%XS_Constant = (
+ '' => '',
+ IV => 'PUSHi(iv)',
+ UV => 'PUSHu((UV)iv)',
+ NV => 'PUSHn(nv)',
+ PV => 'PUSHp(pv, strlen(pv))',
+ PVN => 'PUSHp(pv, iv)',
+ SV => 'PUSHs(sv)',
+ YES => 'PUSHs(&PL_sv_yes)',
+ NO => 'PUSHs(&PL_sv_no)',
+ UNDEF => '', # implicit undef
+);
+
+%XS_TypeSet = (
+ IV => '*iv_return = ',
+ UV => '*iv_return = (IV)',
+ NV => '*nv_return = ',
+ PV => '*pv_return = ',
+ PVN => ['*pv_return = ', '*iv_return = (IV)'],
+ SV => '*sv_return = ',
+ YES => undef,
+ NO => undef,
+ UNDEF => undef,
+);
+
+sub header {
+ my $start = 1;
+ my @lines;
+ push @lines, "#define PERL_constant_NOTFOUND\t$start\n"; $start++;
+ push @lines, "#define PERL_constant_NOTDEF\t$start\n"; $start++;
+ foreach (sort keys %XS_Constant) {
+ next if $_ eq '';
+ push @lines, "#define PERL_constant_IS$_\t$start\n"; $start++;
+ }
+ push @lines, << 'EOT';
+
+#ifndef NVTYPE
+typedef double NV; /* 5.6 and later define NVTYPE, and typedef NV to it. */
+#endif
+#ifndef aTHX_
+#define aTHX_ /* 5.6 or later define this for threading support. */
+#endif
+#ifndef pTHX_
+#define pTHX_ /* 5.6 or later define this for threading support. */
+#endif
+EOT
+
+ return join '', @lines;
+}
+
+sub valid_type {
+ my ($self, $type) = @_;
+ return exists $XS_TypeSet{$type};
+}
+
+# This might actually be a return statement
+sub assignment_clause_for_type {
+ my $self = shift;
+ my $args = shift;
+ my $type = $args->{type};
+ my $typeset = $XS_TypeSet{$type};
+ if (ref $typeset) {
+ die "Type $type is aggregate, but only single value given"
+ if @_ == 1;
+ return map {"$typeset->[$_]$_[$_];"} 0 .. $#$typeset;
+ } elsif (defined $typeset) {
+ confess "Aggregate value given for type $type"
+ if @_ > 1;
+ return "$typeset$_[0];";
+ }
+ return ();
+}
+
+sub return_statement_for_type {
+ my ($self, $type) = @_;
+ # In the future may pass in an options hash
+ $type = $type->{type} if ref $type;
+ "return PERL_constant_IS$type;";
+}
+
+sub return_statement_for_notdef {
+ # my ($self) = @_;
+ "return PERL_constant_NOTDEF;";
+}
+
+sub return_statement_for_notfound {
+ # my ($self) = @_;
+ "return PERL_constant_NOTFOUND;";
+}
+
+sub default_type {
+ 'IV';
+}
+
+sub macro_from_name {
+ my ($self, $item) = @_;
+ my $macro = $item->{name};
+ $macro = $item->{value} unless defined $macro;
+ $macro;
+}
+
+sub macro_from_item {
+ my ($self, $item) = @_;
+ my $macro = $item->{macro};
+ $macro = $self->macro_from_name($item) unless defined $macro;
+ $macro;
+}
+
+# Keep to the traditional perl source macro
+sub memEQ {
+ "memEQ";
+}
+
+sub params {
+ my ($self, $what) = @_;
+ foreach (sort keys %$what) {
+ warn "ExtUtils::Constant doesn't know how to handle values of type $_" unless defined $XS_Constant{$_};
+ }
+ my $params = {};
+ $params->{''} = 1 if $what->{''};
+ $params->{IV} = 1 if $what->{IV} || $what->{UV} || $what->{PVN};
+ $params->{NV} = 1 if $what->{NV};
+ $params->{PV} = 1 if $what->{PV} || $what->{PVN};
+ $params->{SV} = 1 if $what->{SV};
+ return $params;
+}
+
+
+sub C_constant_prefix_param {
+ "aTHX_ ";
+}
+
+sub C_constant_prefix_param_defintion {
+ "pTHX_ ";
+}
+
+sub namelen_param_definition {
+ 'STRLEN ' . $_[0] -> namelen_param;
+}
+
+sub C_constant_other_params_defintion {
+ my ($self, $params) = @_;
+ my $body = '';
+ $body .= ", int utf8" if $params->{''};
+ $body .= ", IV *iv_return" if $params->{IV};
+ $body .= ", NV *nv_return" if $params->{NV};
+ $body .= ", const char **pv_return" if $params->{PV};
+ $body .= ", SV **sv_return" if $params->{SV};
+ $body;
+}
+
+sub C_constant_other_params {
+ my ($self, $params) = @_;
+ my $body = '';
+ $body .= ", utf8" if $params->{''};
+ $body .= ", iv_return" if $params->{IV};
+ $body .= ", nv_return" if $params->{NV};
+ $body .= ", pv_return" if $params->{PV};
+ $body .= ", sv_return" if $params->{SV};
+ $body;
+}
+
+sub dogfood {
+ my ($self, $args, @items) = @_;
+ my ($package, $subname, $default_type, $what, $indent, $breakout) =
+ @{$args}{qw(package subname default_type what indent breakout)};
+ my $result = <<"EOT";
+ /* When generated this function returned values for the list of names given
+ in this section of perl code. Rather than manually editing these functions
+ to add or remove constants, which would result in this comment and section
+ of code becoming inaccurate, we recommend that you edit this section of
+ code, and use it to regenerate a new set of constant functions which you
+ then use to replace the originals.
+
+ Regenerate these constant functions by feeding this entire source file to
+ perl -x
+
+#!$^X -w
+use ExtUtils::Constant qw (constant_types C_constant XS_constant);
+
+EOT
+ $result .= $self->dump_names ({default_type=>$default_type, what=>$what,
+ indent=>0, declare_types=>1},
+ @items);
+ $result .= <<'EOT';
+
+print constant_types(), "\n"; # macro defs
+EOT
+ $package = perl_stringify($package);
+ $result .=
+ "foreach (C_constant (\"$package\", '$subname', '$default_type', \$types, ";
+ # The form of the indent parameter isn't defined. (Yet)
+ if (defined $indent) {
+ require Data::Dumper;
+ $Data::Dumper::Terse=1;
+ $Data::Dumper::Terse=1; # Not used once. :-)
+ chomp ($indent = Data::Dumper::Dumper ($indent));
+ $result .= $indent;
+ } else {
+ $result .= 'undef';
+ }
+ $result .= ", $breakout" . ', @names) ) {
+ print $_, "\n"; # C constant subs
+}
+print "\n#### XS Section:\n";
+print XS_constant ("' . $package . '", $types);
+__END__
+ */
+
+';
+
+ $result;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/Embed.pm b/Master/tlpkg/tlperl/lib/ExtUtils/Embed.pm
new file mode 100644
index 00000000000..24ae9092f52
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/Embed.pm
@@ -0,0 +1,511 @@
+# $Id: Embed.pm,v 1.1.1.1 2002/01/16 19:27:19 schwern Exp $
+require 5.002;
+
+package ExtUtils::Embed;
+require Exporter;
+require FileHandle;
+use Config;
+use Getopt::Std;
+use File::Spec;
+
+#Only when we need them
+#require ExtUtils::MakeMaker;
+#require ExtUtils::Liblist;
+
+use vars qw(@ISA @EXPORT $VERSION
+ @Extensions $Verbose $lib_ext
+ $opt_o $opt_s
+ );
+use strict;
+
+# This is not a dual-life module, so no need for development version numbers
+$VERSION = '1.28';
+
+@ISA = qw(Exporter);
+@EXPORT = qw(&xsinit &ldopts
+ &ccopts &ccflags &ccdlflags &perl_inc
+ &xsi_header &xsi_protos &xsi_body);
+
+#let's have Miniperl borrow from us instead
+#require ExtUtils::Miniperl;
+#*canon = \&ExtUtils::Miniperl::canon;
+
+$Verbose = 0;
+$lib_ext = $Config{lib_ext} || '.a';
+
+sub is_cmd { $0 eq '-e' }
+
+sub my_return {
+ my $val = shift;
+ if(is_cmd) {
+ print $val;
+ }
+ else {
+ return $val;
+ }
+}
+
+sub xsinit {
+ my($file, $std, $mods) = @_;
+ my($fh,@mods,%seen);
+ $file ||= "perlxsi.c";
+ my $xsinit_proto = "pTHX";
+
+ if (@_) {
+ @mods = @$mods if $mods;
+ }
+ else {
+ getopts('o:s:');
+ $file = $opt_o if defined $opt_o;
+ $std = $opt_s if defined $opt_s;
+ @mods = @ARGV;
+ }
+ $std = 1 unless scalar @mods;
+
+ if ($file eq "STDOUT") {
+ $fh = \*STDOUT;
+ }
+ else {
+ $fh = new FileHandle "> $file";
+ }
+
+ push(@mods, static_ext()) if defined $std;
+ @mods = grep(!$seen{$_}++, @mods);
+
+ print $fh &xsi_header();
+ print $fh "EXTERN_C void xs_init ($xsinit_proto);\n\n";
+ print $fh &xsi_protos(@mods);
+
+ print $fh "\nEXTERN_C void\nxs_init($xsinit_proto)\n{\n";
+ print $fh &xsi_body(@mods);
+ print $fh "}\n";
+
+}
+
+sub xsi_header {
+ return <<EOF;
+#include <EXTERN.h>
+#include <perl.h>
+
+EOF
+}
+
+sub xsi_protos {
+ my(@exts) = @_;
+ my(@retval,%seen);
+ my $boot_proto = "pTHX_ CV* cv";
+ foreach $_ (@exts){
+ my($pname) = canon('/', $_);
+ my($mname, $cname);
+ ($mname = $pname) =~ s!/!::!g;
+ ($cname = $pname) =~ s!/!__!g;
+ my($ccode) = "EXTERN_C void boot_${cname} ($boot_proto);\n";
+ next if $seen{$ccode}++;
+ push(@retval, $ccode);
+ }
+ return join '', @retval;
+}
+
+sub xsi_body {
+ my(@exts) = @_;
+ my($pname,@retval,%seen);
+ my($dl) = canon('/','DynaLoader');
+ push(@retval, "\tchar *file = __FILE__;\n");
+ push(@retval, "\tdXSUB_SYS;\n") if $] > 5.002;
+ push(@retval, "\n");
+
+ foreach $_ (@exts){
+ my($pname) = canon('/', $_);
+ my($mname, $cname, $ccode);
+ ($mname = $pname) =~ s!/!::!g;
+ ($cname = $pname) =~ s!/!__!g;
+ if ($pname eq $dl){
+ # Must NOT install 'DynaLoader::boot_DynaLoader' as 'bootstrap'!
+ # boot_DynaLoader is called directly in DynaLoader.pm
+ $ccode = "\t/* DynaLoader is a special case */\n\tnewXS(\"${mname}::boot_${cname}\", boot_${cname}, file);\n";
+ push(@retval, $ccode) unless $seen{$ccode}++;
+ } else {
+ $ccode = "\tnewXS(\"${mname}::bootstrap\", boot_${cname}, file);\n";
+ push(@retval, $ccode) unless $seen{$ccode}++;
+ }
+ }
+ return join '', @retval;
+}
+
+sub static_ext {
+ unless (scalar @Extensions) {
+ my $static_ext = $Config{static_ext};
+ $static_ext =~ s/^\s+//;
+ @Extensions = sort split /\s+/, $static_ext;
+ unshift @Extensions, qw(DynaLoader);
+ }
+ @Extensions;
+}
+
+sub _escape {
+ my $arg = shift;
+ $$arg =~ s/([\(\)])/\\$1/g;
+}
+
+sub _ldflags {
+ my $ldflags = $Config{ldflags};
+ _escape(\$ldflags);
+ return $ldflags;
+}
+
+sub _ccflags {
+ my $ccflags = $Config{ccflags};
+ _escape(\$ccflags);
+ return $ccflags;
+}
+
+sub _ccdlflags {
+ my $ccdlflags = $Config{ccdlflags};
+ _escape(\$ccdlflags);
+ return $ccdlflags;
+}
+
+sub ldopts {
+ require ExtUtils::MakeMaker;
+ require ExtUtils::Liblist;
+ my($std,$mods,$link_args,$path) = @_;
+ my(@mods,@link_args,@argv);
+ my($dllib,$config_libs,@potential_libs,@path);
+ local($") = ' ' unless $" eq ' ';
+ if (scalar @_) {
+ @link_args = @$link_args if $link_args;
+ @mods = @$mods if $mods;
+ }
+ else {
+ @argv = @ARGV;
+ #hmm
+ while($_ = shift @argv) {
+ /^-std$/ && do { $std = 1; next; };
+ /^--$/ && do { @link_args = @argv; last; };
+ /^-I(.*)/ && do { $path = $1 || shift @argv; next; };
+ push(@mods, $_);
+ }
+ }
+ $std = 1 unless scalar @link_args;
+ my $sep = $Config{path_sep} || ':';
+ @path = $path ? split(/\Q$sep/, $path) : @INC;
+
+ push(@potential_libs, @link_args) if scalar @link_args;
+ # makemaker includes std libs on windows by default
+ if ($^O ne 'MSWin32' and defined($std)) {
+ push(@potential_libs, $Config{perllibs});
+ }
+
+ push(@mods, static_ext()) if $std;
+
+ my($mod,@ns,$root,$sub,$extra,$archive,@archives);
+ print STDERR "Searching (@path) for archives\n" if $Verbose;
+ foreach $mod (@mods) {
+ @ns = split(/::|\/|\\/, $mod);
+ $sub = $ns[-1];
+ $root = File::Spec->catdir(@ns);
+
+ print STDERR "searching for '$sub${lib_ext}'\n" if $Verbose;
+ foreach (@path) {
+ next unless -e ($archive = File::Spec->catdir($_,"auto",$root,"$sub$lib_ext"));
+ push @archives, $archive;
+ if(-e ($extra = File::Spec->catdir($_,"auto",$root,"extralibs.ld"))) {
+ local(*FH);
+ if(open(FH, $extra)) {
+ my($libs) = <FH>; chomp $libs;
+ push @potential_libs, split /\s+/, $libs;
+ }
+ else {
+ warn "Couldn't open '$extra'";
+ }
+ }
+ last;
+ }
+ }
+ #print STDERR "\@potential_libs = @potential_libs\n";
+
+ my $libperl;
+ if ($^O eq 'MSWin32') {
+ $libperl = $Config{libperl};
+ }
+ elsif ($^O eq 'os390' && $Config{usedl}) {
+ # Nothing for OS/390 (z/OS) dynamic.
+ } else {
+ $libperl = (grep(/^-l\w*perl\w*$/, @link_args))[0]
+ || ($Config{libperl} =~ /^lib(\w+)(\Q$lib_ext\E|\.\Q$Config{dlext}\E)$/
+ ? "-l$1" : '')
+ || "-lperl";
+ }
+
+ my $lpath = File::Spec->catdir($Config{archlibexp}, 'CORE');
+ $lpath = qq["$lpath"] if $^O eq 'MSWin32';
+ my($extralibs, $bsloadlibs, $ldloadlibs, $ld_run_path) =
+ MM->ext(join ' ', "-L$lpath", $libperl, @potential_libs);
+
+ my $ld_or_bs = $bsloadlibs || $ldloadlibs;
+ print STDERR "bs: $bsloadlibs ** ld: $ldloadlibs" if $Verbose;
+ my $ccdlflags = _ccdlflags();
+ my $ldflags = _ldflags();
+ my $linkage = "$ccdlflags $ldflags @archives $ld_or_bs";
+ print STDERR "ldopts: '$linkage'\n" if $Verbose;
+
+ return $linkage if scalar @_;
+ my_return("$linkage\n");
+}
+
+sub ccflags {
+ my $ccflags = _ccflags();
+ my_return(" $ccflags ");
+}
+
+sub ccdlflags {
+ my $ccdlflags = _ccdlflags();
+ my_return(" $ccdlflags ");
+}
+
+sub perl_inc {
+ my $dir = File::Spec->catdir($Config{archlibexp}, 'CORE');
+ $dir = qq["$dir"] if $^O eq 'MSWin32';
+ my_return(" -I$dir ");
+}
+
+sub ccopts {
+ ccflags . perl_inc;
+}
+
+sub canon {
+ my($as, @ext) = @_;
+ foreach(@ext) {
+ # might be X::Y or lib/auto/X/Y/Y.a
+ next if s!::!/!g;
+ s:^(lib|ext)/(auto/)?::;
+ s:/\w+\.\w+$::;
+ }
+ map(s:/:$as:, @ext) if ($as ne '/');
+ @ext;
+}
+
+__END__
+
+=head1 NAME
+
+ExtUtils::Embed - Utilities for embedding Perl in C/C++ applications
+
+=head1 SYNOPSIS
+
+
+ perl -MExtUtils::Embed -e xsinit
+ perl -MExtUtils::Embed -e ccopts
+ perl -MExtUtils::Embed -e ldopts
+
+=head1 DESCRIPTION
+
+ExtUtils::Embed provides utility functions for embedding a Perl interpreter
+and extensions in your C/C++ applications.
+Typically, an application B<Makefile> will invoke ExtUtils::Embed
+functions while building your application.
+
+=head1 @EXPORT
+
+ExtUtils::Embed exports the following functions:
+
+xsinit(), ldopts(), ccopts(), perl_inc(), ccflags(),
+ccdlflags(), xsi_header(), xsi_protos(), xsi_body()
+
+=head1 FUNCTIONS
+
+=over 4
+
+=item xsinit()
+
+Generate C/C++ code for the XS initializer function.
+
+When invoked as C<`perl -MExtUtils::Embed -e xsinit --`>
+the following options are recognized:
+
+B<-o> E<lt>output filenameE<gt> (Defaults to B<perlxsi.c>)
+
+B<-o STDOUT> will print to STDOUT.
+
+B<-std> (Write code for extensions that are linked with the current Perl.)
+
+Any additional arguments are expected to be names of modules
+to generate code for.
+
+When invoked with parameters the following are accepted and optional:
+
+C<xsinit($filename,$std,[@modules])>
+
+Where,
+
+B<$filename> is equivalent to the B<-o> option.
+
+B<$std> is boolean, equivalent to the B<-std> option.
+
+B<[@modules]> is an array ref, same as additional arguments mentioned above.
+
+=item Examples
+
+
+ perl -MExtUtils::Embed -e xsinit -- -o xsinit.c Socket
+
+
+This will generate code with an B<xs_init> function that glues the perl B<Socket::bootstrap> function
+to the C B<boot_Socket> function and writes it to a file named F<xsinit.c>.
+
+Note that B<DynaLoader> is a special case where it must call B<boot_DynaLoader> directly.
+
+ perl -MExtUtils::Embed -e xsinit
+
+
+This will generate code for linking with B<DynaLoader> and
+each static extension found in B<$Config{static_ext}>.
+The code is written to the default file name B<perlxsi.c>.
+
+
+ perl -MExtUtils::Embed -e xsinit -- -o xsinit.c -std DBI DBD::Oracle
+
+
+Here, code is written for all the currently linked extensions along with code
+for B<DBI> and B<DBD::Oracle>.
+
+If you have a working B<DynaLoader> then there is rarely any need to statically link in any
+other extensions.
+
+=item ldopts()
+
+Output arguments for linking the Perl library and extensions to your
+application.
+
+When invoked as C<`perl -MExtUtils::Embed -e ldopts --`>
+the following options are recognized:
+
+B<-std>
+
+Output arguments for linking the Perl library and any extensions linked
+with the current Perl.
+
+B<-I> E<lt>path1:path2E<gt>
+
+Search path for ModuleName.a archives.
+Default path is B<@INC>.
+Library archives are expected to be found as
+B</some/path/auto/ModuleName/ModuleName.a>
+For example, when looking for B<Socket.a> relative to a search path,
+we should find B<auto/Socket/Socket.a>
+
+When looking for B<DBD::Oracle> relative to a search path,
+we should find B<auto/DBD/Oracle/Oracle.a>
+
+Keep in mind that you can always supply B</my/own/path/ModuleName.a>
+as an additional linker argument.
+
+B<--> E<lt>list of linker argsE<gt>
+
+Additional linker arguments to be considered.
+
+Any additional arguments found before the B<--> token
+are expected to be names of modules to generate code for.
+
+When invoked with parameters the following are accepted and optional:
+
+C<ldopts($std,[@modules],[@link_args],$path)>
+
+Where:
+
+B<$std> is boolean, equivalent to the B<-std> option.
+
+B<[@modules]> is equivalent to additional arguments found before the B<--> token.
+
+B<[@link_args]> is equivalent to arguments found after the B<--> token.
+
+B<$path> is equivalent to the B<-I> option.
+
+In addition, when ldopts is called with parameters, it will return the argument string
+rather than print it to STDOUT.
+
+=item Examples
+
+
+ perl -MExtUtils::Embed -e ldopts
+
+
+This will print arguments for linking with B<libperl> and
+extensions found in B<$Config{static_ext}>. This includes libraries
+found in B<$Config{libs}> and the first ModuleName.a library
+for each extension that is found by searching B<@INC> or the path
+specified by the B<-I> option.
+In addition, when ModuleName.a is found, additional linker arguments
+are picked up from the B<extralibs.ld> file in the same directory.
+
+
+ perl -MExtUtils::Embed -e ldopts -- -std Socket
+
+
+This will do the same as the above example, along with printing additional arguments for linking with the B<Socket> extension.
+
+ perl -MExtUtils::Embed -e ldopts -- -std Msql -- -L/usr/msql/lib -lmsql
+
+Any arguments after the second '--' token are additional linker
+arguments that will be examined for potential conflict. If there is no
+conflict, the additional arguments will be part of the output.
+
+
+=item perl_inc()
+
+For including perl header files this function simply prints:
+
+ -I$Config{archlibexp}/CORE
+
+So, rather than having to say:
+
+ perl -MConfig -e 'print "-I$Config{archlibexp}/CORE"'
+
+Just say:
+
+ perl -MExtUtils::Embed -e perl_inc
+
+=item ccflags(), ccdlflags()
+
+These functions simply print $Config{ccflags} and $Config{ccdlflags}
+
+=item ccopts()
+
+This function combines perl_inc(), ccflags() and ccdlflags() into one.
+
+=item xsi_header()
+
+This function simply returns a string defining the same B<EXTERN_C> macro as
+B<perlmain.c> along with #including B<perl.h> and B<EXTERN.h>.
+
+=item xsi_protos(@modules)
+
+This function returns a string of B<boot_$ModuleName> prototypes for each @modules.
+
+=item xsi_body(@modules)
+
+This function returns a string of calls to B<newXS()> that glue the module B<bootstrap>
+function to B<boot_ModuleName> for each @modules.
+
+B<xsinit()> uses the xsi_* functions to generate most of its code.
+
+=back
+
+=head1 EXAMPLES
+
+For examples on how to use B<ExtUtils::Embed> for building C/C++ applications
+with embedded perl, see L<perlembed>.
+
+=head1 SEE ALSO
+
+L<perlembed>
+
+=head1 AUTHOR
+
+Doug MacEachern E<lt>F<dougm@osf.org>E<gt>
+
+Based on ideas from Tim Bunce E<lt>F<Tim.Bunce@ig.co.uk>E<gt> and
+B<minimod.pl> by Andreas Koenig E<lt>F<k@anna.in-berlin.de>E<gt> and Tim Bunce.
+
+=cut
+
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/Install.pm b/Master/tlpkg/tlperl/lib/ExtUtils/Install.pm
new file mode 100644
index 00000000000..da583650fdf
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/Install.pm
@@ -0,0 +1,1365 @@
+package ExtUtils::Install;
+use strict;
+
+use vars qw(@ISA @EXPORT $VERSION $MUST_REBOOT %Config);
+
+use AutoSplit;
+use Carp ();
+use Config qw(%Config);
+use Cwd qw(cwd);
+use Exporter;
+use ExtUtils::Packlist;
+use File::Basename qw(dirname);
+use File::Compare qw(compare);
+use File::Copy;
+use File::Find qw(find);
+use File::Path;
+use File::Spec;
+
+
+@ISA = ('Exporter');
+@EXPORT = ('install','uninstall','pm_to_blib', 'install_default');
+
+=pod
+
+=head1 NAME
+
+ExtUtils::Install - install files from here to there
+
+=head1 SYNOPSIS
+
+ use ExtUtils::Install;
+
+ install({ 'blib/lib' => 'some/install/dir' } );
+
+ uninstall($packlist);
+
+ pm_to_blib({ 'lib/Foo/Bar.pm' => 'blib/lib/Foo/Bar.pm' });
+
+=head1 VERSION
+
+1.55
+
+=cut
+
+$VERSION = '1.55'; # <---- dont forget to update the POD section just above this line!
+$VERSION = eval $VERSION;
+
+=pod
+
+=head1 DESCRIPTION
+
+Handles the installing and uninstalling of perl modules, scripts, man
+pages, etc...
+
+Both install() and uninstall() are specific to the way
+ExtUtils::MakeMaker handles the installation and deinstallation of
+perl modules. They are not designed as general purpose tools.
+
+On some operating systems such as Win32 installation may not be possible
+until after a reboot has occured. This can have varying consequences:
+removing an old DLL does not impact programs using the new one, but if
+a new DLL cannot be installed properly until reboot then anything
+depending on it must wait. The package variable
+
+ $ExtUtils::Install::MUST_REBOOT
+
+is used to store this status.
+
+If this variable is true then such an operation has occured and
+anything depending on this module cannot proceed until a reboot
+has occured.
+
+If this value is defined but false then such an operation has
+ocurred, but should not impact later operations.
+
+=begin _private
+
+=over
+
+=item _chmod($$;$)
+
+Wrapper to chmod() for debugging and error trapping.
+
+=item _warnonce(@)
+
+Warns about something only once.
+
+=item _choke(@)
+
+Dies with a special message.
+
+=back
+
+=end _private
+
+=cut
+
+my $Is_VMS = $^O eq 'VMS';
+my $Is_VMS_noefs = $Is_VMS;
+my $Is_MacPerl = $^O eq 'MacOS';
+my $Is_Win32 = $^O eq 'MSWin32';
+my $Is_cygwin = $^O eq 'cygwin';
+my $CanMoveAtBoot = ($Is_Win32 || $Is_cygwin);
+
+ if( $Is_VMS ) {
+ my $vms_unix_rpt;
+ my $vms_efs;
+ my $vms_case;
+
+ if (eval { local $SIG{__DIE__}; require VMS::Feature; }) {
+ $vms_unix_rpt = VMS::Feature::current("filename_unix_report");
+ $vms_efs = VMS::Feature::current("efs_charset");
+ $vms_case = VMS::Feature::current("efs_case_preserve");
+ } else {
+ my $unix_rpt = $ENV{'DECC$FILENAME_UNIX_REPORT'} || '';
+ my $efs_charset = $ENV{'DECC$EFS_CHARSET'} || '';
+ my $efs_case = $ENV{'DECC$EFS_CASE_PRESERVE'} || '';
+ $vms_unix_rpt = $unix_rpt =~ /^[ET1]/i;
+ $vms_efs = $efs_charset =~ /^[ET1]/i;
+ $vms_case = $efs_case =~ /^[ET1]/i;
+ }
+ $Is_VMS_noefs = 0 if ($vms_efs);
+ }
+
+
+
+# *note* CanMoveAtBoot is only incidentally the same condition as below
+# this needs not hold true in the future.
+my $Has_Win32API_File = ($Is_Win32 || $Is_cygwin)
+ ? (eval {require Win32API::File; 1} || 0)
+ : 0;
+
+
+my $Inc_uninstall_warn_handler;
+
+# install relative to here
+
+my $INSTALL_ROOT = $ENV{PERL_INSTALL_ROOT};
+
+my $Curdir = File::Spec->curdir;
+my $Updir = File::Spec->updir;
+
+sub _estr(@) {
+ return join "\n",'!' x 72,@_,'!' x 72,'';
+}
+
+{my %warned;
+sub _warnonce(@) {
+ my $first=shift;
+ my $msg=_estr "WARNING: $first",@_;
+ warn $msg unless $warned{$msg}++;
+}}
+
+sub _choke(@) {
+ my $first=shift;
+ my $msg=_estr "ERROR: $first",@_;
+ Carp::croak($msg);
+}
+
+
+sub _chmod($$;$) {
+ my ( $mode, $item, $verbose )=@_;
+ $verbose ||= 0;
+ if (chmod $mode, $item) {
+ printf "chmod(0%o, %s)\n",$mode, $item if $verbose > 1;
+ } else {
+ my $err="$!";
+ _warnonce sprintf "WARNING: Failed chmod(0%o, %s): %s\n",
+ $mode, $item, $err
+ if -e $item;
+ }
+}
+
+=begin _private
+
+=over
+
+=item _move_file_at_boot( $file, $target, $moan )
+
+OS-Specific, Win32/Cygwin
+
+Schedules a file to be moved/renamed/deleted at next boot.
+$file should be a filespec of an existing file
+$target should be a ref to an array if the file is to be deleted
+otherwise it should be a filespec for a rename. If the file is existing
+it will be replaced.
+
+Sets $MUST_REBOOT to 0 to indicate a deletion operation has occured
+and sets it to 1 to indicate that a move operation has been requested.
+
+returns 1 on success, on failure if $moan is false errors are fatal.
+If $moan is true then returns 0 on error and warns instead of dies.
+
+=end _private
+
+=cut
+
+
+
+sub _move_file_at_boot { #XXX OS-SPECIFIC
+ my ( $file, $target, $moan )= @_;
+ Carp::confess("Panic: Can't _move_file_at_boot on this platform!")
+ unless $CanMoveAtBoot;
+
+ my $descr= ref $target
+ ? "'$file' for deletion"
+ : "'$file' for installation as '$target'";
+
+ if ( ! $Has_Win32API_File ) {
+
+ my @msg=(
+ "Cannot schedule $descr at reboot.",
+ "Try installing Win32API::File to allow operations on locked files",
+ "to be scheduled during reboot. Or try to perform the operation by",
+ "hand yourself. (You may need to close other perl processes first)"
+ );
+ if ( $moan ) { _warnonce(@msg) } else { _choke(@msg) }
+ return 0;
+ }
+ my $opts= Win32API::File::MOVEFILE_DELAY_UNTIL_REBOOT();
+ $opts= $opts | Win32API::File::MOVEFILE_REPLACE_EXISTING()
+ unless ref $target;
+
+ _chmod( 0666, $file );
+ _chmod( 0666, $target ) unless ref $target;
+
+ if (Win32API::File::MoveFileEx( $file, $target, $opts )) {
+ $MUST_REBOOT ||= ref $target ? 0 : 1;
+ return 1;
+ } else {
+ my @msg=(
+ "MoveFileEx $descr at reboot failed: $^E",
+ "You may try to perform the operation by hand yourself. ",
+ "(You may need to close other perl processes first).",
+ );
+ if ( $moan ) { _warnonce(@msg) } else { _choke(@msg) }
+ }
+ return 0;
+}
+
+
+=begin _private
+
+
+=item _unlink_or_rename( $file, $tryhard, $installing )
+
+OS-Specific, Win32/Cygwin
+
+Tries to get a file out of the way by unlinking it or renaming it. On
+some OS'es (Win32 based) DLL files can end up locked such that they can
+be renamed but not deleted. Likewise sometimes a file can be locked such
+that it cant even be renamed or changed except at reboot. To handle
+these cases this routine finds a tempfile name that it can either rename
+the file out of the way or use as a proxy for the install so that the
+rename can happen later (at reboot).
+
+ $file : the file to remove.
+ $tryhard : should advanced tricks be used for deletion
+ $installing : we are not merely deleting but we want to overwrite
+
+When $tryhard is not true if the unlink fails its fatal. When $tryhard
+is true then the file is attempted to be renamed. The renamed file is
+then scheduled for deletion. If the rename fails then $installing
+governs what happens. If it is false the failure is fatal. If it is true
+then an attempt is made to schedule installation at boot using a
+temporary file to hold the new file. If this fails then a fatal error is
+thrown, if it succeeds it returns the temporary file name (which will be
+a derivative of the original in the same directory) so that the caller can
+use it to install under. In all other cases of success returns $file.
+On failure throws a fatal error.
+
+=back
+
+=end _private
+
+=cut
+
+
+
+sub _unlink_or_rename { #XXX OS-SPECIFIC
+ my ( $file, $tryhard, $installing )= @_;
+
+ _chmod( 0666, $file );
+ my $unlink_count = 0;
+ while (unlink $file) { $unlink_count++; }
+ return $file if $unlink_count > 0;
+ my $error="$!";
+
+ _choke("Cannot unlink '$file': $!")
+ unless $CanMoveAtBoot && $tryhard;
+
+ my $tmp= "AAA";
+ ++$tmp while -e "$file.$tmp";
+ $tmp= "$file.$tmp";
+
+ warn "WARNING: Unable to unlink '$file': $error\n",
+ "Going to try to rename it to '$tmp'.\n";
+
+ if ( rename $file, $tmp ) {
+ warn "Rename succesful. Scheduling '$tmp'\nfor deletion at reboot.\n";
+ # when $installing we can set $moan to true.
+ # IOW, if we cant delete the renamed file at reboot its
+ # not the end of the world. The other cases are more serious
+ # and need to be fatal.
+ _move_file_at_boot( $tmp, [], $installing );
+ return $file;
+ } elsif ( $installing ) {
+ _warnonce("Rename failed: $!. Scheduling '$tmp'\nfor".
+ " installation as '$file' at reboot.\n");
+ _move_file_at_boot( $tmp, $file );
+ return $tmp;
+ } else {
+ _choke("Rename failed:$!", "Cannot procede.");
+ }
+
+}
+
+
+=pod
+
+=head2 Functions
+
+=begin _private
+
+=over
+
+=item _get_install_skip
+
+Handles loading the INSTALL.SKIP file. Returns an array of patterns to use.
+
+=cut
+
+
+
+sub _get_install_skip {
+ my ( $skip, $verbose )= @_;
+ if ($ENV{EU_INSTALL_IGNORE_SKIP}) {
+ print "EU_INSTALL_IGNORE_SKIP is set, ignore skipfile settings\n"
+ if $verbose>2;
+ return [];
+ }
+ if ( ! defined $skip ) {
+ print "Looking for install skip list\n"
+ if $verbose>2;
+ for my $file ( 'INSTALL.SKIP', $ENV{EU_INSTALL_SITE_SKIPFILE} ) {
+ next unless $file;
+ print "\tChecking for $file\n"
+ if $verbose>2;
+ if (-e $file) {
+ $skip= $file;
+ last;
+ }
+ }
+ }
+ if ($skip && !ref $skip) {
+ print "Reading skip patterns from '$skip'.\n"
+ if $verbose;
+ if (open my $fh,$skip ) {
+ my @patterns;
+ while (<$fh>) {
+ chomp;
+ next if /^\s*(?:#|$)/;
+ print "\tSkip pattern: $_\n" if $verbose>3;
+ push @patterns, $_;
+ }
+ $skip= \@patterns;
+ } else {
+ warn "Can't read skip file:'$skip':$!\n";
+ $skip=[];
+ }
+ } elsif ( UNIVERSAL::isa($skip,'ARRAY') ) {
+ print "Using array for skip list\n"
+ if $verbose>2;
+ } elsif ($verbose) {
+ print "No skip list found.\n"
+ if $verbose>1;
+ $skip= [];
+ }
+ warn "Got @{[0+@$skip]} skip patterns.\n"
+ if $verbose>3;
+ return $skip
+}
+
+=pod
+
+=item _have_write_access
+
+Abstract a -w check that tries to use POSIX::access() if possible.
+
+=cut
+
+{
+ my $has_posix;
+ sub _have_write_access {
+ my $dir=shift;
+ unless (defined $has_posix) {
+ $has_posix= (!$Is_cygwin && !$Is_Win32
+ && eval 'local $^W; require POSIX; 1') || 0;
+ }
+ if ($has_posix) {
+ return POSIX::access($dir, POSIX::W_OK());
+ } else {
+ return -w $dir;
+ }
+ }
+}
+
+=pod
+
+=item _can_write_dir(C<$dir>)
+
+Checks whether a given directory is writable, taking account
+the possibility that the directory might not exist and would have to
+be created first.
+
+Returns a list, containing: C<($writable, $determined_by, @create)>
+
+C<$writable> says whether whether the directory is (hypothetically) writable
+
+C<$determined_by> is the directory the status was determined from. It will be
+either the C<$dir>, or one of its parents.
+
+C<@create> is a list of directories that would probably have to be created
+to make the requested directory. It may not actually be correct on
+relative paths with C<..> in them. But for our purposes it should work ok
+
+=cut
+
+
+sub _can_write_dir {
+ my $dir=shift;
+ return
+ unless defined $dir and length $dir;
+
+ my ($vol, $dirs, $file) = File::Spec->splitpath($dir,1);
+ my @dirs = File::Spec->splitdir($dirs);
+ unshift @dirs, File::Spec->curdir
+ unless File::Spec->file_name_is_absolute($dir);
+
+ my $path='';
+ my @make;
+ while (@dirs) {
+ if ($Is_VMS_noefs) {
+ # There is a bug in catdir that is fixed when the EFS character
+ # set is enabled, which requires this VMS specific code.
+ $dir = File::Spec->catdir($vol,@dirs);
+ }
+ else {
+ $dir = File::Spec->catdir(@dirs);
+ $dir = File::Spec->catpath($vol,$dir,'')
+ if defined $vol and length $vol;
+ }
+ next if ( $dir eq $path );
+ if ( ! -e $dir ) {
+ unshift @make,$dir;
+ next;
+ }
+ if ( _have_write_access($dir) ) {
+ return 1,$dir,@make
+ } else {
+ return 0,$dir,@make
+ }
+ } continue {
+ pop @dirs;
+ }
+ return 0;
+}
+
+=pod
+
+=item _mkpath($dir,$show,$mode,$verbose,$dry_run)
+
+Wrapper around File::Path::mkpath() to handle errors.
+
+If $verbose is true and >1 then additional diagnostics will be produced, also
+this will force $show to true.
+
+If $dry_run is true then the directory will not be created but a check will be
+made to see whether it would be possible to write to the directory, or that
+it would be possible to create the directory.
+
+If $dry_run is not true dies if the directory can not be created or is not
+writable.
+
+=cut
+
+sub _mkpath {
+ my ($dir,$show,$mode,$verbose,$dry_run)=@_;
+ if ( $verbose && $verbose > 1 && ! -d $dir) {
+ $show= 1;
+ printf "mkpath(%s,%d,%#o)\n", $dir, $show, $mode;
+ }
+ if (!$dry_run) {
+ if ( ! eval { File::Path::mkpath($dir,$show,$mode); 1 } ) {
+ _choke("Can't create '$dir'","$@");
+ }
+
+ }
+ my ($can,$root,@make)=_can_write_dir($dir);
+ if (!$can) {
+ my @msg=(
+ "Can't create '$dir'",
+ $root ? "Do not have write permissions on '$root'"
+ : "Unknown Error"
+ );
+ if ($dry_run) {
+ _warnonce @msg;
+ } else {
+ _choke @msg;
+ }
+ } elsif ($show and $dry_run) {
+ print "$_\n" for @make;
+ }
+
+}
+
+=pod
+
+=item _copy($from,$to,$verbose,$dry_run)
+
+Wrapper around File::Copy::copy to handle errors.
+
+If $verbose is true and >1 then additional dignostics will be emitted.
+
+If $dry_run is true then the copy will not actually occur.
+
+Dies if the copy fails.
+
+=cut
+
+
+sub _copy {
+ my ( $from, $to, $verbose, $dry_run)=@_;
+ if ($verbose && $verbose>1) {
+ printf "copy(%s,%s)\n", $from, $to;
+ }
+ if (!$dry_run) {
+ File::Copy::copy($from,$to)
+ or Carp::croak( _estr "ERROR: Cannot copy '$from' to '$to': $!" );
+ }
+}
+
+=pod
+
+=item _chdir($from)
+
+Wrapper around chdir to catch errors.
+
+If not called in void context returns the cwd from before the chdir.
+
+dies on error.
+
+=cut
+
+sub _chdir {
+ my ($dir)= @_;
+ my $ret;
+ if (defined wantarray) {
+ $ret= cwd;
+ }
+ chdir $dir
+ or _choke("Couldn't chdir to '$dir': $!");
+ return $ret;
+}
+
+=pod
+
+=end _private
+
+=item B<install>
+
+ # deprecated forms
+ install(\%from_to);
+ install(\%from_to, $verbose, $dry_run, $uninstall_shadows,
+ $skip, $always_copy, \%result);
+
+ # recommended form as of 1.47
+ install([
+ from_to => \%from_to,
+ verbose => 1,
+ dry_run => 0,
+ uninstall_shadows => 1,
+ skip => undef,
+ always_copy => 1,
+ result => \%install_results,
+ ]);
+
+
+Copies each directory tree of %from_to to its corresponding value
+preserving timestamps and permissions.
+
+There are two keys with a special meaning in the hash: "read" and
+"write". These contain packlist files. After the copying is done,
+install() will write the list of target files to $from_to{write}. If
+$from_to{read} is given the contents of this file will be merged into
+the written file. The read and the written file may be identical, but
+on AFS it is quite likely that people are installing to a different
+directory than the one where the files later appear.
+
+If $verbose is true, will print out each file removed. Default is
+false. This is "make install VERBINST=1". $verbose values going
+up to 5 show increasingly more diagnostics output.
+
+If $dry_run is true it will only print what it was going to do
+without actually doing it. Default is false.
+
+If $uninstall_shadows is true any differing versions throughout @INC
+will be uninstalled. This is "make install UNINST=1"
+
+As of 1.37_02 install() supports the use of a list of patterns to filter out
+files that shouldn't be installed. If $skip is omitted or undefined then
+install will try to read the list from INSTALL.SKIP in the CWD. This file is
+a list of regular expressions and is just like the MANIFEST.SKIP file used
+by L<ExtUtils::Manifest>.
+
+A default site INSTALL.SKIP may be provided by setting then environment
+variable EU_INSTALL_SITE_SKIPFILE, this will only be used when there isn't a
+distribution specific INSTALL.SKIP. If the environment variable
+EU_INSTALL_IGNORE_SKIP is true then no install file filtering will be
+performed.
+
+If $skip is undefined then the skip file will be autodetected and used if it
+is found. If $skip is a reference to an array then it is assumed the array
+contains the list of patterns, if $skip is a true non reference it is
+assumed to be the filename holding the list of patterns, any other value of
+$skip is taken to mean that no install filtering should occur.
+
+B<Changes As of Version 1.47>
+
+As of version 1.47 the following additions were made to the install interface.
+Note that the new argument style and use of the %result hash is recommended.
+
+The $always_copy parameter which when true causes files to be updated
+regardles as to whether they have changed, if it is defined but false then
+copies are made only if the files have changed, if it is undefined then the
+value of the environment variable EU_INSTALL_ALWAYS_COPY is used as default.
+
+The %result hash will be populated with the various keys/subhashes reflecting
+the install. Currently these keys and their structure are:
+
+ install => { $target => $source },
+ install_fail => { $target => $source },
+ install_unchanged => { $target => $source },
+
+ install_filtered => { $source => $pattern },
+
+ uninstall => { $uninstalled => $source },
+ uninstall_fail => { $uninstalled => $source },
+
+where C<$source> is the filespec of the file being installed. C<$target> is where
+it is being installed to, and C<$uninstalled> is any shadow file that is in C<@INC>
+or C<$ENV{PERL5LIB}> or other standard locations, and C<$pattern> is the pattern that
+caused a source file to be skipped. In future more keys will be added, such as to
+show created directories, however this requires changes in other modules and must
+therefore wait.
+
+These keys will be populated before any exceptions are thrown should there be an
+error.
+
+Note that all updates of the %result are additive, the hash will not be
+cleared before use, thus allowing status results of many installs to be easily
+aggregated.
+
+B<NEW ARGUMENT STYLE>
+
+If there is only one argument and it is a reference to an array then
+the array is assumed to contain a list of key-value pairs specifying
+the options. In this case the option "from_to" is mandatory. This style
+means that you dont have to supply a cryptic list of arguments and can
+use a self documenting argument list that is easier to understand.
+
+This is now the recommended interface to install().
+
+B<RETURN>
+
+If all actions were successful install will return a hashref of the results
+as described above for the $result parameter. If any action is a failure
+then install will die, therefore it is recommended to pass in the $result
+parameter instead of using the return value. If the result parameter is
+provided then the returned hashref will be the passed in hashref.
+
+=cut
+
+sub install { #XXX OS-SPECIFIC
+ my($from_to,$verbose,$dry_run,$uninstall_shadows,$skip,$always_copy,$result) = @_;
+ if (@_==1 and eval { 1+@$from_to }) {
+ my %opts = @$from_to;
+ $from_to = $opts{from_to}
+ or Carp::confess("from_to is a mandatory parameter");
+ $verbose = $opts{verbose};
+ $dry_run = $opts{dry_run};
+ $uninstall_shadows = $opts{uninstall_shadows};
+ $skip = $opts{skip};
+ $always_copy = $opts{always_copy};
+ $result = $opts{result};
+ }
+
+ $result ||= {};
+ $verbose ||= 0;
+ $dry_run ||= 0;
+
+ $skip= _get_install_skip($skip,$verbose);
+ $always_copy = $ENV{EU_INSTALL_ALWAYS_COPY}
+ || $ENV{EU_ALWAYS_COPY}
+ || 0
+ unless defined $always_copy;
+
+ my(%from_to) = %$from_to;
+ my(%pack, $dir, %warned);
+ my($packlist) = ExtUtils::Packlist->new();
+
+ local(*DIR);
+ for (qw/read write/) {
+ $pack{$_}=$from_to{$_};
+ delete $from_to{$_};
+ }
+ my $tmpfile = install_rooted_file($pack{"read"});
+ $packlist->read($tmpfile) if (-f $tmpfile);
+ my $cwd = cwd();
+ my @found_files;
+ my %check_dirs;
+
+ MOD_INSTALL: foreach my $source (sort keys %from_to) {
+ #copy the tree to the target directory without altering
+ #timestamp and permission and remember for the .packlist
+ #file. The packlist file contains the absolute paths of the
+ #install locations. AFS users may call this a bug. We'll have
+ #to reconsider how to add the means to satisfy AFS users also.
+
+ #October 1997: we want to install .pm files into archlib if
+ #there are any files in arch. So we depend on having ./blib/arch
+ #hardcoded here.
+
+ my $targetroot = install_rooted_dir($from_to{$source});
+
+ my $blib_lib = File::Spec->catdir('blib', 'lib');
+ my $blib_arch = File::Spec->catdir('blib', 'arch');
+ if ($source eq $blib_lib and
+ exists $from_to{$blib_arch} and
+ directory_not_empty($blib_arch)
+ ){
+ $targetroot = install_rooted_dir($from_to{$blib_arch});
+ print "Files found in $blib_arch: installing files in $blib_lib into architecture dependent library tree\n";
+ }
+
+ next unless -d $source;
+ _chdir($source);
+ # 5.5.3's File::Find missing no_chdir option
+ # XXX OS-SPECIFIC
+ # File::Find seems to always be Unixy except on MacPerl :(
+ my $current_directory= $Is_MacPerl ? $Curdir : '.';
+ find(sub {
+ my ($mode,$size,$atime,$mtime) = (stat)[2,7,8,9];
+
+ return if !-f _;
+ my $origfile = $_;
+
+ return if $origfile eq ".exists";
+ my $targetdir = File::Spec->catdir($targetroot, $File::Find::dir);
+ my $targetfile = File::Spec->catfile($targetdir, $origfile);
+ my $sourcedir = File::Spec->catdir($source, $File::Find::dir);
+ my $sourcefile = File::Spec->catfile($sourcedir, $origfile);
+
+ for my $pat (@$skip) {
+ if ( $sourcefile=~/$pat/ ) {
+ print "Skipping $targetfile (filtered)\n"
+ if $verbose>1;
+ $result->{install_filtered}{$sourcefile} = $pat;
+ return;
+ }
+ }
+ # we have to do this for back compat with old File::Finds
+ # and because the target is relative
+ my $save_cwd = _chdir($cwd);
+ my $diff = 0;
+ # XXX: I wonder how useful this logic is actually -- demerphq
+ if ( $always_copy or !-f $targetfile or -s $targetfile != $size) {
+ $diff++;
+ } else {
+ # we might not need to copy this file
+ $diff = compare($sourcefile, $targetfile);
+ }
+ $check_dirs{$targetdir}++
+ unless -w $targetfile;
+
+ push @found_files,
+ [ $diff, $File::Find::dir, $origfile,
+ $mode, $size, $atime, $mtime,
+ $targetdir, $targetfile, $sourcedir, $sourcefile,
+
+ ];
+ #restore the original directory we were in when File::Find
+ #called us so that it doesnt get horribly confused.
+ _chdir($save_cwd);
+ }, $current_directory );
+ _chdir($cwd);
+ }
+ foreach my $targetdir (sort keys %check_dirs) {
+ _mkpath( $targetdir, 0, 0755, $verbose, $dry_run );
+ }
+ foreach my $found (@found_files) {
+ my ($diff, $ffd, $origfile, $mode, $size, $atime, $mtime,
+ $targetdir, $targetfile, $sourcedir, $sourcefile)= @$found;
+
+ my $realtarget= $targetfile;
+ if ($diff) {
+ eval {
+ if (-f $targetfile) {
+ print "_unlink_or_rename($targetfile)\n" if $verbose>1;
+ $targetfile= _unlink_or_rename( $targetfile, 'tryhard', 'install' )
+ unless $dry_run;
+ } elsif ( ! -d $targetdir ) {
+ _mkpath( $targetdir, 0, 0755, $verbose, $dry_run );
+ }
+ print "Installing $targetfile\n";
+
+ _copy( $sourcefile, $targetfile, $verbose, $dry_run, );
+
+
+ #XXX OS-SPECIFIC
+ print "utime($atime,$mtime,$targetfile)\n" if $verbose>1;
+ utime($atime,$mtime + $Is_VMS,$targetfile) unless $dry_run>1;
+
+
+ $mode = 0444 | ( $mode & 0111 ? 0111 : 0 );
+ $mode = $mode | 0222
+ if $realtarget ne $targetfile;
+ _chmod( $mode, $targetfile, $verbose );
+ $result->{install}{$targetfile} = $sourcefile;
+ 1
+ } or do {
+ $result->{install_fail}{$targetfile} = $sourcefile;
+ die $@;
+ };
+ } else {
+ $result->{install_unchanged}{$targetfile} = $sourcefile;
+ print "Skipping $targetfile (unchanged)\n" if $verbose;
+ }
+
+ if ( $uninstall_shadows ) {
+ inc_uninstall($sourcefile,$ffd, $verbose,
+ $dry_run,
+ $realtarget ne $targetfile ? $realtarget : "",
+ $result);
+ }
+
+ # Record the full pathname.
+ $packlist->{$targetfile}++;
+ }
+
+ if ($pack{'write'}) {
+ $dir = install_rooted_dir(dirname($pack{'write'}));
+ _mkpath( $dir, 0, 0755, $verbose, $dry_run );
+ print "Writing $pack{'write'}\n" if $verbose;
+ $packlist->write(install_rooted_file($pack{'write'})) unless $dry_run;
+ }
+
+ _do_cleanup($verbose);
+ return $result;
+}
+
+=begin _private
+
+=item _do_cleanup
+
+Standardize finish event for after another instruction has occured.
+Handles converting $MUST_REBOOT to a die for instance.
+
+=end _private
+
+=cut
+
+sub _do_cleanup {
+ my ($verbose) = @_;
+ if ($MUST_REBOOT) {
+ die _estr "Operation not completed! ",
+ "You must reboot to complete the installation.",
+ "Sorry.";
+ } elsif (defined $MUST_REBOOT & $verbose) {
+ warn _estr "Installation will be completed at the next reboot.\n",
+ "However it is not necessary to reboot immediately.\n";
+ }
+}
+
+=begin _undocumented
+
+=item install_rooted_file( $file )
+
+Returns $file, or catfile($INSTALL_ROOT,$file) if $INSTALL_ROOT
+is defined.
+
+=item install_rooted_dir( $dir )
+
+Returns $dir, or catdir($INSTALL_ROOT,$dir) if $INSTALL_ROOT
+is defined.
+
+=end _undocumented
+
+=cut
+
+
+sub install_rooted_file {
+ if (defined $INSTALL_ROOT) {
+ File::Spec->catfile($INSTALL_ROOT, $_[0]);
+ } else {
+ $_[0];
+ }
+}
+
+
+sub install_rooted_dir {
+ if (defined $INSTALL_ROOT) {
+ File::Spec->catdir($INSTALL_ROOT, $_[0]);
+ } else {
+ $_[0];
+ }
+}
+
+=begin _undocumented
+
+=item forceunlink( $file, $tryhard )
+
+Tries to delete a file. If $tryhard is true then we will use whatever
+devious tricks we can to delete the file. Currently this only applies to
+Win32 in that it will try to use Win32API::File to schedule a delete at
+reboot. A wrapper for _unlink_or_rename().
+
+=end _undocumented
+
+=cut
+
+
+sub forceunlink {
+ my ( $file, $tryhard )= @_; #XXX OS-SPECIFIC
+ _unlink_or_rename( $file, $tryhard, not("installing") );
+}
+
+=begin _undocumented
+
+=item directory_not_empty( $dir )
+
+Returns 1 if there is an .exists file somewhere in a directory tree.
+Returns 0 if there is not.
+
+=end _undocumented
+
+=cut
+
+sub directory_not_empty ($) {
+ my($dir) = @_;
+ my $files = 0;
+ find(sub {
+ return if $_ eq ".exists";
+ if (-f) {
+ $File::Find::prune++;
+ $files = 1;
+ }
+ }, $dir);
+ return $files;
+}
+
+=pod
+
+=item B<install_default> I<DISCOURAGED>
+
+ install_default();
+ install_default($fullext);
+
+Calls install() with arguments to copy a module from blib/ to the
+default site installation location.
+
+$fullext is the name of the module converted to a directory
+(ie. Foo::Bar would be Foo/Bar). If $fullext is not specified, it
+will attempt to read it from @ARGV.
+
+This is primarily useful for install scripts.
+
+B<NOTE> This function is not really useful because of the hard-coded
+install location with no way to control site vs core vs vendor
+directories and the strange way in which the module name is given.
+Consider its use discouraged.
+
+=cut
+
+sub install_default {
+ @_ < 2 or Carp::croak("install_default should be called with 0 or 1 argument");
+ my $FULLEXT = @_ ? shift : $ARGV[0];
+ defined $FULLEXT or die "Do not know to where to write install log";
+ my $INST_LIB = File::Spec->catdir($Curdir,"blib","lib");
+ my $INST_ARCHLIB = File::Spec->catdir($Curdir,"blib","arch");
+ my $INST_BIN = File::Spec->catdir($Curdir,'blib','bin');
+ my $INST_SCRIPT = File::Spec->catdir($Curdir,'blib','script');
+ my $INST_MAN1DIR = File::Spec->catdir($Curdir,'blib','man1');
+ my $INST_MAN3DIR = File::Spec->catdir($Curdir,'blib','man3');
+
+ my @INST_HTML;
+ if($Config{installhtmldir}) {
+ my $INST_HTMLDIR = File::Spec->catdir($Curdir,'blib','html');
+ @INST_HTML = ($INST_HTMLDIR => $Config{installhtmldir});
+ }
+
+ install({
+ read => "$Config{sitearchexp}/auto/$FULLEXT/.packlist",
+ write => "$Config{installsitearch}/auto/$FULLEXT/.packlist",
+ $INST_LIB => (directory_not_empty($INST_ARCHLIB)) ?
+ $Config{installsitearch} :
+ $Config{installsitelib},
+ $INST_ARCHLIB => $Config{installsitearch},
+ $INST_BIN => $Config{installbin} ,
+ $INST_SCRIPT => $Config{installscript},
+ $INST_MAN1DIR => $Config{installman1dir},
+ $INST_MAN3DIR => $Config{installman3dir},
+ @INST_HTML,
+ },1,0,0);
+}
+
+
+=item B<uninstall>
+
+ uninstall($packlist_file);
+ uninstall($packlist_file, $verbose, $dont_execute);
+
+Removes the files listed in a $packlist_file.
+
+If $verbose is true, will print out each file removed. Default is
+false.
+
+If $dont_execute is true it will only print what it was going to do
+without actually doing it. Default is false.
+
+=cut
+
+sub uninstall {
+ my($fil,$verbose,$dry_run) = @_;
+ $verbose ||= 0;
+ $dry_run ||= 0;
+
+ die _estr "ERROR: no packlist file found: '$fil'"
+ unless -f $fil;
+ # my $my_req = $self->catfile(qw(auto ExtUtils Install forceunlink.al));
+ # require $my_req; # Hairy, but for the first
+ my ($packlist) = ExtUtils::Packlist->new($fil);
+ foreach (sort(keys(%$packlist))) {
+ chomp;
+ print "unlink $_\n" if $verbose;
+ forceunlink($_,'tryhard') unless $dry_run;
+ }
+ print "unlink $fil\n" if $verbose;
+ forceunlink($fil, 'tryhard') unless $dry_run;
+ _do_cleanup($verbose);
+}
+
+=begin _undocumented
+
+=item inc_uninstall($filepath,$libdir,$verbose,$dry_run,$ignore,$results)
+
+Remove shadowed files. If $ignore is true then it is assumed to hold
+a filename to ignore. This is used to prevent spurious warnings from
+occuring when doing an install at reboot.
+
+We now only die when failing to remove a file that has precedence over
+our own, when our install has precedence we only warn.
+
+$results is assumed to contain a hashref which will have the keys
+'uninstall' and 'uninstall_fail' populated with keys for the files
+removed and values of the source files they would shadow.
+
+=end _undocumented
+
+=cut
+
+sub inc_uninstall {
+ my($filepath,$libdir,$verbose,$dry_run,$ignore,$results) = @_;
+ my($dir);
+ $ignore||="";
+ my $file = (File::Spec->splitpath($filepath))[2];
+ my %seen_dir = ();
+
+ my @PERL_ENV_LIB = split $Config{path_sep}, defined $ENV{'PERL5LIB'}
+ ? $ENV{'PERL5LIB'} : $ENV{'PERLLIB'} || '';
+
+ my @dirs=( @PERL_ENV_LIB,
+ @INC,
+ @Config{qw(archlibexp
+ privlibexp
+ sitearchexp
+ sitelibexp)});
+
+ #warn join "\n","---",@dirs,"---";
+ my $seen_ours;
+ foreach $dir ( @dirs ) {
+ my $canonpath = $Is_VMS ? $dir : File::Spec->canonpath($dir);
+ next if $canonpath eq $Curdir;
+ next if $seen_dir{$canonpath}++;
+ my $targetfile = File::Spec->catfile($canonpath,$libdir,$file);
+ next unless -f $targetfile;
+
+ # The reason why we compare file's contents is, that we cannot
+ # know, which is the file we just installed (AFS). So we leave
+ # an identical file in place
+ my $diff = 0;
+ if ( -f $targetfile && -s _ == -s $filepath) {
+ # We have a good chance, we can skip this one
+ $diff = compare($filepath,$targetfile);
+ } else {
+ $diff++;
+ }
+ print "#$file and $targetfile differ\n" if $diff && $verbose > 1;
+
+ if (!$diff or $targetfile eq $ignore) {
+ $seen_ours = 1;
+ next;
+ }
+ if ($dry_run) {
+ $results->{uninstall}{$targetfile} = $filepath;
+ if ($verbose) {
+ $Inc_uninstall_warn_handler ||= ExtUtils::Install::Warn->new();
+ $libdir =~ s|^\./||s ; # That's just cosmetics, no need to port. It looks prettier.
+ $Inc_uninstall_warn_handler->add(
+ File::Spec->catfile($libdir, $file),
+ $targetfile
+ );
+ }
+ # if not verbose, we just say nothing
+ } else {
+ print "Unlinking $targetfile (shadowing?)\n" if $verbose;
+ eval {
+ die "Fake die for testing"
+ if $ExtUtils::Install::Testing and
+ ucase(File::Spec->canonpath($ExtUtils::Install::Testing)) eq ucase($targetfile);
+ forceunlink($targetfile,'tryhard');
+ $results->{uninstall}{$targetfile} = $filepath;
+ 1;
+ } or do {
+ $results->{fail_uninstall}{$targetfile} = $filepath;
+ if ($seen_ours) {
+ warn "Failed to remove probably harmless shadow file '$targetfile'\n";
+ } else {
+ die "$@\n";
+ }
+ };
+ }
+ }
+}
+
+=begin _undocumented
+
+=item run_filter($cmd,$src,$dest)
+
+Filter $src using $cmd into $dest.
+
+=end _undocumented
+
+=cut
+
+sub run_filter {
+ my ($cmd, $src, $dest) = @_;
+ local(*CMD, *SRC);
+ open(CMD, "|$cmd >$dest") || die "Cannot fork: $!";
+ open(SRC, $src) || die "Cannot open $src: $!";
+ my $buf;
+ my $sz = 1024;
+ while (my $len = sysread(SRC, $buf, $sz)) {
+ syswrite(CMD, $buf, $len);
+ }
+ close SRC;
+ close CMD or die "Filter command '$cmd' failed for $src";
+}
+
+=pod
+
+=item B<pm_to_blib>
+
+ pm_to_blib(\%from_to, $autosplit_dir);
+ pm_to_blib(\%from_to, $autosplit_dir, $filter_cmd);
+
+Copies each key of %from_to to its corresponding value efficiently.
+Filenames with the extension .pm are autosplit into the $autosplit_dir.
+Any destination directories are created.
+
+$filter_cmd is an optional shell command to run each .pm file through
+prior to splitting and copying. Input is the contents of the module,
+output the new module contents.
+
+You can have an environment variable PERL_INSTALL_ROOT set which will
+be prepended as a directory to each installed file (and directory).
+
+=cut
+
+sub pm_to_blib {
+ my($fromto,$autodir,$pm_filter) = @_;
+
+ _mkpath($autodir,0,0755);
+ while(my($from, $to) = each %$fromto) {
+ if( -f $to && -s $from == -s $to && -M $to < -M $from ) {
+ print "Skip $to (unchanged)\n";
+ next;
+ }
+
+ # When a pm_filter is defined, we need to pre-process the source first
+ # to determine whether it has changed or not. Therefore, only perform
+ # the comparison check when there's no filter to be ran.
+ # -- RAM, 03/01/2001
+
+ my $need_filtering = defined $pm_filter && length $pm_filter &&
+ $from =~ /\.pm$/;
+
+ if (!$need_filtering && 0 == compare($from,$to)) {
+ print "Skip $to (unchanged)\n";
+ next;
+ }
+ if (-f $to){
+ # we wont try hard here. its too likely to mess things up.
+ forceunlink($to);
+ } else {
+ _mkpath(dirname($to),0,0755);
+ }
+ if ($need_filtering) {
+ run_filter($pm_filter, $from, $to);
+ print "$pm_filter <$from >$to\n";
+ } else {
+ _copy( $from, $to );
+ print "cp $from $to\n";
+ }
+ my($mode,$atime,$mtime) = (stat $from)[2,8,9];
+ utime($atime,$mtime+$Is_VMS,$to);
+ _chmod(0444 | ( $mode & 0111 ? 0111 : 0 ),$to);
+ next unless $from =~ /\.pm$/;
+ _autosplit($to,$autodir);
+ }
+}
+
+
+=begin _private
+
+=item _autosplit
+
+From 1.0307 back, AutoSplit will sometimes leave an open filehandle to
+the file being split. This causes problems on systems with mandatory
+locking (ie. Windows). So we wrap it and close the filehandle.
+
+=end _private
+
+=cut
+
+sub _autosplit { #XXX OS-SPECIFIC
+ my $retval = autosplit(@_);
+ close *AutoSplit::IN if defined *AutoSplit::IN{IO};
+
+ return $retval;
+}
+
+
+package ExtUtils::Install::Warn;
+
+sub new { bless {}, shift }
+
+sub add {
+ my($self,$file,$targetfile) = @_;
+ push @{$self->{$file}}, $targetfile;
+}
+
+sub DESTROY {
+ unless(defined $INSTALL_ROOT) {
+ my $self = shift;
+ my($file,$i,$plural);
+ foreach $file (sort keys %$self) {
+ $plural = @{$self->{$file}} > 1 ? "s" : "";
+ print "## Differing version$plural of $file found. You might like to\n";
+ for (0..$#{$self->{$file}}) {
+ print "rm ", $self->{$file}[$_], "\n";
+ $i++;
+ }
+ }
+ $plural = $i>1 ? "all those files" : "this file";
+ my $inst = (_invokant() eq 'ExtUtils::MakeMaker')
+ ? ( $Config::Config{make} || 'make' ).' install'
+ . ( $Is_VMS ? '/MACRO="UNINST"=1' : ' UNINST=1' )
+ : './Build install uninst=1';
+ print "## Running '$inst' will unlink $plural for you.\n";
+ }
+}
+
+=begin _private
+
+=item _invokant
+
+Does a heuristic on the stack to see who called us for more intelligent
+error messages. Currently assumes we will be called only by Module::Build
+or by ExtUtils::MakeMaker.
+
+=end _private
+
+=cut
+
+sub _invokant {
+ my @stack;
+ my $frame = 0;
+ while (my $file = (caller($frame++))[1]) {
+ push @stack, (File::Spec->splitpath($file))[2];
+ }
+
+ my $builder;
+ my $top = pop @stack;
+ if ($top =~ /^Build/i || exists($INC{'Module/Build.pm'})) {
+ $builder = 'Module::Build';
+ } else {
+ $builder = 'ExtUtils::MakeMaker';
+ }
+ return $builder;
+}
+
+=pod
+
+=back
+
+=head1 ENVIRONMENT
+
+=over 4
+
+=item B<PERL_INSTALL_ROOT>
+
+Will be prepended to each install path.
+
+=item B<EU_INSTALL_IGNORE_SKIP>
+
+Will prevent the automatic use of INSTALL.SKIP as the install skip file.
+
+=item B<EU_INSTALL_SITE_SKIPFILE>
+
+If there is no INSTALL.SKIP file in the make directory then this value
+can be used to provide a default.
+
+=item B<EU_INSTALL_ALWAYS_COPY>
+
+If this environment variable is true then normal install processes will
+always overwrite older identical files during the install process.
+
+Note that the alias EU_ALWAYS_COPY will be supported if EU_INSTALL_ALWAYS_COPY
+is not defined until at least the 1.50 release. Please ensure you use the
+correct EU_INSTALL_ALWAYS_COPY.
+
+=back
+
+=head1 AUTHOR
+
+Original author lost in the mists of time. Probably the same as Makemaker.
+
+Production release currently maintained by demerphq C<yves at cpan.org>,
+extensive changes by Michael G. Schwern.
+
+Send bug reports via http://rt.cpan.org/. Please send your
+generated Makefile along with your report.
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+See L<http://www.perl.com/perl/misc/Artistic.html>
+
+
+=cut
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/Installed.pm b/Master/tlpkg/tlperl/lib/ExtUtils/Installed.pm
new file mode 100644
index 00000000000..9cb1fc10d75
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/Installed.pm
@@ -0,0 +1,462 @@
+package ExtUtils::Installed;
+
+use 5.00503;
+use strict;
+#use warnings; # XXX requires 5.6
+use Carp qw();
+use ExtUtils::Packlist;
+use ExtUtils::MakeMaker;
+use Config;
+use File::Find;
+use File::Basename;
+use File::Spec;
+
+my $Is_VMS = $^O eq 'VMS';
+my $DOSISH = ($^O =~ /^(MSWin\d\d|os2|dos|mint)$/);
+
+require VMS::Filespec if $Is_VMS;
+
+use vars qw($VERSION);
+$VERSION = '1.999_001';
+$VERSION = eval $VERSION;
+
+sub _is_prefix {
+ my ($self, $path, $prefix) = @_;
+ return unless defined $prefix && defined $path;
+
+ if( $Is_VMS ) {
+ $prefix = VMS::Filespec::unixify($prefix);
+ $path = VMS::Filespec::unixify($path);
+ }
+
+ # Unix path normalization.
+ $prefix = File::Spec->canonpath($prefix);
+
+ return 1 if substr($path, 0, length($prefix)) eq $prefix;
+
+ if ($DOSISH) {
+ $path =~ s|\\|/|g;
+ $prefix =~ s|\\|/|g;
+ return 1 if $path =~ m{^\Q$prefix\E}i;
+ }
+ return(0);
+}
+
+sub _is_doc {
+ my ($self, $path) = @_;
+
+ my $man1dir = $self->{':private:'}{Config}{man1direxp};
+ my $man3dir = $self->{':private:'}{Config}{man3direxp};
+ return(($man1dir && $self->_is_prefix($path, $man1dir))
+ ||
+ ($man3dir && $self->_is_prefix($path, $man3dir))
+ ? 1 : 0)
+}
+
+sub _is_type {
+ my ($self, $path, $type) = @_;
+ return 1 if $type eq "all";
+
+ return($self->_is_doc($path)) if $type eq "doc";
+ my $conf= $self->{':private:'}{Config};
+ if ($type eq "prog") {
+ return($self->_is_prefix($path, $conf->{prefix} || $conf->{prefixexp})
+ && !($self->_is_doc($path)) ? 1 : 0);
+ }
+ return(0);
+}
+
+sub _is_under {
+ my ($self, $path, @under) = @_;
+ $under[0] = "" if (! @under);
+ foreach my $dir (@under) {
+ return(1) if ($self->_is_prefix($path, $dir));
+ }
+
+ return(0);
+}
+
+sub _fix_dirs {
+ my ($self, @dirs)= @_;
+ # File::Find does not know how to deal with VMS filepaths.
+ if( $Is_VMS ) {
+ $_ = VMS::Filespec::unixify($_)
+ for @dirs;
+ }
+
+ if ($DOSISH) {
+ s|\\|/|g for @dirs;
+ }
+ return wantarray ? @dirs : $dirs[0];
+}
+
+sub _make_entry {
+ my ($self, $module, $packlist_file, $modfile)= @_;
+
+ my $data= {
+ module => $module,
+ packlist => scalar(ExtUtils::Packlist->new($packlist_file)),
+ packlist_file => $packlist_file,
+ };
+
+ if (!$modfile) {
+ $data->{version} = $self->{':private:'}{Config}{version};
+ } else {
+ $data->{modfile} = $modfile;
+ # Find the top-level module file in @INC
+ $data->{version} = '';
+ foreach my $dir (@{$self->{':private:'}{INC}}) {
+ my $p = File::Spec->catfile($dir, $modfile);
+ if (-r $p) {
+ $module = _module_name($p, $module) if $Is_VMS;
+
+ $data->{version} = MM->parse_version($p);
+ $data->{version_from} = $p;
+ $data->{packlist_valid} = exists $data->{packlist}{$p};
+ last;
+ }
+ }
+ }
+ $self->{$module}= $data;
+}
+
+our $INSTALLED;
+sub new {
+ my ($class) = shift(@_);
+ $class = ref($class) || $class;
+
+ my %args = @_;
+
+ return $INSTALLED if $INSTALLED and ($args{default_get} || $args{default});
+
+ my $self = bless {}, $class;
+
+ $INSTALLED= $self if $args{default_set} || $args{default};
+
+
+ if ($args{config_override}) {
+ eval {
+ $self->{':private:'}{Config} = { %{$args{config_override}} };
+ } or Carp::croak(
+ "The 'config_override' parameter must be a hash reference."
+ );
+ }
+ else {
+ $self->{':private:'}{Config} = \%Config;
+ }
+
+ for my $tuple ([inc_override => INC => [ @INC ] ],
+ [ extra_libs => EXTRA => [] ])
+ {
+ my ($arg,$key,$val)=@$tuple;
+ if ( $args{$arg} ) {
+ eval {
+ $self->{':private:'}{$key} = [ @{$args{$arg}} ];
+ } or Carp::croak(
+ "The '$arg' parameter must be an array reference."
+ );
+ }
+ elsif ($val) {
+ $self->{':private:'}{$key} = $val;
+ }
+ }
+ {
+ my %dupe;
+ @{$self->{':private:'}{LIBDIRS}} = grep { -e $_ && !$dupe{$_}++ }
+ @{$self->{':private:'}{EXTRA}}, @{$self->{':private:'}{INC}};
+ }
+
+ my @dirs= $self->_fix_dirs(@{$self->{':private:'}{LIBDIRS}});
+
+ # Read the core packlist
+ my $archlib = $self->_fix_dirs($self->{':private:'}{Config}{archlibexp});
+ $self->_make_entry("Perl",File::Spec->catfile($archlib, '.packlist'));
+
+ my $root;
+ # Read the module packlists
+ my $sub = sub {
+ # Only process module .packlists
+ return if $_ ne ".packlist" || $File::Find::dir eq $archlib;
+
+ # Hack of the leading bits of the paths & convert to a module name
+ my $module = $File::Find::name;
+ my $found = $module =~ s!^.*?/auto/(.*)/.packlist!$1!s
+ or do {
+ # warn "Woah! \$_=$_\n\$module=$module\n\$File::Find::dir=$File::Find::dir\n",
+ # join ("\n",@dirs);
+ return;
+ };
+
+ my $modfile = "$module.pm";
+ $module =~ s!/!::!g;
+
+ return if $self->{$module}; #shadowing?
+ $self->_make_entry($module,$File::Find::name,$modfile);
+ };
+ while (@dirs) {
+ $root= shift @dirs;
+ next if !-d $root;
+ find($sub,$root);
+ }
+
+ return $self;
+}
+
+# VMS's non-case preserving file-system means the package name can't
+# be reconstructed from the filename.
+sub _module_name {
+ my($file, $orig_module) = @_;
+
+ my $module = '';
+ if (open PACKFH, $file) {
+ while (<PACKFH>) {
+ if (/package\s+(\S+)\s*;/) {
+ my $pack = $1;
+ # Make a sanity check, that lower case $module
+ # is identical to lowercase $pack before
+ # accepting it
+ if (lc($pack) eq lc($orig_module)) {
+ $module = $pack;
+ last;
+ }
+ }
+ }
+ close PACKFH;
+ }
+
+ print STDERR "Couldn't figure out the package name for $file\n"
+ unless $module;
+
+ return $module;
+}
+
+sub modules {
+ my ($self) = @_;
+ $self= $self->new(default=>1) if !ref $self;
+
+ # Bug/feature of sort in scalar context requires this.
+ return wantarray
+ ? sort grep { not /^:private:$/ } keys %$self
+ : grep { not /^:private:$/ } keys %$self;
+}
+
+sub files {
+ my ($self, $module, $type, @under) = @_;
+ $self= $self->new(default=>1) if !ref $self;
+
+ # Validate arguments
+ Carp::croak("$module is not installed") if (! exists($self->{$module}));
+ $type = "all" if (! defined($type));
+ Carp::croak('type must be "all", "prog" or "doc"')
+ if ($type ne "all" && $type ne "prog" && $type ne "doc");
+
+ my (@files);
+ foreach my $file (keys(%{$self->{$module}{packlist}})) {
+ push(@files, $file)
+ if ($self->_is_type($file, $type) &&
+ $self->_is_under($file, @under));
+ }
+ return(@files);
+}
+
+sub directories {
+ my ($self, $module, $type, @under) = @_;
+ $self= $self->new(default=>1) if !ref $self;
+ my (%dirs);
+ foreach my $file ($self->files($module, $type, @under)) {
+ $dirs{dirname($file)}++;
+ }
+ return sort keys %dirs;
+}
+
+sub directory_tree {
+ my ($self, $module, $type, @under) = @_;
+ $self= $self->new(default=>1) if !ref $self;
+ my (%dirs);
+ foreach my $dir ($self->directories($module, $type, @under)) {
+ $dirs{$dir}++;
+ my ($last) = ("");
+ while ($last ne $dir) {
+ $last = $dir;
+ $dir = dirname($dir);
+ last if !$self->_is_under($dir, @under);
+ $dirs{$dir}++;
+ }
+ }
+ return(sort(keys(%dirs)));
+}
+
+sub validate {
+ my ($self, $module, $remove) = @_;
+ $self= $self->new(default=>1) if !ref $self;
+ Carp::croak("$module is not installed") if (! exists($self->{$module}));
+ return($self->{$module}{packlist}->validate($remove));
+}
+
+sub packlist {
+ my ($self, $module) = @_;
+ $self= $self->new(default=>1) if !ref $self;
+ Carp::croak("$module is not installed") if (! exists($self->{$module}));
+ return($self->{$module}{packlist});
+}
+
+sub version {
+ my ($self, $module) = @_;
+ $self= $self->new(default=>1) if !ref $self;
+ Carp::croak("$module is not installed") if (! exists($self->{$module}));
+ return($self->{$module}{version});
+}
+
+sub debug_dump {
+ my ($self, $module) = @_;
+ $self= $self->new(default=>1) if !ref $self;
+ local $self->{":private:"}{Config};
+ require Data::Dumper;
+ print Data::Dumper->new([$self])->Sortkeys(1)->Indent(1)->Dump();
+}
+
+
+1;
+
+__END__
+
+=head1 NAME
+
+ExtUtils::Installed - Inventory management of installed modules
+
+=head1 SYNOPSIS
+
+ use ExtUtils::Installed;
+ my ($inst) = ExtUtils::Installed->new();
+ my (@modules) = $inst->modules();
+ my (@missing) = $inst->validate("DBI");
+ my $all_files = $inst->files("DBI");
+ my $files_below_usr_local = $inst->files("DBI", "all", "/usr/local");
+ my $all_dirs = $inst->directories("DBI");
+ my $dirs_below_usr_local = $inst->directory_tree("DBI", "prog");
+ my $packlist = $inst->packlist("DBI");
+
+=head1 DESCRIPTION
+
+ExtUtils::Installed provides a standard way to find out what core and module
+files have been installed. It uses the information stored in .packlist files
+created during installation to provide this information. In addition it
+provides facilities to classify the installed files and to extract directory
+information from the .packlist files.
+
+=head1 USAGE
+
+The new() function searches for all the installed .packlists on the system, and
+stores their contents. The .packlists can be queried with the functions
+described below. Where it searches by default is determined by the settings found
+in C<%Config::Config>, and what the value is of the PERL5LIB environment variable.
+
+=head1 METHODS
+
+Unless specified otherwise all method can be called as class methods, or as object
+methods. If called as class methods then the "default" object will be used, and if
+necessary created using the current processes %Config and @INC. See the
+'default' option to new() for details.
+
+
+=over 4
+
+=item new()
+
+This takes optional named parameters. Without parameters, this
+searches for all the installed .packlists on the system using
+information from C<%Config::Config> and the default module search
+paths C<@INC>. The packlists are read using the
+L<ExtUtils::Packlist> module.
+
+If the named parameter C<config_override> is specified,
+it should be a reference to a hash which contains all information
+usually found in C<%Config::Config>. For example, you can obtain
+the configuration information for a separate perl installation and
+pass that in.
+
+ my $yoda_cfg = get_fake_config('yoda');
+ my $yoda_inst = ExtUtils::Installed->new(config_override=>$yoda_cfg);
+
+Similarly, the parameter C<inc_override> may be a reference to an
+array which is used in place of the default module search paths
+from C<@INC>.
+
+ use Config;
+ my @dirs = split(/\Q$Config{path_sep}\E/, $ENV{PERL5LIB});
+ my $p5libs = ExtUtils::Installed->new(inc_override=>\@dirs);
+
+B<Note>: You probably do not want to use these options alone, almost always
+you will want to set both together.
+
+The parameter c<extra_libs> can be used to specify B<additional> paths to
+search for installed modules. For instance
+
+ my $installed = ExtUtils::Installed->new(extra_libs=>["/my/lib/path"]);
+
+This should only be necessary if C</my/lib/path> is not in PERL5LIB.
+
+Finally there is the 'default', and the related 'default_get' and 'default_set'
+options. These options control the "default" object which is provided by the
+class interface to the methods. Setting C<default_get> to true tells the constructor
+to return the default object if it is defined. Setting C<default_set> to true tells
+the constructor to make the default object the constructed object. Setting the
+C<default> option is like setting both to true. This is used primarily internally
+and probably isn't interesting to any real user.
+
+=item modules()
+
+This returns a list of the names of all the installed modules. The perl 'core'
+is given the special name 'Perl'.
+
+=item files()
+
+This takes one mandatory parameter, the name of a module. It returns a list of
+all the filenames from the package. To obtain a list of core perl files, use
+the module name 'Perl'. Additional parameters are allowed. The first is one
+of the strings "prog", "doc" or "all", to select either just program files,
+just manual files or all files. The remaining parameters are a list of
+directories. The filenames returned will be restricted to those under the
+specified directories.
+
+=item directories()
+
+This takes one mandatory parameter, the name of a module. It returns a list of
+all the directories from the package. Additional parameters are allowed. The
+first is one of the strings "prog", "doc" or "all", to select either just
+program directories, just manual directories or all directories. The remaining
+parameters are a list of directories. The directories returned will be
+restricted to those under the specified directories. This method returns only
+the leaf directories that contain files from the specified module.
+
+=item directory_tree()
+
+This is identical in operation to directories(), except that it includes all the
+intermediate directories back up to the specified directories.
+
+=item validate()
+
+This takes one mandatory parameter, the name of a module. It checks that all
+the files listed in the modules .packlist actually exist, and returns a list of
+any missing files. If an optional second argument which evaluates to true is
+given any missing files will be removed from the .packlist
+
+=item packlist()
+
+This returns the ExtUtils::Packlist object for the specified module.
+
+=item version()
+
+This returns the version number for the specified module.
+
+=back
+
+=head1 EXAMPLE
+
+See the example in L<ExtUtils::Packlist>.
+
+=head1 AUTHOR
+
+Alan Burlison <Alan.Burlison@uk.sun.com>
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/Liblist.pm b/Master/tlpkg/tlperl/lib/ExtUtils/Liblist.pm
new file mode 100644
index 00000000000..ea4dac4ae7c
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/Liblist.pm
@@ -0,0 +1,286 @@
+package ExtUtils::Liblist;
+
+use strict;
+
+our $VERSION = '6.56';
+
+use File::Spec;
+require ExtUtils::Liblist::Kid;
+our @ISA = qw(ExtUtils::Liblist::Kid File::Spec);
+
+# Backwards compatibility with old interface.
+sub ext {
+ goto &ExtUtils::Liblist::Kid::ext;
+}
+
+sub lsdir {
+ shift;
+ my $rex = qr/$_[1]/;
+ opendir DIR, $_[0];
+ my @out = grep /$rex/, readdir DIR;
+ closedir DIR;
+ return @out;
+}
+
+__END__
+
+=head1 NAME
+
+ExtUtils::Liblist - determine libraries to use and how to use them
+
+=head1 SYNOPSIS
+
+ require ExtUtils::Liblist;
+
+ $MM->ext($potential_libs, $verbose, $need_names);
+
+ # Usually you can get away with:
+ ExtUtils::Liblist->ext($potential_libs, $verbose, $need_names)
+
+=head1 DESCRIPTION
+
+This utility takes a list of libraries in the form C<-llib1 -llib2
+-llib3> and returns lines suitable for inclusion in an extension
+Makefile. Extra library paths may be included with the form
+C<-L/another/path> this will affect the searches for all subsequent
+libraries.
+
+It returns an array of four or five scalar values: EXTRALIBS,
+BSLOADLIBS, LDLOADLIBS, LD_RUN_PATH, and, optionally, a reference to
+the array of the filenames of actual libraries. Some of these don't
+mean anything unless on Unix. See the details about those platform
+specifics below. The list of the filenames is returned only if
+$need_names argument is true.
+
+Dependent libraries can be linked in one of three ways:
+
+=over 2
+
+=item * For static extensions
+
+by the ld command when the perl binary is linked with the extension
+library. See EXTRALIBS below.
+
+=item * For dynamic extensions at build/link time
+
+by the ld command when the shared object is built/linked. See
+LDLOADLIBS below.
+
+=item * For dynamic extensions at load time
+
+by the DynaLoader when the shared object is loaded. See BSLOADLIBS
+below.
+
+=back
+
+=head2 EXTRALIBS
+
+List of libraries that need to be linked with when linking a perl
+binary which includes this extension. Only those libraries that
+actually exist are included. These are written to a file and used
+when linking perl.
+
+=head2 LDLOADLIBS and LD_RUN_PATH
+
+List of those libraries which can or must be linked into the shared
+library when created using ld. These may be static or dynamic
+libraries. LD_RUN_PATH is a colon separated list of the directories
+in LDLOADLIBS. It is passed as an environment variable to the process
+that links the shared library.
+
+=head2 BSLOADLIBS
+
+List of those libraries that are needed but can be linked in
+dynamically at run time on this platform. SunOS/Solaris does not need
+this because ld records the information (from LDLOADLIBS) into the
+object file. This list is used to create a .bs (bootstrap) file.
+
+=head1 PORTABILITY
+
+This module deals with a lot of system dependencies and has quite a
+few architecture specific C<if>s in the code.
+
+=head2 VMS implementation
+
+The version of ext() which is executed under VMS differs from the
+Unix-OS/2 version in several respects:
+
+=over 2
+
+=item *
+
+Input library and path specifications are accepted with or without the
+C<-l> and C<-L> prefixes used by Unix linkers. If neither prefix is
+present, a token is considered a directory to search if it is in fact
+a directory, and a library to search for otherwise. Authors who wish
+their extensions to be portable to Unix or OS/2 should use the Unix
+prefixes, since the Unix-OS/2 version of ext() requires them.
+
+=item *
+
+Wherever possible, shareable images are preferred to object libraries,
+and object libraries to plain object files. In accordance with VMS
+naming conventions, ext() looks for files named I<lib>shr and I<lib>rtl;
+it also looks for I<lib>lib and libI<lib> to accommodate Unix conventions
+used in some ported software.
+
+=item *
+
+For each library that is found, an appropriate directive for a linker options
+file is generated. The return values are space-separated strings of
+these directives, rather than elements used on the linker command line.
+
+=item *
+
+LDLOADLIBS contains both the libraries found based on C<$potential_libs> and
+the CRTLs, if any, specified in Config.pm. EXTRALIBS contains just those
+libraries found based on C<$potential_libs>. BSLOADLIBS and LD_RUN_PATH
+are always empty.
+
+=back
+
+In addition, an attempt is made to recognize several common Unix library
+names, and filter them out or convert them to their VMS equivalents, as
+appropriate.
+
+In general, the VMS version of ext() should properly handle input from
+extensions originally designed for a Unix or VMS environment. If you
+encounter problems, or discover cases where the search could be improved,
+please let us know.
+
+=head2 Win32 implementation
+
+The version of ext() which is executed under Win32 differs from the
+Unix-OS/2 version in several respects:
+
+=over 2
+
+=item *
+
+If C<$potential_libs> is empty, the return value will be empty.
+Otherwise, the libraries specified by C<$Config{perllibs}> (see Config.pm)
+will be appended to the list of C<$potential_libs>. The libraries
+will be searched for in the directories specified in C<$potential_libs>,
+C<$Config{libpth}>, and in C<$Config{installarchlib}/CORE>.
+For each library that is found, a space-separated list of fully qualified
+library pathnames is generated.
+
+=item *
+
+Input library and path specifications are accepted with or without the
+C<-l> and C<-L> prefixes used by Unix linkers.
+
+An entry of the form C<-La:\foo> specifies the C<a:\foo> directory to look
+for the libraries that follow.
+
+An entry of the form C<-lfoo> specifies the library C<foo>, which may be
+spelled differently depending on what kind of compiler you are using. If
+you are using GCC, it gets translated to C<libfoo.a>, but for other win32
+compilers, it becomes C<foo.lib>. If no files are found by those translated
+names, one more attempt is made to find them using either C<foo.a> or
+C<libfoo.lib>, depending on whether GCC or some other win32 compiler is
+being used, respectively.
+
+If neither the C<-L> or C<-l> prefix is present in an entry, the entry is
+considered a directory to search if it is in fact a directory, and a
+library to search for otherwise. The C<$Config{lib_ext}> suffix will
+be appended to any entries that are not directories and don't already have
+the suffix.
+
+Note that the C<-L> and C<-l> prefixes are B<not required>, but authors
+who wish their extensions to be portable to Unix or OS/2 should use the
+prefixes, since the Unix-OS/2 version of ext() requires them.
+
+=item *
+
+Entries cannot be plain object files, as many Win32 compilers will
+not handle object files in the place of libraries.
+
+=item *
+
+Entries in C<$potential_libs> beginning with a colon and followed by
+alphanumeric characters are treated as flags. Unknown flags will be ignored.
+
+An entry that matches C</:nodefault/i> disables the appending of default
+libraries found in C<$Config{perllibs}> (this should be only needed very rarely).
+
+An entry that matches C</:nosearch/i> disables all searching for
+the libraries specified after it. Translation of C<-Lfoo> and
+C<-lfoo> still happens as appropriate (depending on compiler being used,
+as reflected by C<$Config{cc}>), but the entries are not verified to be
+valid files or directories.
+
+An entry that matches C</:search/i> reenables searching for
+the libraries specified after it. You can put it at the end to
+enable searching for default libraries specified by C<$Config{perllibs}>.
+
+=item *
+
+The libraries specified may be a mixture of static libraries and
+import libraries (to link with DLLs). Since both kinds are used
+pretty transparently on the Win32 platform, we do not attempt to
+distinguish between them.
+
+=item *
+
+LDLOADLIBS and EXTRALIBS are always identical under Win32, and BSLOADLIBS
+and LD_RUN_PATH are always empty (this may change in future).
+
+=item *
+
+You must make sure that any paths and path components are properly
+surrounded with double-quotes if they contain spaces. For example,
+C<$potential_libs> could be (literally):
+
+ "-Lc:\Program Files\vc\lib" msvcrt.lib "la test\foo bar.lib"
+
+Note how the first and last entries are protected by quotes in order
+to protect the spaces.
+
+=item *
+
+Since this module is most often used only indirectly from extension
+C<Makefile.PL> files, here is an example C<Makefile.PL> entry to add
+a library to the build process for an extension:
+
+ LIBS => ['-lgl']
+
+When using GCC, that entry specifies that MakeMaker should first look
+for C<libgl.a> (followed by C<gl.a>) in all the locations specified by
+C<$Config{libpth}>.
+
+When using a compiler other than GCC, the above entry will search for
+C<gl.lib> (followed by C<libgl.lib>).
+
+If the library happens to be in a location not in C<$Config{libpth}>,
+you need:
+
+ LIBS => ['-Lc:\gllibs -lgl']
+
+Here is a less often used example:
+
+ LIBS => ['-lgl', ':nosearch -Ld:\mesalibs -lmesa -luser32']
+
+This specifies a search for library C<gl> as before. If that search
+fails to find the library, it looks at the next item in the list. The
+C<:nosearch> flag will prevent searching for the libraries that follow,
+so it simply returns the value as C<-Ld:\mesalibs -lmesa -luser32>,
+since GCC can use that value as is with its linker.
+
+When using the Visual C compiler, the second item is returned as
+C<-libpath:d:\mesalibs mesa.lib user32.lib>.
+
+When using the Borland compiler, the second item is returned as
+C<-Ld:\mesalibs mesa.lib user32.lib>, and MakeMaker takes care of
+moving the C<-Ld:\mesalibs> to the correct place in the linker
+command line.
+
+=back
+
+
+=head1 SEE ALSO
+
+L<ExtUtils::MakeMaker>
+
+=cut
+
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/Liblist/Kid.pm b/Master/tlpkg/tlperl/lib/ExtUtils/Liblist/Kid.pm
new file mode 100644
index 00000000000..b807e97cc86
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/Liblist/Kid.pm
@@ -0,0 +1,546 @@
+package ExtUtils::Liblist::Kid;
+
+# XXX Splitting this out into its own .pm is a temporary solution.
+
+# This kid package is to be used by MakeMaker. It will not work if
+# $self is not a Makemaker.
+
+use 5.006;
+# Broken out of MakeMaker from version 4.11
+
+use strict;
+our $VERSION = 6.56;
+
+use Config;
+use Cwd 'cwd';
+use File::Basename;
+use File::Spec;
+
+sub ext {
+ if ($^O eq 'VMS') { return &_vms_ext; }
+ elsif($^O eq 'MSWin32') { return &_win32_ext; }
+ else { return &_unix_os2_ext; }
+}
+
+sub _unix_os2_ext {
+ my($self,$potential_libs, $verbose, $give_libs) = @_;
+ $verbose ||= 0;
+
+ if ($^O =~ 'os2' and $Config{perllibs}) {
+ # Dynamic libraries are not transitive, so we may need including
+ # the libraries linked against perl.dll again.
+
+ $potential_libs .= " " if $potential_libs;
+ $potential_libs .= $Config{perllibs};
+ }
+ return ("", "", "", "", ($give_libs ? [] : ())) unless $potential_libs;
+ warn "Potential libraries are '$potential_libs':\n" if $verbose;
+
+ my($so) = $Config{so};
+ my($libs) = defined $Config{perllibs} ? $Config{perllibs} : $Config{libs};
+ my $Config_libext = $Config{lib_ext} || ".a";
+
+
+ # compute $extralibs, $bsloadlibs and $ldloadlibs from
+ # $potential_libs
+ # this is a rewrite of Andy Dougherty's extliblist in perl
+
+ my(@searchpath); # from "-L/path" entries in $potential_libs
+ my(@libpath) = split " ", $Config{'libpth'};
+ my(@ldloadlibs, @bsloadlibs, @extralibs, @ld_run_path, %ld_run_path_seen);
+ my(@libs, %libs_seen);
+ my($fullname, @fullname);
+ my($pwd) = cwd(); # from Cwd.pm
+ my($found) = 0;
+
+ foreach my $thislib (split ' ', $potential_libs) {
+
+ # Handle possible linker path arguments.
+ if ($thislib =~ s/^(-[LR]|-Wl,-R)//){ # save path flag type
+ my($ptype) = $1;
+ unless (-d $thislib){
+ warn "$ptype$thislib ignored, directory does not exist\n"
+ if $verbose;
+ next;
+ }
+ my($rtype) = $ptype;
+ if (($ptype eq '-R') or ($ptype eq '-Wl,-R')) {
+ if ($Config{'lddlflags'} =~ /-Wl,-R/) {
+ $rtype = '-Wl,-R';
+ } elsif ($Config{'lddlflags'} =~ /-R/) {
+ $rtype = '-R';
+ }
+ }
+ unless (File::Spec->file_name_is_absolute($thislib)) {
+ warn "Warning: $ptype$thislib changed to $ptype$pwd/$thislib\n";
+ $thislib = $self->catdir($pwd,$thislib);
+ }
+ push(@searchpath, $thislib);
+ push(@extralibs, "$ptype$thislib");
+ push(@ldloadlibs, "$rtype$thislib");
+ next;
+ }
+
+ # Handle possible library arguments.
+ unless ($thislib =~ s/^-l//){
+ warn "Unrecognized argument in LIBS ignored: '$thislib'\n";
+ next;
+ }
+
+ my($found_lib)=0;
+ foreach my $thispth (@searchpath, @libpath) {
+
+ # Try to find the full name of the library. We need this to
+ # determine whether it's a dynamically-loadable library or not.
+ # This tends to be subject to various os-specific quirks.
+ # For gcc-2.6.2 on linux (March 1995), DLD can not load
+ # .sa libraries, with the exception of libm.sa, so we
+ # deliberately skip them.
+ if (@fullname =
+ $self->lsdir($thispth,"^\Qlib$thislib.$so.\E[0-9]+")){
+ # Take care that libfoo.so.10 wins against libfoo.so.9.
+ # Compare two libraries to find the most recent version
+ # number. E.g. if you have libfoo.so.9.0.7 and
+ # libfoo.so.10.1, first convert all digits into two
+ # decimal places. Then we'll add ".00" to the shorter
+ # strings so that we're comparing strings of equal length
+ # Thus we'll compare libfoo.so.09.07.00 with
+ # libfoo.so.10.01.00. Some libraries might have letters
+ # in the version. We don't know what they mean, but will
+ # try to skip them gracefully -- we'll set any letter to
+ # '0'. Finally, sort in reverse so we can take the
+ # first element.
+
+ #TODO: iterate through the directory instead of sorting
+
+ $fullname = "$thispth/" .
+ (sort { my($ma) = $a;
+ my($mb) = $b;
+ $ma =~ tr/A-Za-z/0/s;
+ $ma =~ s/\b(\d)\b/0$1/g;
+ $mb =~ tr/A-Za-z/0/s;
+ $mb =~ s/\b(\d)\b/0$1/g;
+ while (length($ma) < length($mb)) { $ma .= ".00"; }
+ while (length($mb) < length($ma)) { $mb .= ".00"; }
+ # Comparison deliberately backwards
+ $mb cmp $ma;} @fullname)[0];
+ } elsif (-f ($fullname="$thispth/lib$thislib.$so")
+ && (($Config{'dlsrc'} ne "dl_dld.xs") || ($thislib eq "m"))){
+ } elsif (-f ($fullname="$thispth/lib${thislib}_s$Config_libext")
+ && ($Config{'archname'} !~ /RM\d\d\d-svr4/)
+ && ($thislib .= "_s") ){ # we must explicitly use _s version
+ } elsif (-f ($fullname="$thispth/lib$thislib$Config_libext")){
+ } elsif (-f ($fullname="$thispth/$thislib$Config_libext")){
+ } elsif (-f ($fullname="$thispth/lib$thislib.dll$Config_libext")){
+ } elsif (-f ($fullname="$thispth/Slib$thislib$Config_libext")){
+ } elsif ($^O eq 'dgux'
+ && -l ($fullname="$thispth/lib$thislib$Config_libext")
+ && readlink($fullname) =~ /^elink:/s) {
+ # Some of DG's libraries look like misconnected symbolic
+ # links, but development tools can follow them. (They
+ # look like this:
+ #
+ # libm.a -> elink:${SDE_PATH:-/usr}/sde/\
+ # ${TARGET_BINARY_INTERFACE:-m88kdgux}/usr/lib/libm.a
+ #
+ # , the compilation tools expand the environment variables.)
+ } else {
+ warn "$thislib not found in $thispth\n" if $verbose;
+ next;
+ }
+ warn "'-l$thislib' found at $fullname\n" if $verbose;
+ push @libs, $fullname unless $libs_seen{$fullname}++;
+ $found++;
+ $found_lib++;
+
+ # Now update library lists
+
+ # what do we know about this library...
+ my $is_dyna = ($fullname !~ /\Q$Config_libext\E\z/);
+ my $in_perl = ($libs =~ /\B-l\Q${thislib}\E\b/s);
+
+ # include the path to the lib once in the dynamic linker path
+ # but only if it is a dynamic lib and not in Perl itself
+ my($fullnamedir) = dirname($fullname);
+ push @ld_run_path, $fullnamedir
+ if $is_dyna && !$in_perl &&
+ !$ld_run_path_seen{$fullnamedir}++;
+
+ # Do not add it into the list if it is already linked in
+ # with the main perl executable.
+ # We have to special-case the NeXT, because math and ndbm
+ # are both in libsys_s
+ unless ($in_perl ||
+ ($Config{'osname'} eq 'next' &&
+ ($thislib eq 'm' || $thislib eq 'ndbm')) ){
+ push(@extralibs, "-l$thislib");
+ }
+
+ # We might be able to load this archive file dynamically
+ if ( ($Config{'dlsrc'} =~ /dl_next/ && $Config{'osvers'} lt '4_0')
+ || ($Config{'dlsrc'} =~ /dl_dld/) )
+ {
+ # We push -l$thislib instead of $fullname because
+ # it avoids hardwiring a fixed path into the .bs file.
+ # Mkbootstrap will automatically add dl_findfile() to
+ # the .bs file if it sees a name in the -l format.
+ # USE THIS, when dl_findfile() is fixed:
+ # push(@bsloadlibs, "-l$thislib");
+ # OLD USE WAS while checking results against old_extliblist
+ push(@bsloadlibs, "$fullname");
+ } else {
+ if ($is_dyna){
+ # For SunOS4, do not add in this shared library if
+ # it is already linked in the main perl executable
+ push(@ldloadlibs, "-l$thislib")
+ unless ($in_perl and $^O eq 'sunos');
+ } else {
+ push(@ldloadlibs, "-l$thislib");
+ }
+ }
+ last; # found one here so don't bother looking further
+ }
+ warn "Note (probably harmless): "
+ ."No library found for -l$thislib\n"
+ unless $found_lib>0;
+ }
+
+ unless( $found ) {
+ return ('','','','', ($give_libs ? \@libs : ()));
+ }
+ else {
+ return ("@extralibs", "@bsloadlibs", "@ldloadlibs",
+ join(":",@ld_run_path), ($give_libs ? \@libs : ()));
+ }
+}
+
+sub _win32_ext {
+
+ require Text::ParseWords;
+
+ my($self, $potential_libs, $verbose, $give_libs) = @_;
+ $verbose ||= 0;
+
+ # If user did not supply a list, we punt.
+ # (caller should probably use the list in $Config{libs})
+ return ("", "", "", "", ($give_libs ? [] : ())) unless $potential_libs;
+
+ my $cc = $Config{cc};
+ my $VC = $cc =~ /^cl/i;
+ my $BC = $cc =~ /^bcc/i;
+ my $GC = $cc =~ /^gcc/i;
+ my $so = $Config{'so'};
+ my $libs = $Config{'perllibs'};
+ my $libpth = $Config{'libpth'};
+ my $libext = $Config{'lib_ext'} || ".lib";
+ my(@libs, %libs_seen);
+
+ if ($libs and $potential_libs !~ /:nodefault/i) {
+ # If Config.pm defines a set of default libs, we always
+ # tack them on to the user-supplied list, unless the user
+ # specified :nodefault
+
+ $potential_libs .= " " if $potential_libs;
+ $potential_libs .= $libs;
+ }
+ warn "Potential libraries are '$potential_libs':\n" if $verbose;
+
+ # normalize to forward slashes
+ $libpth =~ s,\\,/,g;
+ $potential_libs =~ s,\\,/,g;
+
+ # compute $extralibs from $potential_libs
+
+ my @searchpath; # from "-L/path" in $potential_libs
+ my @libpath = Text::ParseWords::quotewords('\s+', 0, $libpth);
+ my @extralibs;
+ my $pwd = cwd(); # from Cwd.pm
+ my $lib = '';
+ my $found = 0;
+ my $search = 1;
+ my($fullname);
+
+ # add "$Config{installarchlib}/CORE" to default search path
+ push @libpath, "$Config{installarchlib}/CORE";
+
+ if ($VC and exists $ENV{LIB} and $ENV{LIB}) {
+ push @libpath, split /;/, $ENV{LIB};
+ }
+
+ foreach (Text::ParseWords::quotewords('\s+', 0, $potential_libs)){
+
+ my $thislib = $_;
+
+ # see if entry is a flag
+ if (/^:\w+$/) {
+ $search = 0 if lc eq ':nosearch';
+ $search = 1 if lc eq ':search';
+ warn "Ignoring unknown flag '$thislib'\n"
+ if $verbose and !/^:(no)?(search|default)$/i;
+ next;
+ }
+
+ # if searching is disabled, do compiler-specific translations
+ unless ($search) {
+ s/^-l(.+)$/$1.lib/ unless $GC;
+ s/^-L/-libpath:/ if $VC;
+ push(@extralibs, $_);
+ $found++;
+ next;
+ }
+
+ # handle possible linker path arguments
+ if (s/^-L// and not -d) {
+ warn "$thislib ignored, directory does not exist\n"
+ if $verbose;
+ next;
+ }
+ elsif (-d) {
+ unless (File::Spec->file_name_is_absolute($_)) {
+ warn "Warning: '$thislib' changed to '-L$pwd/$_'\n";
+ $_ = $self->catdir($pwd,$_);
+ }
+ push(@searchpath, $_);
+ next;
+ }
+
+ # handle possible library arguments
+ if (s/^-l// and $GC and !/^lib/i) {
+ $_ = "lib$_";
+ }
+ $_ .= $libext if !/\Q$libext\E$/i;
+
+ my $secondpass = 0;
+ LOOKAGAIN:
+
+ # look for the file itself
+ if (-f) {
+ warn "'$thislib' found as '$_'\n" if $verbose;
+ $found++;
+ push(@extralibs, $_);
+ next;
+ }
+
+ my $found_lib = 0;
+ foreach my $thispth (@searchpath, @libpath){
+ unless (-f ($fullname="$thispth\\$_")) {
+ warn "'$thislib' not found as '$fullname'\n" if $verbose;
+ next;
+ }
+ warn "'$thislib' found as '$fullname'\n" if $verbose;
+ $found++;
+ $found_lib++;
+ push(@extralibs, $fullname);
+ push @libs, $fullname unless $libs_seen{$fullname}++;
+ last;
+ }
+
+ # do another pass with (or without) leading 'lib' if they used -l
+ if (!$found_lib and $thislib =~ /^-l/ and !$secondpass++) {
+ if ($GC) {
+ goto LOOKAGAIN if s/^lib//i;
+ }
+ elsif (!/^lib/i) {
+ $_ = "lib$_";
+ goto LOOKAGAIN;
+ }
+ }
+
+ # give up
+ warn "Note (probably harmless): "
+ ."No library found for $thislib\n"
+ unless $found_lib>0;
+
+ }
+
+ return ('','','','', ($give_libs ? \@libs : ())) unless $found;
+
+ # make sure paths with spaces are properly quoted
+ @extralibs = map { (/\s/ && !/^".*"$/) ? qq["$_"] : $_ } @extralibs;
+ @libs = map { (/\s/ && !/^".*"$/) ? qq["$_"] : $_ } @libs;
+ $lib = join(' ',@extralibs);
+
+ # normalize back to backward slashes (to help braindead tools)
+ # XXX this may break equally braindead GNU tools that don't understand
+ # backslashes, either. Seems like one can't win here. Cursed be CP/M.
+ $lib =~ s,/,\\,g;
+
+ warn "Result: $lib\n" if $verbose;
+ wantarray ? ($lib, '', $lib, '', ($give_libs ? \@libs : ())) : $lib;
+}
+
+
+sub _vms_ext {
+ my($self, $potential_libs, $verbose, $give_libs) = @_;
+ $verbose ||= 0;
+
+ my(@crtls,$crtlstr);
+ @crtls = ( ($Config{'ldflags'} =~ m-/Debug-i ? $Config{'dbgprefix'} : '')
+ . 'PerlShr/Share' );
+ push(@crtls, grep { not /\(/ } split /\s+/, $Config{'perllibs'});
+ push(@crtls, grep { not /\(/ } split /\s+/, $Config{'libc'});
+ # In general, we pass through the basic libraries from %Config unchanged.
+ # The one exception is that if we're building in the Perl source tree, and
+ # a library spec could be resolved via a logical name, we go to some trouble
+ # to insure that the copy in the local tree is used, rather than one to
+ # which a system-wide logical may point.
+ if ($self->{PERL_SRC}) {
+ my($locspec,$type);
+ foreach my $lib (@crtls) {
+ if (($locspec,$type) = $lib =~ m{^([\w\$-]+)(/\w+)?} and $locspec =~ /perl/i) {
+ if (lc $type eq '/share') { $locspec .= $Config{'exe_ext'}; }
+ elsif (lc $type eq '/library') { $locspec .= $Config{'lib_ext'}; }
+ else { $locspec .= $Config{'obj_ext'}; }
+ $locspec = $self->catfile($self->{PERL_SRC},$locspec);
+ $lib = "$locspec$type" if -e $locspec;
+ }
+ }
+ }
+ $crtlstr = @crtls ? join(' ',@crtls) : '';
+
+ unless ($potential_libs) {
+ warn "Result:\n\tEXTRALIBS: \n\tLDLOADLIBS: $crtlstr\n" if $verbose;
+ return ('', '', $crtlstr, '', ($give_libs ? [] : ()));
+ }
+
+ my(%found,@fndlibs,$ldlib);
+ my $cwd = cwd();
+ my($so,$lib_ext,$obj_ext) = @Config{'so','lib_ext','obj_ext'};
+ # List of common Unix library names and their VMS equivalents
+ # (VMS equivalent of '' indicates that the library is automatically
+ # searched by the linker, and should be skipped here.)
+ my(@flibs, %libs_seen);
+ my %libmap = ( 'm' => '', 'f77' => '', 'F77' => '', 'V77' => '', 'c' => '',
+ 'malloc' => '', 'crypt' => '', 'resolv' => '', 'c_s' => '',
+ 'socket' => '', 'X11' => 'DECW$XLIBSHR',
+ 'Xt' => 'DECW$XTSHR', 'Xm' => 'DECW$XMLIBSHR',
+ 'Xmu' => 'DECW$XMULIBSHR');
+ if ($Config{'vms_cc_type'} ne 'decc') { $libmap{'curses'} = 'VAXCCURSE'; }
+
+ warn "Potential libraries are '$potential_libs'\n" if $verbose;
+
+ # First, sort out directories and library names in the input
+ my(@dirs, @libs);
+ foreach my $lib (split ' ',$potential_libs) {
+ push(@dirs,$1), next if $lib =~ /^-L(.*)/;
+ push(@dirs,$lib), next if $lib =~ /[:>\]]$/;
+ push(@dirs,$lib), next if -d $lib;
+ push(@libs,$1), next if $lib =~ /^-l(.*)/;
+ push(@libs,$lib);
+ }
+ push(@dirs,split(' ',$Config{'libpth'}));
+
+ # Now make sure we've got VMS-syntax absolute directory specs
+ # (We don't, however, check whether someone's hidden a relative
+ # path in a logical name.)
+ foreach my $dir (@dirs) {
+ unless (-d $dir) {
+ warn "Skipping nonexistent Directory $dir\n" if $verbose > 1;
+ $dir = '';
+ next;
+ }
+ warn "Resolving directory $dir\n" if $verbose;
+ if (File::Spec->file_name_is_absolute($dir)) {
+ $dir = $self->fixpath($dir,1);
+ }
+ else {
+ $dir = $self->catdir($cwd,$dir);
+ }
+ }
+ @dirs = grep { length($_) } @dirs;
+ unshift(@dirs,''); # Check each $lib without additions first
+
+ LIB: foreach my $lib (@libs) {
+ if (exists $libmap{$lib}) {
+ next unless length $libmap{$lib};
+ $lib = $libmap{$lib};
+ }
+
+ my(@variants,$cand);
+ my($ctype) = '';
+
+ # If we don't have a file type, consider it a possibly abbreviated name and
+ # check for common variants. We try these first to grab libraries before
+ # a like-named executable image (e.g. -lperl resolves to perlshr.exe
+ # before perl.exe).
+ if ($lib !~ /\.[^:>\]]*$/) {
+ push(@variants,"${lib}shr","${lib}rtl","${lib}lib");
+ push(@variants,"lib$lib") if $lib !~ /[:>\]]/;
+ }
+ push(@variants,$lib);
+ warn "Looking for $lib\n" if $verbose;
+ foreach my $variant (@variants) {
+ my($fullname, $name);
+
+ foreach my $dir (@dirs) {
+ my($type);
+
+ $name = "$dir$variant";
+ warn "\tChecking $name\n" if $verbose > 2;
+ $fullname = VMS::Filespec::rmsexpand($name);
+ if (defined $fullname and -f $fullname) {
+ # It's got its own suffix, so we'll have to figure out the type
+ if ($fullname =~ /(?:$so|exe)$/i) { $type = 'SHR'; }
+ elsif ($fullname =~ /(?:$lib_ext|olb)$/i) { $type = 'OLB'; }
+ elsif ($fullname =~ /(?:$obj_ext|obj)$/i) {
+ warn "Note (probably harmless): "
+ ."Plain object file $fullname found in library list\n";
+ $type = 'OBJ';
+ }
+ else {
+ warn "Note (probably harmless): "
+ ."Unknown library type for $fullname; assuming shared\n";
+ $type = 'SHR';
+ }
+ }
+ elsif (-f ($fullname = VMS::Filespec::rmsexpand($name,$so)) or
+ -f ($fullname = VMS::Filespec::rmsexpand($name,'.exe'))) {
+ $type = 'SHR';
+ $name = $fullname unless $fullname =~ /exe;?\d*$/i;
+ }
+ elsif (not length($ctype) and # If we've got a lib already,
+ # don't bother
+ ( -f ($fullname = VMS::Filespec::rmsexpand($name,$lib_ext)) or
+ -f ($fullname = VMS::Filespec::rmsexpand($name,'.olb')))) {
+ $type = 'OLB';
+ $name = $fullname unless $fullname =~ /olb;?\d*$/i;
+ }
+ elsif (not length($ctype) and # If we've got a lib already,
+ # don't bother
+ ( -f ($fullname = VMS::Filespec::rmsexpand($name,$obj_ext)) or
+ -f ($fullname = VMS::Filespec::rmsexpand($name,'.obj')))) {
+ warn "Note (probably harmless): "
+ ."Plain object file $fullname found in library list\n";
+ $type = 'OBJ';
+ $name = $fullname unless $fullname =~ /obj;?\d*$/i;
+ }
+ if (defined $type) {
+ $ctype = $type; $cand = $name;
+ last if $ctype eq 'SHR';
+ }
+ }
+ if ($ctype) {
+ # This has to precede any other CRTLs, so just make it first
+ if ($cand eq 'VAXCCURSE') { unshift @{$found{$ctype}}, $cand; }
+ else { push @{$found{$ctype}}, $cand; }
+ warn "\tFound as $cand (really $fullname), type $ctype\n"
+ if $verbose > 1;
+ push @flibs, $name unless $libs_seen{$fullname}++;
+ next LIB;
+ }
+ }
+ warn "Note (probably harmless): "
+ ."No library found for $lib\n";
+ }
+
+ push @fndlibs, @{$found{OBJ}} if exists $found{OBJ};
+ push @fndlibs, map { "$_/Library" } @{$found{OLB}} if exists $found{OLB};
+ push @fndlibs, map { "$_/Share" } @{$found{SHR}} if exists $found{SHR};
+ my $lib = join(' ',@fndlibs);
+
+ $ldlib = $crtlstr ? "$lib $crtlstr" : $lib;
+ warn "Result:\n\tEXTRALIBS: $lib\n\tLDLOADLIBS: $ldlib\n" if $verbose;
+ wantarray ? ($lib, '', $ldlib, '', ($give_libs ? \@flibs : ())) : $lib;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MANIFEST.SKIP b/Master/tlpkg/tlperl/lib/ExtUtils/MANIFEST.SKIP
new file mode 100644
index 00000000000..e50a7b390f7
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MANIFEST.SKIP
@@ -0,0 +1,51 @@
+# Avoid version control files.
+\bRCS\b
+\bCVS\b
+\bSCCS\b
+,v$
+\B\.svn\b
+\B\.git\b
+\B\.gitignore\b
+\b_darcs\b
+\B\.cvsignore$
+
+# Avoid VMS specific MakeMaker generated files
+\bDescrip.MMS$
+\bDESCRIP.MMS$
+\bdescrip.mms$
+
+# Avoid Makemaker generated and utility files.
+\bMANIFEST\.bak
+\bMakefile$
+\bblib/
+\bMakeMaker-\d
+\bpm_to_blib\.ts$
+\bpm_to_blib$
+\bblibdirs\.ts$ # 6.18 through 6.25 generated this
+
+# Avoid Module::Build generated and utility files.
+\bBuild$
+\b_build/
+\bBuild.bat$
+\bBuild.COM$
+\bBUILD.COM$
+\bbuild.com$
+
+# Avoid temp and backup files.
+~$
+\.old$
+\#$
+\b\.#
+\.bak$
+\.tmp$
+\.#
+\.rej$
+
+# Avoid OS-specific files/dirs
+# Mac OSX metadata
+\B\.DS_Store
+# Mac OSX SMB mount metadata files
+\B\._
+
+# Avoid Devel::Cover files.
+\bcover_db\b
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MM.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MM.pm
new file mode 100644
index 00000000000..eac5f483494
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MM.pm
@@ -0,0 +1,90 @@
+package ExtUtils::MM;
+
+use strict;
+use ExtUtils::MakeMaker::Config;
+
+our $VERSION = '6.56';
+
+require ExtUtils::Liblist;
+require ExtUtils::MakeMaker;
+our @ISA = qw(ExtUtils::Liblist ExtUtils::MakeMaker);
+
+=head1 NAME
+
+ExtUtils::MM - OS adjusted ExtUtils::MakeMaker subclass
+
+=head1 SYNOPSIS
+
+ require ExtUtils::MM;
+ my $mm = MM->new(...);
+
+=head1 DESCRIPTION
+
+B<FOR INTERNAL USE ONLY>
+
+ExtUtils::MM is a subclass of ExtUtils::MakeMaker which automatically
+chooses the appropriate OS specific subclass for you
+(ie. ExtUils::MM_Unix, etc...).
+
+It also provides a convenient alias via the MM class (I didn't want
+MakeMaker modules outside of ExtUtils/).
+
+This class might turn out to be a temporary solution, but MM won't go
+away.
+
+=cut
+
+{
+ # Convenient alias.
+ package MM;
+ our @ISA = qw(ExtUtils::MM);
+ sub DESTROY {}
+}
+
+sub _is_win95 {
+ # miniperl might not have the Win32 functions available and we need
+ # to run in miniperl.
+ my $have_win32 = eval { require Win32 };
+ return $have_win32 && defined &Win32::IsWin95 ? Win32::IsWin95()
+ : ! defined $ENV{SYSTEMROOT};
+}
+
+my %Is = ();
+$Is{VMS} = $^O eq 'VMS';
+$Is{OS2} = $^O eq 'os2';
+$Is{MacOS} = $^O eq 'MacOS';
+if( $^O eq 'MSWin32' ) {
+ _is_win95() ? $Is{Win95} = 1 : $Is{Win32} = 1;
+}
+$Is{UWIN} = $^O =~ /^uwin(-nt)?$/;
+$Is{Cygwin} = $^O eq 'cygwin';
+$Is{NW5} = $Config{osname} eq 'NetWare'; # intentional
+$Is{BeOS} = ($^O =~ /beos/i or $^O eq 'haiku');
+$Is{DOS} = $^O eq 'dos';
+if( $Is{NW5} ) {
+ $^O = 'NetWare';
+ delete $Is{Win32};
+}
+$Is{VOS} = $^O eq 'vos';
+$Is{QNX} = $^O eq 'qnx';
+$Is{AIX} = $^O eq 'aix';
+$Is{Darwin} = $^O eq 'darwin';
+
+$Is{Unix} = !grep { $_ } values %Is;
+
+map { delete $Is{$_} unless $Is{$_} } keys %Is;
+_assert( keys %Is == 1 );
+my($OS) = keys %Is;
+
+
+my $class = "ExtUtils::MM_$OS";
+eval "require $class" unless $INC{"ExtUtils/MM_$OS.pm"}; ## no critic
+die $@ if $@;
+unshift @ISA, $class;
+
+
+sub _assert {
+ my $sanity = shift;
+ die sprintf "Assert failed at %s line %d\n", (caller)[1,2] unless $sanity;
+ return;
+}
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MM_AIX.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MM_AIX.pm
new file mode 100644
index 00000000000..5179be4bc2a
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MM_AIX.pm
@@ -0,0 +1,79 @@
+package ExtUtils::MM_AIX;
+
+use strict;
+our $VERSION = '6.56';
+
+require ExtUtils::MM_Unix;
+our @ISA = qw(ExtUtils::MM_Unix);
+
+use ExtUtils::MakeMaker qw(neatvalue);
+
+
+=head1 NAME
+
+ExtUtils::MM_AIX - AIX specific subclass of ExtUtils::MM_Unix
+
+=head1 SYNOPSIS
+
+ Don't use this module directly.
+ Use ExtUtils::MM and let it choose.
+
+=head1 DESCRIPTION
+
+This is a subclass of ExtUtils::MM_Unix which contains functionality for
+AIX.
+
+Unless otherwise stated it works just like ExtUtils::MM_Unix
+
+=head2 Overridden methods
+
+=head3 dlsyms
+
+Define DL_FUNCS and DL_VARS and write the *.exp files.
+
+=cut
+
+sub dlsyms {
+ my($self,%attribs) = @_;
+
+ return '' unless $self->needs_linking();
+
+ my($funcs) = $attribs{DL_FUNCS} || $self->{DL_FUNCS} || {};
+ my($vars) = $attribs{DL_VARS} || $self->{DL_VARS} || [];
+ my($funclist) = $attribs{FUNCLIST} || $self->{FUNCLIST} || [];
+ my(@m);
+
+ push(@m,"
+dynamic :: $self->{BASEEXT}.exp
+
+") unless $self->{SKIPHASH}{'dynamic'}; # dynamic and static are subs, so...
+
+ push(@m,"
+static :: $self->{BASEEXT}.exp
+
+") unless $self->{SKIPHASH}{'static'}; # we avoid a warning if we tick them
+
+ push(@m,"
+$self->{BASEEXT}.exp: Makefile.PL
+",' $(PERLRUN) -e \'use ExtUtils::Mksymlists; \\
+ Mksymlists("NAME" => "',$self->{NAME},'", "DL_FUNCS" => ',
+ neatvalue($funcs), ', "FUNCLIST" => ', neatvalue($funclist),
+ ', "DL_VARS" => ', neatvalue($vars), ');\'
+');
+
+ join('',@m);
+}
+
+
+=head1 AUTHOR
+
+Michael G Schwern <schwern@pobox.com> with code from ExtUtils::MM_Unix
+
+=head1 SEE ALSO
+
+L<ExtUtils::MakeMaker>
+
+=cut
+
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MM_Any.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MM_Any.pm
new file mode 100644
index 00000000000..4905aebc642
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MM_Any.pm
@@ -0,0 +1,2334 @@
+package ExtUtils::MM_Any;
+
+use strict;
+our $VERSION = '6.56';
+
+use Carp;
+use File::Spec;
+use File::Basename;
+BEGIN { our @ISA = qw(File::Spec); }
+
+# We need $Verbose
+use ExtUtils::MakeMaker qw($Verbose);
+
+use ExtUtils::MakeMaker::Config;
+
+
+# So we don't have to keep calling the methods over and over again,
+# we have these globals to cache the values. Faster and shrtr.
+my $Curdir = __PACKAGE__->curdir;
+my $Rootdir = __PACKAGE__->rootdir;
+my $Updir = __PACKAGE__->updir;
+
+
+=head1 NAME
+
+ExtUtils::MM_Any - Platform-agnostic MM methods
+
+=head1 SYNOPSIS
+
+ FOR INTERNAL USE ONLY!
+
+ package ExtUtils::MM_SomeOS;
+
+ # Temporarily, you have to subclass both. Put MM_Any first.
+ require ExtUtils::MM_Any;
+ require ExtUtils::MM_Unix;
+ @ISA = qw(ExtUtils::MM_Any ExtUtils::Unix);
+
+=head1 DESCRIPTION
+
+B<FOR INTERNAL USE ONLY!>
+
+ExtUtils::MM_Any is a superclass for the ExtUtils::MM_* set of
+modules. It contains methods which are either inherently
+cross-platform or are written in a cross-platform manner.
+
+Subclass off of ExtUtils::MM_Any I<and> ExtUtils::MM_Unix. This is a
+temporary solution.
+
+B<THIS MAY BE TEMPORARY!>
+
+
+=head1 METHODS
+
+Any methods marked I<Abstract> must be implemented by subclasses.
+
+
+=head2 Cross-platform helper methods
+
+These are methods which help writing cross-platform code.
+
+
+
+=head3 os_flavor I<Abstract>
+
+ my @os_flavor = $mm->os_flavor;
+
+@os_flavor is the style of operating system this is, usually
+corresponding to the MM_*.pm file we're using.
+
+The first element of @os_flavor is the major family (ie. Unix,
+Windows, VMS, OS/2, etc...) and the rest are sub families.
+
+Some examples:
+
+ Cygwin98 ('Unix', 'Cygwin', 'Cygwin9x')
+ Windows ('Win32')
+ Win98 ('Win32', 'Win9x')
+ Linux ('Unix', 'Linux')
+ MacOS X ('Unix', 'Darwin', 'MacOS', 'MacOS X')
+ OS/2 ('OS/2')
+
+This is used to write code for styles of operating system.
+See os_flavor_is() for use.
+
+
+=head3 os_flavor_is
+
+ my $is_this_flavor = $mm->os_flavor_is($this_flavor);
+ my $is_this_flavor = $mm->os_flavor_is(@one_of_these_flavors);
+
+Checks to see if the current operating system is one of the given flavors.
+
+This is useful for code like:
+
+ if( $mm->os_flavor_is('Unix') ) {
+ $out = `foo 2>&1`;
+ }
+ else {
+ $out = `foo`;
+ }
+
+=cut
+
+sub os_flavor_is {
+ my $self = shift;
+ my %flavors = map { ($_ => 1) } $self->os_flavor;
+ return (grep { $flavors{$_} } @_) ? 1 : 0;
+}
+
+
+=head3 can_load_xs
+
+ my $can_load_xs = $self->can_load_xs;
+
+Returns true if we have the ability to load XS.
+
+This is important because miniperl, used to build XS modules in the
+core, can not load XS.
+
+=cut
+
+sub can_load_xs {
+ return defined &DynaLoader::boot_DynaLoader ? 1 : 0;
+}
+
+
+=head3 split_command
+
+ my @cmds = $MM->split_command($cmd, @args);
+
+Most OS have a maximum command length they can execute at once. Large
+modules can easily generate commands well past that limit. Its
+necessary to split long commands up into a series of shorter commands.
+
+C<split_command> will return a series of @cmds each processing part of
+the args. Collectively they will process all the arguments. Each
+individual line in @cmds will not be longer than the
+$self->max_exec_len being careful to take into account macro expansion.
+
+$cmd should include any switches and repeated initial arguments.
+
+If no @args are given, no @cmds will be returned.
+
+Pairs of arguments will always be preserved in a single command, this
+is a heuristic for things like pm_to_blib and pod2man which work on
+pairs of arguments. This makes things like this safe:
+
+ $self->split_command($cmd, %pod2man);
+
+
+=cut
+
+sub split_command {
+ my($self, $cmd, @args) = @_;
+
+ my @cmds = ();
+ return(@cmds) unless @args;
+
+ # If the command was given as a here-doc, there's probably a trailing
+ # newline.
+ chomp $cmd;
+
+ # set aside 30% for macro expansion.
+ my $len_left = int($self->max_exec_len * 0.70);
+ $len_left -= length $self->_expand_macros($cmd);
+
+ do {
+ my $arg_str = '';
+ my @next_args;
+ while( @next_args = splice(@args, 0, 2) ) {
+ # Two at a time to preserve pairs.
+ my $next_arg_str = "\t ". join ' ', @next_args, "\n";
+
+ if( !length $arg_str ) {
+ $arg_str .= $next_arg_str
+ }
+ elsif( length($arg_str) + length($next_arg_str) > $len_left ) {
+ unshift @args, @next_args;
+ last;
+ }
+ else {
+ $arg_str .= $next_arg_str;
+ }
+ }
+ chop $arg_str;
+
+ push @cmds, $self->escape_newlines("$cmd \n$arg_str");
+ } while @args;
+
+ return @cmds;
+}
+
+
+sub _expand_macros {
+ my($self, $cmd) = @_;
+
+ $cmd =~ s{\$\((\w+)\)}{
+ defined $self->{$1} ? $self->{$1} : "\$($1)"
+ }e;
+ return $cmd;
+}
+
+
+=head3 echo
+
+ my @commands = $MM->echo($text);
+ my @commands = $MM->echo($text, $file);
+ my @commands = $MM->echo($text, $file, $appending);
+
+Generates a set of @commands which print the $text to a $file.
+
+If $file is not given, output goes to STDOUT.
+
+If $appending is true the $file will be appended to rather than
+overwritten.
+
+=cut
+
+sub echo {
+ my($self, $text, $file, $appending) = @_;
+ $appending ||= 0;
+
+ my @cmds = map { '$(NOECHO) $(ECHO) '.$self->quote_literal($_) }
+ split /\n/, $text;
+ if( $file ) {
+ my $redirect = $appending ? '>>' : '>';
+ $cmds[0] .= " $redirect $file";
+ $_ .= " >> $file" foreach @cmds[1..$#cmds];
+ }
+
+ return @cmds;
+}
+
+
+=head3 wraplist
+
+ my $args = $mm->wraplist(@list);
+
+Takes an array of items and turns them into a well-formatted list of
+arguments. In most cases this is simply something like:
+
+ FOO \
+ BAR \
+ BAZ
+
+=cut
+
+sub wraplist {
+ my $self = shift;
+ return join " \\\n\t", @_;
+}
+
+
+=head3 maketext_filter
+
+ my $filter_make_text = $mm->maketext_filter($make_text);
+
+The text of the Makefile is run through this method before writing to
+disk. It allows systems a chance to make portability fixes to the
+Makefile.
+
+By default it does nothing.
+
+This method is protected and not intended to be called outside of
+MakeMaker.
+
+=cut
+
+sub maketext_filter { return $_[1] }
+
+
+=head3 cd I<Abstract>
+
+ my $subdir_cmd = $MM->cd($subdir, @cmds);
+
+This will generate a make fragment which runs the @cmds in the given
+$dir. The rough equivalent to this, except cross platform.
+
+ cd $subdir && $cmd
+
+Currently $dir can only go down one level. "foo" is fine. "foo/bar" is
+not. "../foo" is right out.
+
+The resulting $subdir_cmd has no leading tab nor trailing newline. This
+makes it easier to embed in a make string. For example.
+
+ my $make = sprintf <<'CODE', $subdir_cmd;
+ foo :
+ $(ECHO) what
+ %s
+ $(ECHO) mouche
+ CODE
+
+
+=head3 oneliner I<Abstract>
+
+ my $oneliner = $MM->oneliner($perl_code);
+ my $oneliner = $MM->oneliner($perl_code, \@switches);
+
+This will generate a perl one-liner safe for the particular platform
+you're on based on the given $perl_code and @switches (a -e is
+assumed) suitable for using in a make target. It will use the proper
+shell quoting and escapes.
+
+$(PERLRUN) will be used as perl.
+
+Any newlines in $perl_code will be escaped. Leading and trailing
+newlines will be stripped. Makes this idiom much easier:
+
+ my $code = $MM->oneliner(<<'CODE', [...switches...]);
+some code here
+another line here
+CODE
+
+Usage might be something like:
+
+ # an echo emulation
+ $oneliner = $MM->oneliner('print "Foo\n"');
+ $make = '$oneliner > somefile';
+
+All dollar signs must be doubled in the $perl_code if you expect them
+to be interpreted normally, otherwise it will be considered a make
+macro. Also remember to quote make macros else it might be used as a
+bareword. For example:
+
+ # Assign the value of the $(VERSION_FROM) make macro to $vf.
+ $oneliner = $MM->oneliner('$$vf = "$(VERSION_FROM)"');
+
+Its currently very simple and may be expanded sometime in the figure
+to include more flexible code and switches.
+
+
+=head3 quote_literal I<Abstract>
+
+ my $safe_text = $MM->quote_literal($text);
+
+This will quote $text so it is interpreted literally in the shell.
+
+For example, on Unix this would escape any single-quotes in $text and
+put single-quotes around the whole thing.
+
+
+=head3 escape_newlines I<Abstract>
+
+ my $escaped_text = $MM->escape_newlines($text);
+
+Shell escapes newlines in $text.
+
+
+=head3 max_exec_len I<Abstract>
+
+ my $max_exec_len = $MM->max_exec_len;
+
+Calculates the maximum command size the OS can exec. Effectively,
+this is the max size of a shell command line.
+
+=for _private
+$self->{_MAX_EXEC_LEN} is set by this method, but only for testing purposes.
+
+
+=head3 make
+
+ my $make = $MM->make;
+
+Returns the make variant we're generating the Makefile for. This attempts
+to do some normalization on the information from %Config or the user.
+
+=cut
+
+sub make {
+ my $self = shift;
+
+ my $make = lc $self->{MAKE};
+
+ # Truncate anything like foomake6 to just foomake.
+ $make =~ s/^(\w+make).*/$1/;
+
+ # Turn gnumake into gmake.
+ $make =~ s/^gnu/g/;
+
+ return $make;
+}
+
+
+=head2 Targets
+
+These are methods which produce make targets.
+
+
+=head3 all_target
+
+Generate the default target 'all'.
+
+=cut
+
+sub all_target {
+ my $self = shift;
+
+ return <<'MAKE_EXT';
+all :: pure_all
+ $(NOECHO) $(NOOP)
+MAKE_EXT
+
+}
+
+
+=head3 blibdirs_target
+
+ my $make_frag = $mm->blibdirs_target;
+
+Creates the blibdirs target which creates all the directories we use
+in blib/.
+
+The blibdirs.ts target is deprecated. Depend on blibdirs instead.
+
+
+=cut
+
+sub blibdirs_target {
+ my $self = shift;
+
+ my @dirs = map { uc "\$(INST_$_)" } qw(libdir archlib
+ autodir archautodir
+ bin script
+ man1dir man3dir
+ );
+
+ my @exists = map { $_.'$(DFSEP).exists' } @dirs;
+
+ my $make = sprintf <<'MAKE', join(' ', @exists);
+blibdirs : %s
+ $(NOECHO) $(NOOP)
+
+# Backwards compat with 6.18 through 6.25
+blibdirs.ts : blibdirs
+ $(NOECHO) $(NOOP)
+
+MAKE
+
+ $make .= $self->dir_target(@dirs);
+
+ return $make;
+}
+
+
+=head3 clean (o)
+
+Defines the clean target.
+
+=cut
+
+sub clean {
+# --- Cleanup and Distribution Sections ---
+
+ my($self, %attribs) = @_;
+ my @m;
+ push(@m, '
+# Delete temporary files but do not touch installed files. We don\'t delete
+# the Makefile here so a later make realclean still has a makefile to use.
+
+clean :: clean_subdirs
+');
+
+ my @files = values %{$self->{XS}}; # .c files from *.xs files
+ my @dirs = qw(blib);
+
+ # Normally these are all under blib but they might have been
+ # redefined.
+ # XXX normally this would be a good idea, but the Perl core sets
+ # INST_LIB = ../../lib rather than actually installing the files.
+ # So a "make clean" in an ext/ directory would blow away lib.
+ # Until the core is adjusted let's leave this out.
+# push @dirs, qw($(INST_ARCHLIB) $(INST_LIB)
+# $(INST_BIN) $(INST_SCRIPT)
+# $(INST_MAN1DIR) $(INST_MAN3DIR)
+# $(INST_LIBDIR) $(INST_ARCHLIBDIR) $(INST_AUTODIR)
+# $(INST_STATIC) $(INST_DYNAMIC) $(INST_BOOT)
+# );
+
+
+ if( $attribs{FILES} ) {
+ # Use @dirs because we don't know what's in here.
+ push @dirs, ref $attribs{FILES} ?
+ @{$attribs{FILES}} :
+ split /\s+/, $attribs{FILES} ;
+ }
+
+ push(@files, qw[$(MAKE_APERL_FILE)
+ perlmain.c tmon.out mon.out so_locations
+ blibdirs.ts pm_to_blib pm_to_blib.ts
+ *$(OBJ_EXT) *$(LIB_EXT) perl.exe perl perl$(EXE_EXT)
+ $(BOOTSTRAP) $(BASEEXT).bso
+ $(BASEEXT).def lib$(BASEEXT).def
+ $(BASEEXT).exp $(BASEEXT).x
+ ]);
+
+ push(@files, $self->catfile('$(INST_ARCHAUTODIR)','extralibs.all'));
+ push(@files, $self->catfile('$(INST_ARCHAUTODIR)','extralibs.ld'));
+
+ # core files
+ push(@files, qw[core core.*perl.*.? *perl.core]);
+ push(@files, map { "core." . "[0-9]"x$_ } (1..5));
+
+ # OS specific things to clean up. Use @dirs since we don't know
+ # what might be in here.
+ push @dirs, $self->extra_clean_files;
+
+ # Occasionally files are repeated several times from different sources
+ { my(%f) = map { ($_ => 1) } @files; @files = keys %f; }
+ { my(%d) = map { ($_ => 1) } @dirs; @dirs = keys %d; }
+
+ push @m, map "\t$_\n", $self->split_command('- $(RM_F)', @files);
+ push @m, map "\t$_\n", $self->split_command('- $(RM_RF)', @dirs);
+
+ # Leave Makefile.old around for realclean
+ push @m, <<'MAKE';
+ - $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) $(DEV_NULL)
+MAKE
+
+ push(@m, "\t$attribs{POSTOP}\n") if $attribs{POSTOP};
+
+ join("", @m);
+}
+
+
+=head3 clean_subdirs_target
+
+ my $make_frag = $MM->clean_subdirs_target;
+
+Returns the clean_subdirs target. This is used by the clean target to
+call clean on any subdirectories which contain Makefiles.
+
+=cut
+
+sub clean_subdirs_target {
+ my($self) = shift;
+
+ # No subdirectories, no cleaning.
+ return <<'NOOP_FRAG' unless @{$self->{DIR}};
+clean_subdirs :
+ $(NOECHO) $(NOOP)
+NOOP_FRAG
+
+
+ my $clean = "clean_subdirs :\n";
+
+ for my $dir (@{$self->{DIR}}) {
+ my $subclean = $self->oneliner(sprintf <<'CODE', $dir);
+chdir '%s'; system '$(MAKE) clean' if -f '$(FIRST_MAKEFILE)';
+CODE
+
+ $clean .= "\t$subclean\n";
+ }
+
+ return $clean;
+}
+
+
+=head3 dir_target
+
+ my $make_frag = $mm->dir_target(@directories);
+
+Generates targets to create the specified directories and set its
+permission to PERM_DIR.
+
+Because depending on a directory to just ensure it exists doesn't work
+too well (the modified time changes too often) dir_target() creates a
+.exists file in the created directory. It is this you should depend on.
+For portability purposes you should use the $(DIRFILESEP) macro rather
+than a '/' to seperate the directory from the file.
+
+ yourdirectory$(DIRFILESEP).exists
+
+=cut
+
+sub dir_target {
+ my($self, @dirs) = @_;
+
+ my $make = '';
+ foreach my $dir (@dirs) {
+ $make .= sprintf <<'MAKE', ($dir) x 7;
+%s$(DFSEP).exists :: Makefile.PL
+ $(NOECHO) $(MKPATH) %s
+ $(NOECHO) $(CHMOD) $(PERM_DIR) %s
+ $(NOECHO) $(TOUCH) %s$(DFSEP).exists
+
+MAKE
+
+ }
+
+ return $make;
+}
+
+
+=head3 distdir
+
+Defines the scratch directory target that will hold the distribution
+before tar-ing (or shar-ing).
+
+=cut
+
+# For backwards compatibility.
+*dist_dir = *distdir;
+
+sub distdir {
+ my($self) = shift;
+
+ my $meta_target = $self->{NO_META} ? '' : 'distmeta';
+ my $sign_target = !$self->{SIGN} ? '' : 'distsignature';
+
+ return sprintf <<'MAKE_FRAG', $meta_target, $sign_target;
+create_distdir :
+ $(RM_RF) $(DISTVNAME)
+ $(PERLRUN) "-MExtUtils::Manifest=manicopy,maniread" \
+ -e "manicopy(maniread(),'$(DISTVNAME)', '$(DIST_CP)');"
+
+distdir : create_distdir %s %s
+ $(NOECHO) $(NOOP)
+
+MAKE_FRAG
+
+}
+
+
+=head3 dist_test
+
+Defines a target that produces the distribution in the
+scratchdirectory, and runs 'perl Makefile.PL; make ;make test' in that
+subdirectory.
+
+=cut
+
+sub dist_test {
+ my($self) = shift;
+
+ my $mpl_args = join " ", map qq["$_"], @ARGV;
+
+ my $test = $self->cd('$(DISTVNAME)',
+ '$(ABSPERLRUN) Makefile.PL '.$mpl_args,
+ '$(MAKE) $(PASTHRU)',
+ '$(MAKE) test $(PASTHRU)'
+ );
+
+ return sprintf <<'MAKE_FRAG', $test;
+disttest : distdir
+ %s
+
+MAKE_FRAG
+
+
+}
+
+
+=head3 dynamic (o)
+
+Defines the dynamic target.
+
+=cut
+
+sub dynamic {
+# --- Dynamic Loading Sections ---
+
+ my($self) = shift;
+ '
+dynamic :: $(FIRST_MAKEFILE) $(INST_DYNAMIC) $(INST_BOOT)
+ $(NOECHO) $(NOOP)
+';
+}
+
+
+=head3 makemakerdflt_target
+
+ my $make_frag = $mm->makemakerdflt_target
+
+Returns a make fragment with the makemakerdeflt_target specified.
+This target is the first target in the Makefile, is the default target
+and simply points off to 'all' just in case any make variant gets
+confused or something gets snuck in before the real 'all' target.
+
+=cut
+
+sub makemakerdflt_target {
+ return <<'MAKE_FRAG';
+makemakerdflt : all
+ $(NOECHO) $(NOOP)
+MAKE_FRAG
+
+}
+
+
+=head3 manifypods_target
+
+ my $manifypods_target = $self->manifypods_target;
+
+Generates the manifypods target. This target generates man pages from
+all POD files in MAN1PODS and MAN3PODS.
+
+=cut
+
+sub manifypods_target {
+ my($self) = shift;
+
+ my $man1pods = '';
+ my $man3pods = '';
+ my $dependencies = '';
+
+ # populate manXpods & dependencies:
+ foreach my $name (keys %{$self->{MAN1PODS}}, keys %{$self->{MAN3PODS}}) {
+ $dependencies .= " \\\n\t$name";
+ }
+
+ my $manify = <<END;
+manifypods : pure_all $dependencies
+END
+
+ my @man_cmds;
+ foreach my $section (qw(1 3)) {
+ my $pods = $self->{"MAN${section}PODS"};
+ push @man_cmds, $self->split_command(<<CMD, %$pods);
+ \$(NOECHO) \$(POD2MAN) --section=$section --perm_rw=\$(PERM_RW)
+CMD
+ }
+
+ $manify .= "\t\$(NOECHO) \$(NOOP)\n" unless @man_cmds;
+ $manify .= join '', map { "$_\n" } @man_cmds;
+
+ return $manify;
+}
+
+
+=head3 metafile_target
+
+ my $target = $mm->metafile_target;
+
+Generate the metafile target.
+
+Writes the file META.yml YAML encoded meta-data about the module in
+the distdir. The format follows Module::Build's as closely as
+possible.
+
+=cut
+
+sub metafile_target {
+ my $self = shift;
+
+ return <<'MAKE_FRAG' if $self->{NO_META};
+metafile :
+ $(NOECHO) $(NOOP)
+MAKE_FRAG
+
+ my @metadata = $self->metafile_data(
+ $self->{META_ADD} || {},
+ $self->{META_MERGE} || {},
+ );
+ my $meta = $self->metafile_file(@metadata);
+ my @write_meta = $self->echo($meta, 'META_new.yml');
+
+ return sprintf <<'MAKE_FRAG', join("\n\t", @write_meta);
+metafile : create_distdir
+ $(NOECHO) $(ECHO) Generating META.yml
+ %s
+ -$(NOECHO) $(MV) META_new.yml $(DISTVNAME)/META.yml
+MAKE_FRAG
+
+}
+
+
+=begin private
+
+=head3 _sort_pairs
+
+ my @pairs = _sort_pairs($sort_sub, \%hash);
+
+Sorts the pairs of a hash based on keys ordered according
+to C<$sort_sub>.
+
+=end private
+
+=cut
+
+sub _sort_pairs {
+ my $sort = shift;
+ my $pairs = shift;
+ return map { $_ => $pairs->{$_} }
+ sort $sort
+ keys %$pairs;
+}
+
+
+# Taken from Module::Build::Base
+sub _hash_merge {
+ my ($self, $h, $k, $v) = @_;
+ if (ref $h->{$k} eq 'ARRAY') {
+ push @{$h->{$k}}, ref $v ? @$v : $v;
+ } elsif (ref $h->{$k} eq 'HASH') {
+ $self->_hash_merge($h->{$k}, $_, $v->{$_}) foreach keys %$v;
+ } else {
+ $h->{$k} = $v;
+ }
+}
+
+
+=head3 metafile_data
+
+ my @metadata_pairs = $mm->metafile_data(\%meta_add, \%meta_merge);
+
+Returns the data which MakeMaker turns into the META.yml file.
+
+Values of %meta_add will overwrite any existing metadata in those
+keys. %meta_merge will be merged with them.
+
+=cut
+
+sub metafile_data {
+ my $self = shift;
+ my($meta_add, $meta_merge) = @_;
+
+ # The order in which standard meta keys should be written.
+ my @meta_order = qw(
+ name
+ version
+ abstract
+ author
+ license
+ distribution_type
+
+ configure_requires
+ build_requires
+ requires
+
+ resources
+
+ provides
+ no_index
+
+ generated_by
+ meta-spec
+ );
+
+ # Check the original args so we can tell between the user setting it
+ # to an empty hash and it just being initialized.
+ my $configure_requires;
+ if( $self->{ARGS}{CONFIGURE_REQUIRES} ) {
+ $configure_requires = $self->{CONFIGURE_REQUIRES};
+ } else {
+ $configure_requires = {
+ 'ExtUtils::MakeMaker' => 0,
+ };
+ }
+ my $build_requires;
+ if( $self->{ARGS}{BUILD_REQUIRES} ) {
+ $build_requires = $self->{BUILD_REQUIRES};
+ } else {
+ $build_requires = {
+ 'ExtUtils::MakeMaker' => 0,
+ };
+ }
+
+ my %meta = (
+ name => $self->{DISTNAME},
+ version => $self->{VERSION},
+ abstract => $self->{ABSTRACT},
+ license => $self->{LICENSE} || 'unknown',
+ distribution_type => $self->{PM} ? 'module' : 'script',
+
+ configure_requires => $configure_requires,
+
+ build_requires => $build_requires,
+
+ no_index => {
+ directory => [qw(t inc)]
+ },
+
+ generated_by => "ExtUtils::MakeMaker version $ExtUtils::MakeMaker::VERSION",
+ 'meta-spec' => {
+ url => 'http://module-build.sourceforge.net/META-spec-v1.4.html',
+ version => 1.4
+ },
+ );
+
+ # The author key is required and it takes a list.
+ $meta{author} = defined $self->{AUTHOR} ? [$self->{AUTHOR}] : [];
+
+ $meta{requires} = $self->{PREREQ_PM} if defined $self->{PREREQ_PM};
+ $meta{requires}{perl} = $self->{MIN_PERL_VERSION} if $self->{MIN_PERL_VERSION};
+
+ while( my($key, $val) = each %$meta_add ) {
+ $meta{$key} = $val;
+ }
+
+ while( my($key, $val) = each %$meta_merge ) {
+ $self->_hash_merge(\%meta, $key, $val);
+ }
+
+ my @meta_pairs;
+
+ # Put the standard keys first in the proper order.
+ for my $key (@meta_order) {
+ next unless exists $meta{$key};
+
+ push @meta_pairs, $key, delete $meta{$key};
+ }
+
+ # Then tack everything else onto the end, alpha sorted.
+ for my $key (sort {lc $a cmp lc $b} keys %meta) {
+ push @meta_pairs, $key, $meta{$key};
+ }
+
+ return @meta_pairs
+}
+
+=begin private
+
+=head3 _dump_hash
+
+ $yaml = _dump_hash(\%options, %hash);
+
+Implements a fake YAML dumper for a hash given
+as a list of pairs. No quoting/escaping is done. Keys
+are supposed to be strings. Values are undef, strings,
+hash refs or array refs of strings.
+
+Supported options are:
+
+ delta => STR - indentation delta
+ use_header => BOOL - whether to include a YAML header
+ indent => STR - a string of spaces
+ default: ''
+
+ max_key_length => INT - maximum key length used to align
+ keys and values of the same hash
+ default: 20
+ key_sort => CODE - a sort sub
+ It may be undef, which means no sorting by keys
+ default: sub { lc $a cmp lc $b }
+
+ customs => HASH - special options for certain keys
+ (whose values are hashes themselves)
+ may contain: max_key_length, key_sort, customs
+
+=end private
+
+=cut
+
+sub _dump_hash {
+ croak "first argument should be a hash ref" unless ref $_[0] eq 'HASH';
+ my $options = shift;
+ my %hash = @_;
+
+ # Use a list to preserve order.
+ my @pairs;
+
+ my $k_sort
+ = exists $options->{key_sort} ? $options->{key_sort}
+ : sub { lc $a cmp lc $b };
+ if ($k_sort) {
+ croak "'key_sort' should be a coderef" unless ref $k_sort eq 'CODE';
+ @pairs = _sort_pairs($k_sort, \%hash);
+ } else { # list of pairs, no sorting
+ @pairs = @_;
+ }
+
+ my $yaml = $options->{use_header} ? "--- #YAML:1.0\n" : '';
+ my $indent = $options->{indent} || '';
+ my $k_length = min(
+ ($options->{max_key_length} || 20),
+ max(map { length($_) + 1 } grep { !ref $hash{$_} } keys %hash)
+ );
+ my $customs = $options->{customs} || {};
+
+ # printf format for key
+ my $k_format = "%-${k_length}s";
+
+ while( @pairs ) {
+ my($key, $val) = splice @pairs, 0, 2;
+ $val = '~' unless defined $val;
+ if(ref $val eq 'HASH') {
+ if ( keys %$val ) {
+ my %k_options = ( # options for recursive call
+ delta => $options->{delta},
+ use_header => 0,
+ indent => $indent . $options->{delta},
+ );
+ if (exists $customs->{$key}) {
+ my %k_custom = %{$customs->{$key}};
+ foreach my $k qw(key_sort max_key_length customs) {
+ $k_options{$k} = $k_custom{$k} if exists $k_custom{$k};
+ }
+ }
+ $yaml .= $indent . "$key:\n"
+ . _dump_hash(\%k_options, %$val);
+ }
+ else {
+ $yaml .= $indent . "$key: {}\n";
+ }
+ }
+ elsif (ref $val eq 'ARRAY') {
+ if( @$val ) {
+ $yaml .= $indent . "$key:\n";
+
+ for (@$val) {
+ croak "only nested arrays of non-refs are supported" if ref $_;
+ $yaml .= $indent . $options->{delta} . "- $_\n";
+ }
+ }
+ else {
+ $yaml .= $indent . "$key: []\n";
+ }
+ }
+ elsif( ref $val and !blessed($val) ) {
+ croak "only nested hashes, arrays and objects are supported";
+ }
+ else { # if it's an object, just stringify it
+ $yaml .= $indent . sprintf "$k_format %s\n", "$key:", $val;
+ }
+ };
+
+ return $yaml;
+
+}
+
+sub blessed {
+ return eval { $_[0]->isa("UNIVERSAL"); };
+}
+
+sub max {
+ return (sort { $b <=> $a } @_)[0];
+}
+
+sub min {
+ return (sort { $a <=> $b } @_)[0];
+}
+
+=head3 metafile_file
+
+ my $meta_yml = $mm->metafile_file(@metadata_pairs);
+
+Turns the @metadata_pairs into YAML.
+
+This method does not implement a complete YAML dumper, being limited
+to dump a hash with values which are strings, undef's or nested hashes
+and arrays of strings. No quoting/escaping is done.
+
+=cut
+
+sub metafile_file {
+ my $self = shift;
+
+ my %dump_options = (
+ use_header => 1,
+ delta => ' ' x 4,
+ key_sort => undef,
+ );
+ return _dump_hash(\%dump_options, @_);
+
+}
+
+
+=head3 distmeta_target
+
+ my $make_frag = $mm->distmeta_target;
+
+Generates the distmeta target to add META.yml to the MANIFEST in the
+distdir.
+
+=cut
+
+sub distmeta_target {
+ my $self = shift;
+
+ my $add_meta = $self->oneliner(<<'CODE', ['-MExtUtils::Manifest=maniadd']);
+eval { maniadd({q{META.yml} => q{Module meta-data (added by MakeMaker)}}) }
+ or print "Could not add META.yml to MANIFEST: $${'@'}\n"
+CODE
+
+ my $add_meta_to_distdir = $self->cd('$(DISTVNAME)', $add_meta);
+
+ return sprintf <<'MAKE', $add_meta_to_distdir;
+distmeta : create_distdir metafile
+ $(NOECHO) %s
+
+MAKE
+
+}
+
+
+=head3 realclean (o)
+
+Defines the realclean target.
+
+=cut
+
+sub realclean {
+ my($self, %attribs) = @_;
+
+ my @dirs = qw($(DISTVNAME));
+ my @files = qw($(FIRST_MAKEFILE) $(MAKEFILE_OLD));
+
+ # Special exception for the perl core where INST_* is not in blib.
+ # This cleans up the files built from the ext/ directory (all XS).
+ if( $self->{PERL_CORE} ) {
+ push @dirs, qw($(INST_AUTODIR) $(INST_ARCHAUTODIR));
+ push @files, values %{$self->{PM}};
+ }
+
+ if( $self->has_link_code ){
+ push @files, qw($(OBJECT));
+ }
+
+ if( $attribs{FILES} ) {
+ if( ref $attribs{FILES} ) {
+ push @dirs, @{ $attribs{FILES} };
+ }
+ else {
+ push @dirs, split /\s+/, $attribs{FILES};
+ }
+ }
+
+ # Occasionally files are repeated several times from different sources
+ { my(%f) = map { ($_ => 1) } @files; @files = keys %f; }
+ { my(%d) = map { ($_ => 1) } @dirs; @dirs = keys %d; }
+
+ my $rm_cmd = join "\n\t", map { "$_" }
+ $self->split_command('- $(RM_F)', @files);
+ my $rmf_cmd = join "\n\t", map { "$_" }
+ $self->split_command('- $(RM_RF)', @dirs);
+
+ my $m = sprintf <<'MAKE', $rm_cmd, $rmf_cmd;
+# Delete temporary files (via clean) and also delete dist files
+realclean purge :: clean realclean_subdirs
+ %s
+ %s
+MAKE
+
+ $m .= "\t$attribs{POSTOP}\n" if $attribs{POSTOP};
+
+ return $m;
+}
+
+
+=head3 realclean_subdirs_target
+
+ my $make_frag = $MM->realclean_subdirs_target;
+
+Returns the realclean_subdirs target. This is used by the realclean
+target to call realclean on any subdirectories which contain Makefiles.
+
+=cut
+
+sub realclean_subdirs_target {
+ my $self = shift;
+
+ return <<'NOOP_FRAG' unless @{$self->{DIR}};
+realclean_subdirs :
+ $(NOECHO) $(NOOP)
+NOOP_FRAG
+
+ my $rclean = "realclean_subdirs :\n";
+
+ foreach my $dir (@{$self->{DIR}}) {
+ foreach my $makefile ('$(MAKEFILE_OLD)', '$(FIRST_MAKEFILE)' ) {
+ my $subrclean .= $self->oneliner(sprintf <<'CODE', $dir, ($makefile) x 2);
+chdir '%s'; system '$(MAKE) $(USEMAKEFILE) %s realclean' if -f '%s';
+CODE
+
+ $rclean .= sprintf <<'RCLEAN', $subrclean;
+ - %s
+RCLEAN
+
+ }
+ }
+
+ return $rclean;
+}
+
+
+=head3 signature_target
+
+ my $target = $mm->signature_target;
+
+Generate the signature target.
+
+Writes the file SIGNATURE with "cpansign -s".
+
+=cut
+
+sub signature_target {
+ my $self = shift;
+
+ return <<'MAKE_FRAG';
+signature :
+ cpansign -s
+MAKE_FRAG
+
+}
+
+
+=head3 distsignature_target
+
+ my $make_frag = $mm->distsignature_target;
+
+Generates the distsignature target to add SIGNATURE to the MANIFEST in the
+distdir.
+
+=cut
+
+sub distsignature_target {
+ my $self = shift;
+
+ my $add_sign = $self->oneliner(<<'CODE', ['-MExtUtils::Manifest=maniadd']);
+eval { maniadd({q{SIGNATURE} => q{Public-key signature (added by MakeMaker)}}) }
+ or print "Could not add SIGNATURE to MANIFEST: $${'@'}\n"
+CODE
+
+ my $sign_dist = $self->cd('$(DISTVNAME)' => 'cpansign -s');
+
+ # cpansign -s complains if SIGNATURE is in the MANIFEST yet does not
+ # exist
+ my $touch_sig = $self->cd('$(DISTVNAME)' => '$(TOUCH) SIGNATURE');
+ my $add_sign_to_dist = $self->cd('$(DISTVNAME)' => $add_sign );
+
+ return sprintf <<'MAKE', $add_sign_to_dist, $touch_sig, $sign_dist
+distsignature : create_distdir
+ $(NOECHO) %s
+ $(NOECHO) %s
+ %s
+
+MAKE
+
+}
+
+
+=head3 special_targets
+
+ my $make_frag = $mm->special_targets
+
+Returns a make fragment containing any targets which have special
+meaning to make. For example, .SUFFIXES and .PHONY.
+
+=cut
+
+sub special_targets {
+ my $make_frag = <<'MAKE_FRAG';
+.SUFFIXES : .xs .c .C .cpp .i .s .cxx .cc $(OBJ_EXT)
+
+.PHONY: all config static dynamic test linkext manifest blibdirs clean realclean disttest distdir
+
+MAKE_FRAG
+
+ $make_frag .= <<'MAKE_FRAG' if $ENV{CLEARCASE_ROOT};
+.NO_CONFIG_REC: Makefile
+
+MAKE_FRAG
+
+ return $make_frag;
+}
+
+
+
+
+=head2 Init methods
+
+Methods which help initialize the MakeMaker object and macros.
+
+
+=head3 init_ABSTRACT
+
+ $mm->init_ABSTRACT
+
+=cut
+
+sub init_ABSTRACT {
+ my $self = shift;
+
+ if( $self->{ABSTRACT_FROM} and $self->{ABSTRACT} ) {
+ warn "Both ABSTRACT_FROM and ABSTRACT are set. ".
+ "Ignoring ABSTRACT_FROM.\n";
+ return;
+ }
+
+ if ($self->{ABSTRACT_FROM}){
+ $self->{ABSTRACT} = $self->parse_abstract($self->{ABSTRACT_FROM}) or
+ carp "WARNING: Setting ABSTRACT via file ".
+ "'$self->{ABSTRACT_FROM}' failed\n";
+ }
+}
+
+=head3 init_INST
+
+ $mm->init_INST;
+
+Called by init_main. Sets up all INST_* variables except those related
+to XS code. Those are handled in init_xs.
+
+=cut
+
+sub init_INST {
+ my($self) = shift;
+
+ $self->{INST_ARCHLIB} ||= $self->catdir($Curdir,"blib","arch");
+ $self->{INST_BIN} ||= $self->catdir($Curdir,'blib','bin');
+
+ # INST_LIB typically pre-set if building an extension after
+ # perl has been built and installed. Setting INST_LIB allows
+ # you to build directly into, say $Config{privlibexp}.
+ unless ($self->{INST_LIB}){
+ if ($self->{PERL_CORE}) {
+ if (defined $Cross::platform) {
+ $self->{INST_LIB} = $self->{INST_ARCHLIB} =
+ $self->catdir($self->{PERL_LIB},"..","xlib",
+ $Cross::platform);
+ }
+ else {
+ $self->{INST_LIB} = $self->{INST_ARCHLIB} = $self->{PERL_LIB};
+ }
+ } else {
+ $self->{INST_LIB} = $self->catdir($Curdir,"blib","lib");
+ }
+ }
+
+ my @parentdir = split(/::/, $self->{PARENT_NAME});
+ $self->{INST_LIBDIR} = $self->catdir('$(INST_LIB)', @parentdir);
+ $self->{INST_ARCHLIBDIR} = $self->catdir('$(INST_ARCHLIB)', @parentdir);
+ $self->{INST_AUTODIR} = $self->catdir('$(INST_LIB)', 'auto',
+ '$(FULLEXT)');
+ $self->{INST_ARCHAUTODIR} = $self->catdir('$(INST_ARCHLIB)', 'auto',
+ '$(FULLEXT)');
+
+ $self->{INST_SCRIPT} ||= $self->catdir($Curdir,'blib','script');
+
+ $self->{INST_MAN1DIR} ||= $self->catdir($Curdir,'blib','man1');
+ $self->{INST_MAN3DIR} ||= $self->catdir($Curdir,'blib','man3');
+
+ return 1;
+}
+
+
+=head3 init_INSTALL
+
+ $mm->init_INSTALL;
+
+Called by init_main. Sets up all INSTALL_* variables (except
+INSTALLDIRS) and *PREFIX.
+
+=cut
+
+sub init_INSTALL {
+ my($self) = shift;
+
+ if( $self->{ARGS}{INSTALL_BASE} and $self->{ARGS}{PREFIX} ) {
+ die "Only one of PREFIX or INSTALL_BASE can be given. Not both.\n";
+ }
+
+ if( $self->{ARGS}{INSTALL_BASE} ) {
+ $self->init_INSTALL_from_INSTALL_BASE;
+ }
+ else {
+ $self->init_INSTALL_from_PREFIX;
+ }
+}
+
+
+=head3 init_INSTALL_from_PREFIX
+
+ $mm->init_INSTALL_from_PREFIX;
+
+=cut
+
+sub init_INSTALL_from_PREFIX {
+ my $self = shift;
+
+ $self->init_lib2arch;
+
+ # There are often no Config.pm defaults for these new man variables so
+ # we fall back to the old behavior which is to use installman*dir
+ foreach my $num (1, 3) {
+ my $k = 'installsiteman'.$num.'dir';
+
+ $self->{uc $k} ||= uc "\$(installman${num}dir)"
+ unless $Config{$k};
+ }
+
+ foreach my $num (1, 3) {
+ my $k = 'installvendorman'.$num.'dir';
+
+ unless( $Config{$k} ) {
+ $self->{uc $k} ||= $Config{usevendorprefix}
+ ? uc "\$(installman${num}dir)"
+ : '';
+ }
+ }
+
+ $self->{INSTALLSITEBIN} ||= '$(INSTALLBIN)'
+ unless $Config{installsitebin};
+ $self->{INSTALLSITESCRIPT} ||= '$(INSTALLSCRIPT)'
+ unless $Config{installsitescript};
+
+ unless( $Config{installvendorbin} ) {
+ $self->{INSTALLVENDORBIN} ||= $Config{usevendorprefix}
+ ? $Config{installbin}
+ : '';
+ }
+ unless( $Config{installvendorscript} ) {
+ $self->{INSTALLVENDORSCRIPT} ||= $Config{usevendorprefix}
+ ? $Config{installscript}
+ : '';
+ }
+
+
+ my $iprefix = $Config{installprefixexp} || $Config{installprefix} ||
+ $Config{prefixexp} || $Config{prefix} || '';
+ my $vprefix = $Config{usevendorprefix} ? $Config{vendorprefixexp} : '';
+ my $sprefix = $Config{siteprefixexp} || '';
+
+ # 5.005_03 doesn't have a siteprefix.
+ $sprefix = $iprefix unless $sprefix;
+
+
+ $self->{PREFIX} ||= '';
+
+ if( $self->{PREFIX} ) {
+ @{$self}{qw(PERLPREFIX SITEPREFIX VENDORPREFIX)} =
+ ('$(PREFIX)') x 3;
+ }
+ else {
+ $self->{PERLPREFIX} ||= $iprefix;
+ $self->{SITEPREFIX} ||= $sprefix;
+ $self->{VENDORPREFIX} ||= $vprefix;
+
+ # Lots of MM extension authors like to use $(PREFIX) so we
+ # put something sensible in there no matter what.
+ $self->{PREFIX} = '$('.uc $self->{INSTALLDIRS}.'PREFIX)';
+ }
+
+ my $arch = $Config{archname};
+ my $version = $Config{version};
+
+ # default style
+ my $libstyle = $Config{installstyle} || 'lib/perl5';
+ my $manstyle = '';
+
+ if( $self->{LIBSTYLE} ) {
+ $libstyle = $self->{LIBSTYLE};
+ $manstyle = $self->{LIBSTYLE} eq 'lib/perl5' ? 'lib/perl5' : '';
+ }
+
+ # Some systems, like VOS, set installman*dir to '' if they can't
+ # read man pages.
+ for my $num (1, 3) {
+ $self->{'INSTALLMAN'.$num.'DIR'} ||= 'none'
+ unless $Config{'installman'.$num.'dir'};
+ }
+
+ my %bin_layouts =
+ (
+ bin => { s => $iprefix,
+ t => 'perl',
+ d => 'bin' },
+ vendorbin => { s => $vprefix,
+ t => 'vendor',
+ d => 'bin' },
+ sitebin => { s => $sprefix,
+ t => 'site',
+ d => 'bin' },
+ script => { s => $iprefix,
+ t => 'perl',
+ d => 'bin' },
+ vendorscript=> { s => $vprefix,
+ t => 'vendor',
+ d => 'bin' },
+ sitescript => { s => $sprefix,
+ t => 'site',
+ d => 'bin' },
+ );
+
+ my %man_layouts =
+ (
+ man1dir => { s => $iprefix,
+ t => 'perl',
+ d => 'man/man1',
+ style => $manstyle, },
+ siteman1dir => { s => $sprefix,
+ t => 'site',
+ d => 'man/man1',
+ style => $manstyle, },
+ vendorman1dir => { s => $vprefix,
+ t => 'vendor',
+ d => 'man/man1',
+ style => $manstyle, },
+
+ man3dir => { s => $iprefix,
+ t => 'perl',
+ d => 'man/man3',
+ style => $manstyle, },
+ siteman3dir => { s => $sprefix,
+ t => 'site',
+ d => 'man/man3',
+ style => $manstyle, },
+ vendorman3dir => { s => $vprefix,
+ t => 'vendor',
+ d => 'man/man3',
+ style => $manstyle, },
+ );
+
+ my %lib_layouts =
+ (
+ privlib => { s => $iprefix,
+ t => 'perl',
+ d => '',
+ style => $libstyle, },
+ vendorlib => { s => $vprefix,
+ t => 'vendor',
+ d => '',
+ style => $libstyle, },
+ sitelib => { s => $sprefix,
+ t => 'site',
+ d => 'site_perl',
+ style => $libstyle, },
+
+ archlib => { s => $iprefix,
+ t => 'perl',
+ d => "$version/$arch",
+ style => $libstyle },
+ vendorarch => { s => $vprefix,
+ t => 'vendor',
+ d => "$version/$arch",
+ style => $libstyle },
+ sitearch => { s => $sprefix,
+ t => 'site',
+ d => "site_perl/$version/$arch",
+ style => $libstyle },
+ );
+
+
+ # Special case for LIB.
+ if( $self->{LIB} ) {
+ foreach my $var (keys %lib_layouts) {
+ my $Installvar = uc "install$var";
+
+ if( $var =~ /arch/ ) {
+ $self->{$Installvar} ||=
+ $self->catdir($self->{LIB}, $Config{archname});
+ }
+ else {
+ $self->{$Installvar} ||= $self->{LIB};
+ }
+ }
+ }
+
+ my %type2prefix = ( perl => 'PERLPREFIX',
+ site => 'SITEPREFIX',
+ vendor => 'VENDORPREFIX'
+ );
+
+ my %layouts = (%bin_layouts, %man_layouts, %lib_layouts);
+ while( my($var, $layout) = each(%layouts) ) {
+ my($s, $t, $d, $style) = @{$layout}{qw(s t d style)};
+ my $r = '$('.$type2prefix{$t}.')';
+
+ print STDERR "Prefixing $var\n" if $Verbose >= 2;
+
+ my $installvar = "install$var";
+ my $Installvar = uc $installvar;
+ next if $self->{$Installvar};
+
+ $d = "$style/$d" if $style;
+ $self->prefixify($installvar, $s, $r, $d);
+
+ print STDERR " $Installvar == $self->{$Installvar}\n"
+ if $Verbose >= 2;
+ }
+
+ # Generate these if they weren't figured out.
+ $self->{VENDORARCHEXP} ||= $self->{INSTALLVENDORARCH};
+ $self->{VENDORLIBEXP} ||= $self->{INSTALLVENDORLIB};
+
+ return 1;
+}
+
+
+=head3 init_from_INSTALL_BASE
+
+ $mm->init_from_INSTALL_BASE
+
+=cut
+
+my %map = (
+ lib => [qw(lib perl5)],
+ arch => [('lib', 'perl5', $Config{archname})],
+ bin => [qw(bin)],
+ man1dir => [qw(man man1)],
+ man3dir => [qw(man man3)]
+ );
+$map{script} = $map{bin};
+
+sub init_INSTALL_from_INSTALL_BASE {
+ my $self = shift;
+
+ @{$self}{qw(PREFIX VENDORPREFIX SITEPREFIX PERLPREFIX)} =
+ '$(INSTALL_BASE)';
+
+ my %install;
+ foreach my $thing (keys %map) {
+ foreach my $dir (('', 'SITE', 'VENDOR')) {
+ my $uc_thing = uc $thing;
+ my $key = "INSTALL".$dir.$uc_thing;
+
+ $install{$key} ||=
+ $self->catdir('$(INSTALL_BASE)', @{$map{$thing}});
+ }
+ }
+
+ # Adjust for variable quirks.
+ $install{INSTALLARCHLIB} ||= delete $install{INSTALLARCH};
+ $install{INSTALLPRIVLIB} ||= delete $install{INSTALLLIB};
+
+ foreach my $key (keys %install) {
+ $self->{$key} ||= $install{$key};
+ }
+
+ return 1;
+}
+
+
+=head3 init_VERSION I<Abstract>
+
+ $mm->init_VERSION
+
+Initialize macros representing versions of MakeMaker and other tools
+
+MAKEMAKER: path to the MakeMaker module.
+
+MM_VERSION: ExtUtils::MakeMaker Version
+
+MM_REVISION: ExtUtils::MakeMaker version control revision (for backwards
+ compat)
+
+VERSION: version of your module
+
+VERSION_MACRO: which macro represents the version (usually 'VERSION')
+
+VERSION_SYM: like version but safe for use as an RCS revision number
+
+DEFINE_VERSION: -D line to set the module version when compiling
+
+XS_VERSION: version in your .xs file. Defaults to $(VERSION)
+
+XS_VERSION_MACRO: which macro represents the XS version.
+
+XS_DEFINE_VERSION: -D line to set the xs version when compiling.
+
+Called by init_main.
+
+=cut
+
+sub init_VERSION {
+ my($self) = shift;
+
+ $self->{MAKEMAKER} = $ExtUtils::MakeMaker::Filename;
+ $self->{MM_VERSION} = $ExtUtils::MakeMaker::VERSION;
+ $self->{MM_REVISION}= $ExtUtils::MakeMaker::Revision;
+ $self->{VERSION_FROM} ||= '';
+
+ if ($self->{VERSION_FROM}){
+ $self->{VERSION} = $self->parse_version($self->{VERSION_FROM});
+ if( $self->{VERSION} eq 'undef' ) {
+ carp("WARNING: Setting VERSION via file ".
+ "'$self->{VERSION_FROM}' failed\n");
+ }
+ }
+
+ # strip blanks
+ if (defined $self->{VERSION}) {
+ $self->{VERSION} =~ s/^\s+//;
+ $self->{VERSION} =~ s/\s+$//;
+ }
+ else {
+ $self->{VERSION} = '';
+ }
+
+
+ $self->{VERSION_MACRO} = 'VERSION';
+ ($self->{VERSION_SYM} = $self->{VERSION}) =~ s/\W/_/g;
+ $self->{DEFINE_VERSION} = '-D$(VERSION_MACRO)=\"$(VERSION)\"';
+
+
+ # Graham Barr and Paul Marquess had some ideas how to ensure
+ # version compatibility between the *.pm file and the
+ # corresponding *.xs file. The bottomline was, that we need an
+ # XS_VERSION macro that defaults to VERSION:
+ $self->{XS_VERSION} ||= $self->{VERSION};
+
+ $self->{XS_VERSION_MACRO} = 'XS_VERSION';
+ $self->{XS_DEFINE_VERSION} = '-D$(XS_VERSION_MACRO)=\"$(XS_VERSION)\"';
+
+}
+
+
+=head3 init_others
+
+ $MM->init_others();
+
+Initializes the macro definitions used by tools_other() and places them
+in the $MM object.
+
+If there is no description, its the same as the parameter to
+WriteMakefile() documented in ExtUtils::MakeMaker.
+
+Defines at least these macros.
+
+ Macro Description
+
+ NOOP Do nothing
+ NOECHO Tell make not to display the command itself
+
+ MAKEFILE
+ FIRST_MAKEFILE
+ MAKEFILE_OLD
+ MAKE_APERL_FILE File used by MAKE_APERL
+
+ SHELL Program used to run shell commands
+
+ ECHO Print text adding a newline on the end
+ RM_F Remove a file
+ RM_RF Remove a directory
+ TOUCH Update a file's timestamp
+ TEST_F Test for a file's existence
+ CP Copy a file
+ MV Move a file
+ CHMOD Change permissions on a file
+ FALSE Exit with non-zero
+ TRUE Exit with zero
+
+ UMASK_NULL Nullify umask
+ DEV_NULL Suppress all command output
+
+=cut
+
+sub init_others {
+ my $self = shift;
+
+ $self->{ECHO} ||= $self->oneliner('print qq{@ARGV}', ['-l']);
+ $self->{ECHO_N} ||= $self->oneliner('print qq{@ARGV}');
+
+ $self->{TOUCH} ||= $self->oneliner('touch', ["-MExtUtils::Command"]);
+ $self->{CHMOD} ||= $self->oneliner('chmod', ["-MExtUtils::Command"]);
+ $self->{RM_F} ||= $self->oneliner('rm_f', ["-MExtUtils::Command"]);
+ $self->{RM_RF} ||= $self->oneliner('rm_rf', ["-MExtUtils::Command"]);
+ $self->{TEST_F} ||= $self->oneliner('test_f', ["-MExtUtils::Command"]);
+ $self->{FALSE} ||= $self->oneliner('exit 1');
+ $self->{TRUE} ||= $self->oneliner('exit 0');
+
+ $self->{MKPATH} ||= $self->oneliner('mkpath', ["-MExtUtils::Command"]);
+
+ $self->{CP} ||= $self->oneliner('cp', ["-MExtUtils::Command"]);
+ $self->{MV} ||= $self->oneliner('mv', ["-MExtUtils::Command"]);
+
+ $self->{MOD_INSTALL} ||=
+ $self->oneliner(<<'CODE', ['-MExtUtils::Install']);
+install([ from_to => {@ARGV}, verbose => '$(VERBINST)', uninstall_shadows => '$(UNINST)', dir_mode => '$(PERM_DIR)' ]);
+CODE
+ $self->{DOC_INSTALL} ||= $self->oneliner('perllocal_install', ["-MExtUtils::Command::MM"]);
+ $self->{UNINSTALL} ||= $self->oneliner('uninstall', ["-MExtUtils::Command::MM"]);
+ $self->{WARN_IF_OLD_PACKLIST} ||=
+ $self->oneliner('warn_if_old_packlist', ["-MExtUtils::Command::MM"]);
+ $self->{FIXIN} ||= $self->oneliner('MY->fixin(shift)', ["-MExtUtils::MY"]);
+ $self->{EQUALIZE_TIMESTAMP} ||= $self->oneliner('eqtime', ["-MExtUtils::Command"]);
+
+ $self->{UNINST} ||= 0;
+ $self->{VERBINST} ||= 0;
+
+ $self->{FIRST_MAKEFILE} ||= $self->{MAKEFILE} || 'Makefile';
+ $self->{MAKEFILE} ||= $self->{FIRST_MAKEFILE};
+ $self->{MAKEFILE_OLD} ||= $self->{MAKEFILE}.'.old';
+ $self->{MAKE_APERL_FILE} ||= $self->{MAKEFILE}.'.aperl';
+
+ # Not everybody uses -f to indicate "use this Makefile instead"
+ $self->{USEMAKEFILE} ||= '-f';
+
+ # Some makes require a wrapper around macros passed in on the command
+ # line.
+ $self->{MACROSTART} ||= '';
+ $self->{MACROEND} ||= '';
+
+ $self->{SHELL} ||= $Config{sh};
+
+ # UMASK_NULL is not used by MakeMaker but some CPAN modules
+ # make use of it.
+ $self->{UMASK_NULL} ||= "umask 0";
+
+ # Not the greatest default, but its something.
+ $self->{DEV_NULL} ||= "> /dev/null 2>&1";
+
+ $self->{NOOP} ||= '$(TRUE)';
+ $self->{NOECHO} = '@' unless defined $self->{NOECHO};
+
+ $self->{LD_RUN_PATH} = "";
+
+ $self->{LIBS} = $self->_fix_libs($self->{LIBS});
+
+ # Compute EXTRALIBS, BSLOADLIBS and LDLOADLIBS from $self->{LIBS}
+ foreach my $libs ( @{$self->{LIBS}} ){
+ $libs =~ s/^\s*(.*\S)\s*$/$1/; # remove leading and trailing whitespace
+ my(@libs) = $self->extliblist($libs);
+ if ($libs[0] or $libs[1] or $libs[2]){
+ # LD_RUN_PATH now computed by ExtUtils::Liblist
+ ($self->{EXTRALIBS}, $self->{BSLOADLIBS},
+ $self->{LDLOADLIBS}, $self->{LD_RUN_PATH}) = @libs;
+ last;
+ }
+ }
+
+ if ( $self->{OBJECT} ) {
+ $self->{OBJECT} =~ s!\.o(bj)?\b!\$(OBJ_EXT)!g;
+ } else {
+ # init_dirscan should have found out, if we have C files
+ $self->{OBJECT} = "";
+ $self->{OBJECT} = '$(BASEEXT)$(OBJ_EXT)' if @{$self->{C}||[]};
+ }
+ $self->{OBJECT} =~ s/\n+/ \\\n\t/g;
+
+ $self->{BOOTDEP} = (-f "$self->{BASEEXT}_BS") ? "$self->{BASEEXT}_BS" : "";
+ $self->{PERLMAINCC} ||= '$(CC)';
+ $self->{LDFROM} = '$(OBJECT)' unless $self->{LDFROM};
+
+ # Sanity check: don't define LINKTYPE = dynamic if we're skipping
+ # the 'dynamic' section of MM. We don't have this problem with
+ # 'static', since we either must use it (%Config says we can't
+ # use dynamic loading) or the caller asked for it explicitly.
+ if (!$self->{LINKTYPE}) {
+ $self->{LINKTYPE} = $self->{SKIPHASH}{'dynamic'}
+ ? 'static'
+ : ($Config{usedl} ? 'dynamic' : 'static');
+ }
+
+ return 1;
+}
+
+
+# Lets look at $self->{LIBS} carefully: It may be an anon array, a string or
+# undefined. In any case we turn it into an anon array
+sub _fix_libs {
+ my($self, $libs) = @_;
+
+ return !defined $libs ? [''] :
+ !ref $libs ? [$libs] :
+ !defined $libs->[0] ? [''] :
+ $libs ;
+}
+
+
+=head3 tools_other
+
+ my $make_frag = $MM->tools_other;
+
+Returns a make fragment containing definitions for the macros init_others()
+initializes.
+
+=cut
+
+sub tools_other {
+ my($self) = shift;
+ my @m;
+
+ # We set PM_FILTER as late as possible so it can see all the earlier
+ # on macro-order sensitive makes such as nmake.
+ for my $tool (qw{ SHELL CHMOD CP MV NOOP NOECHO RM_F RM_RF TEST_F TOUCH
+ UMASK_NULL DEV_NULL MKPATH EQUALIZE_TIMESTAMP
+ FALSE TRUE
+ ECHO ECHO_N
+ UNINST VERBINST
+ MOD_INSTALL DOC_INSTALL UNINSTALL
+ WARN_IF_OLD_PACKLIST
+ MACROSTART MACROEND
+ USEMAKEFILE
+ PM_FILTER
+ FIXIN
+ } )
+ {
+ next unless defined $self->{$tool};
+ push @m, "$tool = $self->{$tool}\n";
+ }
+
+ return join "", @m;
+}
+
+
+=head3 init_DIRFILESEP I<Abstract>
+
+ $MM->init_DIRFILESEP;
+ my $dirfilesep = $MM->{DIRFILESEP};
+
+Initializes the DIRFILESEP macro which is the seperator between the
+directory and filename in a filepath. ie. / on Unix, \ on Win32 and
+nothing on VMS.
+
+For example:
+
+ # instead of $(INST_ARCHAUTODIR)/extralibs.ld
+ $(INST_ARCHAUTODIR)$(DIRFILESEP)extralibs.ld
+
+Something of a hack but it prevents a lot of code duplication between
+MM_* variants.
+
+Do not use this as a seperator between directories. Some operating
+systems use different seperators between subdirectories as between
+directories and filenames (for example: VOLUME:[dir1.dir2]file on VMS).
+
+=head3 init_linker I<Abstract>
+
+ $mm->init_linker;
+
+Initialize macros which have to do with linking.
+
+PERL_ARCHIVE: path to libperl.a equivalent to be linked to dynamic
+extensions.
+
+PERL_ARCHIVE_AFTER: path to a library which should be put on the
+linker command line I<after> the external libraries to be linked to
+dynamic extensions. This may be needed if the linker is one-pass, and
+Perl includes some overrides for C RTL functions, such as malloc().
+
+EXPORT_LIST: name of a file that is passed to linker to define symbols
+to be exported.
+
+Some OSes do not need these in which case leave it blank.
+
+
+=head3 init_platform
+
+ $mm->init_platform
+
+Initialize any macros which are for platform specific use only.
+
+A typical one is the version number of your OS specific mocule.
+(ie. MM_Unix_VERSION or MM_VMS_VERSION).
+
+=cut
+
+sub init_platform {
+ return '';
+}
+
+
+=head3 init_MAKE
+
+ $mm->init_MAKE
+
+Initialize MAKE from either a MAKE environment variable or $Config{make}.
+
+=cut
+
+sub init_MAKE {
+ my $self = shift;
+
+ $self->{MAKE} ||= $ENV{MAKE} || $Config{make};
+}
+
+
+=head2 Tools
+
+A grab bag of methods to generate specific macros and commands.
+
+
+
+=head3 manifypods
+
+Defines targets and routines to translate the pods into manpages and
+put them into the INST_* directories.
+
+=cut
+
+sub manifypods {
+ my $self = shift;
+
+ my $POD2MAN_macro = $self->POD2MAN_macro();
+ my $manifypods_target = $self->manifypods_target();
+
+ return <<END_OF_TARGET;
+
+$POD2MAN_macro
+
+$manifypods_target
+
+END_OF_TARGET
+
+}
+
+
+=head3 POD2MAN_macro
+
+ my $pod2man_macro = $self->POD2MAN_macro
+
+Returns a definition for the POD2MAN macro. This is a program
+which emulates the pod2man utility. You can add more switches to the
+command by simply appending them on the macro.
+
+Typical usage:
+
+ $(POD2MAN) --section=3 --perm_rw=$(PERM_RW) podfile1 man_page1 ...
+
+=cut
+
+sub POD2MAN_macro {
+ my $self = shift;
+
+# Need the trailing '--' so perl stops gobbling arguments and - happens
+# to be an alternative end of line seperator on VMS so we quote it
+ return <<'END_OF_DEF';
+POD2MAN_EXE = $(PERLRUN) "-MExtUtils::Command::MM" -e pod2man "--"
+POD2MAN = $(POD2MAN_EXE)
+END_OF_DEF
+}
+
+
+=head3 test_via_harness
+
+ my $command = $mm->test_via_harness($perl, $tests);
+
+Returns a $command line which runs the given set of $tests with
+Test::Harness and the given $perl.
+
+Used on the t/*.t files.
+
+=cut
+
+sub test_via_harness {
+ my($self, $perl, $tests) = @_;
+
+ return qq{\t$perl "-MExtUtils::Command::MM" }.
+ qq{"-e" "test_harness(\$(TEST_VERBOSE), '\$(INST_LIB)', '\$(INST_ARCHLIB)')" $tests\n};
+}
+
+=head3 test_via_script
+
+ my $command = $mm->test_via_script($perl, $script);
+
+Returns a $command line which just runs a single test without
+Test::Harness. No checks are done on the results, they're just
+printed.
+
+Used for test.pl, since they don't always follow Test::Harness
+formatting.
+
+=cut
+
+sub test_via_script {
+ my($self, $perl, $script) = @_;
+ return qq{\t$perl "-I\$(INST_LIB)" "-I\$(INST_ARCHLIB)" $script\n};
+}
+
+
+=head3 tool_autosplit
+
+Defines a simple perl call that runs autosplit. May be deprecated by
+pm_to_blib soon.
+
+=cut
+
+sub tool_autosplit {
+ my($self, %attribs) = @_;
+
+ my $maxlen = $attribs{MAXLEN} ? '$$AutoSplit::Maxlen=$attribs{MAXLEN};'
+ : '';
+
+ my $asplit = $self->oneliner(sprintf <<'PERL_CODE', $maxlen);
+use AutoSplit; %s autosplit($$ARGV[0], $$ARGV[1], 0, 1, 1)
+PERL_CODE
+
+ return sprintf <<'MAKE_FRAG', $asplit;
+# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto
+AUTOSPLITFILE = %s
+
+MAKE_FRAG
+
+}
+
+
+=head3 arch_check
+
+ my $arch_ok = $mm->arch_check(
+ $INC{"Config.pm"},
+ File::Spec->catfile($Config{archlibexp}, "Config.pm")
+ );
+
+A sanity check that what Perl thinks the architecture is and what
+Config thinks the architecture is are the same. If they're not it
+will return false and show a diagnostic message.
+
+When building Perl it will always return true, as nothing is installed
+yet.
+
+The interface is a bit odd because this is the result of a
+quick refactoring. Don't rely on it.
+
+=cut
+
+sub arch_check {
+ my $self = shift;
+ my($pconfig, $cconfig) = @_;
+
+ return 1 if $self->{PERL_SRC};
+
+ my($pvol, $pthinks) = $self->splitpath($pconfig);
+ my($cvol, $cthinks) = $self->splitpath($cconfig);
+
+ $pthinks = $self->canonpath($pthinks);
+ $cthinks = $self->canonpath($cthinks);
+
+ my $ret = 1;
+ if ($pthinks ne $cthinks) {
+ print "Have $pthinks\n";
+ print "Want $cthinks\n";
+
+ $ret = 0;
+
+ my $arch = (grep length, $self->splitdir($pthinks))[-1];
+
+ print STDOUT <<END unless $self->{UNINSTALLED_PERL};
+Your perl and your Config.pm seem to have different ideas about the
+architecture they are running on.
+Perl thinks: [$arch]
+Config says: [$Config{archname}]
+This may or may not cause problems. Please check your installation of perl
+if you have problems building this extension.
+END
+ }
+
+ return $ret;
+}
+
+
+
+=head2 File::Spec wrappers
+
+ExtUtils::MM_Any is a subclass of File::Spec. The methods noted here
+override File::Spec.
+
+
+
+=head3 catfile
+
+File::Spec <= 0.83 has a bug where the file part of catfile is not
+canonicalized. This override fixes that bug.
+
+=cut
+
+sub catfile {
+ my $self = shift;
+ return $self->canonpath($self->SUPER::catfile(@_));
+}
+
+
+
+=head2 Misc
+
+Methods I can't really figure out where they should go yet.
+
+
+=head3 find_tests
+
+ my $test = $mm->find_tests;
+
+Returns a string suitable for feeding to the shell to return all
+tests in t/*.t.
+
+=cut
+
+sub find_tests {
+ my($self) = shift;
+ return -d 't' ? 't/*.t' : '';
+}
+
+
+=head3 extra_clean_files
+
+ my @files_to_clean = $MM->extra_clean_files;
+
+Returns a list of OS specific files to be removed in the clean target in
+addition to the usual set.
+
+=cut
+
+# An empty method here tickled a perl 5.8.1 bug and would return its object.
+sub extra_clean_files {
+ return;
+}
+
+
+=head3 installvars
+
+ my @installvars = $mm->installvars;
+
+A list of all the INSTALL* variables without the INSTALL prefix. Useful
+for iteration or building related variable sets.
+
+=cut
+
+sub installvars {
+ return qw(PRIVLIB SITELIB VENDORLIB
+ ARCHLIB SITEARCH VENDORARCH
+ BIN SITEBIN VENDORBIN
+ SCRIPT SITESCRIPT VENDORSCRIPT
+ MAN1DIR SITEMAN1DIR VENDORMAN1DIR
+ MAN3DIR SITEMAN3DIR VENDORMAN3DIR
+ );
+}
+
+
+=head3 libscan
+
+ my $wanted = $self->libscan($path);
+
+Takes a path to a file or dir and returns an empty string if we don't
+want to include this file in the library. Otherwise it returns the
+the $path unchanged.
+
+Mainly used to exclude version control administrative directories from
+installation.
+
+=cut
+
+sub libscan {
+ my($self,$path) = @_;
+ my($dirs,$file) = ($self->splitpath($path))[1,2];
+ return '' if grep /^(?:RCS|CVS|SCCS|\.svn|_darcs)$/,
+ $self->splitdir($dirs), $file;
+
+ return $path;
+}
+
+
+=head3 platform_constants
+
+ my $make_frag = $mm->platform_constants
+
+Returns a make fragment defining all the macros initialized in
+init_platform() rather than put them in constants().
+
+=cut
+
+sub platform_constants {
+ return '';
+}
+
+=begin private
+
+=head3 _PREREQ_PRINT
+
+ $self->_PREREQ_PRINT;
+
+Implements PREREQ_PRINT.
+
+Refactored out of MakeMaker->new().
+
+=end private
+
+=cut
+
+sub _PREREQ_PRINT {
+ my $self = shift;
+
+ require Data::Dumper;
+ my @what = ('PREREQ_PM');
+ push @what, 'MIN_PERL_VERSION' if $self->{MIN_PERL_VERSION};
+ push @what, 'BUILD_REQUIRES' if $self->{BUILD_REQUIRES};
+ print Data::Dumper->Dump([@{$self}{@what}], \@what);
+ exit 0;
+}
+
+
+=begin private
+
+=head3 _PRINT_PREREQ
+
+ $mm->_PRINT_PREREQ;
+
+Implements PRINT_PREREQ, a slightly different version of PREREQ_PRINT
+added by Redhat to, I think, support generating RPMs from Perl modules.
+
+Should not include BUILD_REQUIRES as RPMs do not incluide them.
+
+Refactored out of MakeMaker->new().
+
+=end private
+
+=cut
+
+sub _PRINT_PREREQ {
+ my $self = shift;
+
+ my $prereqs= $self->{PREREQ_PM};
+ my @prereq = map { [$_, $prereqs->{$_}] } keys %$prereqs;
+
+ if ( $self->{MIN_PERL_VERSION} ) {
+ push @prereq, ['perl' => $self->{MIN_PERL_VERSION}];
+ }
+
+ print join(" ", map { "perl($_->[0])>=$_->[1] " }
+ sort { $a->[0] cmp $b->[0] } @prereq), "\n";
+ exit 0;
+}
+
+
+=begin private
+
+=head3 _all_prereqs
+
+ my $prereqs = $self->_all_prereqs;
+
+Returns a hash ref of both PREREQ_PM and BUILD_REQUIRES.
+
+=end private
+
+=cut
+
+sub _all_prereqs {
+ my $self = shift;
+
+ return { %{$self->{PREREQ_PM}}, %{$self->{BUILD_REQUIRES}} };
+}
+
+
+=head1 AUTHOR
+
+Michael G Schwern <schwern@pobox.com> and the denizens of
+makemaker@perl.org with code from ExtUtils::MM_Unix and
+ExtUtils::MM_Win32.
+
+
+=cut
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MM_BeOS.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MM_BeOS.pm
new file mode 100644
index 00000000000..0b7c8db9225
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MM_BeOS.pm
@@ -0,0 +1,61 @@
+package ExtUtils::MM_BeOS;
+
+use strict;
+
+=head1 NAME
+
+ExtUtils::MM_BeOS - methods to override UN*X behaviour in ExtUtils::MakeMaker
+
+=head1 SYNOPSIS
+
+ use ExtUtils::MM_BeOS; # Done internally by ExtUtils::MakeMaker if needed
+
+=head1 DESCRIPTION
+
+See ExtUtils::MM_Unix for a documentation of the methods provided
+there. This package overrides the implementation of these methods, not
+the semantics.
+
+=over 4
+
+=cut
+
+use ExtUtils::MakeMaker::Config;
+use File::Spec;
+require ExtUtils::MM_Any;
+require ExtUtils::MM_Unix;
+
+our @ISA = qw( ExtUtils::MM_Any ExtUtils::MM_Unix );
+our $VERSION = '6.56';
+
+
+=item os_flavor
+
+BeOS is BeOS.
+
+=cut
+
+sub os_flavor {
+ return('BeOS');
+}
+
+=item init_linker
+
+libperl.a equivalent to be linked to dynamic extensions.
+
+=cut
+
+sub init_linker {
+ my($self) = shift;
+
+ $self->{PERL_ARCHIVE} ||=
+ File::Spec->catdir('$(PERL_INC)',$Config{libperl});
+ $self->{PERL_ARCHIVE_AFTER} ||= '';
+ $self->{EXPORT_LIST} ||= '';
+}
+
+=back
+
+1;
+__END__
+
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MM_Cygwin.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MM_Cygwin.pm
new file mode 100644
index 00000000000..394fbc68a75
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MM_Cygwin.pm
@@ -0,0 +1,123 @@
+package ExtUtils::MM_Cygwin;
+
+use strict;
+
+use ExtUtils::MakeMaker::Config;
+use File::Spec;
+
+require ExtUtils::MM_Unix;
+require ExtUtils::MM_Win32;
+our @ISA = qw( ExtUtils::MM_Unix );
+
+our $VERSION = '6.56';
+
+
+=head1 NAME
+
+ExtUtils::MM_Cygwin - methods to override UN*X behaviour in ExtUtils::MakeMaker
+
+=head1 SYNOPSIS
+
+ use ExtUtils::MM_Cygwin; # Done internally by ExtUtils::MakeMaker if needed
+
+=head1 DESCRIPTION
+
+See ExtUtils::MM_Unix for a documentation of the methods provided there.
+
+=over 4
+
+=item os_flavor
+
+We're Unix and Cygwin.
+
+=cut
+
+sub os_flavor {
+ return('Unix', 'Cygwin');
+}
+
+=item cflags
+
+if configured for dynamic loading, triggers #define EXT in EXTERN.h
+
+=cut
+
+sub cflags {
+ my($self,$libperl)=@_;
+ return $self->{CFLAGS} if $self->{CFLAGS};
+ return '' unless $self->needs_linking();
+
+ my $base = $self->SUPER::cflags($libperl);
+ foreach (split /\n/, $base) {
+ /^(\S*)\s*=\s*(\S*)$/ and $self->{$1} = $2;
+ };
+ $self->{CCFLAGS} .= " -DUSEIMPORTLIB" if ($Config{useshrplib} eq 'true');
+
+ return $self->{CFLAGS} = qq{
+CCFLAGS = $self->{CCFLAGS}
+OPTIMIZE = $self->{OPTIMIZE}
+PERLTYPE = $self->{PERLTYPE}
+};
+
+}
+
+
+=item replace_manpage_separator
+
+replaces strings '::' with '.' in MAN*POD man page names
+
+=cut
+
+sub replace_manpage_separator {
+ my($self, $man) = @_;
+ $man =~ s{/+}{.}g;
+ return $man;
+}
+
+=item init_linker
+
+points to libperl.a
+
+=cut
+
+sub init_linker {
+ my $self = shift;
+
+ if ($Config{useshrplib} eq 'true') {
+ my $libperl = '$(PERL_INC)' .'/'. "$Config{libperl}";
+ if( $] >= 5.006002 ) {
+ $libperl =~ s/a$/dll.a/;
+ }
+ $self->{PERL_ARCHIVE} = $libperl;
+ } else {
+ $self->{PERL_ARCHIVE} =
+ '$(PERL_INC)' .'/'. ("$Config{libperl}" or "libperl.a");
+ }
+
+ $self->{PERL_ARCHIVE_AFTER} ||= '';
+ $self->{EXPORT_LIST} ||= '';
+}
+
+=item maybe_command
+
+If our path begins with F</cygdrive/> then we use C<ExtUtils::MM_Win32>
+to determine if it may be a command. Otherwise we use the tests
+from C<ExtUtils::MM_Unix>.
+
+=cut
+
+sub maybe_command {
+ my ($self, $file) = @_;
+
+ if ($file =~ m{^/cygdrive/}i) {
+ return ExtUtils::MM_Win32->maybe_command($file);
+ }
+
+ return $self->SUPER::maybe_command($file);
+}
+
+=back
+
+=cut
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MM_DOS.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MM_DOS.pm
new file mode 100644
index 00000000000..fc0a7947235
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MM_DOS.pm
@@ -0,0 +1,65 @@
+package ExtUtils::MM_DOS;
+
+use strict;
+
+our $VERSION = 6.56;
+
+require ExtUtils::MM_Any;
+require ExtUtils::MM_Unix;
+our @ISA = qw( ExtUtils::MM_Any ExtUtils::MM_Unix );
+
+
+=head1 NAME
+
+ExtUtils::MM_DOS - DOS specific subclass of ExtUtils::MM_Unix
+
+=head1 SYNOPSIS
+
+ Don't use this module directly.
+ Use ExtUtils::MM and let it choose.
+
+=head1 DESCRIPTION
+
+This is a subclass of ExtUtils::MM_Unix which contains functionality
+for DOS.
+
+Unless otherwise stated, it works just like ExtUtils::MM_Unix
+
+=head2 Overridden methods
+
+=over 4
+
+=item os_flavor
+
+=cut
+
+sub os_flavor {
+ return('DOS');
+}
+
+=item B<replace_manpage_separator>
+
+Generates Foo__Bar.3 style man page names
+
+=cut
+
+sub replace_manpage_separator {
+ my($self, $man) = @_;
+
+ $man =~ s,/+,__,g;
+ return $man;
+}
+
+=back
+
+=head1 AUTHOR
+
+Michael G Schwern <schwern@pobox.com> with code from ExtUtils::MM_Unix
+
+=head1 SEE ALSO
+
+L<ExtUtils::MM_Unix>, L<ExtUtils::MakeMaker>
+
+=cut
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MM_Darwin.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MM_Darwin.pm
new file mode 100644
index 00000000000..1cb87c78815
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MM_Darwin.pm
@@ -0,0 +1,47 @@
+package ExtUtils::MM_Darwin;
+
+use strict;
+
+BEGIN {
+ require ExtUtils::MM_Unix;
+ our @ISA = qw( ExtUtils::MM_Unix );
+}
+
+our $VERSION = '6.56';
+
+
+=head1 NAME
+
+ExtUtils::MM_Darwin - special behaviors for OS X
+
+=head1 SYNOPSIS
+
+ For internal MakeMaker use only
+
+=head1 DESCRIPTION
+
+See L<ExtUtils::MM_Unix> for L<ExtUtils::MM_Any> for documention on the
+methods overridden here.
+
+=head2 Overriden Methods
+
+=head3 init_dist
+
+Turn off Apple tar's tendency to copy resource forks as "._foo" files.
+
+=cut
+
+sub init_dist {
+ my $self = shift;
+
+ # Thank you, Apple, for breaking tar and then breaking the work around.
+ # 10.4 wants COPY_EXTENDED_ATTRIBUTES_DISABLE while 10.5 wants
+ # COPYFILE_DISABLE. I'm not going to push my luck and instead just
+ # set both.
+ $self->{TAR} ||=
+ 'COPY_EXTENDED_ATTRIBUTES_DISABLE=1 COPYFILE_DISABLE=1 tar';
+
+ $self->SUPER::init_dist(@_);
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MM_MacOS.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MM_MacOS.pm
new file mode 100644
index 00000000000..cfc82051e1b
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MM_MacOS.pm
@@ -0,0 +1,40 @@
+package ExtUtils::MM_MacOS;
+
+use strict;
+
+our $VERSION = 6.56;
+
+sub new {
+ die <<'UNSUPPORTED';
+MacOS Classic (MacPerl) is no longer supported by MakeMaker.
+Please use Module::Build instead.
+UNSUPPORTED
+}
+
+=head1 NAME
+
+ExtUtils::MM_MacOS - once produced Makefiles for MacOS Classic
+
+=head1 SYNOPSIS
+
+ # MM_MacOS no longer contains any code. This is just a stub.
+
+=head1 DESCRIPTION
+
+Once upon a time, MakeMaker could produce an approximation of a correct
+Makefile on MacOS Classic (MacPerl). Due to a lack of maintainers, this
+fell out of sync with the rest of MakeMaker and hadn't worked in years.
+Since there's little chance of it being repaired, MacOS Classic is fading
+away, and the code was icky to begin with, the code has been deleted to
+make maintenance easier.
+
+Those interested in writing modules for MacPerl should use Module::Build
+which works better than MakeMaker ever did.
+
+Anyone interested in resurrecting this file should pull the old version
+from the MakeMaker CVS repository and contact makemaker@perl.org, but we
+really encourage you to work on Module::Build instead.
+
+=cut
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MM_NW5.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MM_NW5.pm
new file mode 100644
index 00000000000..0c8f6c0affb
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MM_NW5.pm
@@ -0,0 +1,269 @@
+package ExtUtils::MM_NW5;
+
+=head1 NAME
+
+ExtUtils::MM_NW5 - methods to override UN*X behaviour in ExtUtils::MakeMaker
+
+=head1 SYNOPSIS
+
+ use ExtUtils::MM_NW5; # Done internally by ExtUtils::MakeMaker if needed
+
+=head1 DESCRIPTION
+
+See ExtUtils::MM_Unix for a documentation of the methods provided
+there. This package overrides the implementation of these methods, not
+the semantics.
+
+=over
+
+=cut
+
+use strict;
+use ExtUtils::MakeMaker::Config;
+use File::Basename;
+
+our $VERSION = '6.56';
+
+require ExtUtils::MM_Win32;
+our @ISA = qw(ExtUtils::MM_Win32);
+
+use ExtUtils::MakeMaker qw( &neatvalue );
+
+$ENV{EMXSHELL} = 'sh'; # to run `commands`
+
+my $BORLAND = $Config{'cc'} =~ /^bcc/i;
+my $GCC = $Config{'cc'} =~ /^gcc/i;
+
+
+=item os_flavor
+
+We're Netware in addition to being Windows.
+
+=cut
+
+sub os_flavor {
+ my $self = shift;
+ return ($self->SUPER::os_flavor, 'Netware');
+}
+
+=item init_platform
+
+Add Netware macros.
+
+LIBPTH, BASE_IMPORT, NLM_VERSION, MPKTOOL, TOOLPATH, BOOT_SYMBOL,
+NLM_SHORT_NAME, INCLUDE, PATH, MM_NW5_REVISION
+
+
+=item platform_constants
+
+Add Netware macros initialized above to the Makefile.
+
+=cut
+
+sub init_platform {
+ my($self) = shift;
+
+ # To get Win32's setup.
+ $self->SUPER::init_platform;
+
+ # incpath is copied to makefile var INCLUDE in constants sub, here just
+ # make it empty
+ my $libpth = $Config{'libpth'};
+ $libpth =~ s( )(;);
+ $self->{'LIBPTH'} = $libpth;
+
+ $self->{'BASE_IMPORT'} = $Config{'base_import'};
+
+ # Additional import file specified from Makefile.pl
+ if($self->{'base_import'}) {
+ $self->{'BASE_IMPORT'} .= ', ' . $self->{'base_import'};
+ }
+
+ $self->{'NLM_VERSION'} = $Config{'nlm_version'};
+ $self->{'MPKTOOL'} = $Config{'mpktool'};
+ $self->{'TOOLPATH'} = $Config{'toolpath'};
+
+ (my $boot = $self->{'NAME'}) =~ s/:/_/g;
+ $self->{'BOOT_SYMBOL'}=$boot;
+
+ # If the final binary name is greater than 8 chars,
+ # truncate it here.
+ if(length($self->{'BASEEXT'}) > 8) {
+ $self->{'NLM_SHORT_NAME'} = substr($self->{'BASEEXT'},0,8);
+ }
+
+ # Get the include path and replace the spaces with ;
+ # Copy this to makefile as INCLUDE = d:\...;d:\;
+ ($self->{INCLUDE} = $Config{'incpath'}) =~ s/([ ]*)-I/;/g;
+
+ # Set the path to CodeWarrior binaries which might not have been set in
+ # any other place
+ $self->{PATH} = '$(PATH);$(TOOLPATH)';
+
+ $self->{MM_NW5_VERSION} = $VERSION;
+}
+
+sub platform_constants {
+ my($self) = shift;
+ my $make_frag = '';
+
+ # Setup Win32's constants.
+ $make_frag .= $self->SUPER::platform_constants;
+
+ foreach my $macro (qw(LIBPTH BASE_IMPORT NLM_VERSION MPKTOOL
+ TOOLPATH BOOT_SYMBOL NLM_SHORT_NAME INCLUDE PATH
+ MM_NW5_VERSION
+ ))
+ {
+ next unless defined $self->{$macro};
+ $make_frag .= "$macro = $self->{$macro}\n";
+ }
+
+ return $make_frag;
+}
+
+
+=item const_cccmd
+
+=cut
+
+sub const_cccmd {
+ my($self,$libperl)=@_;
+ return $self->{CONST_CCCMD} if $self->{CONST_CCCMD};
+ return '' unless $self->needs_linking();
+ return $self->{CONST_CCCMD} = <<'MAKE_FRAG';
+CCCMD = $(CC) $(CCFLAGS) $(INC) $(OPTIMIZE) \
+ $(PERLTYPE) $(MPOLLUTE) -o $@ \
+ -DVERSION=\"$(VERSION)\" -DXS_VERSION=\"$(XS_VERSION)\"
+MAKE_FRAG
+
+}
+
+
+=item static_lib
+
+=cut
+
+sub static_lib {
+ my($self) = @_;
+
+ return '' unless $self->has_link_code;
+
+ my $m = <<'END';
+$(INST_STATIC): $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DFSEP).exists
+ $(RM_RF) $@
+END
+
+ # If this extension has it's own library (eg SDBM_File)
+ # then copy that to $(INST_STATIC) and add $(OBJECT) into it.
+ $m .= <<'END' if $self->{MYEXTLIB};
+ $self->{CP} $(MYEXTLIB) $@
+END
+
+ my $ar_arg;
+ if( $BORLAND ) {
+ $ar_arg = '$@ $(OBJECT:^"+")';
+ }
+ elsif( $GCC ) {
+ $ar_arg = '-ru $@ $(OBJECT)';
+ }
+ else {
+ $ar_arg = '-type library -o $@ $(OBJECT)';
+ }
+
+ $m .= sprintf <<'END', $ar_arg;
+ $(AR) %s
+ $(NOECHO) $(ECHO) "$(EXTRALIBS)" > $(INST_ARCHAUTODIR)\extralibs.ld
+ $(CHMOD) 755 $@
+END
+
+ $m .= <<'END' if $self->{PERL_SRC};
+ $(NOECHO) $(ECHO) "$(EXTRALIBS)" >> $(PERL_SRC)\ext.libs
+
+
+END
+ return $m;
+}
+
+=item dynamic_lib
+
+Defines how to produce the *.so (or equivalent) files.
+
+=cut
+
+sub dynamic_lib {
+ my($self, %attribs) = @_;
+ return '' unless $self->needs_linking(); #might be because of a subdir
+
+ return '' unless $self->has_link_code;
+
+ my($otherldflags) = $attribs{OTHERLDFLAGS} || ($BORLAND ? 'c0d32.obj': '');
+ my($inst_dynamic_dep) = $attribs{INST_DYNAMIC_DEP} || "";
+ my($ldfrom) = '$(LDFROM)';
+
+ (my $boot = $self->{NAME}) =~ s/:/_/g;
+
+ my $m = <<'MAKE_FRAG';
+# This section creates the dynamically loadable $(INST_DYNAMIC)
+# from $(OBJECT) and possibly $(MYEXTLIB).
+OTHERLDFLAGS = '.$otherldflags.'
+INST_DYNAMIC_DEP = '.$inst_dynamic_dep.'
+
+# Create xdc data for an MT safe NLM in case of mpk build
+$(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)$(DFSEP).exists
+ $(NOECHO) $(ECHO) Export boot_$(BOOT_SYMBOL) > $(BASEEXT).def
+ $(NOECHO) $(ECHO) $(BASE_IMPORT) >> $(BASEEXT).def
+ $(NOECHO) $(ECHO) Import @$(PERL_INC)\perl.imp >> $(BASEEXT).def
+MAKE_FRAG
+
+
+ if ( $self->{CCFLAGS} =~ m/ -DMPK_ON /) {
+ $m .= <<'MAKE_FRAG';
+ $(MPKTOOL) $(XDCFLAGS) $(BASEEXT).xdc
+ $(NOECHO) $(ECHO) xdcdata $(BASEEXT).xdc >> $(BASEEXT).def
+MAKE_FRAG
+ }
+
+ # Reconstruct the X.Y.Z version.
+ my $version = join '.', map { sprintf "%d", $_ }
+ $] =~ /(\d)\.(\d{3})(\d{2})/;
+ $m .= sprintf ' $(LD) $(LDFLAGS) $(OBJECT:.obj=.obj) -desc "Perl %s Extension ($(BASEEXT)) XS_VERSION: $(XS_VERSION)" -nlmversion $(NLM_VERSION)', $version;
+
+ # Taking care of long names like FileHandle, ByteLoader, SDBM_File etc
+ if($self->{NLM_SHORT_NAME}) {
+ # In case of nlms with names exceeding 8 chars, build nlm in the
+ # current dir, rename and move to auto\lib.
+ $m .= q{ -o $(NLM_SHORT_NAME).$(DLEXT)}
+ } else {
+ $m .= q{ -o $(INST_AUTODIR)\\$(BASEEXT).$(DLEXT)}
+ }
+
+ # Add additional lib files if any (SDBM_File)
+ $m .= q{ $(MYEXTLIB) } if $self->{MYEXTLIB};
+
+ $m .= q{ $(PERL_INC)\Main.lib -commandfile $(BASEEXT).def}."\n";
+
+ if($self->{NLM_SHORT_NAME}) {
+ $m .= <<'MAKE_FRAG';
+ if exist $(INST_AUTODIR)\$(NLM_SHORT_NAME).$(DLEXT) del $(INST_AUTODIR)\$(NLM_SHORT_NAME).$(DLEXT)
+ move $(NLM_SHORT_NAME).$(DLEXT) $(INST_AUTODIR)
+MAKE_FRAG
+ }
+
+ $m .= <<'MAKE_FRAG';
+
+ $(CHMOD) 755 $@
+MAKE_FRAG
+
+ return $m;
+}
+
+
+1;
+__END__
+
+=back
+
+=cut
+
+
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MM_OS2.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MM_OS2.pm
new file mode 100644
index 00000000000..680502baf24
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MM_OS2.pm
@@ -0,0 +1,152 @@
+package ExtUtils::MM_OS2;
+
+use strict;
+
+use ExtUtils::MakeMaker qw(neatvalue);
+use File::Spec;
+
+our $VERSION = '6.56';
+
+require ExtUtils::MM_Any;
+require ExtUtils::MM_Unix;
+our @ISA = qw(ExtUtils::MM_Any ExtUtils::MM_Unix);
+
+=pod
+
+=head1 NAME
+
+ExtUtils::MM_OS2 - methods to override UN*X behaviour in ExtUtils::MakeMaker
+
+=head1 SYNOPSIS
+
+ use ExtUtils::MM_OS2; # Done internally by ExtUtils::MakeMaker if needed
+
+=head1 DESCRIPTION
+
+See ExtUtils::MM_Unix for a documentation of the methods provided
+there. This package overrides the implementation of these methods, not
+the semantics.
+
+=head1 METHODS
+
+=over 4
+
+=item init_dist
+
+Define TO_UNIX to convert OS2 linefeeds to Unix style.
+
+=cut
+
+sub init_dist {
+ my($self) = @_;
+
+ $self->{TO_UNIX} ||= <<'MAKE_TEXT';
+$(NOECHO) $(TEST_F) tmp.zip && $(RM_F) tmp.zip; $(ZIP) -ll -mr tmp.zip $(DISTVNAME) && unzip -o tmp.zip && $(RM_F) tmp.zip
+MAKE_TEXT
+
+ $self->SUPER::init_dist;
+}
+
+sub dlsyms {
+ my($self,%attribs) = @_;
+
+ my($funcs) = $attribs{DL_FUNCS} || $self->{DL_FUNCS} || {};
+ my($vars) = $attribs{DL_VARS} || $self->{DL_VARS} || [];
+ my($funclist) = $attribs{FUNCLIST} || $self->{FUNCLIST} || [];
+ my($imports) = $attribs{IMPORTS} || $self->{IMPORTS} || {};
+ my(@m);
+ (my $boot = $self->{NAME}) =~ s/:/_/g;
+
+ if (not $self->{SKIPHASH}{'dynamic'}) {
+ push(@m,"
+$self->{BASEEXT}.def: Makefile.PL
+",
+ ' $(PERL) "-I$(PERL_ARCHLIB)" "-I$(PERL_LIB)" -e \'use ExtUtils::Mksymlists; \\
+ Mksymlists("NAME" => "$(NAME)", "DLBASE" => "$(DLBASE)", ',
+ '"VERSION" => "$(VERSION)", "DISTNAME" => "$(DISTNAME)", ',
+ '"INSTALLDIRS" => "$(INSTALLDIRS)", ',
+ '"DL_FUNCS" => ',neatvalue($funcs),
+ ', "FUNCLIST" => ',neatvalue($funclist),
+ ', "IMPORTS" => ',neatvalue($imports),
+ ', "DL_VARS" => ', neatvalue($vars), ');\'
+');
+ }
+ if ($self->{IMPORTS} && %{$self->{IMPORTS}}) {
+ # Make import files (needed for static build)
+ -d 'tmp_imp' or mkdir 'tmp_imp', 0777 or die "Can't mkdir tmp_imp";
+ open my $imp, '>', 'tmpimp.imp' or die "Can't open tmpimp.imp";
+ while (my($name, $exp) = each %{$self->{IMPORTS}}) {
+ my ($lib, $id) = ($exp =~ /(.*)\.(.*)/) or die "Malformed IMPORT `$exp'";
+ print $imp "$name $lib $id ?\n";
+ }
+ close $imp or die "Can't close tmpimp.imp";
+ # print "emximp -o tmpimp$Config::Config{lib_ext} tmpimp.imp\n";
+ system "emximp -o tmpimp$Config::Config{lib_ext} tmpimp.imp"
+ and die "Cannot make import library: $!, \$?=$?";
+ # May be running under miniperl, so have no glob...
+ eval "unlink <tmp_imp/*>; 1" or system "rm tmp_imp/*";
+ system "cd tmp_imp; $Config::Config{ar} x ../tmpimp$Config::Config{lib_ext}"
+ and die "Cannot extract import objects: $!, \$?=$?";
+ }
+ join('',@m);
+}
+
+sub static_lib {
+ my($self) = @_;
+ my $old = $self->ExtUtils::MM_Unix::static_lib();
+ return $old unless $self->{IMPORTS} && %{$self->{IMPORTS}};
+
+ my @chunks = split /\n{2,}/, $old;
+ shift @chunks unless length $chunks[0]; # Empty lines at the start
+ $chunks[0] .= <<'EOC';
+
+ $(AR) $(AR_STATIC_ARGS) $@ tmp_imp/* && $(RANLIB) $@
+EOC
+ return join "\n\n". '', @chunks;
+}
+
+sub replace_manpage_separator {
+ my($self,$man) = @_;
+ $man =~ s,/+,.,g;
+ $man;
+}
+
+sub maybe_command {
+ my($self,$file) = @_;
+ $file =~ s,[/\\]+,/,g;
+ return $file if -x $file && ! -d _;
+ return "$file.exe" if -x "$file.exe" && ! -d _;
+ return "$file.cmd" if -x "$file.cmd" && ! -d _;
+ return;
+}
+
+=item init_linker
+
+=cut
+
+sub init_linker {
+ my $self = shift;
+
+ $self->{PERL_ARCHIVE} = "\$(PERL_INC)/libperl\$(LIB_EXT)";
+
+ $self->{PERL_ARCHIVE_AFTER} = $OS2::is_aout
+ ? ''
+ : '$(PERL_INC)/libperl_override$(LIB_EXT)';
+ $self->{EXPORT_LIST} = '$(BASEEXT).def';
+}
+
+=item os_flavor
+
+OS/2 is OS/2
+
+=cut
+
+sub os_flavor {
+ return('OS/2');
+}
+
+=back
+
+=cut
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MM_QNX.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MM_QNX.pm
new file mode 100644
index 00000000000..f78d5e8a9ee
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MM_QNX.pm
@@ -0,0 +1,57 @@
+package ExtUtils::MM_QNX;
+
+use strict;
+our $VERSION = '6.56';
+
+require ExtUtils::MM_Unix;
+our @ISA = qw(ExtUtils::MM_Unix);
+
+
+=head1 NAME
+
+ExtUtils::MM_QNX - QNX specific subclass of ExtUtils::MM_Unix
+
+=head1 SYNOPSIS
+
+ Don't use this module directly.
+ Use ExtUtils::MM and let it choose.
+
+=head1 DESCRIPTION
+
+This is a subclass of ExtUtils::MM_Unix which contains functionality for
+QNX.
+
+Unless otherwise stated it works just like ExtUtils::MM_Unix
+
+=head2 Overridden methods
+
+=head3 extra_clean_files
+
+Add .err files corresponding to each .c file.
+
+=cut
+
+sub extra_clean_files {
+ my $self = shift;
+
+ my @errfiles = @{$self->{C}};
+ for ( @errfiles ) {
+ s/.c$/.err/;
+ }
+
+ return( @errfiles, 'perlmain.err' );
+}
+
+
+=head1 AUTHOR
+
+Michael G Schwern <schwern@pobox.com> with code from ExtUtils::MM_Unix
+
+=head1 SEE ALSO
+
+L<ExtUtils::MakeMaker>
+
+=cut
+
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MM_UWIN.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MM_UWIN.pm
new file mode 100644
index 00000000000..5adc46ea8d2
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MM_UWIN.pm
@@ -0,0 +1,64 @@
+package ExtUtils::MM_UWIN;
+
+use strict;
+our $VERSION = 6.56;
+
+require ExtUtils::MM_Unix;
+our @ISA = qw(ExtUtils::MM_Unix);
+
+
+=head1 NAME
+
+ExtUtils::MM_UWIN - U/WIN specific subclass of ExtUtils::MM_Unix
+
+=head1 SYNOPSIS
+
+ Don't use this module directly.
+ Use ExtUtils::MM and let it choose.
+
+=head1 DESCRIPTION
+
+This is a subclass of ExtUtils::MM_Unix which contains functionality for
+the AT&T U/WIN UNIX on Windows environment.
+
+Unless otherwise stated it works just like ExtUtils::MM_Unix
+
+=head2 Overridden methods
+
+=over 4
+
+=item os_flavor
+
+In addition to being Unix, we're U/WIN.
+
+=cut
+
+sub os_flavor {
+ return('Unix', 'U/WIN');
+}
+
+
+=item B<replace_manpage_separator>
+
+=cut
+
+sub replace_manpage_separator {
+ my($self, $man) = @_;
+
+ $man =~ s,/+,.,g;
+ return $man;
+}
+
+=back
+
+=head1 AUTHOR
+
+Michael G Schwern <schwern@pobox.com> with code from ExtUtils::MM_Unix
+
+=head1 SEE ALSO
+
+L<ExtUtils::MM_Win32>, L<ExtUtils::MakeMaker>
+
+=cut
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MM_Unix.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MM_Unix.pm
new file mode 100644
index 00000000000..239d6df826c
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MM_Unix.pm
@@ -0,0 +1,3634 @@
+package ExtUtils::MM_Unix;
+
+require 5.006;
+
+use strict;
+
+use Carp;
+use ExtUtils::MakeMaker::Config;
+use File::Basename qw(basename dirname);
+use DirHandle;
+
+our %Config_Override;
+
+use ExtUtils::MakeMaker qw($Verbose neatvalue);
+
+# If we make $VERSION an our variable parse_version() breaks
+use vars qw($VERSION);
+$VERSION = '6.56';
+
+require ExtUtils::MM_Any;
+our @ISA = qw(ExtUtils::MM_Any);
+
+my %Is;
+BEGIN {
+ $Is{OS2} = $^O eq 'os2';
+ $Is{Win32} = $^O eq 'MSWin32' || $Config{osname} eq 'NetWare';
+ $Is{Dos} = $^O eq 'dos';
+ $Is{VMS} = $^O eq 'VMS';
+ $Is{OSF} = $^O eq 'dec_osf';
+ $Is{IRIX} = $^O eq 'irix';
+ $Is{NetBSD} = $^O eq 'netbsd';
+ $Is{Interix} = $^O eq 'interix';
+ $Is{SunOS4} = $^O eq 'sunos';
+ $Is{Solaris} = $^O eq 'solaris';
+ $Is{SunOS} = $Is{SunOS4} || $Is{Solaris};
+ $Is{BSD} = ($^O =~ /^(?:free|net|open)bsd$/ or
+ grep( $^O eq $_, qw(bsdos interix dragonfly) )
+ );
+}
+
+BEGIN {
+ if( $Is{VMS} ) {
+ # For things like vmsify()
+ require VMS::Filespec;
+ VMS::Filespec->import;
+ }
+}
+
+
+=head1 NAME
+
+ExtUtils::MM_Unix - methods used by ExtUtils::MakeMaker
+
+=head1 SYNOPSIS
+
+C<require ExtUtils::MM_Unix;>
+
+=head1 DESCRIPTION
+
+The methods provided by this package are designed to be used in
+conjunction with ExtUtils::MakeMaker. When MakeMaker writes a
+Makefile, it creates one or more objects that inherit their methods
+from a package C<MM>. MM itself doesn't provide any methods, but it
+ISA ExtUtils::MM_Unix class. The inheritance tree of MM lets operating
+specific packages take the responsibility for all the methods provided
+by MM_Unix. We are trying to reduce the number of the necessary
+overrides by defining rather primitive operations within
+ExtUtils::MM_Unix.
+
+If you are going to write a platform specific MM package, please try
+to limit the necessary overrides to primitive methods, and if it is not
+possible to do so, let's work out how to achieve that gain.
+
+If you are overriding any of these methods in your Makefile.PL (in the
+MY class), please report that to the makemaker mailing list. We are
+trying to minimize the necessary method overrides and switch to data
+driven Makefile.PLs wherever possible. In the long run less methods
+will be overridable via the MY class.
+
+=head1 METHODS
+
+The following description of methods is still under
+development. Please refer to the code for not suitably documented
+sections and complain loudly to the makemaker@perl.org mailing list.
+Better yet, provide a patch.
+
+Not all of the methods below are overridable in a
+Makefile.PL. Overridable methods are marked as (o). All methods are
+overridable by a platform specific MM_*.pm file.
+
+Cross-platform methods are being moved into MM_Any. If you can't find
+something that used to be in here, look in MM_Any.
+
+=cut
+
+# So we don't have to keep calling the methods over and over again,
+# we have these globals to cache the values. Faster and shrtr.
+my $Curdir = __PACKAGE__->curdir;
+my $Rootdir = __PACKAGE__->rootdir;
+my $Updir = __PACKAGE__->updir;
+
+
+=head2 Methods
+
+=over 4
+
+=item os_flavor
+
+Simply says that we're Unix.
+
+=cut
+
+sub os_flavor {
+ return('Unix');
+}
+
+
+=item c_o (o)
+
+Defines the suffix rules to compile different flavors of C files to
+object files.
+
+=cut
+
+sub c_o {
+# --- Translation Sections ---
+
+ my($self) = shift;
+ return '' unless $self->needs_linking();
+ my(@m);
+
+ my $command = '$(CCCMD)';
+ my $flags = '$(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE)';
+
+ if (my $cpp = $Config{cpprun}) {
+ my $cpp_cmd = $self->const_cccmd;
+ $cpp_cmd =~ s/^CCCMD\s*=\s*\$\(CC\)/$cpp/;
+ push @m, qq{
+.c.i:
+ $cpp_cmd $flags \$*.c > \$*.i
+};
+ }
+
+ push @m, qq{
+.c.s:
+ $command -S $flags \$*.c
+
+.c\$(OBJ_EXT):
+ $command $flags \$*.c
+
+.cpp\$(OBJ_EXT):
+ $command $flags \$*.cpp
+
+.cxx\$(OBJ_EXT):
+ $command $flags \$*.cxx
+
+.cc\$(OBJ_EXT):
+ $command $flags \$*.cc
+};
+
+ push @m, qq{
+.C\$(OBJ_EXT):
+ $command $flags \$*.C
+} if !$Is{OS2} and !$Is{Win32} and !$Is{Dos}; #Case-specific
+
+ return join "", @m;
+}
+
+=item cflags (o)
+
+Does very much the same as the cflags script in the perl
+distribution. It doesn't return the whole compiler command line, but
+initializes all of its parts. The const_cccmd method then actually
+returns the definition of the CCCMD macro which uses these parts.
+
+=cut
+
+#'
+
+sub cflags {
+ my($self,$libperl)=@_;
+ return $self->{CFLAGS} if $self->{CFLAGS};
+ return '' unless $self->needs_linking();
+
+ my($prog, $uc, $perltype, %cflags);
+ $libperl ||= $self->{LIBPERL_A} || "libperl$self->{LIB_EXT}" ;
+ $libperl =~ s/\.\$\(A\)$/$self->{LIB_EXT}/;
+
+ @cflags{qw(cc ccflags optimize shellflags)}
+ = @Config{qw(cc ccflags optimize shellflags)};
+ my($optdebug) = "";
+
+ $cflags{shellflags} ||= '';
+
+ my(%map) = (
+ D => '-DDEBUGGING',
+ E => '-DEMBED',
+ DE => '-DDEBUGGING -DEMBED',
+ M => '-DEMBED -DMULTIPLICITY',
+ DM => '-DDEBUGGING -DEMBED -DMULTIPLICITY',
+ );
+
+ if ($libperl =~ /libperl(\w*)\Q$self->{LIB_EXT}/){
+ $uc = uc($1);
+ } else {
+ $uc = ""; # avoid warning
+ }
+ $perltype = $map{$uc} ? $map{$uc} : "";
+
+ if ($uc =~ /^D/) {
+ $optdebug = "-g";
+ }
+
+
+ my($name);
+ ( $name = $self->{NAME} . "_cflags" ) =~ s/:/_/g ;
+ if ($prog = $Config{$name}) {
+ # Expand hints for this extension via the shell
+ print STDOUT "Processing $name hint:\n" if $Verbose;
+ my(@o)=`cc=\"$cflags{cc}\"
+ ccflags=\"$cflags{ccflags}\"
+ optimize=\"$cflags{optimize}\"
+ perltype=\"$cflags{perltype}\"
+ optdebug=\"$cflags{optdebug}\"
+ eval '$prog'
+ echo cc=\$cc
+ echo ccflags=\$ccflags
+ echo optimize=\$optimize
+ echo perltype=\$perltype
+ echo optdebug=\$optdebug
+ `;
+ foreach my $line (@o){
+ chomp $line;
+ if ($line =~ /(.*?)=\s*(.*)\s*$/){
+ $cflags{$1} = $2;
+ print STDOUT " $1 = $2\n" if $Verbose;
+ } else {
+ print STDOUT "Unrecognised result from hint: '$line'\n";
+ }
+ }
+ }
+
+ if ($optdebug) {
+ $cflags{optimize} = $optdebug;
+ }
+
+ for (qw(ccflags optimize perltype)) {
+ $cflags{$_} ||= '';
+ $cflags{$_} =~ s/^\s+//;
+ $cflags{$_} =~ s/\s+/ /g;
+ $cflags{$_} =~ s/\s+$//;
+ $self->{uc $_} ||= $cflags{$_};
+ }
+
+ if ($self->{POLLUTE}) {
+ $self->{CCFLAGS} .= ' -DPERL_POLLUTE ';
+ }
+
+ my $pollute = '';
+ if ($Config{usemymalloc} and not $Config{bincompat5005}
+ and not $Config{ccflags} =~ /-DPERL_POLLUTE_MALLOC\b/
+ and $self->{PERL_MALLOC_OK}) {
+ $pollute = '$(PERL_MALLOC_DEF)';
+ }
+
+ $self->{CCFLAGS} = quote_paren($self->{CCFLAGS});
+ $self->{OPTIMIZE} = quote_paren($self->{OPTIMIZE});
+
+ return $self->{CFLAGS} = qq{
+CCFLAGS = $self->{CCFLAGS}
+OPTIMIZE = $self->{OPTIMIZE}
+PERLTYPE = $self->{PERLTYPE}
+MPOLLUTE = $pollute
+};
+
+}
+
+
+=item const_cccmd (o)
+
+Returns the full compiler call for C programs and stores the
+definition in CONST_CCCMD.
+
+=cut
+
+sub const_cccmd {
+ my($self,$libperl)=@_;
+ return $self->{CONST_CCCMD} if $self->{CONST_CCCMD};
+ return '' unless $self->needs_linking();
+ return $self->{CONST_CCCMD} =
+ q{CCCMD = $(CC) -c $(PASTHRU_INC) $(INC) \\
+ $(CCFLAGS) $(OPTIMIZE) \\
+ $(PERLTYPE) $(MPOLLUTE) $(DEFINE_VERSION) \\
+ $(XS_DEFINE_VERSION)};
+}
+
+=item const_config (o)
+
+Defines a couple of constants in the Makefile that are imported from
+%Config.
+
+=cut
+
+sub const_config {
+# --- Constants Sections ---
+
+ my($self) = shift;
+ my @m = <<"END";
+
+# These definitions are from config.sh (via $INC{'Config.pm'}).
+# They may have been overridden via Makefile.PL or on the command line.
+END
+
+ my(%once_only);
+ foreach my $key (@{$self->{CONFIG}}){
+ # SITE*EXP macros are defined in &constants; avoid duplicates here
+ next if $once_only{$key};
+ $self->{uc $key} = quote_paren($self->{uc $key});
+ push @m, uc($key) , ' = ' , $self->{uc $key}, "\n";
+ $once_only{$key} = 1;
+ }
+ join('', @m);
+}
+
+=item const_loadlibs (o)
+
+Defines EXTRALIBS, LDLOADLIBS, BSLOADLIBS, LD_RUN_PATH. See
+L<ExtUtils::Liblist> for details.
+
+=cut
+
+sub const_loadlibs {
+ my($self) = shift;
+ return "" unless $self->needs_linking;
+ my @m;
+ push @m, qq{
+# $self->{NAME} might depend on some other libraries:
+# See ExtUtils::Liblist for details
+#
+};
+ for my $tmp (qw/
+ EXTRALIBS LDLOADLIBS BSLOADLIBS
+ /) {
+ next unless defined $self->{$tmp};
+ push @m, "$tmp = $self->{$tmp}\n";
+ }
+ # don't set LD_RUN_PATH if empty
+ for my $tmp (qw/
+ LD_RUN_PATH
+ /) {
+ next unless $self->{$tmp};
+ push @m, "$tmp = $self->{$tmp}\n";
+ }
+ return join "", @m;
+}
+
+=item constants (o)
+
+ my $make_frag = $mm->constants;
+
+Prints out macros for lots of constants.
+
+=cut
+
+sub constants {
+ my($self) = @_;
+ my @m = ();
+
+ $self->{DFSEP} = '$(DIRFILESEP)'; # alias for internal use
+
+ for my $macro (qw(
+
+ AR_STATIC_ARGS DIRFILESEP DFSEP
+ NAME NAME_SYM
+ VERSION VERSION_MACRO VERSION_SYM DEFINE_VERSION
+ XS_VERSION XS_VERSION_MACRO XS_DEFINE_VERSION
+ INST_ARCHLIB INST_SCRIPT INST_BIN INST_LIB
+ INST_MAN1DIR INST_MAN3DIR
+ MAN1EXT MAN3EXT
+ INSTALLDIRS INSTALL_BASE DESTDIR PREFIX
+ PERLPREFIX SITEPREFIX VENDORPREFIX
+ ),
+ (map { ("INSTALL".$_,
+ "DESTINSTALL".$_)
+ } $self->installvars),
+ qw(
+ PERL_LIB
+ PERL_ARCHLIB
+ LIBPERL_A MYEXTLIB
+ FIRST_MAKEFILE MAKEFILE_OLD MAKE_APERL_FILE
+ PERLMAINCC PERL_SRC PERL_INC
+ PERL FULLPERL ABSPERL
+ PERLRUN FULLPERLRUN ABSPERLRUN
+ PERLRUNINST FULLPERLRUNINST ABSPERLRUNINST
+ PERL_CORE
+ PERM_DIR PERM_RW PERM_RWX
+
+ ) )
+ {
+ next unless defined $self->{$macro};
+
+ # pathnames can have sharp signs in them; escape them so
+ # make doesn't think it is a comment-start character.
+ $self->{$macro} =~ s/#/\\#/g;
+ push @m, "$macro = $self->{$macro}\n";
+ }
+
+ push @m, qq{
+MAKEMAKER = $self->{MAKEMAKER}
+MM_VERSION = $self->{MM_VERSION}
+MM_REVISION = $self->{MM_REVISION}
+};
+
+ push @m, q{
+# FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle).
+# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle)
+# PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar)
+# DLBASE = Basename part of dynamic library. May be just equal BASEEXT.
+};
+
+ for my $macro (qw/
+ MAKE
+ FULLEXT BASEEXT PARENT_NAME DLBASE VERSION_FROM INC DEFINE OBJECT
+ LDFROM LINKTYPE BOOTDEP
+ / )
+ {
+ next unless defined $self->{$macro};
+ push @m, "$macro = $self->{$macro}\n";
+ }
+
+ push @m, "
+# Handy lists of source code files:
+XS_FILES = ".$self->wraplist(sort keys %{$self->{XS}})."
+C_FILES = ".$self->wraplist(@{$self->{C}})."
+O_FILES = ".$self->wraplist(@{$self->{O_FILES}})."
+H_FILES = ".$self->wraplist(@{$self->{H}})."
+MAN1PODS = ".$self->wraplist(sort keys %{$self->{MAN1PODS}})."
+MAN3PODS = ".$self->wraplist(sort keys %{$self->{MAN3PODS}})."
+";
+
+
+ push @m, q{
+# Where is the Config information that we are using/depend on
+CONFIGDEP = $(PERL_ARCHLIB)$(DFSEP)Config.pm $(PERL_INC)$(DFSEP)config.h
+};
+
+
+ push @m, qq{
+# Where to build things
+INST_LIBDIR = $self->{INST_LIBDIR}
+INST_ARCHLIBDIR = $self->{INST_ARCHLIBDIR}
+
+INST_AUTODIR = $self->{INST_AUTODIR}
+INST_ARCHAUTODIR = $self->{INST_ARCHAUTODIR}
+
+INST_STATIC = $self->{INST_STATIC}
+INST_DYNAMIC = $self->{INST_DYNAMIC}
+INST_BOOT = $self->{INST_BOOT}
+};
+
+
+ push @m, qq{
+# Extra linker info
+EXPORT_LIST = $self->{EXPORT_LIST}
+PERL_ARCHIVE = $self->{PERL_ARCHIVE}
+PERL_ARCHIVE_AFTER = $self->{PERL_ARCHIVE_AFTER}
+};
+
+ push @m, "
+
+TO_INST_PM = ".$self->wraplist(sort keys %{$self->{PM}})."
+
+PM_TO_BLIB = ".$self->wraplist(%{$self->{PM}})."
+";
+
+ join('',@m);
+}
+
+
+=item depend (o)
+
+Same as macro for the depend attribute.
+
+=cut
+
+sub depend {
+ my($self,%attribs) = @_;
+ my(@m,$key,$val);
+ while (($key,$val) = each %attribs){
+ last unless defined $key;
+ push @m, "$key : $val\n";
+ }
+ join "", @m;
+}
+
+
+=item init_DEST
+
+ $mm->init_DEST
+
+Defines the DESTDIR and DEST* variables paralleling the INSTALL*.
+
+=cut
+
+sub init_DEST {
+ my $self = shift;
+
+ # Initialize DESTDIR
+ $self->{DESTDIR} ||= '';
+
+ # Make DEST variables.
+ foreach my $var ($self->installvars) {
+ my $destvar = 'DESTINSTALL'.$var;
+ $self->{$destvar} ||= '$(DESTDIR)$(INSTALL'.$var.')';
+ }
+}
+
+
+=item init_dist
+
+ $mm->init_dist;
+
+Defines a lot of macros for distribution support.
+
+ macro description default
+
+ TAR tar command to use tar
+ TARFLAGS flags to pass to TAR cvf
+
+ ZIP zip command to use zip
+ ZIPFLAGS flags to pass to ZIP -r
+
+ COMPRESS compression command to gzip --best
+ use for tarfiles
+ SUFFIX suffix to put on .gz
+ compressed files
+
+ SHAR shar command to use shar
+
+ PREOP extra commands to run before
+ making the archive
+ POSTOP extra commands to run after
+ making the archive
+
+ TO_UNIX a command to convert linefeeds
+ to Unix style in your archive
+
+ CI command to checkin your ci -u
+ sources to version control
+ RCS_LABEL command to label your sources rcs -Nv$(VERSION_SYM): -q
+ just after CI is run
+
+ DIST_CP $how argument to manicopy() best
+ when the distdir is created
+
+ DIST_DEFAULT default target to use to tardist
+ create a distribution
+
+ DISTVNAME name of the resulting archive $(DISTNAME)-$(VERSION)
+ (minus suffixes)
+
+=cut
+
+sub init_dist {
+ my $self = shift;
+
+ $self->{TAR} ||= 'tar';
+ $self->{TARFLAGS} ||= 'cvf';
+ $self->{ZIP} ||= 'zip';
+ $self->{ZIPFLAGS} ||= '-r';
+ $self->{COMPRESS} ||= 'gzip --best';
+ $self->{SUFFIX} ||= '.gz';
+ $self->{SHAR} ||= 'shar';
+ $self->{PREOP} ||= '$(NOECHO) $(NOOP)'; # eg update MANIFEST
+ $self->{POSTOP} ||= '$(NOECHO) $(NOOP)'; # eg remove the distdir
+ $self->{TO_UNIX} ||= '$(NOECHO) $(NOOP)';
+
+ $self->{CI} ||= 'ci -u';
+ $self->{RCS_LABEL}||= 'rcs -Nv$(VERSION_SYM): -q';
+ $self->{DIST_CP} ||= 'best';
+ $self->{DIST_DEFAULT} ||= 'tardist';
+
+ ($self->{DISTNAME} = $self->{NAME}) =~ s{::}{-}g unless $self->{DISTNAME};
+ $self->{DISTVNAME} ||= $self->{DISTNAME}.'-'.$self->{VERSION};
+
+}
+
+=item dist (o)
+
+ my $dist_macros = $mm->dist(%overrides);
+
+Generates a make fragment defining all the macros initialized in
+init_dist.
+
+%overrides can be used to override any of the above.
+
+=cut
+
+sub dist {
+ my($self, %attribs) = @_;
+
+ my $make = '';
+ foreach my $key (qw(
+ TAR TARFLAGS ZIP ZIPFLAGS COMPRESS SUFFIX SHAR
+ PREOP POSTOP TO_UNIX
+ CI RCS_LABEL DIST_CP DIST_DEFAULT
+ DISTNAME DISTVNAME
+ ))
+ {
+ my $value = $attribs{$key} || $self->{$key};
+ $make .= "$key = $value\n";
+ }
+
+ return $make;
+}
+
+=item dist_basics (o)
+
+Defines the targets distclean, distcheck, skipcheck, manifest, veryclean.
+
+=cut
+
+sub dist_basics {
+ my($self) = shift;
+
+ return <<'MAKE_FRAG';
+distclean :: realclean distcheck
+ $(NOECHO) $(NOOP)
+
+distcheck :
+ $(PERLRUN) "-MExtUtils::Manifest=fullcheck" -e fullcheck
+
+skipcheck :
+ $(PERLRUN) "-MExtUtils::Manifest=skipcheck" -e skipcheck
+
+manifest :
+ $(PERLRUN) "-MExtUtils::Manifest=mkmanifest" -e mkmanifest
+
+veryclean : realclean
+ $(RM_F) *~ */*~ *.orig */*.orig *.bak */*.bak *.old */*.old
+
+MAKE_FRAG
+
+}
+
+=item dist_ci (o)
+
+Defines a check in target for RCS.
+
+=cut
+
+sub dist_ci {
+ my($self) = shift;
+ return q{
+ci :
+ $(PERLRUN) "-MExtUtils::Manifest=maniread" \\
+ -e "@all = keys %{ maniread() };" \\
+ -e "print(qq{Executing $(CI) @all\n}); system(qq{$(CI) @all});" \\
+ -e "print(qq{Executing $(RCS_LABEL) ...\n}); system(qq{$(RCS_LABEL) @all});"
+};
+}
+
+=item dist_core (o)
+
+ my $dist_make_fragment = $MM->dist_core;
+
+Puts the targets necessary for 'make dist' together into one make
+fragment.
+
+=cut
+
+sub dist_core {
+ my($self) = shift;
+
+ my $make_frag = '';
+ foreach my $target (qw(dist tardist uutardist tarfile zipdist zipfile
+ shdist))
+ {
+ my $method = $target.'_target';
+ $make_frag .= "\n";
+ $make_frag .= $self->$method();
+ }
+
+ return $make_frag;
+}
+
+
+=item B<dist_target>
+
+ my $make_frag = $MM->dist_target;
+
+Returns the 'dist' target to make an archive for distribution. This
+target simply checks to make sure the Makefile is up-to-date and
+depends on $(DIST_DEFAULT).
+
+=cut
+
+sub dist_target {
+ my($self) = shift;
+
+ my $date_check = $self->oneliner(<<'CODE', ['-l']);
+print 'Warning: Makefile possibly out of date with $(VERSION_FROM)'
+ if -e '$(VERSION_FROM)' and -M '$(VERSION_FROM)' < -M '$(FIRST_MAKEFILE)';
+CODE
+
+ return sprintf <<'MAKE_FRAG', $date_check;
+dist : $(DIST_DEFAULT) $(FIRST_MAKEFILE)
+ $(NOECHO) %s
+MAKE_FRAG
+}
+
+=item B<tardist_target>
+
+ my $make_frag = $MM->tardist_target;
+
+Returns the 'tardist' target which is simply so 'make tardist' works.
+The real work is done by the dynamically named tardistfile_target()
+method, tardist should have that as a dependency.
+
+=cut
+
+sub tardist_target {
+ my($self) = shift;
+
+ return <<'MAKE_FRAG';
+tardist : $(DISTVNAME).tar$(SUFFIX)
+ $(NOECHO) $(NOOP)
+MAKE_FRAG
+}
+
+=item B<zipdist_target>
+
+ my $make_frag = $MM->zipdist_target;
+
+Returns the 'zipdist' target which is simply so 'make zipdist' works.
+The real work is done by the dynamically named zipdistfile_target()
+method, zipdist should have that as a dependency.
+
+=cut
+
+sub zipdist_target {
+ my($self) = shift;
+
+ return <<'MAKE_FRAG';
+zipdist : $(DISTVNAME).zip
+ $(NOECHO) $(NOOP)
+MAKE_FRAG
+}
+
+=item B<tarfile_target>
+
+ my $make_frag = $MM->tarfile_target;
+
+The name of this target is the name of the tarball generated by
+tardist. This target does the actual work of turning the distdir into
+a tarball.
+
+=cut
+
+sub tarfile_target {
+ my($self) = shift;
+
+ return <<'MAKE_FRAG';
+$(DISTVNAME).tar$(SUFFIX) : distdir
+ $(PREOP)
+ $(TO_UNIX)
+ $(TAR) $(TARFLAGS) $(DISTVNAME).tar $(DISTVNAME)
+ $(RM_RF) $(DISTVNAME)
+ $(COMPRESS) $(DISTVNAME).tar
+ $(POSTOP)
+MAKE_FRAG
+}
+
+=item zipfile_target
+
+ my $make_frag = $MM->zipfile_target;
+
+The name of this target is the name of the zip file generated by
+zipdist. This target does the actual work of turning the distdir into
+a zip file.
+
+=cut
+
+sub zipfile_target {
+ my($self) = shift;
+
+ return <<'MAKE_FRAG';
+$(DISTVNAME).zip : distdir
+ $(PREOP)
+ $(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME)
+ $(RM_RF) $(DISTVNAME)
+ $(POSTOP)
+MAKE_FRAG
+}
+
+=item uutardist_target
+
+ my $make_frag = $MM->uutardist_target;
+
+Converts the tarfile into a uuencoded file
+
+=cut
+
+sub uutardist_target {
+ my($self) = shift;
+
+ return <<'MAKE_FRAG';
+uutardist : $(DISTVNAME).tar$(SUFFIX)
+ uuencode $(DISTVNAME).tar$(SUFFIX) $(DISTVNAME).tar$(SUFFIX) > $(DISTVNAME).tar$(SUFFIX)_uu
+MAKE_FRAG
+}
+
+
+=item shdist_target
+
+ my $make_frag = $MM->shdist_target;
+
+Converts the distdir into a shell archive.
+
+=cut
+
+sub shdist_target {
+ my($self) = shift;
+
+ return <<'MAKE_FRAG';
+shdist : distdir
+ $(PREOP)
+ $(SHAR) $(DISTVNAME) > $(DISTVNAME).shar
+ $(RM_RF) $(DISTVNAME)
+ $(POSTOP)
+MAKE_FRAG
+}
+
+
+=item dlsyms (o)
+
+Used by some OS' to define DL_FUNCS and DL_VARS and write the *.exp files.
+
+Normally just returns an empty string.
+
+=cut
+
+sub dlsyms {
+ return '';
+}
+
+
+=item dynamic_bs (o)
+
+Defines targets for bootstrap files.
+
+=cut
+
+sub dynamic_bs {
+ my($self, %attribs) = @_;
+ return '
+BOOTSTRAP =
+' unless $self->has_link_code();
+
+ my $target = $Is{VMS} ? '$(MMS$TARGET)' : '$@';
+
+ return sprintf <<'MAKE_FRAG', ($target) x 5;
+BOOTSTRAP = $(BASEEXT).bs
+
+# As Mkbootstrap might not write a file (if none is required)
+# we use touch to prevent make continually trying to remake it.
+# The DynaLoader only reads a non-empty file.
+$(BOOTSTRAP) : $(FIRST_MAKEFILE) $(BOOTDEP) $(INST_ARCHAUTODIR)$(DFSEP).exists
+ $(NOECHO) $(ECHO) "Running Mkbootstrap for $(NAME) ($(BSLOADLIBS))"
+ $(NOECHO) $(PERLRUN) \
+ "-MExtUtils::Mkbootstrap" \
+ -e "Mkbootstrap('$(BASEEXT)','$(BSLOADLIBS)');"
+ $(NOECHO) $(TOUCH) %s
+ $(CHMOD) $(PERM_RW) %s
+
+$(INST_BOOT) : $(BOOTSTRAP) $(INST_ARCHAUTODIR)$(DFSEP).exists
+ $(NOECHO) $(RM_RF) %s
+ - $(CP) $(BOOTSTRAP) %s
+ $(CHMOD) $(PERM_RW) %s
+MAKE_FRAG
+}
+
+=item dynamic_lib (o)
+
+Defines how to produce the *.so (or equivalent) files.
+
+=cut
+
+sub dynamic_lib {
+ my($self, %attribs) = @_;
+ return '' unless $self->needs_linking(); #might be because of a subdir
+
+ return '' unless $self->has_link_code;
+
+ my($otherldflags) = $attribs{OTHERLDFLAGS} || "";
+ my($inst_dynamic_dep) = $attribs{INST_DYNAMIC_DEP} || "";
+ my($armaybe) = $attribs{ARMAYBE} || $self->{ARMAYBE} || ":";
+ my($ldfrom) = '$(LDFROM)';
+ $armaybe = 'ar' if ($Is{OSF} and $armaybe eq ':');
+ my(@m);
+ my $ld_opt = $Is{OS2} ? '$(OPTIMIZE) ' : ''; # Useful on other systems too?
+ my $ld_fix = $Is{OS2} ? '|| ( $(RM_F) $@ && sh -c false )' : '';
+ push(@m,'
+# This section creates the dynamically loadable $(INST_DYNAMIC)
+# from $(OBJECT) and possibly $(MYEXTLIB).
+ARMAYBE = '.$armaybe.'
+OTHERLDFLAGS = '.$ld_opt.$otherldflags.'
+INST_DYNAMIC_DEP = '.$inst_dynamic_dep.'
+INST_DYNAMIC_FIX = '.$ld_fix.'
+
+$(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)$(DFSEP).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(PERL_ARCHIVE_AFTER) $(INST_DYNAMIC_DEP)
+');
+ if ($armaybe ne ':'){
+ $ldfrom = 'tmp$(LIB_EXT)';
+ push(@m,' $(ARMAYBE) cr '.$ldfrom.' $(OBJECT)'."\n");
+ push(@m,' $(RANLIB) '."$ldfrom\n");
+ }
+ $ldfrom = "-all $ldfrom -none" if $Is{OSF};
+
+ # The IRIX linker doesn't use LD_RUN_PATH
+ my $ldrun = $Is{IRIX} && $self->{LD_RUN_PATH} ?
+ qq{-rpath "$self->{LD_RUN_PATH}"} : '';
+
+ # For example in AIX the shared objects/libraries from previous builds
+ # linger quite a while in the shared dynalinker cache even when nobody
+ # is using them. This is painful if one for instance tries to restart
+ # a failed build because the link command will fail unnecessarily 'cos
+ # the shared object/library is 'busy'.
+ push(@m,' $(RM_F) $@
+');
+
+ my $libs = '$(LDLOADLIBS)';
+
+ if (($Is{NetBSD} || $Is{Interix}) && $Config{'useshrplib'} eq 'true') {
+ # Use nothing on static perl platforms, and to the flags needed
+ # to link against the shared libperl library on shared perl
+ # platforms. We peek at lddlflags to see if we need -Wl,-R
+ # or -R to add paths to the run-time library search path.
+ if ($Config{'lddlflags'} =~ /-Wl,-R/) {
+ $libs .= ' -L$(PERL_INC) -Wl,-R$(INSTALLARCHLIB)/CORE -Wl,-R$(PERL_ARCHLIB)/CORE -lperl';
+ } elsif ($Config{'lddlflags'} =~ /-R/) {
+ $libs .= ' -L$(PERL_INC) -R$(INSTALLARCHLIB)/CORE -R$(PERL_ARCHLIB)/CORE -lperl';
+ }
+ }
+
+ my $ld_run_path_shell = "";
+ if ($self->{LD_RUN_PATH} ne "") {
+ $ld_run_path_shell = 'LD_RUN_PATH="$(LD_RUN_PATH)" ';
+ }
+
+ push @m, sprintf <<'MAKE', $ld_run_path_shell, $ldrun, $ldfrom, $libs;
+ %s$(LD) %s $(LDDLFLAGS) %s $(OTHERLDFLAGS) -o $@ $(MYEXTLIB) \
+ $(PERL_ARCHIVE) %s $(PERL_ARCHIVE_AFTER) $(EXPORT_LIST) \
+ $(INST_DYNAMIC_FIX)
+MAKE
+
+ push @m, <<'MAKE';
+ $(CHMOD) $(PERM_RWX) $@
+MAKE
+
+ return join('',@m);
+}
+
+=item exescan
+
+Deprecated method. Use libscan instead.
+
+=cut
+
+sub exescan {
+ my($self,$path) = @_;
+ $path;
+}
+
+=item extliblist
+
+Called by init_others, and calls ext ExtUtils::Liblist. See
+L<ExtUtils::Liblist> for details.
+
+=cut
+
+sub extliblist {
+ my($self,$libs) = @_;
+ require ExtUtils::Liblist;
+ $self->ext($libs, $Verbose);
+}
+
+=item find_perl
+
+Finds the executables PERL and FULLPERL
+
+=cut
+
+sub find_perl {
+ my($self, $ver, $names, $dirs, $trace) = @_;
+
+ if ($trace >= 2){
+ print "Looking for perl $ver by these names:
+@$names
+in these dirs:
+@$dirs
+";
+ }
+
+ my $stderr_duped = 0;
+ local *STDERR_COPY;
+
+ unless ($Is{BSD}) {
+ # >& and lexical filehandles together give 5.6.2 indigestion
+ if( open(STDERR_COPY, '>&STDERR') ) { ## no critic
+ $stderr_duped = 1;
+ }
+ else {
+ warn <<WARNING;
+find_perl() can't dup STDERR: $!
+You might see some garbage while we search for Perl
+WARNING
+ }
+ }
+
+ foreach my $name (@$names){
+ foreach my $dir (@$dirs){
+ next unless defined $dir; # $self->{PERL_SRC} may be undefined
+ my ($abs, $val);
+ if ($self->file_name_is_absolute($name)) { # /foo/bar
+ $abs = $name;
+ } elsif ($self->canonpath($name) eq
+ $self->canonpath(basename($name))) { # foo
+ $abs = $self->catfile($dir, $name);
+ } else { # foo/bar
+ $abs = $self->catfile($Curdir, $name);
+ }
+ print "Checking $abs\n" if ($trace >= 2);
+ next unless $self->maybe_command($abs);
+ print "Executing $abs\n" if ($trace >= 2);
+
+ my $version_check = qq{$abs -le "require $ver; print qq{VER_OK}"};
+ $version_check = "$Config{run} $version_check"
+ if defined $Config{run} and length $Config{run};
+
+ # To avoid using the unportable 2>&1 to suppress STDERR,
+ # we close it before running the command.
+ # However, thanks to a thread library bug in many BSDs
+ # ( http://www.freebsd.org/cgi/query-pr.cgi?pr=51535 )
+ # we cannot use the fancier more portable way in here
+ # but instead need to use the traditional 2>&1 construct.
+ if ($Is{BSD}) {
+ $val = `$version_check 2>&1`;
+ } else {
+ close STDERR if $stderr_duped;
+ $val = `$version_check`;
+
+ # 5.6.2's 3-arg open doesn't work with >&
+ open STDERR, ">&STDERR_COPY" ## no critic
+ if $stderr_duped;
+ }
+
+ if ($val =~ /^VER_OK/m) {
+ print "Using PERL=$abs\n" if $trace;
+ return $abs;
+ } elsif ($trace >= 2) {
+ print "Result: '$val' ".($? >> 8)."\n";
+ }
+ }
+ }
+ print STDOUT "Unable to find a perl $ver (by these names: @$names, in these dirs: @$dirs)\n";
+ 0; # false and not empty
+}
+
+
+=item fixin
+
+ $mm->fixin(@files);
+
+Inserts the sharpbang or equivalent magic number to a set of @files.
+
+=cut
+
+sub fixin { # stolen from the pink Camel book, more or less
+ my ( $self, @files ) = @_;
+
+ my ($does_shbang) = $Config{'sharpbang'} =~ /^\s*\#\!/;
+ for my $file (@files) {
+ my $file_new = "$file.new";
+ my $file_bak = "$file.bak";
+
+ open( my $fixin, '<', $file ) or croak "Can't process '$file': $!";
+ local $/ = "\n";
+ chomp( my $line = <$fixin> );
+ next unless $line =~ s/^\s*\#!\s*//; # Not a shbang file.
+ # Now figure out the interpreter name.
+ my ( $cmd, $arg ) = split ' ', $line, 2;
+ $cmd =~ s!^.*/!!;
+
+ # Now look (in reverse) for interpreter in absolute PATH (unless perl).
+ my $interpreter;
+ if ( $cmd =~ m{^perl(?:\z|[^a-z])} ) {
+ if ( $Config{startperl} =~ m,^\#!.*/perl, ) {
+ $interpreter = $Config{startperl};
+ $interpreter =~ s,^\#!,,;
+ }
+ else {
+ $interpreter = $Config{perlpath};
+ }
+ }
+ else {
+ my (@absdirs)
+ = reverse grep { $self->file_name_is_absolute($_) } $self->path;
+ $interpreter = '';
+
+ foreach my $dir (@absdirs) {
+ if ( $self->maybe_command($cmd) ) {
+ warn "Ignoring $interpreter in $file\n"
+ if $Verbose && $interpreter;
+ $interpreter = $self->catfile( $dir, $cmd );
+ }
+ }
+ }
+
+ # Figure out how to invoke interpreter on this machine.
+
+ my ($shb) = "";
+ if ($interpreter) {
+ print STDOUT "Changing sharpbang in $file to $interpreter"
+ if $Verbose;
+
+ # this is probably value-free on DOSISH platforms
+ if ($does_shbang) {
+ $shb .= "$Config{'sharpbang'}$interpreter";
+ $shb .= ' ' . $arg if defined $arg;
+ $shb .= "\n";
+ }
+ $shb .= qq{
+eval 'exec $interpreter $arg -S \$0 \${1+"\$\@"}'
+ if 0; # not running under some shell
+} unless $Is{Win32}; # this won't work on win32, so don't
+ }
+ else {
+ warn "Can't find $cmd in PATH, $file unchanged"
+ if $Verbose;
+ next;
+ }
+
+ open( my $fixout, ">", "$file_new" ) or do {
+ warn "Can't create new $file: $!\n";
+ next;
+ };
+
+ # Print out the new #! line (or equivalent).
+ local $\;
+ local $/;
+ print $fixout $shb, <$fixin>;
+ close $fixin;
+ close $fixout;
+
+ chmod 0666, $file_bak;
+ unlink $file_bak;
+ unless ( _rename( $file, $file_bak ) ) {
+ warn "Can't rename $file to $file_bak: $!";
+ next;
+ }
+ unless ( _rename( $file_new, $file ) ) {
+ warn "Can't rename $file_new to $file: $!";
+ unless ( _rename( $file_bak, $file ) ) {
+ warn "Can't rename $file_bak back to $file either: $!";
+ warn "Leaving $file renamed as $file_bak\n";
+ }
+ next;
+ }
+ unlink $file_bak;
+ }
+ continue {
+ system("$Config{'eunicefix'} $file") if $Config{'eunicefix'} ne ':';
+ }
+}
+
+
+sub _rename {
+ my($old, $new) = @_;
+
+ foreach my $file ($old, $new) {
+ if( $Is{VMS} and basename($file) !~ /\./ ) {
+ # rename() in 5.8.0 on VMS will not rename a file if it
+ # does not contain a dot yet it returns success.
+ $file = "$file.";
+ }
+ }
+
+ return rename($old, $new);
+}
+
+
+=item force (o)
+
+Writes an empty FORCE: target.
+
+=cut
+
+sub force {
+ my($self) = shift;
+ '# Phony target to force checking subdirectories.
+FORCE :
+ $(NOECHO) $(NOOP)
+';
+}
+
+=item guess_name
+
+Guess the name of this package by examining the working directory's
+name. MakeMaker calls this only if the developer has not supplied a
+NAME attribute.
+
+=cut
+
+# ';
+
+sub guess_name {
+ my($self) = @_;
+ use Cwd 'cwd';
+ my $name = basename(cwd());
+ $name =~ s|[\-_][\d\.\-]+\z||; # this is new with MM 5.00, we
+ # strip minus or underline
+ # followed by a float or some such
+ print "Warning: Guessing NAME [$name] from current directory name.\n";
+ $name;
+}
+
+=item has_link_code
+
+Returns true if C, XS, MYEXTLIB or similar objects exist within this
+object that need a compiler. Does not descend into subdirectories as
+needs_linking() does.
+
+=cut
+
+sub has_link_code {
+ my($self) = shift;
+ return $self->{HAS_LINK_CODE} if defined $self->{HAS_LINK_CODE};
+ if ($self->{OBJECT} or @{$self->{C} || []} or $self->{MYEXTLIB}){
+ $self->{HAS_LINK_CODE} = 1;
+ return 1;
+ }
+ return $self->{HAS_LINK_CODE} = 0;
+}
+
+
+=item init_dirscan
+
+Scans the directory structure and initializes DIR, XS, XS_FILES,
+C, C_FILES, O_FILES, H, H_FILES, PL_FILES, EXE_FILES.
+
+Called by init_main.
+
+=cut
+
+sub init_dirscan { # --- File and Directory Lists (.xs .pm .pod etc)
+ my($self) = @_;
+ my(%dir, %xs, %c, %h, %pl_files, %pm);
+
+ my %ignore = map {( $_ => 1 )} qw(Makefile.PL Build.PL test.pl t);
+
+ # ignore the distdir
+ $Is{VMS} ? $ignore{"$self->{DISTVNAME}.dir"} = 1
+ : $ignore{$self->{DISTVNAME}} = 1;
+
+ @ignore{map lc, keys %ignore} = values %ignore if $Is{VMS};
+
+ foreach my $name ($self->lsdir($Curdir)){
+ next if $name =~ /\#/;
+ next if $name eq $Curdir or $name eq $Updir or $ignore{$name};
+ next unless $self->libscan($name);
+ if (-d $name){
+ next if -l $name; # We do not support symlinks at all
+ next if $self->{NORECURS};
+ $dir{$name} = $name if (-f $self->catfile($name,"Makefile.PL"));
+ } elsif ($name =~ /\.xs\z/){
+ my($c); ($c = $name) =~ s/\.xs\z/.c/;
+ $xs{$name} = $c;
+ $c{$c} = 1;
+ } elsif ($name =~ /\.c(pp|xx|c)?\z/i){ # .c .C .cpp .cxx .cc
+ $c{$name} = 1
+ unless $name =~ m/perlmain\.c/; # See MAP_TARGET
+ } elsif ($name =~ /\.h\z/i){
+ $h{$name} = 1;
+ } elsif ($name =~ /\.PL\z/) {
+ ($pl_files{$name} = $name) =~ s/\.PL\z// ;
+ } elsif (($Is{VMS} || $Is{Dos}) && $name =~ /[._]pl$/i) {
+ # case-insensitive filesystem, one dot per name, so foo.h.PL
+ # under Unix appears as foo.h_pl under VMS or fooh.pl on Dos
+ local($/); open(my $pl, '<', $name); my $txt = <$pl>; close $pl;
+ if ($txt =~ /Extracting \S+ \(with variable substitutions/) {
+ ($pl_files{$name} = $name) =~ s/[._]pl\z//i ;
+ }
+ else {
+ $pm{$name} = $self->catfile($self->{INST_LIBDIR},$name);
+ }
+ } elsif ($name =~ /\.(p[ml]|pod)\z/){
+ $pm{$name} = $self->catfile($self->{INST_LIBDIR},$name);
+ }
+ }
+
+ $self->{PL_FILES} ||= \%pl_files;
+ $self->{DIR} ||= [sort keys %dir];
+ $self->{XS} ||= \%xs;
+ $self->{C} ||= [sort keys %c];
+ $self->{H} ||= [sort keys %h];
+ $self->{PM} ||= \%pm;
+
+ my @o_files = @{$self->{C}};
+ $self->{O_FILES} = [grep s/\.c(pp|xx|c)?\z/$self->{OBJ_EXT}/i, @o_files];
+}
+
+
+=item init_MANPODS
+
+Determines if man pages should be generated and initializes MAN1PODS
+and MAN3PODS as appropriate.
+
+=cut
+
+sub init_MANPODS {
+ my $self = shift;
+
+ # Set up names of manual pages to generate from pods
+ foreach my $man (qw(MAN1 MAN3)) {
+ if ( $self->{"${man}PODS"}
+ or $self->{"INSTALL${man}DIR"} =~ /^(none|\s*)$/
+ ) {
+ $self->{"${man}PODS"} ||= {};
+ }
+ else {
+ my $init_method = "init_${man}PODS";
+ $self->$init_method();
+ }
+ }
+}
+
+
+sub _has_pod {
+ my($self, $file) = @_;
+
+ my($ispod)=0;
+ if (open( my $fh, '<', $file )) {
+ while (<$fh>) {
+ if (/^=(?:head\d+|item|pod)\b/) {
+ $ispod=1;
+ last;
+ }
+ }
+ close $fh;
+ } else {
+ # If it doesn't exist yet, we assume, it has pods in it
+ $ispod = 1;
+ }
+
+ return $ispod;
+}
+
+
+=item init_MAN1PODS
+
+Initializes MAN1PODS from the list of EXE_FILES.
+
+=cut
+
+sub init_MAN1PODS {
+ my($self) = @_;
+
+ if ( exists $self->{EXE_FILES} ) {
+ foreach my $name (@{$self->{EXE_FILES}}) {
+ next unless $self->_has_pod($name);
+
+ $self->{MAN1PODS}->{$name} =
+ $self->catfile("\$(INST_MAN1DIR)",
+ basename($name).".\$(MAN1EXT)");
+ }
+ }
+}
+
+
+=item init_MAN3PODS
+
+Initializes MAN3PODS from the list of PM files.
+
+=cut
+
+sub init_MAN3PODS {
+ my $self = shift;
+
+ my %manifypods = (); # we collect the keys first, i.e. the files
+ # we have to convert to pod
+
+ foreach my $name (keys %{$self->{PM}}) {
+ if ($name =~ /\.pod\z/ ) {
+ $manifypods{$name} = $self->{PM}{$name};
+ } elsif ($name =~ /\.p[ml]\z/ ) {
+ if( $self->_has_pod($name) ) {
+ $manifypods{$name} = $self->{PM}{$name};
+ }
+ }
+ }
+
+ my $parentlibs_re = join '|', @{$self->{PMLIBPARENTDIRS}};
+
+ # Remove "Configure.pm" and similar, if it's not the only pod listed
+ # To force inclusion, just name it "Configure.pod", or override
+ # MAN3PODS
+ foreach my $name (keys %manifypods) {
+ if ($self->{PERL_CORE} and $name =~ /(config|setup).*\.pm/is) {
+ delete $manifypods{$name};
+ next;
+ }
+ my($manpagename) = $name;
+ $manpagename =~ s/\.p(od|m|l)\z//;
+ # everything below lib is ok
+ unless($manpagename =~ s!^\W*($parentlibs_re)\W+!!s) {
+ $manpagename = $self->catfile(
+ split(/::/,$self->{PARENT_NAME}),$manpagename
+ );
+ }
+ $manpagename = $self->replace_manpage_separator($manpagename);
+ $self->{MAN3PODS}->{$name} =
+ $self->catfile("\$(INST_MAN3DIR)", "$manpagename.\$(MAN3EXT)");
+ }
+}
+
+
+=item init_PM
+
+Initializes PMLIBDIRS and PM from PMLIBDIRS.
+
+=cut
+
+sub init_PM {
+ my $self = shift;
+
+ # Some larger extensions often wish to install a number of *.pm/pl
+ # files into the library in various locations.
+
+ # The attribute PMLIBDIRS holds an array reference which lists
+ # subdirectories which we should search for library files to
+ # install. PMLIBDIRS defaults to [ 'lib', $self->{BASEEXT} ]. We
+ # recursively search through the named directories (skipping any
+ # which don't exist or contain Makefile.PL files).
+
+ # For each *.pm or *.pl file found $self->libscan() is called with
+ # the default installation path in $_[1]. The return value of
+ # libscan defines the actual installation location. The default
+ # libscan function simply returns the path. The file is skipped
+ # if libscan returns false.
+
+ # The default installation location passed to libscan in $_[1] is:
+ #
+ # ./*.pm => $(INST_LIBDIR)/*.pm
+ # ./xyz/... => $(INST_LIBDIR)/xyz/...
+ # ./lib/... => $(INST_LIB)/...
+ #
+ # In this way the 'lib' directory is seen as the root of the actual
+ # perl library whereas the others are relative to INST_LIBDIR
+ # (which includes PARENT_NAME). This is a subtle distinction but one
+ # that's important for nested modules.
+
+ unless( $self->{PMLIBDIRS} ) {
+ if( $Is{VMS} ) {
+ # Avoid logical name vs directory collisions
+ $self->{PMLIBDIRS} = ['./lib', "./$self->{BASEEXT}"];
+ }
+ else {
+ $self->{PMLIBDIRS} = ['lib', $self->{BASEEXT}];
+ }
+ }
+
+ #only existing directories that aren't in $dir are allowed
+
+ # Avoid $_ wherever possible:
+ # @{$self->{PMLIBDIRS}} = grep -d && !$dir{$_}, @{$self->{PMLIBDIRS}};
+ my (@pmlibdirs) = @{$self->{PMLIBDIRS}};
+ @{$self->{PMLIBDIRS}} = ();
+ my %dir = map { ($_ => $_) } @{$self->{DIR}};
+ foreach my $pmlibdir (@pmlibdirs) {
+ -d $pmlibdir && !$dir{$pmlibdir} && push @{$self->{PMLIBDIRS}}, $pmlibdir;
+ }
+
+ unless( $self->{PMLIBPARENTDIRS} ) {
+ @{$self->{PMLIBPARENTDIRS}} = ('lib');
+ }
+
+ return if $self->{PM} and $self->{ARGS}{PM};
+
+ if (@{$self->{PMLIBDIRS}}){
+ print "Searching PMLIBDIRS: @{$self->{PMLIBDIRS}}\n"
+ if ($Verbose >= 2);
+ require File::Find;
+ File::Find::find(sub {
+ if (-d $_){
+ unless ($self->libscan($_)){
+ $File::Find::prune = 1;
+ }
+ return;
+ }
+ return if /\#/;
+ return if /~$/; # emacs temp files
+ return if /,v$/; # RCS files
+ return if m{\.swp$}; # vim swap files
+
+ my $path = $File::Find::name;
+ my $prefix = $self->{INST_LIBDIR};
+ my $striplibpath;
+
+ my $parentlibs_re = join '|', @{$self->{PMLIBPARENTDIRS}};
+ $prefix = $self->{INST_LIB}
+ if ($striplibpath = $path) =~ s{^(\W*)($parentlibs_re)\W}
+ {$1}i;
+
+ my($inst) = $self->catfile($prefix,$striplibpath);
+ local($_) = $inst; # for backwards compatibility
+ $inst = $self->libscan($inst);
+ print "libscan($path) => '$inst'\n" if ($Verbose >= 2);
+ return unless $inst;
+ $self->{PM}{$path} = $inst;
+ }, @{$self->{PMLIBDIRS}});
+ }
+}
+
+
+=item init_DIRFILESEP
+
+Using / for Unix. Called by init_main.
+
+=cut
+
+sub init_DIRFILESEP {
+ my($self) = shift;
+
+ $self->{DIRFILESEP} = '/';
+}
+
+
+=item init_main
+
+Initializes AR, AR_STATIC_ARGS, BASEEXT, CONFIG, DISTNAME, DLBASE,
+EXE_EXT, FULLEXT, FULLPERL, FULLPERLRUN, FULLPERLRUNINST, INST_*,
+INSTALL*, INSTALLDIRS, LIB_EXT, LIBPERL_A, MAP_TARGET, NAME,
+OBJ_EXT, PARENT_NAME, PERL, PERL_ARCHLIB, PERL_INC, PERL_LIB,
+PERL_SRC, PERLRUN, PERLRUNINST, PREFIX, VERSION,
+VERSION_SYM, XS_VERSION.
+
+=cut
+
+sub init_main {
+ my($self) = @_;
+
+ # --- Initialize Module Name and Paths
+
+ # NAME = Foo::Bar::Oracle
+ # FULLEXT = Foo/Bar/Oracle
+ # BASEEXT = Oracle
+ # PARENT_NAME = Foo::Bar
+### Only UNIX:
+### ($self->{FULLEXT} =
+### $self->{NAME}) =~ s!::!/!g ; #eg. BSD/Foo/Socket
+ $self->{FULLEXT} = $self->catdir(split /::/, $self->{NAME});
+
+
+ # Copied from DynaLoader:
+
+ my(@modparts) = split(/::/,$self->{NAME});
+ my($modfname) = $modparts[-1];
+
+ # Some systems have restrictions on files names for DLL's etc.
+ # mod2fname returns appropriate file base name (typically truncated)
+ # It may also edit @modparts if required.
+ if (defined &DynaLoader::mod2fname) {
+ $modfname = &DynaLoader::mod2fname(\@modparts);
+ }
+
+ ($self->{PARENT_NAME}, $self->{BASEEXT}) = $self->{NAME} =~ m!(?:([\w:]+)::)?(\w+)\z! ;
+ $self->{PARENT_NAME} ||= '';
+
+ if (defined &DynaLoader::mod2fname) {
+ # As of 5.001m, dl_os2 appends '_'
+ $self->{DLBASE} = $modfname;
+ } else {
+ $self->{DLBASE} = '$(BASEEXT)';
+ }
+
+
+ # --- Initialize PERL_LIB, PERL_SRC
+
+ # *Real* information: where did we get these two from? ...
+ my $inc_config_dir = dirname($INC{'Config.pm'});
+ my $inc_carp_dir = dirname($INC{'Carp.pm'});
+
+ unless ($self->{PERL_SRC}){
+ foreach my $dir_count (1..8) { # 8 is the VMS limit for nesting
+ my $dir = $self->catdir(($Updir) x $dir_count);
+
+ if (-f $self->catfile($dir,"config_h.SH") &&
+ -f $self->catfile($dir,"perl.h") &&
+ -f $self->catfile($dir,"lib","strict.pm")
+ ) {
+ $self->{PERL_SRC}=$dir ;
+ last;
+ }
+ }
+ }
+
+ warn "PERL_CORE is set but I can't find your PERL_SRC!\n" if
+ $self->{PERL_CORE} and !$self->{PERL_SRC};
+
+ if ($self->{PERL_SRC}){
+ $self->{PERL_LIB} ||= $self->catdir("$self->{PERL_SRC}","lib");
+
+ if (defined $Cross::platform) {
+ $self->{PERL_ARCHLIB} =
+ $self->catdir("$self->{PERL_SRC}","xlib",$Cross::platform);
+ $self->{PERL_INC} =
+ $self->catdir("$self->{PERL_SRC}","xlib",$Cross::platform,
+ $Is{Win32}?("CORE"):());
+ }
+ else {
+ $self->{PERL_ARCHLIB} = $self->{PERL_LIB};
+ $self->{PERL_INC} = ($Is{Win32}) ?
+ $self->catdir($self->{PERL_LIB},"CORE") : $self->{PERL_SRC};
+ }
+
+ # catch a situation that has occurred a few times in the past:
+ unless (
+ -s $self->catfile($self->{PERL_SRC},'cflags')
+ or
+ $Is{VMS}
+ &&
+ -s $self->catfile($self->{PERL_SRC},'vmsish.h')
+ or
+ $Is{Win32}
+ ){
+ warn qq{
+You cannot build extensions below the perl source tree after executing
+a 'make clean' in the perl source tree.
+
+To rebuild extensions distributed with the perl source you should
+simply Configure (to include those extensions) and then build perl as
+normal. After installing perl the source tree can be deleted. It is
+not needed for building extensions by running 'perl Makefile.PL'
+usually without extra arguments.
+
+It is recommended that you unpack and build additional extensions away
+from the perl source tree.
+};
+ }
+ } else {
+ # we should also consider $ENV{PERL5LIB} here
+ my $old = $self->{PERL_LIB} || $self->{PERL_ARCHLIB} || $self->{PERL_INC};
+ $self->{PERL_LIB} ||= $Config{privlibexp};
+ $self->{PERL_ARCHLIB} ||= $Config{archlibexp};
+ $self->{PERL_INC} = $self->catdir("$self->{PERL_ARCHLIB}","CORE"); # wild guess for now
+ my $perl_h;
+
+ if (not -f ($perl_h = $self->catfile($self->{PERL_INC},"perl.h"))
+ and not $old){
+ # Maybe somebody tries to build an extension with an
+ # uninstalled Perl outside of Perl build tree
+ my $lib;
+ for my $dir (@INC) {
+ $lib = $dir, last if -e $self->catfile($dir, "Config.pm");
+ }
+ if ($lib) {
+ # Win32 puts its header files in /perl/src/lib/CORE.
+ # Unix leaves them in /perl/src.
+ my $inc = $Is{Win32} ? $self->catdir($lib, "CORE" )
+ : dirname $lib;
+ if (-e $self->catfile($inc, "perl.h")) {
+ $self->{PERL_LIB} = $lib;
+ $self->{PERL_ARCHLIB} = $lib;
+ $self->{PERL_INC} = $inc;
+ $self->{UNINSTALLED_PERL} = 1;
+ print STDOUT <<EOP;
+... Detected uninstalled Perl. Trying to continue.
+EOP
+ }
+ }
+ }
+ }
+
+ # We get SITELIBEXP and SITEARCHEXP directly via
+ # Get_from_Config. When we are running standard modules, these
+ # won't matter, we will set INSTALLDIRS to "perl". Otherwise we
+ # set it to "site". I prefer that INSTALLDIRS be set from outside
+ # MakeMaker.
+ $self->{INSTALLDIRS} ||= "site";
+
+ $self->{MAN1EXT} ||= $Config{man1ext};
+ $self->{MAN3EXT} ||= $Config{man3ext};
+
+ # Get some stuff out of %Config if we haven't yet done so
+ print STDOUT "CONFIG must be an array ref\n"
+ if ($self->{CONFIG} and ref $self->{CONFIG} ne 'ARRAY');
+ $self->{CONFIG} = [] unless (ref $self->{CONFIG});
+ push(@{$self->{CONFIG}}, @ExtUtils::MakeMaker::Get_from_Config);
+ push(@{$self->{CONFIG}}, 'shellflags') if $Config{shellflags};
+ my(%once_only);
+ foreach my $m (@{$self->{CONFIG}}){
+ next if $once_only{$m};
+ print STDOUT "CONFIG key '$m' does not exist in Config.pm\n"
+ unless exists $Config{$m};
+ $self->{uc $m} ||= $Config{$m};
+ $once_only{$m} = 1;
+ }
+
+# This is too dangerous:
+# if ($^O eq "next") {
+# $self->{AR} = "libtool";
+# $self->{AR_STATIC_ARGS} = "-o";
+# }
+# But I leave it as a placeholder
+
+ $self->{AR_STATIC_ARGS} ||= "cr";
+
+ # These should never be needed
+ $self->{OBJ_EXT} ||= '.o';
+ $self->{LIB_EXT} ||= '.a';
+
+ $self->{MAP_TARGET} ||= "perl";
+
+ $self->{LIBPERL_A} ||= "libperl$self->{LIB_EXT}";
+
+ # make a simple check if we find strict
+ warn "Warning: PERL_LIB ($self->{PERL_LIB}) seems not to be a perl library directory
+ (strict.pm not found)"
+ unless -f $self->catfile("$self->{PERL_LIB}","strict.pm") ||
+ $self->{NAME} eq "ExtUtils::MakeMaker";
+}
+
+=item init_others
+
+Initializes EXTRALIBS, BSLOADLIBS, LDLOADLIBS, LIBS, LD_RUN_PATH, LD,
+OBJECT, BOOTDEP, PERLMAINCC, LDFROM, LINKTYPE, SHELL, NOOP,
+FIRST_MAKEFILE, MAKEFILE_OLD, NOECHO, RM_F, RM_RF, TEST_F,
+TOUCH, CP, MV, CHMOD, UMASK_NULL, ECHO, ECHO_N
+
+=cut
+
+sub init_others { # --- Initialize Other Attributes
+ my($self) = shift;
+
+ $self->{ECHO} ||= 'echo';
+ $self->{ECHO_N} ||= 'echo -n';
+ $self->{RM_F} ||= "rm -f";
+ $self->{RM_RF} ||= "rm -rf";
+ $self->{TOUCH} ||= "touch";
+ $self->{TEST_F} ||= "test -f";
+ $self->{CP} ||= "cp";
+ $self->{MV} ||= "mv";
+ $self->{CHMOD} ||= "chmod";
+ $self->{FALSE} ||= 'false';
+ $self->{TRUE} ||= 'true';
+
+ $self->{LD} ||= 'ld';
+
+ $self->SUPER::init_others(@_);
+
+ # After SUPER::init_others so $Config{shell} has a
+ # chance to get set.
+ $self->{SHELL} ||= '/bin/sh';
+
+ return 1;
+}
+
+
+=item init_linker
+
+Unix has no need of special linker flags.
+
+=cut
+
+sub init_linker {
+ my($self) = shift;
+ $self->{PERL_ARCHIVE} ||= '';
+ $self->{PERL_ARCHIVE_AFTER} ||= '';
+ $self->{EXPORT_LIST} ||= '';
+}
+
+
+=begin _protected
+
+=item init_lib2arch
+
+ $mm->init_lib2arch
+
+=end _protected
+
+=cut
+
+sub init_lib2arch {
+ my($self) = shift;
+
+ # The user who requests an installation directory explicitly
+ # should not have to tell us an architecture installation directory
+ # as well. We look if a directory exists that is named after the
+ # architecture. If not we take it as a sign that it should be the
+ # same as the requested installation directory. Otherwise we take
+ # the found one.
+ for my $libpair ({l=>"privlib", a=>"archlib"},
+ {l=>"sitelib", a=>"sitearch"},
+ {l=>"vendorlib", a=>"vendorarch"},
+ )
+ {
+ my $lib = "install$libpair->{l}";
+ my $Lib = uc $lib;
+ my $Arch = uc "install$libpair->{a}";
+ if( $self->{$Lib} && ! $self->{$Arch} ){
+ my($ilib) = $Config{$lib};
+
+ $self->prefixify($Arch,$ilib,$self->{$Lib});
+
+ unless (-d $self->{$Arch}) {
+ print STDOUT "Directory $self->{$Arch} not found\n"
+ if $Verbose;
+ $self->{$Arch} = $self->{$Lib};
+ }
+ print STDOUT "Defaulting $Arch to $self->{$Arch}\n" if $Verbose;
+ }
+ }
+}
+
+
+=item init_PERL
+
+ $mm->init_PERL;
+
+Called by init_main. Sets up ABSPERL, PERL, FULLPERL and all the
+*PERLRUN* permutations.
+
+ PERL is allowed to be miniperl
+ FULLPERL must be a complete perl
+
+ ABSPERL is PERL converted to an absolute path
+
+ *PERLRUN contains everything necessary to run perl, find it's
+ libraries, etc...
+
+ *PERLRUNINST is *PERLRUN + everything necessary to find the
+ modules being built.
+
+=cut
+
+sub init_PERL {
+ my($self) = shift;
+
+ my @defpath = ();
+ foreach my $component ($self->{PERL_SRC}, $self->path(),
+ $Config{binexp})
+ {
+ push @defpath, $component if defined $component;
+ }
+
+ # Build up a set of file names (not command names).
+ my $thisperl = $self->canonpath($^X);
+ $thisperl .= $Config{exe_ext} unless
+ # VMS might have a file version # at the end
+ $Is{VMS} ? $thisperl =~ m/$Config{exe_ext}(;\d+)?$/i
+ : $thisperl =~ m/$Config{exe_ext}$/i;
+
+ # We need a relative path to perl when in the core.
+ $thisperl = $self->abs2rel($thisperl) if $self->{PERL_CORE};
+
+ my @perls = ($thisperl);
+ push @perls, map { "$_$Config{exe_ext}" }
+ ('perl', 'perl5', "perl$Config{version}");
+
+ # miniperl has priority over all but the cannonical perl when in the
+ # core. Otherwise its a last resort.
+ my $miniperl = "miniperl$Config{exe_ext}";
+ if( $self->{PERL_CORE} ) {
+ splice @perls, 1, 0, $miniperl;
+ }
+ else {
+ push @perls, $miniperl;
+ }
+
+ $self->{PERL} ||=
+ $self->find_perl(5.0, \@perls, \@defpath, $Verbose );
+ # don't check if perl is executable, maybe they have decided to
+ # supply switches with perl
+
+ # When built for debugging, VMS doesn't create perl.exe but ndbgperl.exe.
+ my $perl_name = 'perl';
+ $perl_name = 'ndbgperl' if $Is{VMS} &&
+ defined $Config{usevmsdebug} && $Config{usevmsdebug} eq 'define';
+
+ # XXX This logic is flawed. If "miniperl" is anywhere in the path
+ # it will get confused. It should be fixed to work only on the filename.
+ # Define 'FULLPERL' to be a non-miniperl (used in test: target)
+ ($self->{FULLPERL} = $self->{PERL}) =~ s/miniperl/$perl_name/i
+ unless $self->{FULLPERL};
+
+ # Little hack to get around VMS's find_perl putting "MCR" in front
+ # sometimes.
+ $self->{ABSPERL} = $self->{PERL};
+ my $has_mcr = $self->{ABSPERL} =~ s/^MCR\s*//;
+ if( $self->file_name_is_absolute($self->{ABSPERL}) ) {
+ $self->{ABSPERL} = '$(PERL)';
+ }
+ else {
+ $self->{ABSPERL} = $self->rel2abs($self->{ABSPERL});
+
+ # Quote the perl command if it contains whitespace
+ $self->{ABSPERL} = $self->quote_literal($self->{ABSPERL})
+ if $self->{ABSPERL} =~ /\s/;
+
+ $self->{ABSPERL} = 'MCR '.$self->{ABSPERL} if $has_mcr;
+ }
+
+ # Are we building the core?
+ $self->{PERL_CORE} = $ENV{PERL_CORE} unless exists $self->{PERL_CORE};
+ $self->{PERL_CORE} = 0 unless defined $self->{PERL_CORE};
+
+ # How do we run perl?
+ foreach my $perl (qw(PERL FULLPERL ABSPERL)) {
+ my $run = $perl.'RUN';
+
+ $self->{$run} = "\$($perl)";
+
+ # Make sure perl can find itself before it's installed.
+ $self->{$run} .= q{ "-I$(PERL_LIB)" "-I$(PERL_ARCHLIB)"}
+ if $self->{UNINSTALLED_PERL} || $self->{PERL_CORE};
+
+ $self->{$perl.'RUNINST'} =
+ sprintf q{$(%sRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)"}, $perl;
+ }
+
+ return 1;
+}
+
+
+=item init_platform
+
+=item platform_constants
+
+Add MM_Unix_VERSION.
+
+=cut
+
+sub init_platform {
+ my($self) = shift;
+
+ $self->{MM_Unix_VERSION} = $VERSION;
+ $self->{PERL_MALLOC_DEF} = '-DPERL_EXTMALLOC_DEF -Dmalloc=Perl_malloc '.
+ '-Dfree=Perl_mfree -Drealloc=Perl_realloc '.
+ '-Dcalloc=Perl_calloc';
+
+}
+
+sub platform_constants {
+ my($self) = shift;
+ my $make_frag = '';
+
+ foreach my $macro (qw(MM_Unix_VERSION PERL_MALLOC_DEF))
+ {
+ next unless defined $self->{$macro};
+ $make_frag .= "$macro = $self->{$macro}\n";
+ }
+
+ return $make_frag;
+}
+
+
+=item init_PERM
+
+ $mm->init_PERM
+
+Called by init_main. Initializes PERL_*
+
+=cut
+
+sub init_PERM {
+ my($self) = shift;
+
+ $self->{PERM_DIR} = 755 unless defined $self->{PERM_DIR};
+ $self->{PERM_RW} = 644 unless defined $self->{PERM_RW};
+ $self->{PERM_RWX} = 755 unless defined $self->{PERM_RWX};
+
+ return 1;
+}
+
+
+=item init_xs
+
+ $mm->init_xs
+
+Sets up macros having to do with XS code. Currently just INST_STATIC,
+INST_DYNAMIC and INST_BOOT.
+
+=cut
+
+sub init_xs {
+ my $self = shift;
+
+ if ($self->has_link_code()) {
+ $self->{INST_STATIC} =
+ $self->catfile('$(INST_ARCHAUTODIR)', '$(BASEEXT)$(LIB_EXT)');
+ $self->{INST_DYNAMIC} =
+ $self->catfile('$(INST_ARCHAUTODIR)', '$(DLBASE).$(DLEXT)');
+ $self->{INST_BOOT} =
+ $self->catfile('$(INST_ARCHAUTODIR)', '$(BASEEXT).bs');
+ } else {
+ $self->{INST_STATIC} = '';
+ $self->{INST_DYNAMIC} = '';
+ $self->{INST_BOOT} = '';
+ }
+}
+
+=item install (o)
+
+Defines the install target.
+
+=cut
+
+sub install {
+ my($self, %attribs) = @_;
+ my(@m);
+
+ push @m, q{
+install :: pure_install doc_install
+ $(NOECHO) $(NOOP)
+
+install_perl :: pure_perl_install doc_perl_install
+ $(NOECHO) $(NOOP)
+
+install_site :: pure_site_install doc_site_install
+ $(NOECHO) $(NOOP)
+
+install_vendor :: pure_vendor_install doc_vendor_install
+ $(NOECHO) $(NOOP)
+
+pure_install :: pure_$(INSTALLDIRS)_install
+ $(NOECHO) $(NOOP)
+
+doc_install :: doc_$(INSTALLDIRS)_install
+ $(NOECHO) $(NOOP)
+
+pure__install : pure_site_install
+ $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
+
+doc__install : doc_site_install
+ $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
+
+pure_perl_install :: all
+ $(NOECHO) $(MOD_INSTALL) \
+ read }.$self->catfile('$(PERL_ARCHLIB)','auto','$(FULLEXT)','.packlist').q{ \
+ write }.$self->catfile('$(DESTINSTALLARCHLIB)','auto','$(FULLEXT)','.packlist').q{ \
+ $(INST_LIB) $(DESTINSTALLPRIVLIB) \
+ $(INST_ARCHLIB) $(DESTINSTALLARCHLIB) \
+ $(INST_BIN) $(DESTINSTALLBIN) \
+ $(INST_SCRIPT) $(DESTINSTALLSCRIPT) \
+ $(INST_MAN1DIR) $(DESTINSTALLMAN1DIR) \
+ $(INST_MAN3DIR) $(DESTINSTALLMAN3DIR)
+ $(NOECHO) $(WARN_IF_OLD_PACKLIST) \
+ }.$self->catdir('$(SITEARCHEXP)','auto','$(FULLEXT)').q{
+
+
+pure_site_install :: all
+ $(NOECHO) $(MOD_INSTALL) \
+ read }.$self->catfile('$(SITEARCHEXP)','auto','$(FULLEXT)','.packlist').q{ \
+ write }.$self->catfile('$(DESTINSTALLSITEARCH)','auto','$(FULLEXT)','.packlist').q{ \
+ $(INST_LIB) $(DESTINSTALLSITELIB) \
+ $(INST_ARCHLIB) $(DESTINSTALLSITEARCH) \
+ $(INST_BIN) $(DESTINSTALLSITEBIN) \
+ $(INST_SCRIPT) $(DESTINSTALLSITESCRIPT) \
+ $(INST_MAN1DIR) $(DESTINSTALLSITEMAN1DIR) \
+ $(INST_MAN3DIR) $(DESTINSTALLSITEMAN3DIR)
+ $(NOECHO) $(WARN_IF_OLD_PACKLIST) \
+ }.$self->catdir('$(PERL_ARCHLIB)','auto','$(FULLEXT)').q{
+
+pure_vendor_install :: all
+ $(NOECHO) $(MOD_INSTALL) \
+ read }.$self->catfile('$(VENDORARCHEXP)','auto','$(FULLEXT)','.packlist').q{ \
+ write }.$self->catfile('$(DESTINSTALLVENDORARCH)','auto','$(FULLEXT)','.packlist').q{ \
+ $(INST_LIB) $(DESTINSTALLVENDORLIB) \
+ $(INST_ARCHLIB) $(DESTINSTALLVENDORARCH) \
+ $(INST_BIN) $(DESTINSTALLVENDORBIN) \
+ $(INST_SCRIPT) $(DESTINSTALLVENDORSCRIPT) \
+ $(INST_MAN1DIR) $(DESTINSTALLVENDORMAN1DIR) \
+ $(INST_MAN3DIR) $(DESTINSTALLVENDORMAN3DIR)
+
+doc_perl_install :: all
+ $(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod
+ -$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
+ -$(NOECHO) $(DOC_INSTALL) \
+ "Module" "$(NAME)" \
+ "installed into" "$(INSTALLPRIVLIB)" \
+ LINKTYPE "$(LINKTYPE)" \
+ VERSION "$(VERSION)" \
+ EXE_FILES "$(EXE_FILES)" \
+ >> }.$self->catfile('$(DESTINSTALLARCHLIB)','perllocal.pod').q{
+
+doc_site_install :: all
+ $(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod
+ -$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
+ -$(NOECHO) $(DOC_INSTALL) \
+ "Module" "$(NAME)" \
+ "installed into" "$(INSTALLSITELIB)" \
+ LINKTYPE "$(LINKTYPE)" \
+ VERSION "$(VERSION)" \
+ EXE_FILES "$(EXE_FILES)" \
+ >> }.$self->catfile('$(DESTINSTALLARCHLIB)','perllocal.pod').q{
+
+doc_vendor_install :: all
+ $(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod
+ -$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
+ -$(NOECHO) $(DOC_INSTALL) \
+ "Module" "$(NAME)" \
+ "installed into" "$(INSTALLVENDORLIB)" \
+ LINKTYPE "$(LINKTYPE)" \
+ VERSION "$(VERSION)" \
+ EXE_FILES "$(EXE_FILES)" \
+ >> }.$self->catfile('$(DESTINSTALLARCHLIB)','perllocal.pod').q{
+
+};
+
+ push @m, q{
+uninstall :: uninstall_from_$(INSTALLDIRS)dirs
+ $(NOECHO) $(NOOP)
+
+uninstall_from_perldirs ::
+ $(NOECHO) $(UNINSTALL) }.$self->catfile('$(PERL_ARCHLIB)','auto','$(FULLEXT)','.packlist').q{
+
+uninstall_from_sitedirs ::
+ $(NOECHO) $(UNINSTALL) }.$self->catfile('$(SITEARCHEXP)','auto','$(FULLEXT)','.packlist').q{
+
+uninstall_from_vendordirs ::
+ $(NOECHO) $(UNINSTALL) }.$self->catfile('$(VENDORARCHEXP)','auto','$(FULLEXT)','.packlist').q{
+};
+
+ join("",@m);
+}
+
+=item installbin (o)
+
+Defines targets to make and to install EXE_FILES.
+
+=cut
+
+sub installbin {
+ my($self) = shift;
+
+ return "" unless $self->{EXE_FILES} && ref $self->{EXE_FILES} eq "ARRAY";
+ my @exefiles = @{$self->{EXE_FILES}};
+ return "" unless @exefiles;
+
+ @exefiles = map vmsify($_), @exefiles if $Is{VMS};
+
+ my %fromto;
+ for my $from (@exefiles) {
+ my($path)= $self->catfile('$(INST_SCRIPT)', basename($from));
+
+ local($_) = $path; # for backwards compatibility
+ my $to = $self->libscan($path);
+ print "libscan($from) => '$to'\n" if ($Verbose >=2);
+
+ $to = vmsify($to) if $Is{VMS};
+ $fromto{$from} = $to;
+ }
+ my @to = values %fromto;
+
+ my @m;
+ push(@m, qq{
+EXE_FILES = @exefiles
+
+pure_all :: @to
+ \$(NOECHO) \$(NOOP)
+
+realclean ::
+});
+
+ # realclean can get rather large.
+ push @m, map "\t$_\n", $self->split_command('$(RM_F)', @to);
+ push @m, "\n";
+
+
+ # A target for each exe file.
+ while (my($from,$to) = each %fromto) {
+ last unless defined $from;
+
+ push @m, sprintf <<'MAKE', $to, $from, $to, $from, $to, $to, $to;
+%s : %s $(FIRST_MAKEFILE) $(INST_SCRIPT)$(DFSEP).exists $(INST_BIN)$(DFSEP).exists
+ $(NOECHO) $(RM_F) %s
+ $(CP) %s %s
+ $(FIXIN) %s
+ -$(NOECHO) $(CHMOD) $(PERM_RWX) %s
+
+MAKE
+
+ }
+
+ join "", @m;
+}
+
+
+=item linkext (o)
+
+Defines the linkext target which in turn defines the LINKTYPE.
+
+=cut
+
+sub linkext {
+ my($self, %attribs) = @_;
+ # LINKTYPE => static or dynamic or ''
+ my($linktype) = defined $attribs{LINKTYPE} ?
+ $attribs{LINKTYPE} : '$(LINKTYPE)';
+ "
+linkext :: $linktype
+ \$(NOECHO) \$(NOOP)
+";
+}
+
+=item lsdir
+
+Takes as arguments a directory name and a regular expression. Returns
+all entries in the directory that match the regular expression.
+
+=cut
+
+sub lsdir {
+ my($self) = shift;
+ my($dir, $regex) = @_;
+ my(@ls);
+ my $dh = new DirHandle;
+ $dh->open($dir || ".") or return ();
+ @ls = $dh->read;
+ $dh->close;
+ @ls = grep(/$regex/, @ls) if $regex;
+ @ls;
+}
+
+=item macro (o)
+
+Simple subroutine to insert the macros defined by the macro attribute
+into the Makefile.
+
+=cut
+
+sub macro {
+ my($self,%attribs) = @_;
+ my(@m,$key,$val);
+ while (($key,$val) = each %attribs){
+ last unless defined $key;
+ push @m, "$key = $val\n";
+ }
+ join "", @m;
+}
+
+=item makeaperl (o)
+
+Called by staticmake. Defines how to write the Makefile to produce a
+static new perl.
+
+By default the Makefile produced includes all the static extensions in
+the perl library. (Purified versions of library files, e.g.,
+DynaLoader_pure_p1_c0_032.a are automatically ignored to avoid link errors.)
+
+=cut
+
+sub makeaperl {
+ my($self, %attribs) = @_;
+ my($makefilename, $searchdirs, $static, $extra, $perlinc, $target, $tmp, $libperl) =
+ @attribs{qw(MAKE DIRS STAT EXTRA INCL TARGET TMP LIBPERL)};
+ my(@m);
+ push @m, "
+# --- MakeMaker makeaperl section ---
+MAP_TARGET = $target
+FULLPERL = $self->{FULLPERL}
+";
+ return join '', @m if $self->{PARENT};
+
+ my($dir) = join ":", @{$self->{DIR}};
+
+ unless ($self->{MAKEAPERL}) {
+ push @m, q{
+$(MAP_TARGET) :: static $(MAKE_APERL_FILE)
+ $(MAKE) $(USEMAKEFILE) $(MAKE_APERL_FILE) $@
+
+$(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) pm_to_blib
+ $(NOECHO) $(ECHO) Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET)
+ $(NOECHO) $(PERLRUNINST) \
+ Makefile.PL DIR=}, $dir, q{ \
+ MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \
+ MAKEAPERL=1 NORECURS=1 CCCDLFLAGS=};
+
+ foreach (@ARGV){
+ if( /\s/ ){
+ s/=(.*)/='$1'/;
+ }
+ push @m, " \\\n\t\t$_";
+ }
+# push @m, map( " \\\n\t\t$_", @ARGV );
+ push @m, "\n";
+
+ return join '', @m;
+ }
+
+
+
+ my($cccmd, $linkcmd, $lperl);
+
+
+ $cccmd = $self->const_cccmd($libperl);
+ $cccmd =~ s/^CCCMD\s*=\s*//;
+ $cccmd =~ s/\$\(INC\)/ "-I$self->{PERL_INC}" /;
+ $cccmd .= " $Config{cccdlflags}"
+ if ($Config{useshrplib} eq 'true');
+ $cccmd =~ s/\(CC\)/\(PERLMAINCC\)/;
+
+ # The front matter of the linkcommand...
+ $linkcmd = join ' ', "\$(CC)",
+ grep($_, @Config{qw(ldflags ccdlflags)});
+ $linkcmd =~ s/\s+/ /g;
+ $linkcmd =~ s,(perl\.exp),\$(PERL_INC)/$1,;
+
+ # Which *.a files could we make use of...
+ my %static;
+ require File::Find;
+ File::Find::find(sub {
+ return unless m/\Q$self->{LIB_EXT}\E$/;
+
+ # Skip perl's libraries.
+ return if m/^libperl/ or m/^perl\Q$self->{LIB_EXT}\E$/;
+
+ # Skip purified versions of libraries
+ # (e.g., DynaLoader_pure_p1_c0_032.a)
+ return if m/_pure_\w+_\w+_\w+\.\w+$/ and -f "$File::Find::dir/.pure";
+
+ if( exists $self->{INCLUDE_EXT} ){
+ my $found = 0;
+
+ (my $xx = $File::Find::name) =~ s,.*?/auto/,,s;
+ $xx =~ s,/?$_,,;
+ $xx =~ s,/,::,g;
+
+ # Throw away anything not explicitly marked for inclusion.
+ # DynaLoader is implied.
+ foreach my $incl ((@{$self->{INCLUDE_EXT}},'DynaLoader')){
+ if( $xx eq $incl ){
+ $found++;
+ last;
+ }
+ }
+ return unless $found;
+ }
+ elsif( exists $self->{EXCLUDE_EXT} ){
+ (my $xx = $File::Find::name) =~ s,.*?/auto/,,s;
+ $xx =~ s,/?$_,,;
+ $xx =~ s,/,::,g;
+
+ # Throw away anything explicitly marked for exclusion
+ foreach my $excl (@{$self->{EXCLUDE_EXT}}){
+ return if( $xx eq $excl );
+ }
+ }
+
+ # don't include the installed version of this extension. I
+ # leave this line here, although it is not necessary anymore:
+ # I patched minimod.PL instead, so that Miniperl.pm won't
+ # enclude duplicates
+
+ # Once the patch to minimod.PL is in the distribution, I can
+ # drop it
+ return if $File::Find::name =~ m:auto/$self->{FULLEXT}/$self->{BASEEXT}$self->{LIB_EXT}\z:;
+ use Cwd 'cwd';
+ $static{cwd() . "/" . $_}++;
+ }, grep( -d $_, @{$searchdirs || []}) );
+
+ # We trust that what has been handed in as argument, will be buildable
+ $static = [] unless $static;
+ @static{@{$static}} = (1) x @{$static};
+
+ $extra = [] unless $extra && ref $extra eq 'ARRAY';
+ for (sort keys %static) {
+ next unless /\Q$self->{LIB_EXT}\E\z/;
+ $_ = dirname($_) . "/extralibs.ld";
+ push @$extra, $_;
+ }
+
+ s/^(.*)/"-I$1"/ for @{$perlinc || []};
+
+ $target ||= "perl";
+ $tmp ||= ".";
+
+# MAP_STATIC doesn't look into subdirs yet. Once "all" is made and we
+# regenerate the Makefiles, MAP_STATIC and the dependencies for
+# extralibs.all are computed correctly
+ push @m, "
+MAP_LINKCMD = $linkcmd
+MAP_PERLINC = @{$perlinc || []}
+MAP_STATIC = ",
+join(" \\\n\t", reverse sort keys %static), "
+
+MAP_PRELIBS = $Config{perllibs} $Config{cryptlib}
+";
+
+ if (defined $libperl) {
+ ($lperl = $libperl) =~ s/\$\(A\)/$self->{LIB_EXT}/;
+ }
+ unless ($libperl && -f $lperl) { # Ilya's code...
+ my $dir = $self->{PERL_SRC} || "$self->{PERL_ARCHLIB}/CORE";
+ $dir = "$self->{PERL_ARCHLIB}/.." if $self->{UNINSTALLED_PERL};
+ $libperl ||= "libperl$self->{LIB_EXT}";
+ $libperl = "$dir/$libperl";
+ $lperl ||= "libperl$self->{LIB_EXT}";
+ $lperl = "$dir/$lperl";
+
+ if (! -f $libperl and ! -f $lperl) {
+ # We did not find a static libperl. Maybe there is a shared one?
+ if ($Is{SunOS}) {
+ $lperl = $libperl = "$dir/$Config{libperl}";
+ # SUNOS ld does not take the full path to a shared library
+ $libperl = '' if $Is{SunOS4};
+ }
+ }
+
+ print STDOUT "Warning: $libperl not found
+ If you're going to build a static perl binary, make sure perl is installed
+ otherwise ignore this warning\n"
+ unless (-f $lperl || defined($self->{PERL_SRC}));
+ }
+
+ # SUNOS ld does not take the full path to a shared library
+ my $llibperl = $libperl ? '$(MAP_LIBPERL)' : '-lperl';
+
+ push @m, "
+MAP_LIBPERL = $libperl
+LLIBPERL = $llibperl
+";
+
+ push @m, '
+$(INST_ARCHAUTODIR)/extralibs.all : $(INST_ARCHAUTODIR)$(DFSEP).exists '.join(" \\\n\t", @$extra).'
+ $(NOECHO) $(RM_F) $@
+ $(NOECHO) $(TOUCH) $@
+';
+
+ foreach my $catfile (@$extra){
+ push @m, "\tcat $catfile >> \$\@\n";
+ }
+
+push @m, "
+\$(MAP_TARGET) :: $tmp/perlmain\$(OBJ_EXT) \$(MAP_LIBPERL) \$(MAP_STATIC) \$(INST_ARCHAUTODIR)/extralibs.all
+ \$(MAP_LINKCMD) -o \$\@ \$(OPTIMIZE) $tmp/perlmain\$(OBJ_EXT) \$(LDFROM) \$(MAP_STATIC) \$(LLIBPERL) `cat \$(INST_ARCHAUTODIR)/extralibs.all` \$(MAP_PRELIBS)
+ \$(NOECHO) \$(ECHO) 'To install the new \"\$(MAP_TARGET)\" binary, call'
+ \$(NOECHO) \$(ECHO) ' \$(MAKE) \$(USEMAKEFILE) $makefilename inst_perl MAP_TARGET=\$(MAP_TARGET)'
+ \$(NOECHO) \$(ECHO) 'To remove the intermediate files say'
+ \$(NOECHO) \$(ECHO) ' \$(MAKE) \$(USEMAKEFILE) $makefilename map_clean'
+
+$tmp/perlmain\$(OBJ_EXT): $tmp/perlmain.c
+";
+ push @m, "\t".$self->cd($tmp, qq[$cccmd "-I\$(PERL_INC)" perlmain.c])."\n";
+
+ push @m, qq{
+$tmp/perlmain.c: $makefilename}, q{
+ $(NOECHO) $(ECHO) Writing $@
+ $(NOECHO) $(PERL) $(MAP_PERLINC) "-MExtUtils::Miniperl" \\
+ -e "writemain(grep s#.*/auto/##s, split(q| |, q|$(MAP_STATIC)|))" > $@t && $(MV) $@t $@
+
+};
+ push @m, "\t", q{$(NOECHO) $(PERL) $(INSTALLSCRIPT)/fixpmain
+} if (defined (&Dos::UseLFN) && Dos::UseLFN()==0);
+
+
+ push @m, q{
+doc_inst_perl :
+ $(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod
+ -$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
+ -$(NOECHO) $(DOC_INSTALL) \
+ "Perl binary" "$(MAP_TARGET)" \
+ MAP_STATIC "$(MAP_STATIC)" \
+ MAP_EXTRA "`cat $(INST_ARCHAUTODIR)/extralibs.all`" \
+ MAP_LIBPERL "$(MAP_LIBPERL)" \
+ >> }.$self->catfile('$(DESTINSTALLARCHLIB)','perllocal.pod').q{
+
+};
+
+ push @m, q{
+inst_perl : pure_inst_perl doc_inst_perl
+
+pure_inst_perl : $(MAP_TARGET)
+ }.$self->{CP}.q{ $(MAP_TARGET) }.$self->catfile('$(DESTINSTALLBIN)','$(MAP_TARGET)').q{
+
+clean :: map_clean
+
+map_clean :
+ }.$self->{RM_F}.qq{ $tmp/perlmain\$(OBJ_EXT) $tmp/perlmain.c \$(MAP_TARGET) $makefilename \$(INST_ARCHAUTODIR)/extralibs.all
+};
+
+ join '', @m;
+}
+
+=item makefile (o)
+
+Defines how to rewrite the Makefile.
+
+=cut
+
+sub makefile {
+ my($self) = shift;
+ my $m;
+ # We do not know what target was originally specified so we
+ # must force a manual rerun to be sure. But as it should only
+ # happen very rarely it is not a significant problem.
+ $m = '
+$(OBJECT) : $(FIRST_MAKEFILE)
+
+' if $self->{OBJECT};
+
+ my $newer_than_target = $Is{VMS} ? '$(MMS$SOURCE_LIST)' : '$?';
+ my $mpl_args = join " ", map qq["$_"], @ARGV;
+
+ $m .= sprintf <<'MAKE_FRAG', $newer_than_target, $mpl_args;
+# We take a very conservative approach here, but it's worth it.
+# We move Makefile to Makefile.old here to avoid gnu make looping.
+$(FIRST_MAKEFILE) : Makefile.PL $(CONFIGDEP)
+ $(NOECHO) $(ECHO) "Makefile out-of-date with respect to %s"
+ $(NOECHO) $(ECHO) "Cleaning current config before rebuilding Makefile..."
+ -$(NOECHO) $(RM_F) $(MAKEFILE_OLD)
+ -$(NOECHO) $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD)
+ - $(MAKE) $(USEMAKEFILE) $(MAKEFILE_OLD) clean $(DEV_NULL)
+ $(PERLRUN) Makefile.PL %s
+ $(NOECHO) $(ECHO) "==> Your Makefile has been rebuilt. <=="
+ $(NOECHO) $(ECHO) "==> Please rerun the $(MAKE) command. <=="
+ $(FALSE)
+
+MAKE_FRAG
+
+ return $m;
+}
+
+
+=item maybe_command
+
+Returns true, if the argument is likely to be a command.
+
+=cut
+
+sub maybe_command {
+ my($self,$file) = @_;
+ return $file if -x $file && ! -d $file;
+ return;
+}
+
+
+=item needs_linking (o)
+
+Does this module need linking? Looks into subdirectory objects (see
+also has_link_code())
+
+=cut
+
+sub needs_linking {
+ my($self) = shift;
+
+ my $caller = (caller(0))[3];
+ confess("needs_linking called too early") if
+ $caller =~ /^ExtUtils::MakeMaker::/;
+ return $self->{NEEDS_LINKING} if defined $self->{NEEDS_LINKING};
+ if ($self->has_link_code or $self->{MAKEAPERL}){
+ $self->{NEEDS_LINKING} = 1;
+ return 1;
+ }
+ foreach my $child (keys %{$self->{CHILDREN}}) {
+ if ($self->{CHILDREN}->{$child}->needs_linking) {
+ $self->{NEEDS_LINKING} = 1;
+ return 1;
+ }
+ }
+ return $self->{NEEDS_LINKING} = 0;
+}
+
+
+=item parse_abstract
+
+parse a file and return what you think is the ABSTRACT
+
+=cut
+
+sub parse_abstract {
+ my($self,$parsefile) = @_;
+ my $result;
+
+ local $/ = "\n";
+ open(my $fh, '<', $parsefile) or die "Could not open '$parsefile': $!";
+ my $inpod = 0;
+ my $package = $self->{DISTNAME};
+ $package =~ s/-/::/g;
+ while (<$fh>) {
+ $inpod = /^=(?!cut)/ ? 1 : /^=cut/ ? 0 : $inpod;
+ next if !$inpod;
+ chop;
+ next unless /^($package\s-\s)(.*)/;
+ $result = $2;
+ last;
+ }
+ close $fh;
+
+ return $result;
+}
+
+=item parse_version
+
+ my $version = MM->parse_version($file);
+
+Parse a $file and return what $VERSION is set to by the first assignment.
+It will return the string "undef" if it can't figure out what $VERSION
+is. $VERSION should be for all to see, so C<our $VERSION> or plain $VERSION
+are okay, but C<my $VERSION> is not.
+
+C<<package Foo VERSION>> is also checked for. The first version
+declaration found is used, but this may change as it differs from how
+Perl does it.
+
+parse_version() will try to C<use version> before checking for
+C<$VERSION> so the following will work.
+
+ $VERSION = qv(1.2.3);
+
+=cut
+
+sub parse_version {
+ my($self,$parsefile) = @_;
+ my $result;
+
+ local $/ = "\n";
+ local $_;
+ open(my $fh, '<', $parsefile) or die "Could not open '$parsefile': $!";
+ my $inpod = 0;
+ while (<$fh>) {
+ $inpod = /^=(?!cut)/ ? 1 : /^=cut/ ? 0 : $inpod;
+ next if $inpod || /^\s*#/;
+ chop;
+ next if /^\s*(if|unless)/;
+ if ( m{^ \s* package \s+ \w[\w\:\']* \s+ (v?[0-9._]+) \s* ; }x ) {
+ local $^W = 0;
+ $result = $1;
+ }
+ elsif ( m{(?<!\\) ([\$*]) (([\w\:\']*) \bVERSION)\b .* =}x ) {
+ my $eval = qq{
+ package ExtUtils::MakeMaker::_version;
+ no strict;
+ BEGIN { eval {
+ # Ensure any version() routine which might have leaked
+ # into this package has been deleted. Interferes with
+ # version->import()
+ undef *version;
+ require version;
+ "version"->import;
+ } }
+
+ local $1$2;
+ \$$2=undef;
+ do {
+ $_
+ };
+ \$$2;
+ };
+ local $^W = 0;
+ $result = eval($eval); ## no critic
+ warn "Could not eval '$eval' in $parsefile: $@" if $@;
+ }
+ else {
+ next;
+ }
+ last if defined $result;
+ }
+ close $fh;
+
+ $result = "undef" unless defined $result;
+ return $result;
+}
+
+
+=item pasthru (o)
+
+Defines the string that is passed to recursive make calls in
+subdirectories.
+
+=cut
+
+sub pasthru {
+ my($self) = shift;
+ my(@m);
+
+ my(@pasthru);
+ my($sep) = $Is{VMS} ? ',' : '';
+ $sep .= "\\\n\t";
+
+ foreach my $key (qw(LIB LIBPERL_A LINKTYPE OPTIMIZE
+ PREFIX INSTALL_BASE)
+ )
+ {
+ next unless defined $self->{$key};
+ push @pasthru, "$key=\"\$($key)\"";
+ }
+
+ foreach my $key (qw(DEFINE INC)) {
+ next unless defined $self->{$key};
+ push @pasthru, "PASTHRU_$key=\"\$(PASTHRU_$key)\"";
+ }
+
+ push @m, "\nPASTHRU = ", join ($sep, @pasthru), "\n";
+ join "", @m;
+}
+
+=item perl_script
+
+Takes one argument, a file name, and returns the file name, if the
+argument is likely to be a perl script. On MM_Unix this is true for
+any ordinary, readable file.
+
+=cut
+
+sub perl_script {
+ my($self,$file) = @_;
+ return $file if -r $file && -f _;
+ return;
+}
+
+=item perldepend (o)
+
+Defines the dependency from all *.h files that come with the perl
+distribution.
+
+=cut
+
+sub perldepend {
+ my($self) = shift;
+ my(@m);
+
+ my $make_config = $self->cd('$(PERL_SRC)', '$(MAKE) lib/Config.pm');
+
+ push @m, sprintf <<'MAKE_FRAG', $make_config if $self->{PERL_SRC};
+# Check for unpropogated config.sh changes. Should never happen.
+# We do NOT just update config.h because that is not sufficient.
+# An out of date config.h is not fatal but complains loudly!
+$(PERL_INC)/config.h: $(PERL_SRC)/config.sh
+ -$(NOECHO) $(ECHO) "Warning: $(PERL_INC)/config.h out of date with $(PERL_SRC)/config.sh"; $(FALSE)
+
+$(PERL_ARCHLIB)/Config.pm: $(PERL_SRC)/config.sh
+ $(NOECHO) $(ECHO) "Warning: $(PERL_ARCHLIB)/Config.pm may be out of date with $(PERL_SRC)/config.sh"
+ %s
+MAKE_FRAG
+
+ return join "", @m unless $self->needs_linking;
+
+ push @m, q{
+PERL_HDRS = \
+ $(PERL_INC)/EXTERN.h \
+ $(PERL_INC)/INTERN.h \
+ $(PERL_INC)/XSUB.h \
+ $(PERL_INC)/av.h \
+ $(PERL_INC)/cc_runtime.h \
+ $(PERL_INC)/config.h \
+ $(PERL_INC)/cop.h \
+ $(PERL_INC)/cv.h \
+ $(PERL_INC)/dosish.h \
+ $(PERL_INC)/embed.h \
+ $(PERL_INC)/embedvar.h \
+ $(PERL_INC)/fakethr.h \
+ $(PERL_INC)/form.h \
+ $(PERL_INC)/gv.h \
+ $(PERL_INC)/handy.h \
+ $(PERL_INC)/hv.h \
+ $(PERL_INC)/intrpvar.h \
+ $(PERL_INC)/iperlsys.h \
+ $(PERL_INC)/keywords.h \
+ $(PERL_INC)/mg.h \
+ $(PERL_INC)/nostdio.h \
+ $(PERL_INC)/op.h \
+ $(PERL_INC)/opcode.h \
+ $(PERL_INC)/patchlevel.h \
+ $(PERL_INC)/perl.h \
+ $(PERL_INC)/perlio.h \
+ $(PERL_INC)/perlsdio.h \
+ $(PERL_INC)/perlsfio.h \
+ $(PERL_INC)/perlvars.h \
+ $(PERL_INC)/perly.h \
+ $(PERL_INC)/pp.h \
+ $(PERL_INC)/pp_proto.h \
+ $(PERL_INC)/proto.h \
+ $(PERL_INC)/regcomp.h \
+ $(PERL_INC)/regexp.h \
+ $(PERL_INC)/regnodes.h \
+ $(PERL_INC)/scope.h \
+ $(PERL_INC)/sv.h \
+ $(PERL_INC)/thread.h \
+ $(PERL_INC)/unixish.h \
+ $(PERL_INC)/util.h
+
+$(OBJECT) : $(PERL_HDRS)
+} if $self->{OBJECT};
+
+ push @m, join(" ", values %{$self->{XS}})." : \$(XSUBPPDEPS)\n" if %{$self->{XS}};
+
+ join "\n", @m;
+}
+
+
+=item pm_to_blib
+
+Defines target that copies all files in the hash PM to their
+destination and autosplits them. See L<ExtUtils::Install/DESCRIPTION>
+
+=cut
+
+sub pm_to_blib {
+ my $self = shift;
+ my($autodir) = $self->catdir('$(INST_LIB)','auto');
+ my $r = q{
+pm_to_blib : $(FIRST_MAKEFILE) $(TO_INST_PM)
+};
+
+ # VMS will swallow '' and PM_FILTER is often empty. So use q[]
+ my $pm_to_blib = $self->oneliner(<<CODE, ['-MExtUtils::Install']);
+pm_to_blib({\@ARGV}, '$autodir', q[\$(PM_FILTER)], '\$(PERM_DIR)')
+CODE
+
+ my @cmds = $self->split_command($pm_to_blib, %{$self->{PM}});
+
+ $r .= join '', map { "\t\$(NOECHO) $_\n" } @cmds;
+ $r .= qq{\t\$(NOECHO) \$(TOUCH) pm_to_blib\n};
+
+ return $r;
+}
+
+=item post_constants (o)
+
+Returns an empty string per default. Dedicated to overrides from
+within Makefile.PL after all constants have been defined.
+
+=cut
+
+sub post_constants{
+ "";
+}
+
+=item post_initialize (o)
+
+Returns an empty string per default. Used in Makefile.PLs to add some
+chunk of text to the Makefile after the object is initialized.
+
+=cut
+
+sub post_initialize {
+ "";
+}
+
+=item postamble (o)
+
+Returns an empty string. Can be used in Makefile.PLs to write some
+text to the Makefile at the end.
+
+=cut
+
+sub postamble {
+ "";
+}
+
+# transform dot-separated version string into comma-separated quadruple
+# examples: '1.2.3.4.5' => '1,2,3,4'
+# '1.2.3' => '1,2,3,0'
+sub _ppd_version {
+ my ($self, $string) = @_;
+ return join ',', ((split /\./, $string), (0) x 4)[0..3];
+}
+
+=item ppd
+
+Defines target that creates a PPD (Perl Package Description) file
+for a binary distribution.
+
+=cut
+
+sub ppd {
+ my($self) = @_;
+
+ my $abstract = $self->{ABSTRACT} || '';
+ $abstract =~ s/\n/\\n/sg;
+ $abstract =~ s/</&lt;/g;
+ $abstract =~ s/>/&gt;/g;
+
+ my $author = $self->{AUTHOR} || '';
+ $author =~ s/</&lt;/g;
+ $author =~ s/>/&gt;/g;
+
+ my $ppd_xml = sprintf <<'PPD_HTML', $self->{VERSION}, $abstract, $author;
+<SOFTPKG NAME="$(DISTNAME)" VERSION="%s">
+ <ABSTRACT>%s</ABSTRACT>
+ <AUTHOR>%s</AUTHOR>
+PPD_HTML
+
+ $ppd_xml .= " <IMPLEMENTATION>\n";
+ if ( $self->{MIN_PERL_VERSION} ) {
+ my $min_perl_version = $self->_ppd_version($self->{MIN_PERL_VERSION});
+ $ppd_xml .= sprintf <<'PPD_PERLVERS', $min_perl_version;
+ <PERLCORE VERSION="%s" />
+PPD_PERLVERS
+
+ }
+
+ # Don't add "perl" to requires. perl dependencies are
+ # handles by ARCHITECTURE.
+ my %prereqs = %{$self->{PREREQ_PM}};
+ delete $prereqs{perl};
+
+ # Build up REQUIRE
+ foreach my $prereq (sort keys %prereqs) {
+ my $name = $prereq;
+ $name .= '::' unless $name =~ /::/;
+ my $version = $prereqs{$prereq}+0; # force numification
+
+ my %attrs = ( NAME => $name );
+ $attrs{VERSION} = $version if $version;
+ my $attrs = join " ", map { qq[$_="$attrs{$_}"] } keys %attrs;
+ $ppd_xml .= qq( <REQUIRE $attrs />\n);
+ }
+
+ my $archname = $Config{archname};
+ if ($] >= 5.008) {
+ # archname did not change from 5.6 to 5.8, but those versions may
+ # not be not binary compatible so now we append the part of the
+ # version that changes when binary compatibility may change
+ $archname .= "-$Config{PERL_REVISION}.$Config{PERL_VERSION}";
+ }
+ $ppd_xml .= sprintf <<'PPD_OUT', $archname;
+ <ARCHITECTURE NAME="%s" />
+PPD_OUT
+
+ if ($self->{PPM_INSTALL_SCRIPT}) {
+ if ($self->{PPM_INSTALL_EXEC}) {
+ $ppd_xml .= sprintf qq{ <INSTALL EXEC="%s">%s</INSTALL>\n},
+ $self->{PPM_INSTALL_EXEC}, $self->{PPM_INSTALL_SCRIPT};
+ }
+ else {
+ $ppd_xml .= sprintf qq{ <INSTALL>%s</INSTALL>\n},
+ $self->{PPM_INSTALL_SCRIPT};
+ }
+ }
+
+ my ($bin_location) = $self->{BINARY_LOCATION} || '';
+ $bin_location =~ s/\\/\\\\/g;
+
+ $ppd_xml .= sprintf <<'PPD_XML', $bin_location;
+ <CODEBASE HREF="%s" />
+ </IMPLEMENTATION>
+</SOFTPKG>
+PPD_XML
+
+ my @ppd_cmds = $self->echo($ppd_xml, '$(DISTNAME).ppd');
+
+ return sprintf <<'PPD_OUT', join "\n\t", @ppd_cmds;
+# Creates a PPD (Perl Package Description) for a binary distribution.
+ppd :
+ %s
+PPD_OUT
+
+}
+
+=item prefixify
+
+ $MM->prefixify($var, $prefix, $new_prefix, $default);
+
+Using either $MM->{uc $var} || $Config{lc $var}, it will attempt to
+replace it's $prefix with a $new_prefix.
+
+Should the $prefix fail to match I<AND> a PREFIX was given as an
+argument to WriteMakefile() it will set it to the $new_prefix +
+$default. This is for systems whose file layouts don't neatly fit into
+our ideas of prefixes.
+
+This is for heuristics which attempt to create directory structures
+that mirror those of the installed perl.
+
+For example:
+
+ $MM->prefixify('installman1dir', '/usr', '/home/foo', 'man/man1');
+
+this will attempt to remove '/usr' from the front of the
+$MM->{INSTALLMAN1DIR} path (initializing it to $Config{installman1dir}
+if necessary) and replace it with '/home/foo'. If this fails it will
+simply use '/home/foo/man/man1'.
+
+=cut
+
+sub prefixify {
+ my($self,$var,$sprefix,$rprefix,$default) = @_;
+
+ my $path = $self->{uc $var} ||
+ $Config_Override{lc $var} || $Config{lc $var} || '';
+
+ $rprefix .= '/' if $sprefix =~ m|/$|;
+
+ print STDERR " prefixify $var => $path\n" if $Verbose >= 2;
+ print STDERR " from $sprefix to $rprefix\n" if $Verbose >= 2;
+
+ if( $self->{ARGS}{PREFIX} &&
+ $path !~ s{^\Q$sprefix\E\b}{$rprefix}s )
+ {
+
+ print STDERR " cannot prefix, using default.\n" if $Verbose >= 2;
+ print STDERR " no default!\n" if !$default && $Verbose >= 2;
+
+ $path = $self->catdir($rprefix, $default) if $default;
+ }
+
+ print " now $path\n" if $Verbose >= 2;
+ return $self->{uc $var} = $path;
+}
+
+
+=item processPL (o)
+
+Defines targets to run *.PL files.
+
+=cut
+
+sub processPL {
+ my $self = shift;
+ my $pl_files = $self->{PL_FILES};
+
+ return "" unless $pl_files;
+
+ my $m = '';
+ foreach my $plfile (sort keys %$pl_files) {
+ my $list = ref($pl_files->{$plfile})
+ ? $pl_files->{$plfile}
+ : [$pl_files->{$plfile}];
+
+ foreach my $target (@$list) {
+ if( $Is{VMS} ) {
+ $plfile = vmsify($self->eliminate_macros($plfile));
+ $target = vmsify($self->eliminate_macros($target));
+ }
+
+ # Normally a .PL file runs AFTER pm_to_blib so it can have
+ # blib in its @INC and load the just built modules. BUT if
+ # the generated module is something in $(TO_INST_PM) which
+ # pm_to_blib depends on then it can't depend on pm_to_blib
+ # else we have a dependency loop.
+ my $pm_dep;
+ my $perlrun;
+ if( defined $self->{PM}{$target} ) {
+ $pm_dep = '';
+ $perlrun = 'PERLRUN';
+ }
+ else {
+ $pm_dep = 'pm_to_blib';
+ $perlrun = 'PERLRUNINST';
+ }
+
+ $m .= <<MAKE_FRAG;
+
+all :: $target
+ \$(NOECHO) \$(NOOP)
+
+$target :: $plfile $pm_dep
+ \$($perlrun) $plfile $target
+MAKE_FRAG
+
+ }
+ }
+
+ return $m;
+}
+
+=item quote_paren
+
+Backslashes parentheses C<()> in command line arguments.
+Doesn't handle recursive Makefile C<$(...)> constructs,
+but handles simple ones.
+
+=cut
+
+sub quote_paren {
+ my $arg = shift;
+ $arg =~ s{\$\((.+?)\)}{\$\\\\($1\\\\)}g; # protect $(...)
+ $arg =~ s{(?<!\\)([()])}{\\$1}g; # quote unprotected
+ $arg =~ s{\$\\\\\((.+?)\\\\\)}{\$($1)}g; # unprotect $(...)
+ return $arg;
+}
+
+=item replace_manpage_separator
+
+ my $man_name = $MM->replace_manpage_separator($file_path);
+
+Takes the name of a package, which may be a nested package, in the
+form 'Foo/Bar.pm' and replaces the slash with C<::> or something else
+safe for a man page file name. Returns the replacement.
+
+=cut
+
+sub replace_manpage_separator {
+ my($self,$man) = @_;
+
+ $man =~ s,/+,::,g;
+ return $man;
+}
+
+
+=item cd
+
+=cut
+
+sub cd {
+ my($self, $dir, @cmds) = @_;
+
+ # No leading tab and no trailing newline makes for easier embedding
+ my $make_frag = join "\n\t", map { "cd $dir && $_" } @cmds;
+
+ return $make_frag;
+}
+
+=item oneliner
+
+=cut
+
+sub oneliner {
+ my($self, $cmd, $switches) = @_;
+ $switches = [] unless defined $switches;
+
+ # Strip leading and trailing newlines
+ $cmd =~ s{^\n+}{};
+ $cmd =~ s{\n+$}{};
+
+ my @cmds = split /\n/, $cmd;
+ $cmd = join " \n\t -e ", map $self->quote_literal($_), @cmds;
+ $cmd = $self->escape_newlines($cmd);
+
+ $switches = join ' ', @$switches;
+
+ return qq{\$(ABSPERLRUN) $switches -e $cmd --};
+}
+
+
+=item quote_literal
+
+=cut
+
+sub quote_literal {
+ my($self, $text) = @_;
+
+ # I think all we have to quote is single quotes and I think
+ # this is a safe way to do it.
+ $text =~ s{'}{'\\''}g;
+
+ return "'$text'";
+}
+
+
+=item escape_newlines
+
+=cut
+
+sub escape_newlines {
+ my($self, $text) = @_;
+
+ $text =~ s{\n}{\\\n}g;
+
+ return $text;
+}
+
+
+=item max_exec_len
+
+Using POSIX::ARG_MAX. Otherwise falling back to 4096.
+
+=cut
+
+sub max_exec_len {
+ my $self = shift;
+
+ if (!defined $self->{_MAX_EXEC_LEN}) {
+ if (my $arg_max = eval { require POSIX; &POSIX::ARG_MAX }) {
+ $self->{_MAX_EXEC_LEN} = $arg_max;
+ }
+ else { # POSIX minimum exec size
+ $self->{_MAX_EXEC_LEN} = 4096;
+ }
+ }
+
+ return $self->{_MAX_EXEC_LEN};
+}
+
+
+=item static (o)
+
+Defines the static target.
+
+=cut
+
+sub static {
+# --- Static Loading Sections ---
+
+ my($self) = shift;
+ '
+## $(INST_PM) has been moved to the all: target.
+## It remains here for awhile to allow for old usage: "make static"
+static :: $(FIRST_MAKEFILE) $(INST_STATIC)
+ $(NOECHO) $(NOOP)
+';
+}
+
+=item static_lib (o)
+
+Defines how to produce the *.a (or equivalent) files.
+
+=cut
+
+sub static_lib {
+ my($self) = @_;
+ return '' unless $self->has_link_code;
+
+ my(@m);
+ push(@m, <<'END');
+
+$(INST_STATIC) : $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DFSEP).exists
+ $(RM_RF) $@
+END
+
+ # If this extension has its own library (eg SDBM_File)
+ # then copy that to $(INST_STATIC) and add $(OBJECT) into it.
+ push(@m, <<'MAKE_FRAG') if $self->{MYEXTLIB};
+ $(CP) $(MYEXTLIB) $@
+MAKE_FRAG
+
+ my $ar;
+ if (exists $self->{FULL_AR} && -x $self->{FULL_AR}) {
+ # Prefer the absolute pathed ar if available so that PATH
+ # doesn't confuse us. Perl itself is built with the full_ar.
+ $ar = 'FULL_AR';
+ } else {
+ $ar = 'AR';
+ }
+ push @m, sprintf <<'MAKE_FRAG', $ar;
+ $(%s) $(AR_STATIC_ARGS) $@ $(OBJECT) && $(RANLIB) $@
+ $(CHMOD) $(PERM_RWX) $@
+ $(NOECHO) $(ECHO) "$(EXTRALIBS)" > $(INST_ARCHAUTODIR)/extralibs.ld
+MAKE_FRAG
+
+ # Old mechanism - still available:
+ push @m, <<'MAKE_FRAG' if $self->{PERL_SRC} && $self->{EXTRALIBS};
+ $(NOECHO) $(ECHO) "$(EXTRALIBS)" >> $(PERL_SRC)/ext.libs
+MAKE_FRAG
+
+ join('', @m);
+}
+
+=item staticmake (o)
+
+Calls makeaperl.
+
+=cut
+
+sub staticmake {
+ my($self, %attribs) = @_;
+ my(@static);
+
+ my(@searchdirs)=($self->{PERL_ARCHLIB}, $self->{SITEARCHEXP}, $self->{INST_ARCHLIB});
+
+ # And as it's not yet built, we add the current extension
+ # but only if it has some C code (or XS code, which implies C code)
+ if (@{$self->{C}}) {
+ @static = $self->catfile($self->{INST_ARCHLIB},
+ "auto",
+ $self->{FULLEXT},
+ "$self->{BASEEXT}$self->{LIB_EXT}"
+ );
+ }
+
+ # Either we determine now, which libraries we will produce in the
+ # subdirectories or we do it at runtime of the make.
+
+ # We could ask all subdir objects, but I cannot imagine, why it
+ # would be necessary.
+
+ # Instead we determine all libraries for the new perl at
+ # runtime.
+ my(@perlinc) = ($self->{INST_ARCHLIB}, $self->{INST_LIB}, $self->{PERL_ARCHLIB}, $self->{PERL_LIB});
+
+ $self->makeaperl(MAKE => $self->{MAKEFILE},
+ DIRS => \@searchdirs,
+ STAT => \@static,
+ INCL => \@perlinc,
+ TARGET => $self->{MAP_TARGET},
+ TMP => "",
+ LIBPERL => $self->{LIBPERL_A}
+ );
+}
+
+=item subdir_x (o)
+
+Helper subroutine for subdirs
+
+=cut
+
+sub subdir_x {
+ my($self, $subdir) = @_;
+
+ my $subdir_cmd = $self->cd($subdir,
+ '$(MAKE) $(USEMAKEFILE) $(FIRST_MAKEFILE) all $(PASTHRU)'
+ );
+ return sprintf <<'EOT', $subdir_cmd;
+
+subdirs ::
+ $(NOECHO) %s
+EOT
+
+}
+
+=item subdirs (o)
+
+Defines targets to process subdirectories.
+
+=cut
+
+sub subdirs {
+# --- Sub-directory Sections ---
+ my($self) = shift;
+ my(@m);
+ # This method provides a mechanism to automatically deal with
+ # subdirectories containing further Makefile.PL scripts.
+ # It calls the subdir_x() method for each subdirectory.
+ foreach my $dir (@{$self->{DIR}}){
+ push(@m, $self->subdir_x($dir));
+#### print "Including $dir subdirectory\n";
+ }
+ if (@m){
+ unshift(@m, "
+# The default clean, realclean and test targets in this Makefile
+# have automatically been given entries for each subdir.
+
+");
+ } else {
+ push(@m, "\n# none")
+ }
+ join('',@m);
+}
+
+=item test (o)
+
+Defines the test targets.
+
+=cut
+
+sub test {
+# --- Test and Installation Sections ---
+
+ my($self, %attribs) = @_;
+ my $tests = $attribs{TESTS} || '';
+ if (!$tests && -d 't') {
+ $tests = $self->find_tests;
+ }
+ # note: 'test.pl' name is also hardcoded in init_dirscan()
+ my(@m);
+ push(@m,"
+TEST_VERBOSE=0
+TEST_TYPE=test_\$(LINKTYPE)
+TEST_FILE = test.pl
+TEST_FILES = $tests
+TESTDB_SW = -d
+
+testdb :: testdb_\$(LINKTYPE)
+
+test :: \$(TEST_TYPE) subdirs-test
+
+subdirs-test ::
+ \$(NOECHO) \$(NOOP)
+
+");
+
+ foreach my $dir (@{ $self->{DIR} }) {
+ my $test = $self->cd($dir, '$(MAKE) test $(PASTHRU)');
+
+ push @m, <<END
+subdirs-test ::
+ \$(NOECHO) $test
+
+END
+ }
+
+ push(@m, "\t\$(NOECHO) \$(ECHO) 'No tests defined for \$(NAME) extension.'\n")
+ unless $tests or -f "test.pl" or @{$self->{DIR}};
+ push(@m, "\n");
+
+ push(@m, "test_dynamic :: pure_all\n");
+ push(@m, $self->test_via_harness('$(FULLPERLRUN)', '$(TEST_FILES)'))
+ if $tests;
+ push(@m, $self->test_via_script('$(FULLPERLRUN)', '$(TEST_FILE)'))
+ if -f "test.pl";
+ push(@m, "\n");
+
+ push(@m, "testdb_dynamic :: pure_all\n");
+ push(@m, $self->test_via_script('$(FULLPERLRUN) $(TESTDB_SW)',
+ '$(TEST_FILE)'));
+ push(@m, "\n");
+
+ # Occasionally we may face this degenerate target:
+ push @m, "test_ : test_dynamic\n\n";
+
+ if ($self->needs_linking()) {
+ push(@m, "test_static :: pure_all \$(MAP_TARGET)\n");
+ push(@m, $self->test_via_harness('./$(MAP_TARGET)', '$(TEST_FILES)')) if $tests;
+ push(@m, $self->test_via_script('./$(MAP_TARGET)', '$(TEST_FILE)')) if -f "test.pl";
+ push(@m, "\n");
+ push(@m, "testdb_static :: pure_all \$(MAP_TARGET)\n");
+ push(@m, $self->test_via_script('./$(MAP_TARGET) $(TESTDB_SW)', '$(TEST_FILE)'));
+ push(@m, "\n");
+ } else {
+ push @m, "test_static :: test_dynamic\n";
+ push @m, "testdb_static :: testdb_dynamic\n";
+ }
+ join("", @m);
+}
+
+=item test_via_harness (override)
+
+For some reason which I forget, Unix machines like to have
+PERL_DL_NONLAZY set for tests.
+
+=cut
+
+sub test_via_harness {
+ my($self, $perl, $tests) = @_;
+ return $self->SUPER::test_via_harness("PERL_DL_NONLAZY=1 $perl", $tests);
+}
+
+=item test_via_script (override)
+
+Again, the PERL_DL_NONLAZY thing.
+
+=cut
+
+sub test_via_script {
+ my($self, $perl, $script) = @_;
+ return $self->SUPER::test_via_script("PERL_DL_NONLAZY=1 $perl", $script);
+}
+
+
+=item tool_xsubpp (o)
+
+Determines typemaps, xsubpp version, prototype behaviour.
+
+=cut
+
+sub tool_xsubpp {
+ my($self) = shift;
+ return "" unless $self->needs_linking;
+
+ my $xsdir;
+ my @xsubpp_dirs = @INC;
+
+ # Make sure we pick up the new xsubpp if we're building perl.
+ unshift @xsubpp_dirs, $self->{PERL_LIB} if $self->{PERL_CORE};
+
+ foreach my $dir (@xsubpp_dirs) {
+ $xsdir = $self->catdir($dir, 'ExtUtils');
+ if( -r $self->catfile($xsdir, "xsubpp") ) {
+ last;
+ }
+ }
+
+ my $tmdir = File::Spec->catdir($self->{PERL_LIB},"ExtUtils");
+ my(@tmdeps) = $self->catfile($tmdir,'typemap');
+ if( $self->{TYPEMAPS} ){
+ foreach my $typemap (@{$self->{TYPEMAPS}}){
+ if( ! -f $typemap ) {
+ warn "Typemap $typemap not found.\n";
+ }
+ else {
+ push(@tmdeps, $typemap);
+ }
+ }
+ }
+ push(@tmdeps, "typemap") if -f "typemap";
+ my(@tmargs) = map("-typemap $_", @tmdeps);
+ if( exists $self->{XSOPT} ){
+ unshift( @tmargs, $self->{XSOPT} );
+ }
+
+ if ($Is{VMS} &&
+ $Config{'ldflags'} &&
+ $Config{'ldflags'} =~ m!/Debug!i &&
+ (!exists($self->{XSOPT}) || $self->{XSOPT} !~ /linenumbers/)
+ )
+ {
+ unshift(@tmargs,'-nolinenumbers');
+ }
+
+
+ $self->{XSPROTOARG} = "" unless defined $self->{XSPROTOARG};
+
+ return qq{
+XSUBPPDIR = $xsdir
+XSUBPP = \$(XSUBPPDIR)\$(DFSEP)xsubpp
+XSUBPPRUN = \$(PERLRUN) \$(XSUBPP)
+XSPROTOARG = $self->{XSPROTOARG}
+XSUBPPDEPS = @tmdeps \$(XSUBPP)
+XSUBPPARGS = @tmargs
+XSUBPP_EXTRA_ARGS =
+};
+};
+
+
+=item all_target
+
+Build man pages, too
+
+=cut
+
+sub all_target {
+ my $self = shift;
+
+ return <<'MAKE_EXT';
+all :: pure_all manifypods
+ $(NOECHO) $(NOOP)
+MAKE_EXT
+}
+
+=item top_targets (o)
+
+Defines the targets all, subdirs, config, and O_FILES
+
+=cut
+
+sub top_targets {
+# --- Target Sections ---
+
+ my($self) = shift;
+ my(@m);
+
+ push @m, $self->all_target, "\n" unless $self->{SKIPHASH}{'all'};
+
+ push @m, '
+pure_all :: config pm_to_blib subdirs linkext
+ $(NOECHO) $(NOOP)
+
+subdirs :: $(MYEXTLIB)
+ $(NOECHO) $(NOOP)
+
+config :: $(FIRST_MAKEFILE) blibdirs
+ $(NOECHO) $(NOOP)
+';
+
+ push @m, '
+$(O_FILES): $(H_FILES)
+' if @{$self->{O_FILES} || []} && @{$self->{H} || []};
+
+ push @m, q{
+help :
+ perldoc ExtUtils::MakeMaker
+};
+
+ join('',@m);
+}
+
+=item writedoc
+
+Obsolete, deprecated method. Not used since Version 5.21.
+
+=cut
+
+sub writedoc {
+# --- perllocal.pod section ---
+ my($self,$what,$name,@attribs)=@_;
+ my $time = localtime;
+ print "=head2 $time: $what C<$name>\n\n=over 4\n\n=item *\n\n";
+ print join "\n\n=item *\n\n", map("C<$_>",@attribs);
+ print "\n\n=back\n\n";
+}
+
+=item xs_c (o)
+
+Defines the suffix rules to compile XS files to C.
+
+=cut
+
+sub xs_c {
+ my($self) = shift;
+ return '' unless $self->needs_linking();
+ '
+.xs.c:
+ $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $(XSUBPP_EXTRA_ARGS) $*.xs > $*.xsc && $(MV) $*.xsc $*.c
+';
+}
+
+=item xs_cpp (o)
+
+Defines the suffix rules to compile XS files to C++.
+
+=cut
+
+sub xs_cpp {
+ my($self) = shift;
+ return '' unless $self->needs_linking();
+ '
+.xs.cpp:
+ $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.xsc && $(MV) $*.xsc $*.cpp
+';
+}
+
+=item xs_o (o)
+
+Defines suffix rules to go from XS to object files directly. This is
+only intended for broken make implementations.
+
+=cut
+
+sub xs_o { # many makes are too dumb to use xs_c then c_o
+ my($self) = shift;
+ return '' unless $self->needs_linking();
+ '
+.xs$(OBJ_EXT):
+ $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.xsc && $(MV) $*.xsc $*.c
+ $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $*.c
+';
+}
+
+
+1;
+
+=back
+
+=head1 SEE ALSO
+
+L<ExtUtils::MakeMaker>
+
+=cut
+
+__END__
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MM_VMS.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MM_VMS.pm
new file mode 100644
index 00000000000..2066d035976
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MM_VMS.pm
@@ -0,0 +1,1994 @@
+package ExtUtils::MM_VMS;
+
+use strict;
+
+use ExtUtils::MakeMaker::Config;
+require Exporter;
+
+BEGIN {
+ # so we can compile the thing on non-VMS platforms.
+ if( $^O eq 'VMS' ) {
+ require VMS::Filespec;
+ VMS::Filespec->import;
+ }
+}
+
+use File::Basename;
+
+our $VERSION = '6.56';
+
+require ExtUtils::MM_Any;
+require ExtUtils::MM_Unix;
+our @ISA = qw( ExtUtils::MM_Any ExtUtils::MM_Unix );
+
+use ExtUtils::MakeMaker qw($Verbose neatvalue);
+our $Revision = $ExtUtils::MakeMaker::Revision;
+
+
+=head1 NAME
+
+ExtUtils::MM_VMS - methods to override UN*X behaviour in ExtUtils::MakeMaker
+
+=head1 SYNOPSIS
+
+ Do not use this directly.
+ Instead, use ExtUtils::MM and it will figure out which MM_*
+ class to use for you.
+
+=head1 DESCRIPTION
+
+See ExtUtils::MM_Unix for a documentation of the methods provided
+there. This package overrides the implementation of these methods, not
+the semantics.
+
+=head2 Methods always loaded
+
+=over 4
+
+=item wraplist
+
+Converts a list into a string wrapped at approximately 80 columns.
+
+=cut
+
+sub wraplist {
+ my($self) = shift;
+ my($line,$hlen) = ('',0);
+
+ foreach my $word (@_) {
+ # Perl bug -- seems to occasionally insert extra elements when
+ # traversing array (scalar(@array) doesn't show them, but
+ # foreach(@array) does) (5.00307)
+ next unless $word =~ /\w/;
+ $line .= ' ' if length($line);
+ if ($hlen > 80) { $line .= "\\\n\t"; $hlen = 0; }
+ $line .= $word;
+ $hlen += length($word) + 2;
+ }
+ $line;
+}
+
+
+# This isn't really an override. It's just here because ExtUtils::MM_VMS
+# appears in @MM::ISA before ExtUtils::Liblist::Kid, so if there isn't an ext()
+# in MM_VMS, then AUTOLOAD is called, and bad things happen. So, we just
+# mimic inheritance here and hand off to ExtUtils::Liblist::Kid.
+# XXX This hackery will die soon. --Schwern
+sub ext {
+ require ExtUtils::Liblist::Kid;
+ goto &ExtUtils::Liblist::Kid::ext;
+}
+
+=back
+
+=head2 Methods
+
+Those methods which override default MM_Unix methods are marked
+"(override)", while methods unique to MM_VMS are marked "(specific)".
+For overridden methods, documentation is limited to an explanation
+of why this method overrides the MM_Unix method; see the ExtUtils::MM_Unix
+documentation for more details.
+
+=over 4
+
+=item guess_name (override)
+
+Try to determine name of extension being built. We begin with the name
+of the current directory. Since VMS filenames are case-insensitive,
+however, we look for a F<.pm> file whose name matches that of the current
+directory (presumably the 'main' F<.pm> file for this extension), and try
+to find a C<package> statement from which to obtain the Mixed::Case
+package name.
+
+=cut
+
+sub guess_name {
+ my($self) = @_;
+ my($defname,$defpm,@pm,%xs);
+ local *PM;
+
+ $defname = basename(fileify($ENV{'DEFAULT'}));
+ $defname =~ s![\d\-_]*\.dir.*$!!; # Clip off .dir;1 suffix, and package version
+ $defpm = $defname;
+ # Fallback in case for some reason a user has copied the files for an
+ # extension into a working directory whose name doesn't reflect the
+ # extension's name. We'll use the name of a unique .pm file, or the
+ # first .pm file with a matching .xs file.
+ if (not -e "${defpm}.pm") {
+ @pm = glob('*.pm');
+ s/.pm$// for @pm;
+ if (@pm == 1) { ($defpm = $pm[0]) =~ s/.pm$//; }
+ elsif (@pm) {
+ %xs = map { s/.xs$//; ($_,1) } glob('*.xs'); ## no critic
+ if (keys %xs) {
+ foreach my $pm (@pm) {
+ $defpm = $pm, last if exists $xs{$pm};
+ }
+ }
+ }
+ }
+ if (open(my $pm, '<', "${defpm}.pm")){
+ while (<$pm>) {
+ if (/^\s*package\s+([^;]+)/i) {
+ $defname = $1;
+ last;
+ }
+ }
+ print STDOUT "Warning (non-fatal): Couldn't find package name in ${defpm}.pm;\n\t",
+ "defaulting package name to $defname\n"
+ if eof($pm);
+ close $pm;
+ }
+ else {
+ print STDOUT "Warning (non-fatal): Couldn't find ${defpm}.pm;\n\t",
+ "defaulting package name to $defname\n";
+ }
+ $defname =~ s#[\d.\-_]+$##;
+ $defname;
+}
+
+=item find_perl (override)
+
+Use VMS file specification syntax and CLI commands to find and
+invoke Perl images.
+
+=cut
+
+sub find_perl {
+ my($self, $ver, $names, $dirs, $trace) = @_;
+ my($vmsfile,@sdirs,@snames,@cand);
+ my($rslt);
+ my($inabs) = 0;
+ local *TCF;
+
+ if( $self->{PERL_CORE} ) {
+ # Check in relative directories first, so we pick up the current
+ # version of Perl if we're running MakeMaker as part of the main build.
+ @sdirs = sort { my($absa) = $self->file_name_is_absolute($a);
+ my($absb) = $self->file_name_is_absolute($b);
+ if ($absa && $absb) { return $a cmp $b }
+ else { return $absa ? 1 : ($absb ? -1 : ($a cmp $b)); }
+ } @$dirs;
+ # Check miniperl before perl, and check names likely to contain
+ # version numbers before "generic" names, so we pick up an
+ # executable that's less likely to be from an old installation.
+ @snames = sort { my($ba) = $a =~ m!([^:>\]/]+)$!; # basename
+ my($bb) = $b =~ m!([^:>\]/]+)$!;
+ my($ahasdir) = (length($a) - length($ba) > 0);
+ my($bhasdir) = (length($b) - length($bb) > 0);
+ if ($ahasdir and not $bhasdir) { return 1; }
+ elsif ($bhasdir and not $ahasdir) { return -1; }
+ else { $bb =~ /\d/ <=> $ba =~ /\d/
+ or substr($ba,0,1) cmp substr($bb,0,1)
+ or length($bb) <=> length($ba) } } @$names;
+ }
+ else {
+ @sdirs = @$dirs;
+ @snames = @$names;
+ }
+
+ # Image names containing Perl version use '_' instead of '.' under VMS
+ s/\.(\d+)$/_$1/ for @snames;
+ if ($trace >= 2){
+ print "Looking for perl $ver by these names:\n";
+ print "\t@snames,\n";
+ print "in these dirs:\n";
+ print "\t@sdirs\n";
+ }
+ foreach my $dir (@sdirs){
+ next unless defined $dir; # $self->{PERL_SRC} may be undefined
+ $inabs++ if $self->file_name_is_absolute($dir);
+ if ($inabs == 1) {
+ # We've covered relative dirs; everything else is an absolute
+ # dir (probably an installed location). First, we'll try
+ # potential command names, to see whether we can avoid a long
+ # MCR expression.
+ foreach my $name (@snames) {
+ push(@cand,$name) if $name =~ /^[\w\-\$]+$/;
+ }
+ $inabs++; # Should happen above in next $dir, but just in case...
+ }
+ foreach my $name (@snames){
+ push @cand, ($name !~ m![/:>\]]!) ? $self->catfile($dir,$name)
+ : $self->fixpath($name,0);
+ }
+ }
+ foreach my $name (@cand) {
+ print "Checking $name\n" if $trace >= 2;
+ # If it looks like a potential command, try it without the MCR
+ if ($name =~ /^[\w\-\$]+$/) {
+ open(my $tcf, ">", "temp_mmvms.com")
+ or die('unable to open temp file');
+ print $tcf "\$ set message/nofacil/nosever/noident/notext\n";
+ print $tcf "\$ $name -e \"require $ver; print \"\"VER_OK\\n\"\"\"\n";
+ close $tcf;
+ $rslt = `\@temp_mmvms.com` ;
+ unlink('temp_mmvms.com');
+ if ($rslt =~ /VER_OK/) {
+ print "Using PERL=$name\n" if $trace;
+ return $name;
+ }
+ }
+ next unless $vmsfile = $self->maybe_command($name);
+ $vmsfile =~ s/;[\d\-]*$//; # Clip off version number; we can use a newer version as well
+ print "Executing $vmsfile\n" if ($trace >= 2);
+ open(my $tcf, '>', "temp_mmvms.com")
+ or die('unable to open temp file');
+ print $tcf "\$ set message/nofacil/nosever/noident/notext\n";
+ print $tcf "\$ mcr $vmsfile -e \"require $ver; print \"\"VER_OK\\n\"\"\" \n";
+ close $tcf;
+ $rslt = `\@temp_mmvms.com`;
+ unlink('temp_mmvms.com');
+ if ($rslt =~ /VER_OK/) {
+ print "Using PERL=MCR $vmsfile\n" if $trace;
+ return "MCR $vmsfile";
+ }
+ }
+ print STDOUT "Unable to find a perl $ver (by these names: @$names, in these dirs: @$dirs)\n";
+ 0; # false and not empty
+}
+
+=item maybe_command (override)
+
+Follows VMS naming conventions for executable files.
+If the name passed in doesn't exactly match an executable file,
+appends F<.Exe> (or equivalent) to check for executable image, and F<.Com>
+to check for DCL procedure. If this fails, checks directories in DCL$PATH
+and finally F<Sys$System:> for an executable file having the name specified,
+with or without the F<.Exe>-equivalent suffix.
+
+=cut
+
+sub maybe_command {
+ my($self,$file) = @_;
+ return $file if -x $file && ! -d _;
+ my(@dirs) = ('');
+ my(@exts) = ('',$Config{'exe_ext'},'.exe','.com');
+
+ if ($file !~ m![/:>\]]!) {
+ for (my $i = 0; defined $ENV{"DCL\$PATH;$i"}; $i++) {
+ my $dir = $ENV{"DCL\$PATH;$i"};
+ $dir .= ':' unless $dir =~ m%[\]:]$%;
+ push(@dirs,$dir);
+ }
+ push(@dirs,'Sys$System:');
+ foreach my $dir (@dirs) {
+ my $sysfile = "$dir$file";
+ foreach my $ext (@exts) {
+ return $file if -x "$sysfile$ext" && ! -d _;
+ }
+ }
+ }
+ return 0;
+}
+
+
+=item pasthru (override)
+
+VMS has $(MMSQUALIFIERS) which is a listing of all the original command line
+options. This is used in every invocation of make in the VMS Makefile so
+PASTHRU should not be necessary. Using PASTHRU tends to blow commands past
+the 256 character limit.
+
+=cut
+
+sub pasthru {
+ return "PASTHRU=\n";
+}
+
+
+=item pm_to_blib (override)
+
+VMS wants a dot in every file so we can't have one called 'pm_to_blib',
+it becomes 'pm_to_blib.' and MMS/K isn't smart enough to know that when
+you have a target called 'pm_to_blib' it should look for 'pm_to_blib.'.
+
+So in VMS its pm_to_blib.ts.
+
+=cut
+
+sub pm_to_blib {
+ my $self = shift;
+
+ my $make = $self->SUPER::pm_to_blib;
+
+ $make =~ s{^pm_to_blib :}{pm_to_blib.ts :}m;
+ $make =~ s{\$\(TOUCH\) pm_to_blib}{\$(TOUCH) pm_to_blib.ts};
+
+ $make = <<'MAKE' . $make;
+# Dummy target to match Unix target name; we use pm_to_blib.ts as
+# timestamp file to avoid repeated invocations under VMS
+pm_to_blib : pm_to_blib.ts
+ $(NOECHO) $(NOOP)
+
+MAKE
+
+ return $make;
+}
+
+
+=item perl_script (override)
+
+If name passed in doesn't specify a readable file, appends F<.com> or
+F<.pl> and tries again, since it's customary to have file types on all files
+under VMS.
+
+=cut
+
+sub perl_script {
+ my($self,$file) = @_;
+ return $file if -r $file && ! -d _;
+ return "$file.com" if -r "$file.com";
+ return "$file.pl" if -r "$file.pl";
+ return '';
+}
+
+
+=item replace_manpage_separator
+
+Use as separator a character which is legal in a VMS-syntax file name.
+
+=cut
+
+sub replace_manpage_separator {
+ my($self,$man) = @_;
+ $man = unixify($man);
+ $man =~ s#/+#__#g;
+ $man;
+}
+
+=item init_DEST
+
+(override) Because of the difficulty concatenating VMS filepaths we
+must pre-expand the DEST* variables.
+
+=cut
+
+sub init_DEST {
+ my $self = shift;
+
+ $self->SUPER::init_DEST;
+
+ # Expand DEST variables.
+ foreach my $var ($self->installvars) {
+ my $destvar = 'DESTINSTALL'.$var;
+ $self->{$destvar} = $self->eliminate_macros($self->{$destvar});
+ }
+}
+
+
+=item init_DIRFILESEP
+
+No seperator between a directory path and a filename on VMS.
+
+=cut
+
+sub init_DIRFILESEP {
+ my($self) = shift;
+
+ $self->{DIRFILESEP} = '';
+ return 1;
+}
+
+
+=item init_main (override)
+
+
+=cut
+
+sub init_main {
+ my($self) = shift;
+
+ $self->SUPER::init_main;
+
+ $self->{DEFINE} ||= '';
+ if ($self->{DEFINE} ne '') {
+ my(@terms) = split(/\s+/,$self->{DEFINE});
+ my(@defs,@udefs);
+ foreach my $def (@terms) {
+ next unless $def;
+ my $targ = \@defs;
+ if ($def =~ s/^-([DU])//) { # If it was a Unix-style definition
+ $targ = \@udefs if $1 eq 'U';
+ $def =~ s/='(.*)'$/=$1/; # then remove shell-protection ''
+ $def =~ s/^'(.*)'$/$1/; # from entire term or argument
+ }
+ if ($def =~ /=/) {
+ $def =~ s/"/""/g; # Protect existing " from DCL
+ $def = qq["$def"]; # and quote to prevent parsing of =
+ }
+ push @$targ, $def;
+ }
+
+ $self->{DEFINE} = '';
+ if (@defs) {
+ $self->{DEFINE} = '/Define=(' . join(',',@defs) . ')';
+ }
+ if (@udefs) {
+ $self->{DEFINE} .= '/Undef=(' . join(',',@udefs) . ')';
+ }
+ }
+}
+
+=item init_others (override)
+
+Provide VMS-specific forms of various utility commands, then hand
+off to the default MM_Unix method.
+
+DEV_NULL should probably be overriden with something.
+
+Also changes EQUALIZE_TIMESTAMP to set revision date of target file to
+one second later than source file, since MMK interprets precisely
+equal revision dates for a source and target file as a sign that the
+target needs to be updated.
+
+=cut
+
+sub init_others {
+ my($self) = @_;
+
+ $self->{NOOP} = 'Continue';
+ $self->{NOECHO} ||= '@ ';
+
+ $self->{MAKEFILE} ||= $self->{FIRST_MAKEFILE} || 'Descrip.MMS';
+ $self->{FIRST_MAKEFILE} ||= $self->{MAKEFILE};
+ $self->{MAKE_APERL_FILE} ||= 'Makeaperl.MMS';
+ $self->{MAKEFILE_OLD} ||= $self->eliminate_macros('$(FIRST_MAKEFILE)_old');
+#
+# If an extension is not specified, then MMS/MMK assumes an
+# an extension of .MMS. If there really is no extension,
+# then a trailing "." needs to be appended to specify a
+# a null extension.
+#
+ $self->{MAKEFILE} .= '.' unless $self->{MAKEFILE} =~ m/\./;
+ $self->{FIRST_MAKEFILE} .= '.' unless $self->{FIRST_MAKEFILE} =~ m/\./;
+ $self->{MAKE_APERL_FILE} .= '.' unless $self->{MAKE_APERL_FILE} =~ m/\./;
+ $self->{MAKEFILE_OLD} .= '.' unless $self->{MAKEFILE_OLD} =~ m/\./;
+
+ $self->{MACROSTART} ||= '/Macro=(';
+ $self->{MACROEND} ||= ')';
+ $self->{USEMAKEFILE} ||= '/Descrip=';
+
+ $self->{EQUALIZE_TIMESTAMP} ||= '$(ABSPERLRUN) -we "open F,qq{>>$ARGV[1]};close F;utime(0,(stat($ARGV[0]))[9]+1,$ARGV[1])"';
+
+ $self->{MOD_INSTALL} ||=
+ $self->oneliner(<<'CODE', ['-MExtUtils::Install']);
+install([ from_to => {split(' ', <STDIN>)}, verbose => '$(VERBINST)', uninstall_shadows => '$(UNINST)', dir_mode => '$(PERM_DIR)' ]);
+CODE
+
+ $self->SUPER::init_others;
+
+ $self->{SHELL} ||= 'Posix';
+
+ $self->{UMASK_NULL} = '! ';
+
+ # Redirection on VMS goes before the command, not after as on Unix.
+ # $(DEV_NULL) is used once and its not worth going nuts over making
+ # it work. However, Unix's DEV_NULL is quite wrong for VMS.
+ $self->{DEV_NULL} = '';
+
+ if ($self->{OBJECT} =~ /\s/) {
+ $self->{OBJECT} =~ s/(\\)?\n+\s+/ /g;
+ $self->{OBJECT} = $self->wraplist(
+ map $self->fixpath($_,0), split /,?\s+/, $self->{OBJECT}
+ );
+ }
+
+ $self->{LDFROM} = $self->wraplist(
+ map $self->fixpath($_,0), split /,?\s+/, $self->{LDFROM}
+ );
+}
+
+
+=item init_platform (override)
+
+Add PERL_VMS, MM_VMS_REVISION and MM_VMS_VERSION.
+
+MM_VMS_REVISION is for backwards compatibility before MM_VMS had a
+$VERSION.
+
+=cut
+
+sub init_platform {
+ my($self) = shift;
+
+ $self->{MM_VMS_REVISION} = $Revision;
+ $self->{MM_VMS_VERSION} = $VERSION;
+ $self->{PERL_VMS} = $self->catdir($self->{PERL_SRC}, 'VMS')
+ if $self->{PERL_SRC};
+}
+
+
+=item platform_constants
+
+=cut
+
+sub platform_constants {
+ my($self) = shift;
+ my $make_frag = '';
+
+ foreach my $macro (qw(PERL_VMS MM_VMS_REVISION MM_VMS_VERSION))
+ {
+ next unless defined $self->{$macro};
+ $make_frag .= "$macro = $self->{$macro}\n";
+ }
+
+ return $make_frag;
+}
+
+
+=item init_VERSION (override)
+
+Override the *DEFINE_VERSION macros with VMS semantics. Translate the
+MAKEMAKER filepath to VMS style.
+
+=cut
+
+sub init_VERSION {
+ my $self = shift;
+
+ $self->SUPER::init_VERSION;
+
+ $self->{DEFINE_VERSION} = '"$(VERSION_MACRO)=""$(VERSION)"""';
+ $self->{XS_DEFINE_VERSION} = '"$(XS_VERSION_MACRO)=""$(XS_VERSION)"""';
+ $self->{MAKEMAKER} = vmsify($INC{'ExtUtils/MakeMaker.pm'});
+}
+
+
+=item constants (override)
+
+Fixes up numerous file and directory macros to insure VMS syntax
+regardless of input syntax. Also makes lists of files
+comma-separated.
+
+=cut
+
+sub constants {
+ my($self) = @_;
+
+ # Be kind about case for pollution
+ for (@ARGV) { $_ = uc($_) if /POLLUTE/i; }
+
+ # Cleanup paths for directories in MMS macros.
+ foreach my $macro ( qw [
+ INST_BIN INST_SCRIPT INST_LIB INST_ARCHLIB
+ PERL_LIB PERL_ARCHLIB
+ PERL_INC PERL_SRC ],
+ (map { 'INSTALL'.$_ } $self->installvars)
+ )
+ {
+ next unless defined $self->{$macro};
+ next if $macro =~ /MAN/ && $self->{$macro} eq 'none';
+ $self->{$macro} = $self->fixpath($self->{$macro},1);
+ }
+
+ # Cleanup paths for files in MMS macros.
+ foreach my $macro ( qw[LIBPERL_A FIRST_MAKEFILE MAKEFILE_OLD
+ MAKE_APERL_FILE MYEXTLIB] )
+ {
+ next unless defined $self->{$macro};
+ $self->{$macro} = $self->fixpath($self->{$macro},0);
+ }
+
+ # Fixup files for MMS macros
+ # XXX is this list complete?
+ for my $macro (qw/
+ FULLEXT VERSION_FROM OBJECT LDFROM
+ / ) {
+ next unless defined $self->{$macro};
+ $self->{$macro} = $self->fixpath($self->{$macro},0);
+ }
+
+
+ for my $macro (qw/ XS MAN1PODS MAN3PODS PM /) {
+ # Where is the space coming from? --jhi
+ next unless $self ne " " && defined $self->{$macro};
+ my %tmp = ();
+ for my $key (keys %{$self->{$macro}}) {
+ $tmp{$self->fixpath($key,0)} =
+ $self->fixpath($self->{$macro}{$key},0);
+ }
+ $self->{$macro} = \%tmp;
+ }
+
+ for my $macro (qw/ C O_FILES H /) {
+ next unless defined $self->{$macro};
+ my @tmp = ();
+ for my $val (@{$self->{$macro}}) {
+ push(@tmp,$self->fixpath($val,0));
+ }
+ $self->{$macro} = \@tmp;
+ }
+
+ # mms/k does not define a $(MAKE) macro.
+ $self->{MAKE} = '$(MMS)$(MMSQUALIFIERS)';
+
+ return $self->SUPER::constants;
+}
+
+
+=item special_targets
+
+Clear the default .SUFFIXES and put in our own list.
+
+=cut
+
+sub special_targets {
+ my $self = shift;
+
+ my $make_frag .= <<'MAKE_FRAG';
+.SUFFIXES :
+.SUFFIXES : $(OBJ_EXT) .c .cpp .cxx .xs
+
+MAKE_FRAG
+
+ return $make_frag;
+}
+
+=item cflags (override)
+
+Bypass shell script and produce qualifiers for CC directly (but warn
+user if a shell script for this extension exists). Fold multiple
+/Defines into one, since some C compilers pay attention to only one
+instance of this qualifier on the command line.
+
+=cut
+
+sub cflags {
+ my($self,$libperl) = @_;
+ my($quals) = $self->{CCFLAGS} || $Config{'ccflags'};
+ my($definestr,$undefstr,$flagoptstr) = ('','','');
+ my($incstr) = '/Include=($(PERL_INC)';
+ my($name,$sys,@m);
+
+ ( $name = $self->{NAME} . "_cflags" ) =~ s/:/_/g ;
+ print STDOUT "Unix shell script ".$Config{"$self->{'BASEEXT'}_cflags"}.
+ " required to modify CC command for $self->{'BASEEXT'}\n"
+ if ($Config{$name});
+
+ if ($quals =~ / -[DIUOg]/) {
+ while ($quals =~ / -([Og])(\d*)\b/) {
+ my($type,$lvl) = ($1,$2);
+ $quals =~ s/ -$type$lvl\b\s*//;
+ if ($type eq 'g') { $flagoptstr = '/NoOptimize'; }
+ else { $flagoptstr = '/Optimize' . (defined($lvl) ? "=$lvl" : ''); }
+ }
+ while ($quals =~ / -([DIU])(\S+)/) {
+ my($type,$def) = ($1,$2);
+ $quals =~ s/ -$type$def\s*//;
+ $def =~ s/"/""/g;
+ if ($type eq 'D') { $definestr .= qq["$def",]; }
+ elsif ($type eq 'I') { $incstr .= ',' . $self->fixpath($def,1); }
+ else { $undefstr .= qq["$def",]; }
+ }
+ }
+ if (length $quals and $quals !~ m!/!) {
+ warn "MM_VMS: Ignoring unrecognized CCFLAGS elements \"$quals\"\n";
+ $quals = '';
+ }
+ $definestr .= q["PERL_POLLUTE",] if $self->{POLLUTE};
+ if (length $definestr) { chop($definestr); $quals .= "/Define=($definestr)"; }
+ if (length $undefstr) { chop($undefstr); $quals .= "/Undef=($undefstr)"; }
+ # Deal with $self->{DEFINE} here since some C compilers pay attention
+ # to only one /Define clause on command line, so we have to
+ # conflate the ones from $Config{'ccflags'} and $self->{DEFINE}
+ # ($self->{DEFINE} has already been VMSified in constants() above)
+ if ($self->{DEFINE}) { $quals .= $self->{DEFINE}; }
+ for my $type (qw(Def Undef)) {
+ my(@terms);
+ while ($quals =~ m:/${type}i?n?e?=([^/]+):ig) {
+ my $term = $1;
+ $term =~ s:^\((.+)\)$:$1:;
+ push @terms, $term;
+ }
+ if ($type eq 'Def') {
+ push @terms, qw[ $(DEFINE_VERSION) $(XS_DEFINE_VERSION) ];
+ }
+ if (@terms) {
+ $quals =~ s:/${type}i?n?e?=[^/]+::ig;
+ $quals .= "/${type}ine=(" . join(',',@terms) . ')';
+ }
+ }
+
+ $libperl or $libperl = $self->{LIBPERL_A} || "libperl.olb";
+
+ # Likewise with $self->{INC} and /Include
+ if ($self->{'INC'}) {
+ my(@includes) = split(/\s+/,$self->{INC});
+ foreach (@includes) {
+ s/^-I//;
+ $incstr .= ','.$self->fixpath($_,1);
+ }
+ }
+ $quals .= "$incstr)";
+# $quals =~ s/,,/,/g; $quals =~ s/\(,/(/g;
+ $self->{CCFLAGS} = $quals;
+
+ $self->{PERLTYPE} ||= '';
+
+ $self->{OPTIMIZE} ||= $flagoptstr || $Config{'optimize'};
+ if ($self->{OPTIMIZE} !~ m!/!) {
+ if ($self->{OPTIMIZE} =~ m!-g!) { $self->{OPTIMIZE} = '/Debug/NoOptimize' }
+ elsif ($self->{OPTIMIZE} =~ /-O(\d*)/) {
+ $self->{OPTIMIZE} = '/Optimize' . (defined($1) ? "=$1" : '');
+ }
+ else {
+ warn "MM_VMS: Can't parse OPTIMIZE \"$self->{OPTIMIZE}\"; using default\n" if length $self->{OPTIMIZE};
+ $self->{OPTIMIZE} = '/Optimize';
+ }
+ }
+
+ return $self->{CFLAGS} = qq{
+CCFLAGS = $self->{CCFLAGS}
+OPTIMIZE = $self->{OPTIMIZE}
+PERLTYPE = $self->{PERLTYPE}
+};
+}
+
+=item const_cccmd (override)
+
+Adds directives to point C preprocessor to the right place when
+handling #include E<lt>sys/foo.hE<gt> directives. Also constructs CC
+command line a bit differently than MM_Unix method.
+
+=cut
+
+sub const_cccmd {
+ my($self,$libperl) = @_;
+ my(@m);
+
+ return $self->{CONST_CCCMD} if $self->{CONST_CCCMD};
+ return '' unless $self->needs_linking();
+ if ($Config{'vms_cc_type'} eq 'gcc') {
+ push @m,'
+.FIRST
+ ',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" Then Define/NoLog SYS GNU_CC_Include:[VMS]';
+ }
+ elsif ($Config{'vms_cc_type'} eq 'vaxc') {
+ push @m,'
+.FIRST
+ ',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" .and. F$TrnLnm("VAXC$Include").eqs."" Then Define/NoLog SYS Sys$Library
+ ',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" .and. F$TrnLnm("VAXC$Include").nes."" Then Define/NoLog SYS VAXC$Include';
+ }
+ else {
+ push @m,'
+.FIRST
+ ',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" .and. F$TrnLnm("DECC$System_Include").eqs."" Then Define/NoLog SYS ',
+ ($Config{'archname'} eq 'VMS_AXP' ? 'Sys$Library' : 'DECC$Library_Include'),'
+ ',$self->{NOECHO},'If F$TrnLnm("Sys").eqs."" .and. F$TrnLnm("DECC$System_Include").nes."" Then Define/NoLog SYS DECC$System_Include';
+ }
+
+ push(@m, "\n\nCCCMD = $Config{'cc'} \$(CCFLAGS)\$(OPTIMIZE)\n");
+
+ $self->{CONST_CCCMD} = join('',@m);
+}
+
+
+=item tools_other (override)
+
+Throw in some dubious extra macros for Makefile args.
+
+Also keep around the old $(SAY) macro in case somebody's using it.
+
+=cut
+
+sub tools_other {
+ my($self) = @_;
+
+ # XXX Are these necessary? Does anyone override them? They're longer
+ # than just typing the literal string.
+ my $extra_tools = <<'EXTRA_TOOLS';
+
+# Just in case anyone is using the old macro.
+USEMACROS = $(MACROSTART)
+SAY = $(ECHO)
+
+EXTRA_TOOLS
+
+ return $self->SUPER::tools_other . $extra_tools;
+}
+
+=item init_dist (override)
+
+VMSish defaults for some values.
+
+ macro description default
+
+ ZIPFLAGS flags to pass to ZIP -Vu
+
+ COMPRESS compression command to gzip
+ use for tarfiles
+ SUFFIX suffix to put on -gz
+ compressed files
+
+ SHAR shar command to use vms_share
+
+ DIST_DEFAULT default target to use to tardist
+ create a distribution
+
+ DISTVNAME Use VERSION_SYM instead of $(DISTNAME)-$(VERSION_SYM)
+ VERSION for the name
+
+=cut
+
+sub init_dist {
+ my($self) = @_;
+ $self->{ZIPFLAGS} ||= '-Vu';
+ $self->{COMPRESS} ||= 'gzip';
+ $self->{SUFFIX} ||= '-gz';
+ $self->{SHAR} ||= 'vms_share';
+ $self->{DIST_DEFAULT} ||= 'zipdist';
+
+ $self->SUPER::init_dist;
+
+ $self->{DISTVNAME} = "$self->{DISTNAME}-$self->{VERSION_SYM}"
+ unless $self->{ARGS}{DISTVNAME};
+
+ return;
+}
+
+=item c_o (override)
+
+Use VMS syntax on command line. In particular, $(DEFINE) and
+$(PERL_INC) have been pulled into $(CCCMD). Also use MM[SK] macros.
+
+=cut
+
+sub c_o {
+ my($self) = @_;
+ return '' unless $self->needs_linking();
+ '
+.c$(OBJ_EXT) :
+ $(CCCMD) $(CCCDLFLAGS) $(MMS$TARGET_NAME).c
+
+.cpp$(OBJ_EXT) :
+ $(CCCMD) $(CCCDLFLAGS) $(MMS$TARGET_NAME).cpp
+
+.cxx$(OBJ_EXT) :
+ $(CCCMD) $(CCCDLFLAGS) $(MMS$TARGET_NAME).cxx
+
+';
+}
+
+=item xs_c (override)
+
+Use MM[SK] macros.
+
+=cut
+
+sub xs_c {
+ my($self) = @_;
+ return '' unless $self->needs_linking();
+ '
+.xs.c :
+ $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $(MMS$TARGET_NAME).xs >$(MMS$TARGET)
+';
+}
+
+=item xs_o (override)
+
+Use MM[SK] macros, and VMS command line for C compiler.
+
+=cut
+
+sub xs_o { # many makes are too dumb to use xs_c then c_o
+ my($self) = @_;
+ return '' unless $self->needs_linking();
+ '
+.xs$(OBJ_EXT) :
+ $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $(MMS$TARGET_NAME).xs >$(MMS$TARGET_NAME).c
+ $(CCCMD) $(CCCDLFLAGS) $(MMS$TARGET_NAME).c
+';
+}
+
+
+=item dlsyms (override)
+
+Create VMS linker options files specifying universal symbols for this
+extension's shareable image, and listing other shareable images or
+libraries to which it should be linked.
+
+=cut
+
+sub dlsyms {
+ my($self,%attribs) = @_;
+
+ return '' unless $self->needs_linking();
+
+ my($funcs) = $attribs{DL_FUNCS} || $self->{DL_FUNCS} || {};
+ my($vars) = $attribs{DL_VARS} || $self->{DL_VARS} || [];
+ my($funclist) = $attribs{FUNCLIST} || $self->{FUNCLIST} || [];
+ my(@m);
+
+ unless ($self->{SKIPHASH}{'dynamic'}) {
+ push(@m,'
+dynamic :: $(INST_ARCHAUTODIR)$(BASEEXT).opt
+ $(NOECHO) $(NOOP)
+');
+ }
+
+ push(@m,'
+static :: $(INST_ARCHAUTODIR)$(BASEEXT).opt
+ $(NOECHO) $(NOOP)
+') unless $self->{SKIPHASH}{'static'};
+
+ push @m,'
+$(INST_ARCHAUTODIR)$(BASEEXT).opt : $(BASEEXT).opt
+ $(CP) $(MMS$SOURCE) $(MMS$TARGET)
+
+$(BASEEXT).opt : Makefile.PL
+ $(PERLRUN) -e "use ExtUtils::Mksymlists;" -
+ ',qq[-e "Mksymlists('NAME' => '$self->{NAME}', 'DL_FUNCS' => ],
+ neatvalue($funcs),q[, 'DL_VARS' => ],neatvalue($vars),
+ q[, 'FUNCLIST' => ],neatvalue($funclist),qq[)"\n];
+
+ push @m, ' $(PERL) -e "print ""$(INST_STATIC)/Include=';
+ if ($self->{OBJECT} =~ /\bBASEEXT\b/ or
+ $self->{OBJECT} =~ /\b$self->{BASEEXT}\b/i) {
+ push @m, ($Config{d_vms_case_sensitive_symbols}
+ ? uc($self->{BASEEXT}) :'$(BASEEXT)');
+ }
+ else { # We don't have a "main" object file, so pull 'em all in
+ # Upcase module names if linker is being case-sensitive
+ my($upcase) = $Config{d_vms_case_sensitive_symbols};
+ my(@omods) = split ' ', $self->eliminate_macros($self->{OBJECT});
+ for (@omods) {
+ s/\.[^.]*$//; # Trim off file type
+ s[\$\(\w+_EXT\)][]; # even as a macro
+ s/.*[:>\/\]]//; # Trim off dir spec
+ $_ = uc if $upcase;
+ };
+
+ my(@lines);
+ my $tmp = shift @omods;
+ foreach my $elt (@omods) {
+ $tmp .= ",$elt";
+ if (length($tmp) > 80) { push @lines, $tmp; $tmp = ''; }
+ }
+ push @lines, $tmp;
+ push @m, '(', join( qq[, -\\n\\t"";" >>\$(MMS\$TARGET)\n\t\$(PERL) -e "print ""], @lines),')';
+ }
+ push @m, '\n$(INST_STATIC)/Library\n"";" >>$(MMS$TARGET)',"\n";
+
+ if (length $self->{LDLOADLIBS}) {
+ my($line) = '';
+ foreach my $lib (split ' ', $self->{LDLOADLIBS}) {
+ $lib =~ s%\$%\\\$%g; # Escape '$' in VMS filespecs
+ if (length($line) + length($lib) > 160) {
+ push @m, "\t\$(PERL) -e \"print qq{$line}\" >>\$(MMS\$TARGET)\n";
+ $line = $lib . '\n';
+ }
+ else { $line .= $lib . '\n'; }
+ }
+ push @m, "\t\$(PERL) -e \"print qq{$line}\" >>\$(MMS\$TARGET)\n" if $line;
+ }
+
+ join('',@m);
+
+}
+
+=item dynamic_lib (override)
+
+Use VMS Link command.
+
+=cut
+
+sub dynamic_lib {
+ my($self, %attribs) = @_;
+ return '' unless $self->needs_linking(); #might be because of a subdir
+
+ return '' unless $self->has_link_code();
+
+ my($otherldflags) = $attribs{OTHERLDFLAGS} || "";
+ my($inst_dynamic_dep) = $attribs{INST_DYNAMIC_DEP} || "";
+ my $shr = $Config{'dbgprefix'} . 'PerlShr';
+ my(@m);
+ push @m,"
+
+OTHERLDFLAGS = $otherldflags
+INST_DYNAMIC_DEP = $inst_dynamic_dep
+
+";
+ push @m, '
+$(INST_DYNAMIC) : $(INST_STATIC) $(PERL_INC)perlshr_attr.opt $(INST_ARCHAUTODIR)$(DFSEP).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP)
+ If F$TrnLNm("',$shr,'").eqs."" Then Define/NoLog/User ',"$shr Sys\$Share:$shr.$Config{'dlext'}",'
+ Link $(LDFLAGS) /Shareable=$(MMS$TARGET)$(OTHERLDFLAGS) $(BASEEXT).opt/Option,$(PERL_INC)perlshr_attr.opt/Option
+';
+
+ join('',@m);
+}
+
+
+=item static_lib (override)
+
+Use VMS commands to manipulate object library.
+
+=cut
+
+sub static_lib {
+ my($self) = @_;
+ return '' unless $self->needs_linking();
+
+ return '
+$(INST_STATIC) :
+ $(NOECHO) $(NOOP)
+' unless ($self->{OBJECT} or @{$self->{C} || []} or $self->{MYEXTLIB});
+
+ my(@m);
+ push @m,'
+# Rely on suffix rule for update action
+$(OBJECT) : $(INST_ARCHAUTODIR)$(DFSEP).exists
+
+$(INST_STATIC) : $(OBJECT) $(MYEXTLIB)
+';
+ # If this extension has its own library (eg SDBM_File)
+ # then copy that to $(INST_STATIC) and add $(OBJECT) into it.
+ push(@m, "\t",'$(CP) $(MYEXTLIB) $(MMS$TARGET)',"\n") if $self->{MYEXTLIB};
+
+ push(@m,"\t",'If F$Search("$(MMS$TARGET)").eqs."" Then Library/Object/Create $(MMS$TARGET)',"\n");
+
+ # if there was a library to copy, then we can't use MMS$SOURCE_LIST,
+ # 'cause it's a library and you can't stick them in other libraries.
+ # In that case, we use $OBJECT instead and hope for the best
+ if ($self->{MYEXTLIB}) {
+ push(@m,"\t",'Library/Object/Replace $(MMS$TARGET) $(OBJECT)',"\n");
+ } else {
+ push(@m,"\t",'Library/Object/Replace $(MMS$TARGET) $(MMS$SOURCE_LIST)',"\n");
+ }
+
+ push @m, "\t\$(NOECHO) \$(PERL) -e 1 >\$(INST_ARCHAUTODIR)extralibs.ld\n";
+ foreach my $lib (split ' ', $self->{EXTRALIBS}) {
+ push(@m,"\t",'$(NOECHO) $(PERL) -e "print qq{',$lib,'\n}" >>$(INST_ARCHAUTODIR)extralibs.ld',"\n");
+ }
+ join('',@m);
+}
+
+
+=item extra_clean_files
+
+Clean up some OS specific files. Plus the temp file used to shorten
+a lot of commands.
+
+=cut
+
+sub extra_clean_files {
+ return qw(
+ *.Map *.Dmp *.Lis *.cpp *.$(DLEXT) *.Opt $(BASEEXT).bso
+ .MM_Tmp
+ );
+}
+
+
+=item zipfile_target
+
+=item tarfile_target
+
+=item shdist_target
+
+Syntax for invoking shar, tar and zip differs from that for Unix.
+
+=cut
+
+sub zipfile_target {
+ my($self) = shift;
+
+ return <<'MAKE_FRAG';
+$(DISTVNAME).zip : distdir
+ $(PREOP)
+ $(ZIP) "$(ZIPFLAGS)" $(MMS$TARGET) [.$(DISTVNAME)...]*.*;
+ $(RM_RF) $(DISTVNAME)
+ $(POSTOP)
+MAKE_FRAG
+}
+
+sub tarfile_target {
+ my($self) = shift;
+
+ return <<'MAKE_FRAG';
+$(DISTVNAME).tar$(SUFFIX) : distdir
+ $(PREOP)
+ $(TO_UNIX)
+ $(TAR) "$(TARFLAGS)" $(DISTVNAME).tar [.$(DISTVNAME)...]
+ $(RM_RF) $(DISTVNAME)
+ $(COMPRESS) $(DISTVNAME).tar
+ $(POSTOP)
+MAKE_FRAG
+}
+
+sub shdist_target {
+ my($self) = shift;
+
+ return <<'MAKE_FRAG';
+shdist : distdir
+ $(PREOP)
+ $(SHAR) [.$(DISTVNAME)...]*.*; $(DISTVNAME).share
+ $(RM_RF) $(DISTVNAME)
+ $(POSTOP)
+MAKE_FRAG
+}
+
+
+# --- Test and Installation Sections ---
+
+=item install (override)
+
+Work around DCL's 255 character limit several times,and use
+VMS-style command line quoting in a few cases.
+
+=cut
+
+sub install {
+ my($self, %attribs) = @_;
+ my(@m);
+
+ push @m, q[
+install :: all pure_install doc_install
+ $(NOECHO) $(NOOP)
+
+install_perl :: all pure_perl_install doc_perl_install
+ $(NOECHO) $(NOOP)
+
+install_site :: all pure_site_install doc_site_install
+ $(NOECHO) $(NOOP)
+
+pure_install :: pure_$(INSTALLDIRS)_install
+ $(NOECHO) $(NOOP)
+
+doc_install :: doc_$(INSTALLDIRS)_install
+ $(NOECHO) $(NOOP)
+
+pure__install : pure_site_install
+ $(NOECHO) $(ECHO) "INSTALLDIRS not defined, defaulting to INSTALLDIRS=site"
+
+doc__install : doc_site_install
+ $(NOECHO) $(ECHO) "INSTALLDIRS not defined, defaulting to INSTALLDIRS=site"
+
+# This hack brought to you by DCL's 255-character command line limit
+pure_perl_install ::
+ $(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'read '.File::Spec->catfile('$(PERL_ARCHLIB)','auto','$(FULLEXT)','.packlist').' '" >.MM_tmp
+ $(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'write '.File::Spec->catfile('$(DESTINSTALLARCHLIB)','auto','$(FULLEXT)','.packlist').' '" >>.MM_tmp
+ $(NOECHO) $(ECHO_N) "$(INST_LIB) $(DESTINSTALLPRIVLIB) " >>.MM_tmp
+ $(NOECHO) $(ECHO_N) "$(INST_ARCHLIB) $(DESTINSTALLARCHLIB) " >>.MM_tmp
+ $(NOECHO) $(ECHO_N) "$(INST_BIN) $(DESTINSTALLBIN) " >>.MM_tmp
+ $(NOECHO) $(ECHO_N) "$(INST_SCRIPT) $(DESTINSTALLSCRIPT) " >>.MM_tmp
+ $(NOECHO) $(ECHO_N) "$(INST_MAN1DIR) $(DESTINSTALLMAN1DIR) " >>.MM_tmp
+ $(NOECHO) $(ECHO_N) "$(INST_MAN3DIR) $(DESTINSTALLMAN3DIR) " >>.MM_tmp
+ $(NOECHO) $(MOD_INSTALL) <.MM_tmp
+ $(NOECHO) $(RM_F) .MM_tmp
+ $(NOECHO) $(WARN_IF_OLD_PACKLIST) ].$self->catfile($self->{SITEARCHEXP},'auto',$self->{FULLEXT},'.packlist').q[
+
+# Likewise
+pure_site_install ::
+ $(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'read '.File::Spec->catfile('$(SITEARCHEXP)','auto','$(FULLEXT)','.packlist').' '" >.MM_tmp
+ $(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'write '.File::Spec->catfile('$(DESTINSTALLSITEARCH)','auto','$(FULLEXT)','.packlist').' '" >>.MM_tmp
+ $(NOECHO) $(ECHO_N) "$(INST_LIB) $(DESTINSTALLSITELIB) " >>.MM_tmp
+ $(NOECHO) $(ECHO_N) "$(INST_ARCHLIB) $(DESTINSTALLSITEARCH) " >>.MM_tmp
+ $(NOECHO) $(ECHO_N) "$(INST_BIN) $(DESTINSTALLSITEBIN) " >>.MM_tmp
+ $(NOECHO) $(ECHO_N) "$(INST_SCRIPT) $(DESTINSTALLSCRIPT) " >>.MM_tmp
+ $(NOECHO) $(ECHO_N) "$(INST_MAN1DIR) $(DESTINSTALLSITEMAN1DIR) " >>.MM_tmp
+ $(NOECHO) $(ECHO_N) "$(INST_MAN3DIR) $(DESTINSTALLSITEMAN3DIR) " >>.MM_tmp
+ $(NOECHO) $(MOD_INSTALL) <.MM_tmp
+ $(NOECHO) $(RM_F) .MM_tmp
+ $(NOECHO) $(WARN_IF_OLD_PACKLIST) ].$self->catfile($self->{PERL_ARCHLIB},'auto',$self->{FULLEXT},'.packlist').q[
+
+pure_vendor_install ::
+ $(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'read '.File::Spec->catfile('$(VENDORARCHEXP)','auto','$(FULLEXT)','.packlist').' '" >.MM_tmp
+ $(NOECHO) $(PERLRUN) "-MFile::Spec" -e "print 'write '.File::Spec->catfile('$(DESTINSTALLVENDORARCH)','auto','$(FULLEXT)','.packlist').' '" >>.MM_tmp
+ $(NOECHO) $(ECHO_N) "$(INST_LIB) $(DESTINSTALLVENDORLIB) " >>.MM_tmp
+ $(NOECHO) $(ECHO_N) "$(INST_ARCHLIB) $(DESTINSTALLVENDORARCH) " >>.MM_tmp
+ $(NOECHO) $(ECHO_N) "$(INST_BIN) $(DESTINSTALLVENDORBIN) " >>.MM_tmp
+ $(NOECHO) $(ECHO_N) "$(INST_SCRIPT) $(DESTINSTALLSCRIPT) " >>.MM_tmp
+ $(NOECHO) $(ECHO_N) "$(INST_MAN1DIR) $(DESTINSTALLVENDORMAN1DIR) " >>.MM_tmp
+ $(NOECHO) $(ECHO_N) "$(INST_MAN3DIR) $(DESTINSTALLVENDORMAN3DIR) " >>.MM_tmp
+ $(NOECHO) $(MOD_INSTALL) <.MM_tmp
+ $(NOECHO) $(RM_F) .MM_tmp
+
+# Ditto
+doc_perl_install ::
+ $(NOECHO) $(ECHO) "Appending installation info to ].$self->catfile($self->{DESTINSTALLARCHLIB}, 'perllocal.pod').q["
+ $(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
+ $(NOECHO) $(ECHO_N) "installed into|$(INSTALLPRIVLIB)|" >.MM_tmp
+ $(NOECHO) $(ECHO_N) "LINKTYPE|$(LINKTYPE)|VERSION|$(VERSION)|EXE_FILES|$(EXE_FILES) " >>.MM_tmp
+ $(NOECHO) $(DOC_INSTALL) "Module" "$(NAME)" <.MM_tmp >>].$self->catfile($self->{DESTINSTALLARCHLIB},'perllocal.pod').q[
+ $(NOECHO) $(RM_F) .MM_tmp
+
+# And again
+doc_site_install ::
+ $(NOECHO) $(ECHO) "Appending installation info to ].$self->catfile($self->{DESTINSTALLARCHLIB}, 'perllocal.pod').q["
+ $(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
+ $(NOECHO) $(ECHO_N) "installed into|$(INSTALLSITELIB)|" >.MM_tmp
+ $(NOECHO) $(ECHO_N) "LINKTYPE|$(LINKTYPE)|VERSION|$(VERSION)|EXE_FILES|$(EXE_FILES) " >>.MM_tmp
+ $(NOECHO) $(DOC_INSTALL) "Module" "$(NAME)" <.MM_tmp >>].$self->catfile($self->{DESTINSTALLARCHLIB},'perllocal.pod').q[
+ $(NOECHO) $(RM_F) .MM_tmp
+
+doc_vendor_install ::
+ $(NOECHO) $(ECHO) "Appending installation info to ].$self->catfile($self->{DESTINSTALLARCHLIB}, 'perllocal.pod').q["
+ $(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
+ $(NOECHO) $(ECHO_N) "installed into|$(INSTALLVENDORLIB)|" >.MM_tmp
+ $(NOECHO) $(ECHO_N) "LINKTYPE|$(LINKTYPE)|VERSION|$(VERSION)|EXE_FILES|$(EXE_FILES) " >>.MM_tmp
+ $(NOECHO) $(DOC_INSTALL) "Module" "$(NAME)" <.MM_tmp >>].$self->catfile($self->{DESTINSTALLARCHLIB},'perllocal.pod').q[
+ $(NOECHO) $(RM_F) .MM_tmp
+
+];
+
+ push @m, q[
+uninstall :: uninstall_from_$(INSTALLDIRS)dirs
+ $(NOECHO) $(NOOP)
+
+uninstall_from_perldirs ::
+ $(NOECHO) $(UNINSTALL) ].$self->catfile($self->{PERL_ARCHLIB},'auto',$self->{FULLEXT},'.packlist').q[
+ $(NOECHO) $(ECHO) "Uninstall is now deprecated and makes no actual changes."
+ $(NOECHO) $(ECHO) "Please check the list above carefully for errors, and manually remove"
+ $(NOECHO) $(ECHO) "the appropriate files. Sorry for the inconvenience."
+
+uninstall_from_sitedirs ::
+ $(NOECHO) $(UNINSTALL) ].$self->catfile($self->{SITEARCHEXP},'auto',$self->{FULLEXT},'.packlist').q[
+ $(NOECHO) $(ECHO) "Uninstall is now deprecated and makes no actual changes."
+ $(NOECHO) $(ECHO) "Please check the list above carefully for errors, and manually remove"
+ $(NOECHO) $(ECHO) "the appropriate files. Sorry for the inconvenience."
+];
+
+ join('',@m);
+}
+
+=item perldepend (override)
+
+Use VMS-style syntax for files; it's cheaper to just do it directly here
+than to have the MM_Unix method call C<catfile> repeatedly. Also, if
+we have to rebuild Config.pm, use MM[SK] to do it.
+
+=cut
+
+sub perldepend {
+ my($self) = @_;
+ my(@m);
+
+ push @m, '
+$(OBJECT) : $(PERL_INC)EXTERN.h, $(PERL_INC)INTERN.h, $(PERL_INC)XSUB.h
+$(OBJECT) : $(PERL_INC)av.h, $(PERL_INC)cc_runtime.h, $(PERL_INC)config.h
+$(OBJECT) : $(PERL_INC)cop.h, $(PERL_INC)cv.h, $(PERL_INC)embed.h
+$(OBJECT) : $(PERL_INC)embedvar.h, $(PERL_INC)form.h
+$(OBJECT) : $(PERL_INC)gv.h, $(PERL_INC)handy.h, $(PERL_INC)hv.h
+$(OBJECT) : $(PERL_INC)intrpvar.h, $(PERL_INC)iperlsys.h, $(PERL_INC)keywords.h
+$(OBJECT) : $(PERL_INC)mg.h, $(PERL_INC)nostdio.h, $(PERL_INC)op.h
+$(OBJECT) : $(PERL_INC)opcode.h, $(PERL_INC)patchlevel.h
+$(OBJECT) : $(PERL_INC)perl.h, $(PERL_INC)perlio.h
+$(OBJECT) : $(PERL_INC)perlsdio.h, $(PERL_INC)perlvars.h
+$(OBJECT) : $(PERL_INC)perly.h, $(PERL_INC)pp.h, $(PERL_INC)pp_proto.h
+$(OBJECT) : $(PERL_INC)proto.h, $(PERL_INC)regcomp.h, $(PERL_INC)regexp.h
+$(OBJECT) : $(PERL_INC)regnodes.h, $(PERL_INC)scope.h, $(PERL_INC)sv.h
+$(OBJECT) : $(PERL_INC)thread.h, $(PERL_INC)util.h, $(PERL_INC)vmsish.h
+
+' if $self->{OBJECT};
+
+ if ($self->{PERL_SRC}) {
+ my(@macros);
+ my($mmsquals) = '$(USEMAKEFILE)[.vms]$(FIRST_MAKEFILE)';
+ push(@macros,'__AXP__=1') if $Config{'archname'} eq 'VMS_AXP';
+ push(@macros,'DECC=1') if $Config{'vms_cc_type'} eq 'decc';
+ push(@macros,'GNUC=1') if $Config{'vms_cc_type'} eq 'gcc';
+ push(@macros,'SOCKET=1') if $Config{'d_has_sockets'};
+ push(@macros,qq["CC=$Config{'cc'}"]) if $Config{'cc'} =~ m!/!;
+ $mmsquals .= '$(USEMACROS)' . join(',',@macros) . '$(MACROEND)' if @macros;
+ push(@m,q[
+# Check for unpropagated config.sh changes. Should never happen.
+# We do NOT just update config.h because that is not sufficient.
+# An out of date config.h is not fatal but complains loudly!
+$(PERL_INC)config.h : $(PERL_SRC)config.sh
+ $(NOOP)
+
+$(PERL_ARCHLIB)Config.pm : $(PERL_SRC)config.sh
+ $(NOECHO) Write Sys$Error "$(PERL_ARCHLIB)Config.pm may be out of date with config.h or genconfig.pl"
+ olddef = F$Environment("Default")
+ Set Default $(PERL_SRC)
+ $(MMS)],$mmsquals,);
+ if ($self->{PERL_ARCHLIB} =~ m|\[-| && $self->{PERL_SRC} =~ m|(\[-+)|) {
+ my($prefix,$target) = ($1,$self->fixpath('$(PERL_ARCHLIB)Config.pm',0));
+ $target =~ s/\Q$prefix/[/;
+ push(@m," $target");
+ }
+ else { push(@m,' $(MMS$TARGET)'); }
+ push(@m,q[
+ Set Default 'olddef'
+]);
+ }
+
+ push(@m, join(" ", map($self->fixpath($_,0),values %{$self->{XS}}))." : \$(XSUBPPDEPS)\n")
+ if %{$self->{XS}};
+
+ join('',@m);
+}
+
+
+=item makeaperl (override)
+
+Undertake to build a new set of Perl images using VMS commands. Since
+VMS does dynamic loading, it's not necessary to statically link each
+extension into the Perl image, so this isn't the normal build path.
+Consequently, it hasn't really been tested, and may well be incomplete.
+
+=cut
+
+our %olbs; # needs to be localized
+
+sub makeaperl {
+ my($self, %attribs) = @_;
+ my($makefilename, $searchdirs, $static, $extra, $perlinc, $target, $tmpdir, $libperl) =
+ @attribs{qw(MAKE DIRS STAT EXTRA INCL TARGET TMP LIBPERL)};
+ my(@m);
+ push @m, "
+# --- MakeMaker makeaperl section ---
+MAP_TARGET = $target
+";
+ return join '', @m if $self->{PARENT};
+
+ my($dir) = join ":", @{$self->{DIR}};
+
+ unless ($self->{MAKEAPERL}) {
+ push @m, q{
+$(MAKE_APERL_FILE) : $(FIRST_MAKEFILE)
+ $(NOECHO) $(ECHO) "Writing ""$(MMS$TARGET)"" for this $(MAP_TARGET)"
+ $(NOECHO) $(PERLRUNINST) \
+ Makefile.PL DIR=}, $dir, q{ \
+ FIRST_MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \
+ MAKEAPERL=1 NORECURS=1 };
+
+ push @m, map(q[ \\\n\t\t"$_"], @ARGV),q{
+
+$(MAP_TARGET) :: $(MAKE_APERL_FILE)
+ $(MAKE)$(USEMAKEFILE)$(MAKE_APERL_FILE) static $(MMS$TARGET)
+};
+ push @m, "\n";
+
+ return join '', @m;
+ }
+
+
+ my($linkcmd,@optlibs,@staticpkgs,$extralist,$targdir,$libperldir,%libseen);
+ local($_);
+
+ # The front matter of the linkcommand...
+ $linkcmd = join ' ', $Config{'ld'},
+ grep($_, @Config{qw(large split ldflags ccdlflags)});
+ $linkcmd =~ s/\s+/ /g;
+
+ # Which *.olb files could we make use of...
+ local(%olbs); # XXX can this be lexical?
+ $olbs{$self->{INST_ARCHAUTODIR}} = "$self->{BASEEXT}\$(LIB_EXT)";
+ require File::Find;
+ File::Find::find(sub {
+ return unless m/\Q$self->{LIB_EXT}\E$/;
+ return if m/^libperl/;
+
+ if( exists $self->{INCLUDE_EXT} ){
+ my $found = 0;
+
+ (my $xx = $File::Find::name) =~ s,.*?/auto/,,;
+ $xx =~ s,/?$_,,;
+ $xx =~ s,/,::,g;
+
+ # Throw away anything not explicitly marked for inclusion.
+ # DynaLoader is implied.
+ foreach my $incl ((@{$self->{INCLUDE_EXT}},'DynaLoader')){
+ if( $xx eq $incl ){
+ $found++;
+ last;
+ }
+ }
+ return unless $found;
+ }
+ elsif( exists $self->{EXCLUDE_EXT} ){
+ (my $xx = $File::Find::name) =~ s,.*?/auto/,,;
+ $xx =~ s,/?$_,,;
+ $xx =~ s,/,::,g;
+
+ # Throw away anything explicitly marked for exclusion
+ foreach my $excl (@{$self->{EXCLUDE_EXT}}){
+ return if( $xx eq $excl );
+ }
+ }
+
+ $olbs{$ENV{DEFAULT}} = $_;
+ }, grep( -d $_, @{$searchdirs || []}));
+
+ # We trust that what has been handed in as argument will be buildable
+ $static = [] unless $static;
+ @olbs{@{$static}} = (1) x @{$static};
+
+ $extra = [] unless $extra && ref $extra eq 'ARRAY';
+ # Sort the object libraries in inverse order of
+ # filespec length to try to insure that dependent extensions
+ # will appear before their parents, so the linker will
+ # search the parent library to resolve references.
+ # (e.g. Intuit::DWIM will precede Intuit, so unresolved
+ # references from [.intuit.dwim]dwim.obj can be found
+ # in [.intuit]intuit.olb).
+ for (sort { length($a) <=> length($b) } keys %olbs) {
+ next unless $olbs{$_} =~ /\Q$self->{LIB_EXT}\E$/;
+ my($dir) = $self->fixpath($_,1);
+ my($extralibs) = $dir . "extralibs.ld";
+ my($extopt) = $dir . $olbs{$_};
+ $extopt =~ s/$self->{LIB_EXT}$/.opt/;
+ push @optlibs, "$dir$olbs{$_}";
+ # Get external libraries this extension will need
+ if (-f $extralibs ) {
+ my %seenthis;
+ open my $list, "<", $extralibs or warn $!,next;
+ while (<$list>) {
+ chomp;
+ # Include a library in the link only once, unless it's mentioned
+ # multiple times within a single extension's options file, in which
+ # case we assume the builder needed to search it again later in the
+ # link.
+ my $skip = exists($libseen{$_}) && !exists($seenthis{$_});
+ $libseen{$_}++; $seenthis{$_}++;
+ next if $skip;
+ push @$extra,$_;
+ }
+ }
+ # Get full name of extension for ExtUtils::Miniperl
+ if (-f $extopt) {
+ open my $opt, '<', $extopt or die $!;
+ while (<$opt>) {
+ next unless /(?:UNIVERSAL|VECTOR)=boot_([\w_]+)/;
+ my $pkg = $1;
+ $pkg =~ s#__*#::#g;
+ push @staticpkgs,$pkg;
+ }
+ }
+ }
+ # Place all of the external libraries after all of the Perl extension
+ # libraries in the final link, in order to maximize the opportunity
+ # for XS code from multiple extensions to resolve symbols against the
+ # same external library while only including that library once.
+ push @optlibs, @$extra;
+
+ $target = "Perl$Config{'exe_ext'}" unless $target;
+ my $shrtarget;
+ ($shrtarget,$targdir) = fileparse($target);
+ $shrtarget =~ s/^([^.]*)/$1Shr/;
+ $shrtarget = $targdir . $shrtarget;
+ $target = "Perlshr.$Config{'dlext'}" unless $target;
+ $tmpdir = "[]" unless $tmpdir;
+ $tmpdir = $self->fixpath($tmpdir,1);
+ if (@optlibs) { $extralist = join(' ',@optlibs); }
+ else { $extralist = ''; }
+ # Let ExtUtils::Liblist find the necessary libs for us (but skip PerlShr)
+ # that's what we're building here).
+ push @optlibs, grep { !/PerlShr/i } split ' ', +($self->ext())[2];
+ if ($libperl) {
+ unless (-f $libperl || -f ($libperl = $self->catfile($Config{'installarchlib'},'CORE',$libperl))) {
+ print STDOUT "Warning: $libperl not found\n";
+ undef $libperl;
+ }
+ }
+ unless ($libperl) {
+ if (defined $self->{PERL_SRC}) {
+ $libperl = $self->catfile($self->{PERL_SRC},"libperl$self->{LIB_EXT}");
+ } elsif (-f ($libperl = $self->catfile($Config{'installarchlib'},'CORE',"libperl$self->{LIB_EXT}")) ) {
+ } else {
+ print STDOUT "Warning: $libperl not found
+ If you're going to build a static perl binary, make sure perl is installed
+ otherwise ignore this warning\n";
+ }
+ }
+ $libperldir = $self->fixpath((fileparse($libperl))[1],1);
+
+ push @m, '
+# Fill in the target you want to produce if it\'s not perl
+MAP_TARGET = ',$self->fixpath($target,0),'
+MAP_SHRTARGET = ',$self->fixpath($shrtarget,0),"
+MAP_LINKCMD = $linkcmd
+MAP_PERLINC = ", $perlinc ? map('"$_" ',@{$perlinc}) : '',"
+MAP_EXTRA = $extralist
+MAP_LIBPERL = ",$self->fixpath($libperl,0),'
+';
+
+
+ push @m,"\n${tmpdir}Makeaperl.Opt : \$(MAP_EXTRA)\n";
+ foreach (@optlibs) {
+ push @m,' $(NOECHO) $(PERL) -e "print q{',$_,'}" >>$(MMS$TARGET)',"\n";
+ }
+ push @m,"\n${tmpdir}PerlShr.Opt :\n\t";
+ push @m,'$(NOECHO) $(PERL) -e "print q{$(MAP_SHRTARGET)}" >$(MMS$TARGET)',"\n";
+
+ push @m,'
+$(MAP_SHRTARGET) : $(MAP_LIBPERL) Makeaperl.Opt ',"${libperldir}Perlshr_Attr.Opt",'
+ $(MAP_LINKCMD)/Shareable=$(MMS$TARGET) $(MAP_LIBPERL), Makeaperl.Opt/Option ',"${libperldir}Perlshr_Attr.Opt/Option",'
+$(MAP_TARGET) : $(MAP_SHRTARGET) ',"${tmpdir}perlmain\$(OBJ_EXT) ${tmpdir}PerlShr.Opt",'
+ $(MAP_LINKCMD) ',"${tmpdir}perlmain\$(OBJ_EXT)",', PerlShr.Opt/Option
+ $(NOECHO) $(ECHO) "To install the new ""$(MAP_TARGET)"" binary, say"
+ $(NOECHO) $(ECHO) " $(MAKE)$(USEMAKEFILE)$(FIRST_MAKEFILE) inst_perl $(USEMACROS)MAP_TARGET=$(MAP_TARGET)$(ENDMACRO)"
+ $(NOECHO) $(ECHO) "To remove the intermediate files, say
+ $(NOECHO) $(ECHO) " $(MAKE)$(USEMAKEFILE)$(FIRST_MAKEFILE) map_clean"
+';
+ push @m,"\n${tmpdir}perlmain.c : \$(FIRST_MAKEFILE)\n\t\$(NOECHO) \$(PERL) -e 1 >${tmpdir}Writemain.tmp\n";
+ push @m, "# More from the 255-char line length limit\n";
+ foreach (@staticpkgs) {
+ push @m,' $(NOECHO) $(PERL) -e "print q{',$_,qq[}" >>${tmpdir}Writemain.tmp\n];
+ }
+
+ push @m, sprintf <<'MAKE_FRAG', $tmpdir, $tmpdir;
+ $(NOECHO) $(PERL) $(MAP_PERLINC) -ane "use ExtUtils::Miniperl; writemain(@F)" %sWritemain.tmp >$(MMS$TARGET)
+ $(NOECHO) $(RM_F) %sWritemain.tmp
+MAKE_FRAG
+
+ push @m, q[
+# Still more from the 255-char line length limit
+doc_inst_perl :
+ $(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
+ $(NOECHO) $(ECHO) "Perl binary $(MAP_TARGET)|" >.MM_tmp
+ $(NOECHO) $(ECHO) "MAP_STATIC|$(MAP_STATIC)|" >>.MM_tmp
+ $(NOECHO) $(PERL) -pl040 -e " " ].$self->catfile('$(INST_ARCHAUTODIR)','extralibs.all'),q[ >>.MM_tmp
+ $(NOECHO) $(ECHO) -e "MAP_LIBPERL|$(MAP_LIBPERL)|" >>.MM_tmp
+ $(NOECHO) $(DOC_INSTALL) <.MM_tmp >>].$self->catfile('$(DESTINSTALLARCHLIB)','perllocal.pod').q[
+ $(NOECHO) $(RM_F) .MM_tmp
+];
+
+ push @m, "
+inst_perl : pure_inst_perl doc_inst_perl
+ \$(NOECHO) \$(NOOP)
+
+pure_inst_perl : \$(MAP_TARGET)
+ $self->{CP} \$(MAP_SHRTARGET) ",$self->fixpath($Config{'installbin'},1),"
+ $self->{CP} \$(MAP_TARGET) ",$self->fixpath($Config{'installbin'},1),"
+
+clean :: map_clean
+ \$(NOECHO) \$(NOOP)
+
+map_clean :
+ \$(RM_F) ${tmpdir}perlmain\$(OBJ_EXT) ${tmpdir}perlmain.c \$(FIRST_MAKEFILE)
+ \$(RM_F) ${tmpdir}Makeaperl.Opt ${tmpdir}PerlShr.Opt \$(MAP_TARGET)
+";
+
+ join '', @m;
+}
+
+
+# --- Output postprocessing section ---
+
+=item maketext_filter (override)
+
+Insure that colons marking targets are preceded by space, in order
+to distinguish the target delimiter from a colon appearing as
+part of a filespec.
+
+=cut
+
+sub maketext_filter {
+ my($self, $text) = @_;
+
+ $text =~ s/^([^\s:=]+)(:+\s)/$1 $2/mg;
+ return $text;
+}
+
+=item prefixify (override)
+
+prefixifying on VMS is simple. Each should simply be:
+
+ perl_root:[some.dir]
+
+which can just be converted to:
+
+ volume:[your.prefix.some.dir]
+
+otherwise you get the default layout.
+
+In effect, your search prefix is ignored and $Config{vms_prefix} is
+used instead.
+
+=cut
+
+sub prefixify {
+ my($self, $var, $sprefix, $rprefix, $default) = @_;
+
+ # Translate $(PERLPREFIX) to a real path.
+ $rprefix = $self->eliminate_macros($rprefix);
+ $rprefix = vmspath($rprefix) if $rprefix;
+ $sprefix = vmspath($sprefix) if $sprefix;
+
+ $default = vmsify($default)
+ unless $default =~ /\[.*\]/;
+
+ (my $var_no_install = $var) =~ s/^install//;
+ my $path = $self->{uc $var} ||
+ $ExtUtils::MM_Unix::Config_Override{lc $var} ||
+ $Config{lc $var} || $Config{lc $var_no_install};
+
+ if( !$path ) {
+ print STDERR " no Config found for $var.\n" if $Verbose >= 2;
+ $path = $self->_prefixify_default($rprefix, $default);
+ }
+ elsif( !$self->{ARGS}{PREFIX} || !$self->file_name_is_absolute($path) ) {
+ # do nothing if there's no prefix or if its relative
+ }
+ elsif( $sprefix eq $rprefix ) {
+ print STDERR " no new prefix.\n" if $Verbose >= 2;
+ }
+ else {
+
+ print STDERR " prefixify $var => $path\n" if $Verbose >= 2;
+ print STDERR " from $sprefix to $rprefix\n" if $Verbose >= 2;
+
+ my($path_vol, $path_dirs) = $self->splitpath( $path );
+ if( $path_vol eq $Config{vms_prefix}.':' ) {
+ print STDERR " $Config{vms_prefix}: seen\n" if $Verbose >= 2;
+
+ $path_dirs =~ s{^\[}{\[.} unless $path_dirs =~ m{^\[\.};
+ $path = $self->_catprefix($rprefix, $path_dirs);
+ }
+ else {
+ $path = $self->_prefixify_default($rprefix, $default);
+ }
+ }
+
+ print " now $path\n" if $Verbose >= 2;
+ return $self->{uc $var} = $path;
+}
+
+
+sub _prefixify_default {
+ my($self, $rprefix, $default) = @_;
+
+ print STDERR " cannot prefix, using default.\n" if $Verbose >= 2;
+
+ if( !$default ) {
+ print STDERR "No default!\n" if $Verbose >= 1;
+ return;
+ }
+ if( !$rprefix ) {
+ print STDERR "No replacement prefix!\n" if $Verbose >= 1;
+ return '';
+ }
+
+ return $self->_catprefix($rprefix, $default);
+}
+
+sub _catprefix {
+ my($self, $rprefix, $default) = @_;
+
+ my($rvol, $rdirs) = $self->splitpath($rprefix);
+ if( $rvol ) {
+ return $self->catpath($rvol,
+ $self->catdir($rdirs, $default),
+ ''
+ )
+ }
+ else {
+ return $self->catdir($rdirs, $default);
+ }
+}
+
+
+=item cd
+
+=cut
+
+sub cd {
+ my($self, $dir, @cmds) = @_;
+
+ $dir = vmspath($dir);
+
+ my $cmd = join "\n\t", map "$_", @cmds;
+
+ # No leading tab makes it look right when embedded
+ my $make_frag = sprintf <<'MAKE_FRAG', $dir, $cmd;
+startdir = F$Environment("Default")
+ Set Default %s
+ %s
+ Set Default 'startdir'
+MAKE_FRAG
+
+ # No trailing newline makes this easier to embed
+ chomp $make_frag;
+
+ return $make_frag;
+}
+
+
+=item oneliner
+
+=cut
+
+sub oneliner {
+ my($self, $cmd, $switches) = @_;
+ $switches = [] unless defined $switches;
+
+ # Strip leading and trailing newlines
+ $cmd =~ s{^\n+}{};
+ $cmd =~ s{\n+$}{};
+
+ $cmd = $self->quote_literal($cmd);
+ $cmd = $self->escape_newlines($cmd);
+
+ # Switches must be quoted else they will be lowercased.
+ $switches = join ' ', map { qq{"$_"} } @$switches;
+
+ return qq{\$(ABSPERLRUN) $switches -e $cmd "--"};
+}
+
+
+=item B<echo>
+
+perl trips up on "<foo>" thinking it's an input redirect. So we use the
+native Write command instead. Besides, its faster.
+
+=cut
+
+sub echo {
+ my($self, $text, $file, $appending) = @_;
+ $appending ||= 0;
+
+ my $opencmd = $appending ? 'Open/Append' : 'Open/Write';
+
+ my @cmds = ("\$(NOECHO) $opencmd MMECHOFILE $file ");
+ push @cmds, map { '$(NOECHO) Write MMECHOFILE '.$self->quote_literal($_) }
+ split /\n/, $text;
+ push @cmds, '$(NOECHO) Close MMECHOFILE';
+ return @cmds;
+}
+
+
+=item quote_literal
+
+=cut
+
+sub quote_literal {
+ my($self, $text) = @_;
+
+ # I believe this is all we should need.
+ $text =~ s{"}{""}g;
+
+ return qq{"$text"};
+}
+
+=item escape_newlines
+
+=cut
+
+sub escape_newlines {
+ my($self, $text) = @_;
+
+ $text =~ s{\n}{-\n}g;
+
+ return $text;
+}
+
+=item max_exec_len
+
+256 characters.
+
+=cut
+
+sub max_exec_len {
+ my $self = shift;
+
+ return $self->{_MAX_EXEC_LEN} ||= 256;
+}
+
+=item init_linker
+
+=cut
+
+sub init_linker {
+ my $self = shift;
+ $self->{EXPORT_LIST} ||= '$(BASEEXT).opt';
+
+ my $shr = $Config{dbgprefix} . 'PERLSHR';
+ if ($self->{PERL_SRC}) {
+ $self->{PERL_ARCHIVE} ||=
+ $self->catfile($self->{PERL_SRC}, "$shr.$Config{'dlext'}");
+ }
+ else {
+ $self->{PERL_ARCHIVE} ||=
+ $ENV{$shr} ? $ENV{$shr} : "Sys\$Share:$shr.$Config{'dlext'}";
+ }
+
+ $self->{PERL_ARCHIVE_AFTER} ||= '';
+}
+
+
+=item catdir (override)
+
+=item catfile (override)
+
+Eliminate the macros in the output to the MMS/MMK file.
+
+(File::Spec::VMS used to do this for us, but it's being removed)
+
+=cut
+
+sub catdir {
+ my $self = shift;
+
+ # Process the macros on VMS MMS/MMK
+ my @args = map { m{\$\(} ? $self->eliminate_macros($_) : $_ } @_;
+
+ my $dir = $self->SUPER::catdir(@args);
+
+ # Fix up the directory and force it to VMS format.
+ $dir = $self->fixpath($dir, 1);
+
+ return $dir;
+}
+
+sub catfile {
+ my $self = shift;
+
+ # Process the macros on VMS MMS/MMK
+ my @args = map { m{\$\(} ? $self->eliminate_macros($_) : $_ } @_;
+
+ my $file = $self->SUPER::catfile(@args);
+
+ $file = vmsify($file);
+
+ return $file
+}
+
+
+=item eliminate_macros
+
+Expands MM[KS]/Make macros in a text string, using the contents of
+identically named elements of C<%$self>, and returns the result
+as a file specification in Unix syntax.
+
+NOTE: This is the canonical version of the method. The version in
+File::Spec::VMS is deprecated.
+
+=cut
+
+sub eliminate_macros {
+ my($self,$path) = @_;
+ return '' unless $path;
+ $self = {} unless ref $self;
+
+ if ($path =~ /\s/) {
+ return join ' ', map { $self->eliminate_macros($_) } split /\s+/, $path;
+ }
+
+ my($npath) = unixify($path);
+ # sometimes unixify will return a string with an off-by-one trailing null
+ $npath =~ s{\0$}{};
+
+ my($complex) = 0;
+ my($head,$macro,$tail);
+
+ # perform m##g in scalar context so it acts as an iterator
+ while ($npath =~ m#(.*?)\$\((\S+?)\)(.*)#gs) {
+ if (defined $self->{$2}) {
+ ($head,$macro,$tail) = ($1,$2,$3);
+ if (ref $self->{$macro}) {
+ if (ref $self->{$macro} eq 'ARRAY') {
+ $macro = join ' ', @{$self->{$macro}};
+ }
+ else {
+ print "Note: can't expand macro \$($macro) containing ",ref($self->{$macro}),
+ "\n\t(using MMK-specific deferred substitutuon; MMS will break)\n";
+ $macro = "\cB$macro\cB";
+ $complex = 1;
+ }
+ }
+ else { ($macro = unixify($self->{$macro})) =~ s#/\Z(?!\n)##; }
+ $npath = "$head$macro$tail";
+ }
+ }
+ if ($complex) { $npath =~ s#\cB(.*?)\cB#\${$1}#gs; }
+ $npath;
+}
+
+=item fixpath
+
+ my $path = $mm->fixpath($path);
+ my $path = $mm->fixpath($path, $is_dir);
+
+Catchall routine to clean up problem MM[SK]/Make macros. Expands macros
+in any directory specification, in order to avoid juxtaposing two
+VMS-syntax directories when MM[SK] is run. Also expands expressions which
+are all macro, so that we can tell how long the expansion is, and avoid
+overrunning DCL's command buffer when MM[KS] is running.
+
+fixpath() checks to see whether the result matches the name of a
+directory in the current default directory and returns a directory or
+file specification accordingly. C<$is_dir> can be set to true to
+force fixpath() to consider the path to be a directory or false to force
+it to be a file.
+
+NOTE: This is the canonical version of the method. The version in
+File::Spec::VMS is deprecated.
+
+=cut
+
+sub fixpath {
+ my($self,$path,$force_path) = @_;
+ return '' unless $path;
+ $self = bless {}, $self unless ref $self;
+ my($fixedpath,$prefix,$name);
+
+ if ($path =~ /[ \t]/) {
+ return join ' ',
+ map { $self->fixpath($_,$force_path) }
+ split /[ \t]+/, $path;
+ }
+
+ if ($path =~ m#^\$\([^\)]+\)\Z(?!\n)#s || $path =~ m#[/:>\]]#) {
+ if ($force_path or $path =~ /(?:DIR\)|\])\Z(?!\n)/) {
+ $fixedpath = vmspath($self->eliminate_macros($path));
+ }
+ else {
+ $fixedpath = vmsify($self->eliminate_macros($path));
+ }
+ }
+ elsif ((($prefix,$name) = ($path =~ m#^\$\(([^\)]+)\)(.+)#s)) && $self->{$prefix}) {
+ my($vmspre) = $self->eliminate_macros("\$($prefix)");
+ # is it a dir or just a name?
+ $vmspre = ($vmspre =~ m|/| or $prefix =~ /DIR\Z(?!\n)/) ? vmspath($vmspre) : '';
+ $fixedpath = ($vmspre ? $vmspre : $self->{$prefix}) . $name;
+ $fixedpath = vmspath($fixedpath) if $force_path;
+ }
+ else {
+ $fixedpath = $path;
+ $fixedpath = vmspath($fixedpath) if $force_path;
+ }
+ # No hints, so we try to guess
+ if (!defined($force_path) and $fixedpath !~ /[:>(.\]]/) {
+ $fixedpath = vmspath($fixedpath) if -d $fixedpath;
+ }
+
+ # Trim off root dirname if it's had other dirs inserted in front of it.
+ $fixedpath =~ s/\.000000([\]>])/$1/;
+ # Special case for VMS absolute directory specs: these will have had device
+ # prepended during trip through Unix syntax in eliminate_macros(), since
+ # Unix syntax has no way to express "absolute from the top of this device's
+ # directory tree".
+ if ($path =~ /^[\[>][^.\-]/) { $fixedpath =~ s/^[^\[<]+//; }
+
+ return $fixedpath;
+}
+
+
+=item os_flavor
+
+VMS is VMS.
+
+=cut
+
+sub os_flavor {
+ return('VMS');
+}
+
+=back
+
+
+=head1 AUTHOR
+
+Original author Charles Bailey F<bailey@newman.upenn.edu>
+
+Maintained by Michael G Schwern F<schwern@pobox.com>
+
+See L<ExtUtils::MakeMaker> for patching and contact information.
+
+
+=cut
+
+1;
+
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MM_VOS.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MM_VOS.pm
new file mode 100644
index 00000000000..1814a1dae4c
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MM_VOS.pm
@@ -0,0 +1,50 @@
+package ExtUtils::MM_VOS;
+
+use strict;
+our $VERSION = '6.56';
+
+require ExtUtils::MM_Unix;
+our @ISA = qw(ExtUtils::MM_Unix);
+
+
+=head1 NAME
+
+ExtUtils::MM_VOS - VOS specific subclass of ExtUtils::MM_Unix
+
+=head1 SYNOPSIS
+
+ Don't use this module directly.
+ Use ExtUtils::MM and let it choose.
+
+=head1 DESCRIPTION
+
+This is a subclass of ExtUtils::MM_Unix which contains functionality for
+VOS.
+
+Unless otherwise stated it works just like ExtUtils::MM_Unix
+
+=head2 Overridden methods
+
+=head3 extra_clean_files
+
+Cleanup VOS core files
+
+=cut
+
+sub extra_clean_files {
+ return qw(*.kp);
+}
+
+
+=head1 AUTHOR
+
+Michael G Schwern <schwern@pobox.com> with code from ExtUtils::MM_Unix
+
+=head1 SEE ALSO
+
+L<ExtUtils::MakeMaker>
+
+=cut
+
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MM_Win32.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MM_Win32.pm
new file mode 100644
index 00000000000..19e462de593
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MM_Win32.pm
@@ -0,0 +1,585 @@
+package ExtUtils::MM_Win32;
+
+use strict;
+
+
+=head1 NAME
+
+ExtUtils::MM_Win32 - methods to override UN*X behaviour in ExtUtils::MakeMaker
+
+=head1 SYNOPSIS
+
+ use ExtUtils::MM_Win32; # Done internally by ExtUtils::MakeMaker if needed
+
+=head1 DESCRIPTION
+
+See ExtUtils::MM_Unix for a documentation of the methods provided
+there. This package overrides the implementation of these methods, not
+the semantics.
+
+=cut
+
+use ExtUtils::MakeMaker::Config;
+use File::Basename;
+use File::Spec;
+use ExtUtils::MakeMaker qw( neatvalue );
+
+require ExtUtils::MM_Any;
+require ExtUtils::MM_Unix;
+our @ISA = qw( ExtUtils::MM_Any ExtUtils::MM_Unix );
+our $VERSION = '6.56';
+
+$ENV{EMXSHELL} = 'sh'; # to run `commands`
+
+my $BORLAND = $Config{'cc'} =~ /^bcc/i ? 1 : 0;
+my $GCC = $Config{'cc'} =~ /\bgcc$/i ? 1 : 0;
+my $DLLTOOL = $Config{'dlltool'} || 'dlltool';
+
+
+=head2 Overridden methods
+
+=over 4
+
+=item B<dlsyms>
+
+=cut
+
+sub dlsyms {
+ my($self,%attribs) = @_;
+
+ my($funcs) = $attribs{DL_FUNCS} || $self->{DL_FUNCS} || {};
+ my($vars) = $attribs{DL_VARS} || $self->{DL_VARS} || [];
+ my($funclist) = $attribs{FUNCLIST} || $self->{FUNCLIST} || [];
+ my($imports) = $attribs{IMPORTS} || $self->{IMPORTS} || {};
+ my(@m);
+
+ if (not $self->{SKIPHASH}{'dynamic'}) {
+ push(@m,"
+$self->{BASEEXT}.def: Makefile.PL
+",
+ q! $(PERLRUN) -MExtUtils::Mksymlists \\
+ -e "Mksymlists('NAME'=>\"!, $self->{NAME},
+ q!\", 'DLBASE' => '!,$self->{DLBASE},
+ # The above two lines quoted differently to work around
+ # a bug in the 4DOS/4NT command line interpreter. The visible
+ # result of the bug was files named q('extension_name',) *with the
+ # single quotes and the comma* in the extension build directories.
+ q!', 'DL_FUNCS' => !,neatvalue($funcs),
+ q!, 'FUNCLIST' => !,neatvalue($funclist),
+ q!, 'IMPORTS' => !,neatvalue($imports),
+ q!, 'DL_VARS' => !, neatvalue($vars), q!);"
+!);
+ }
+ join('',@m);
+}
+
+=item replace_manpage_separator
+
+Changes the path separator with .
+
+=cut
+
+sub replace_manpage_separator {
+ my($self,$man) = @_;
+ $man =~ s,/+,.,g;
+ $man;
+}
+
+
+=item B<maybe_command>
+
+Since Windows has nothing as simple as an executable bit, we check the
+file extension.
+
+The PATHEXT env variable will be used to get a list of extensions that
+might indicate a command, otherwise .com, .exe, .bat and .cmd will be
+used by default.
+
+=cut
+
+sub maybe_command {
+ my($self,$file) = @_;
+ my @e = exists($ENV{'PATHEXT'})
+ ? split(/;/, $ENV{PATHEXT})
+ : qw(.com .exe .bat .cmd);
+ my $e = '';
+ for (@e) { $e .= "\Q$_\E|" }
+ chop $e;
+ # see if file ends in one of the known extensions
+ if ($file =~ /($e)$/i) {
+ return $file if -e $file;
+ }
+ else {
+ for (@e) {
+ return "$file$_" if -e "$file$_";
+ }
+ }
+ return;
+}
+
+
+=item B<init_DIRFILESEP>
+
+Using \ for Windows.
+
+=cut
+
+sub init_DIRFILESEP {
+ my($self) = shift;
+
+ # The ^ makes sure its not interpreted as an escape in nmake
+ $self->{DIRFILESEP} = $self->is_make_type('nmake') ? '^\\' :
+ $self->is_make_type('dmake') ? '\\\\'
+ : '\\';
+}
+
+=item B<init_others>
+
+Override some of the Unix specific commands with portable
+ExtUtils::Command ones.
+
+Also provide defaults for LD and AR in case the %Config values aren't
+set.
+
+LDLOADLIBS's default is changed to $Config{libs}.
+
+Adjustments are made for Borland's quirks needing -L to come first.
+
+=cut
+
+sub init_others {
+ my ($self) = @_;
+
+ $self->{NOOP} ||= 'rem';
+ $self->{DEV_NULL} ||= '> NUL';
+
+ $self->{FIXIN} ||= $self->{PERL_CORE} ?
+ "\$(PERLRUN) $self->{PERL_SRC}/win32/bin/pl2bat.pl" :
+ 'pl2bat.bat';
+
+ $self->{LD} ||= 'link';
+ $self->{AR} ||= 'lib';
+
+ $self->SUPER::init_others;
+
+ # Setting SHELL from $Config{sh} can break dmake. Its ok without it.
+ delete $self->{SHELL};
+
+ $self->{LDLOADLIBS} ||= $Config{libs};
+ # -Lfoo must come first for Borland, so we put it in LDDLFLAGS
+ if ($BORLAND) {
+ my $libs = $self->{LDLOADLIBS};
+ my $libpath = '';
+ while ($libs =~ s/(?:^|\s)(("?)-L.+?\2)(?:\s|$)/ /) {
+ $libpath .= ' ' if length $libpath;
+ $libpath .= $1;
+ }
+ $self->{LDLOADLIBS} = $libs;
+ $self->{LDDLFLAGS} ||= $Config{lddlflags};
+ $self->{LDDLFLAGS} .= " $libpath";
+ }
+
+ return 1;
+}
+
+
+=item init_platform
+
+Add MM_Win32_VERSION.
+
+=item platform_constants
+
+=cut
+
+sub init_platform {
+ my($self) = shift;
+
+ $self->{MM_Win32_VERSION} = $VERSION;
+}
+
+sub platform_constants {
+ my($self) = shift;
+ my $make_frag = '';
+
+ foreach my $macro (qw(MM_Win32_VERSION))
+ {
+ next unless defined $self->{$macro};
+ $make_frag .= "$macro = $self->{$macro}\n";
+ }
+
+ return $make_frag;
+}
+
+
+=item special_targets
+
+Add .USESHELL target for dmake.
+
+=cut
+
+sub special_targets {
+ my($self) = @_;
+
+ my $make_frag = $self->SUPER::special_targets;
+
+ $make_frag .= <<'MAKE_FRAG' if $self->is_make_type('dmake');
+.USESHELL :
+MAKE_FRAG
+
+ return $make_frag;
+}
+
+
+=item static_lib
+
+Changes how to run the linker.
+
+The rest is duplicate code from MM_Unix. Should move the linker code
+to its own method.
+
+=cut
+
+sub static_lib {
+ my($self) = @_;
+ return '' unless $self->has_link_code;
+
+ my(@m);
+ push(@m, <<'END');
+$(INST_STATIC): $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DFSEP).exists
+ $(RM_RF) $@
+END
+
+ # If this extension has its own library (eg SDBM_File)
+ # then copy that to $(INST_STATIC) and add $(OBJECT) into it.
+ push @m, <<'MAKE_FRAG' if $self->{MYEXTLIB};
+ $(CP) $(MYEXTLIB) $@
+MAKE_FRAG
+
+ push @m,
+q{ $(AR) }.($BORLAND ? '$@ $(OBJECT:^"+")'
+ : ($GCC ? '-ru $@ $(OBJECT)'
+ : '-out:$@ $(OBJECT)')).q{
+ $(CHMOD) $(PERM_RWX) $@
+ $(NOECHO) $(ECHO) "$(EXTRALIBS)" > $(INST_ARCHAUTODIR)\extralibs.ld
+};
+
+ # Old mechanism - still available:
+ push @m, <<'MAKE_FRAG' if $self->{PERL_SRC} && $self->{EXTRALIBS};
+ $(NOECHO) $(ECHO) "$(EXTRALIBS)" >> $(PERL_SRC)\ext.libs
+MAKE_FRAG
+
+ join('', @m);
+}
+
+
+=item dynamic_lib
+
+Complicated stuff for Win32 that I don't understand. :(
+
+=cut
+
+sub dynamic_lib {
+ my($self, %attribs) = @_;
+ return '' unless $self->needs_linking(); #might be because of a subdir
+
+ return '' unless $self->has_link_code;
+
+ my($otherldflags) = $attribs{OTHERLDFLAGS} || ($BORLAND ? 'c0d32.obj': '');
+ my($inst_dynamic_dep) = $attribs{INST_DYNAMIC_DEP} || "";
+ my($ldfrom) = '$(LDFROM)';
+ my(@m);
+
+# one thing for GCC/Mingw32:
+# we try to overcome non-relocateable-DLL problems by generating
+# a (hopefully unique) image-base from the dll's name
+# -- BKS, 10-19-1999
+ if ($GCC) {
+ my $dllname = $self->{BASEEXT} . "." . $self->{DLEXT};
+ $dllname =~ /(....)(.{0,4})/;
+ my $baseaddr = unpack("n", $1 ^ $2);
+ $otherldflags .= sprintf("-Wl,--image-base,0x%x0000 ", $baseaddr);
+ }
+
+ push(@m,'
+# This section creates the dynamically loadable $(INST_DYNAMIC)
+# from $(OBJECT) and possibly $(MYEXTLIB).
+OTHERLDFLAGS = '.$otherldflags.'
+INST_DYNAMIC_DEP = '.$inst_dynamic_dep.'
+
+$(INST_DYNAMIC): $(OBJECT) $(MYEXTLIB) $(BOOTSTRAP) $(INST_ARCHAUTODIR)$(DFSEP).exists $(EXPORT_LIST) $(PERL_ARCHIVE) $(INST_DYNAMIC_DEP)
+');
+ if ($GCC) {
+ push(@m,
+ q{ }.$DLLTOOL.q{ --def $(EXPORT_LIST) --output-exp dll.exp
+ $(LD) -o $@ -Wl,--base-file -Wl,dll.base $(LDDLFLAGS) }.$ldfrom.q{ $(OTHERLDFLAGS) $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) dll.exp
+ }.$DLLTOOL.q{ --def $(EXPORT_LIST) --base-file dll.base --output-exp dll.exp
+ $(LD) -o $@ $(LDDLFLAGS) }.$ldfrom.q{ $(OTHERLDFLAGS) $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) dll.exp });
+ } elsif ($BORLAND) {
+ push(@m,
+ q{ $(LD) $(LDDLFLAGS) $(OTHERLDFLAGS) }.$ldfrom.q{,$@,,}
+ .($self->is_make_type('dmake')
+ ? q{$(PERL_ARCHIVE:s,/,\,) $(LDLOADLIBS:s,/,\,) }
+ .q{$(MYEXTLIB:s,/,\,),$(EXPORT_LIST:s,/,\,)}
+ : q{$(subst /,\,$(PERL_ARCHIVE)) $(subst /,\,$(LDLOADLIBS)) }
+ .q{$(subst /,\,$(MYEXTLIB)),$(subst /,\,$(EXPORT_LIST))})
+ .q{,$(RESFILES)});
+ } else { # VC
+ push(@m,
+ q{ $(LD) -out:$@ $(LDDLFLAGS) }.$ldfrom.q{ $(OTHERLDFLAGS) }
+ .q{$(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) -def:$(EXPORT_LIST)});
+
+ # Embed the manifest file if it exists
+ push(@m, q{
+ if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2
+ if exist $@.manifest del $@.manifest});
+ }
+ push @m, '
+ $(CHMOD) $(PERM_RWX) $@
+';
+
+ join('',@m);
+}
+
+=item extra_clean_files
+
+Clean out some extra dll.{base,exp} files which might be generated by
+gcc. Otherwise, take out all *.pdb files.
+
+=cut
+
+sub extra_clean_files {
+ my $self = shift;
+
+ return $GCC ? (qw(dll.base dll.exp)) : ('*.pdb');
+}
+
+=item init_linker
+
+=cut
+
+sub init_linker {
+ my $self = shift;
+
+ $self->{PERL_ARCHIVE} = "\$(PERL_INC)\\$Config{libperl}";
+ $self->{PERL_ARCHIVE_AFTER} = '';
+ $self->{EXPORT_LIST} = '$(BASEEXT).def';
+}
+
+
+=item perl_script
+
+Checks for the perl program under several common perl extensions.
+
+=cut
+
+sub perl_script {
+ my($self,$file) = @_;
+ return $file if -r $file && -f _;
+ return "$file.pl" if -r "$file.pl" && -f _;
+ return "$file.plx" if -r "$file.plx" && -f _;
+ return "$file.bat" if -r "$file.bat" && -f _;
+ return;
+}
+
+
+=item xs_o
+
+This target is stubbed out. Not sure why.
+
+=cut
+
+sub xs_o {
+ return ''
+}
+
+
+=item pasthru
+
+All we send is -nologo to nmake to prevent it from printing its damned
+banner.
+
+=cut
+
+sub pasthru {
+ my($self) = shift;
+ return "PASTHRU = " . ($self->is_make_type('nmake') ? "-nologo" : "");
+}
+
+
+=item arch_check (override)
+
+Normalize all arguments for consistency of comparison.
+
+=cut
+
+sub arch_check {
+ my $self = shift;
+
+ # Win32 is an XS module, minperl won't have it.
+ # arch_check() is not critical, so just fake it.
+ return 1 unless $self->can_load_xs;
+ return $self->SUPER::arch_check( map { $self->_normalize_path_name($_) } @_);
+}
+
+sub _normalize_path_name {
+ my $self = shift;
+ my $file = shift;
+
+ require Win32;
+ my $short = Win32::GetShortPathName($file);
+ return defined $short ? lc $short : lc $file;
+}
+
+
+=item oneliner
+
+These are based on what command.com does on Win98. They may be wrong
+for other Windows shells, I don't know.
+
+=cut
+
+sub oneliner {
+ my($self, $cmd, $switches) = @_;
+ $switches = [] unless defined $switches;
+
+ # Strip leading and trailing newlines
+ $cmd =~ s{^\n+}{};
+ $cmd =~ s{\n+$}{};
+
+ $cmd = $self->quote_literal($cmd);
+ $cmd = $self->escape_newlines($cmd);
+
+ $switches = join ' ', @$switches;
+
+ return qq{\$(ABSPERLRUN) $switches -e $cmd --};
+}
+
+
+sub quote_literal {
+ my($self, $text) = @_;
+
+ # I don't know if this is correct, but it seems to work on
+ # Win98's command.com
+ $text =~ s{"}{\\"}g;
+
+ # dmake eats '{' inside double quotes and leaves alone { outside double
+ # quotes; however it transforms {{ into { either inside and outside double
+ # quotes. It also translates }} into }. The escaping below is not
+ # 100% correct.
+ if( $self->is_make_type('dmake') ) {
+ $text =~ s/{/{{/g;
+ $text =~ s/}}/}}}/g;
+ }
+
+ return qq{"$text"};
+}
+
+
+sub escape_newlines {
+ my($self, $text) = @_;
+
+ # Escape newlines
+ $text =~ s{\n}{\\\n}g;
+
+ return $text;
+}
+
+
+=item cd
+
+dmake can handle Unix style cd'ing but nmake (at least 1.5) cannot. It
+wants:
+
+ cd dir1\dir2
+ command
+ another_command
+ cd ..\..
+
+=cut
+
+sub cd {
+ my($self, $dir, @cmds) = @_;
+
+ return $self->SUPER::cd($dir, @cmds) unless $self->is_make_type('nmake');
+
+ my $cmd = join "\n\t", map "$_", @cmds;
+
+ my $updirs = $self->catdir(map { $self->updir } $self->splitdir($dir));
+
+ # No leading tab and no trailing newline makes for easier embedding.
+ my $make_frag = sprintf <<'MAKE_FRAG', $dir, $cmd, $updirs;
+cd %s
+ %s
+ cd %s
+MAKE_FRAG
+
+ chomp $make_frag;
+
+ return $make_frag;
+}
+
+
+=item max_exec_len
+
+nmake 1.50 limits command length to 2048 characters.
+
+=cut
+
+sub max_exec_len {
+ my $self = shift;
+
+ return $self->{_MAX_EXEC_LEN} ||= 2 * 1024;
+}
+
+
+=item os_flavor
+
+Windows is Win32.
+
+=cut
+
+sub os_flavor {
+ return('Win32');
+}
+
+
+=item cflags
+
+Defines the PERLDLL symbol if we are configured for static building since all
+code destined for the perl5xx.dll must be compiled with the PERLDLL symbol
+defined.
+
+=cut
+
+sub cflags {
+ my($self,$libperl)=@_;
+ return $self->{CFLAGS} if $self->{CFLAGS};
+ return '' unless $self->needs_linking();
+
+ my $base = $self->SUPER::cflags($libperl);
+ foreach (split /\n/, $base) {
+ /^(\S*)\s*=\s*(\S*)$/ and $self->{$1} = $2;
+ };
+ $self->{CCFLAGS} .= " -DPERLDLL" if ($self->{LINKTYPE} eq 'static');
+
+ return $self->{CFLAGS} = qq{
+CCFLAGS = $self->{CCFLAGS}
+OPTIMIZE = $self->{OPTIMIZE}
+PERLTYPE = $self->{PERLTYPE}
+};
+
+}
+
+sub is_make_type {
+ my($self, $type) = @_;
+ return !! ($self->make =~ /\b$type(?:\.exe)?$/);
+}
+
+1;
+__END__
+
+=back
+
+=cut
+
+
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MM_Win95.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MM_Win95.pm
new file mode 100644
index 00000000000..c47147695e8
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MM_Win95.pm
@@ -0,0 +1,124 @@
+package ExtUtils::MM_Win95;
+
+use strict;
+
+our $VERSION = '6.56';
+
+require ExtUtils::MM_Win32;
+our @ISA = qw(ExtUtils::MM_Win32);
+
+use ExtUtils::MakeMaker::Config;
+
+
+=head1 NAME
+
+ExtUtils::MM_Win95 - method to customize MakeMaker for Win9X
+
+=head1 SYNOPSIS
+
+ You should not be using this module directly.
+
+=head1 DESCRIPTION
+
+This is a subclass of ExtUtils::MM_Win32 containing changes necessary
+to get MakeMaker playing nice with command.com and other Win9Xisms.
+
+=head2 Overridden methods
+
+Most of these make up for limitations in the Win9x/nmake command shell.
+Mostly its lack of &&.
+
+=over 4
+
+
+=item xs_c
+
+The && problem.
+
+=cut
+
+sub xs_c {
+ my($self) = shift;
+ return '' unless $self->needs_linking();
+ '
+.xs.c:
+ $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.c
+ '
+}
+
+
+=item xs_cpp
+
+The && problem
+
+=cut
+
+sub xs_cpp {
+ my($self) = shift;
+ return '' unless $self->needs_linking();
+ '
+.xs.cpp:
+ $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.cpp
+ ';
+}
+
+=item xs_o
+
+The && problem.
+
+=cut
+
+sub xs_o {
+ my($self) = shift;
+ return '' unless $self->needs_linking();
+ '
+.xs$(OBJ_EXT):
+ $(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $*.xs > $*.c
+ $(CCCMD) $(CCCDLFLAGS) -I$(PERL_INC) $(DEFINE) $*.c
+ ';
+}
+
+
+=item max_exec_len
+
+Win98 chokes on things like Encode if we set the max length to nmake's max
+of 2K. So we go for a more conservative value of 1K.
+
+=cut
+
+sub max_exec_len {
+ my $self = shift;
+
+ return $self->{_MAX_EXEC_LEN} ||= 1024;
+}
+
+
+=item os_flavor
+
+Win95 and Win98 and WinME are collectively Win9x and Win32
+
+=cut
+
+sub os_flavor {
+ my $self = shift;
+ return ($self->SUPER::os_flavor, 'Win9x');
+}
+
+
+=back
+
+
+=head1 AUTHOR
+
+Code originally inside MM_Win32. Original author unknown.
+
+Currently maintained by Michael G Schwern C<schwern@pobox.com>.
+
+Send patches and ideas to C<makemaker@perl.org>.
+
+See http://www.makemaker.org.
+
+=cut
+
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MY.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MY.pm
new file mode 100644
index 00000000000..bed177d210a
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MY.pm
@@ -0,0 +1,40 @@
+package ExtUtils::MY;
+
+use strict;
+require ExtUtils::MM;
+
+our $VERSION = 6.56;
+our @ISA = qw(ExtUtils::MM);
+
+{
+ package MY;
+ our @ISA = qw(ExtUtils::MY);
+}
+
+sub DESTROY {}
+
+
+=head1 NAME
+
+ExtUtils::MY - ExtUtils::MakeMaker subclass for customization
+
+=head1 SYNOPSIS
+
+ # in your Makefile.PL
+ sub MY::whatever {
+ ...
+ }
+
+=head1 DESCRIPTION
+
+B<FOR INTERNAL USE ONLY>
+
+ExtUtils::MY is a subclass of ExtUtils::MM. Its provided in your
+Makefile.PL for you to add and override MakeMaker functionality.
+
+It also provides a convenient alias via the MY class.
+
+ExtUtils::MY might turn out to be a temporary solution, but MY won't
+go away.
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MakeMaker.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MakeMaker.pm
new file mode 100644
index 00000000000..4422b686ce7
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MakeMaker.pm
@@ -0,0 +1,2807 @@
+# $Id$
+package ExtUtils::MakeMaker;
+
+use strict;
+
+BEGIN {require 5.006;}
+
+require Exporter;
+use ExtUtils::MakeMaker::Config;
+use Carp ();
+use File::Path;
+
+our $Verbose = 0; # exported
+our @Parent; # needs to be localized
+our @Get_from_Config; # referenced by MM_Unix
+our @MM_Sections;
+our @Overridable;
+my @Prepend_parent;
+my %Recognized_Att_Keys;
+
+our $VERSION = '6.56';
+
+# Emulate something resembling CVS $Revision$
+(our $Revision = $VERSION) =~ s{_}{};
+$Revision = int $Revision * 10000;
+
+our $Filename = __FILE__; # referenced outside MakeMaker
+
+our @ISA = qw(Exporter);
+our @EXPORT = qw(&WriteMakefile &writeMakefile $Verbose &prompt);
+our @EXPORT_OK = qw($VERSION &neatvalue &mkbootstrap &mksymlists
+ &WriteEmptyMakefile);
+
+# These will go away once the last of the Win32 & VMS specific code is
+# purged.
+my $Is_VMS = $^O eq 'VMS';
+my $Is_Win32 = $^O eq 'MSWin32';
+
+full_setup();
+
+require ExtUtils::MM; # Things like CPAN assume loading ExtUtils::MakeMaker
+ # will give them MM.
+
+require ExtUtils::MY; # XXX pre-5.8 versions of ExtUtils::Embed expect
+ # loading ExtUtils::MakeMaker will give them MY.
+ # This will go when Embed is its own CPAN module.
+
+
+sub WriteMakefile {
+ Carp::croak "WriteMakefile: Need even number of args" if @_ % 2;
+
+ require ExtUtils::MY;
+ my %att = @_;
+
+ _verify_att(\%att);
+
+ my $mm = MM->new(\%att);
+ $mm->flush;
+
+ return $mm;
+}
+
+
+# Basic signatures of the attributes WriteMakefile takes. Each is the
+# reference type. Empty value indicate it takes a non-reference
+# scalar.
+my %Att_Sigs;
+my %Special_Sigs = (
+ C => 'ARRAY',
+ CONFIG => 'ARRAY',
+ CONFIGURE => 'CODE',
+ DIR => 'ARRAY',
+ DL_FUNCS => 'HASH',
+ DL_VARS => 'ARRAY',
+ EXCLUDE_EXT => 'ARRAY',
+ EXE_FILES => 'ARRAY',
+ FUNCLIST => 'ARRAY',
+ H => 'ARRAY',
+ IMPORTS => 'HASH',
+ INCLUDE_EXT => 'ARRAY',
+ LIBS => ['ARRAY',''],
+ MAN1PODS => 'HASH',
+ MAN3PODS => 'HASH',
+ META_ADD => 'HASH',
+ META_MERGE => 'HASH',
+ PL_FILES => 'HASH',
+ PM => 'HASH',
+ PMLIBDIRS => 'ARRAY',
+ PMLIBPARENTDIRS => 'ARRAY',
+ PREREQ_PM => 'HASH',
+ BUILD_REQUIRES => 'HASH',
+ CONFIGURE_REQUIRES => 'HASH',
+ SKIP => 'ARRAY',
+ TYPEMAPS => 'ARRAY',
+ XS => 'HASH',
+ VERSION => ['version',''],
+ _KEEP_AFTER_FLUSH => '',
+
+ clean => 'HASH',
+ depend => 'HASH',
+ dist => 'HASH',
+ dynamic_lib=> 'HASH',
+ linkext => 'HASH',
+ macro => 'HASH',
+ postamble => 'HASH',
+ realclean => 'HASH',
+ test => 'HASH',
+ tool_autosplit => 'HASH',
+);
+
+@Att_Sigs{keys %Recognized_Att_Keys} = ('') x keys %Recognized_Att_Keys;
+@Att_Sigs{keys %Special_Sigs} = values %Special_Sigs;
+
+
+sub _verify_att {
+ my($att) = @_;
+
+ while( my($key, $val) = each %$att ) {
+ my $sig = $Att_Sigs{$key};
+ unless( defined $sig ) {
+ warn "WARNING: $key is not a known parameter.\n";
+ next;
+ }
+
+ my @sigs = ref $sig ? @$sig : $sig;
+ my $given = ref $val;
+ unless( grep { _is_of_type($val, $_) } @sigs ) {
+ my $takes = join " or ", map { _format_att($_) } @sigs;
+
+ my $has = _format_att($given);
+ warn "WARNING: $key takes a $takes not a $has.\n".
+ " Please inform the author.\n";
+ }
+ }
+}
+
+
+# Check if a given thing is a reference or instance of $type
+sub _is_of_type {
+ my($thing, $type) = @_;
+
+ return 1 if ref $thing eq $type;
+
+ local $SIG{__DIE__};
+ return 1 if eval{ $thing->isa($type) };
+
+ return 0;
+}
+
+
+sub _format_att {
+ my $given = shift;
+
+ return $given eq '' ? "string/number"
+ : uc $given eq $given ? "$given reference"
+ : "$given object"
+ ;
+}
+
+
+sub prompt ($;$) { ## no critic
+ my($mess, $def) = @_;
+ Carp::confess("prompt function called without an argument")
+ unless defined $mess;
+
+ my $isa_tty = -t STDIN && (-t STDOUT || !(-f STDOUT || -c STDOUT)) ;
+
+ my $dispdef = defined $def ? "[$def] " : " ";
+ $def = defined $def ? $def : "";
+
+ local $|=1;
+ local $\;
+ print "$mess $dispdef";
+
+ my $ans;
+ if ($ENV{PERL_MM_USE_DEFAULT} || (!$isa_tty && eof STDIN)) {
+ print "$def\n";
+ }
+ else {
+ $ans = <STDIN>;
+ if( defined $ans ) {
+ chomp $ans;
+ }
+ else { # user hit ctrl-D
+ print "\n";
+ }
+ }
+
+ return (!defined $ans || $ans eq '') ? $def : $ans;
+}
+
+sub eval_in_subdirs {
+ my($self) = @_;
+ use Cwd qw(cwd abs_path);
+ my $pwd = cwd() || die "Can't figure out your cwd!";
+
+ local @INC = map eval {abs_path($_) if -e} || $_, @INC;
+ push @INC, '.'; # '.' has to always be at the end of @INC
+
+ foreach my $dir (@{$self->{DIR}}){
+ my($abs) = $self->catdir($pwd,$dir);
+ eval { $self->eval_in_x($abs); };
+ last if $@;
+ }
+ chdir $pwd;
+ die $@ if $@;
+}
+
+sub eval_in_x {
+ my($self,$dir) = @_;
+ chdir $dir or Carp::carp("Couldn't change to directory $dir: $!");
+
+ {
+ package main;
+ do './Makefile.PL';
+ };
+ if ($@) {
+# if ($@ =~ /prerequisites/) {
+# die "MakeMaker WARNING: $@";
+# } else {
+# warn "WARNING from evaluation of $dir/Makefile.PL: $@";
+# }
+ die "ERROR from evaluation of $dir/Makefile.PL: $@";
+ }
+}
+
+
+# package name for the classes into which the first object will be blessed
+my $PACKNAME = 'PACK000';
+
+sub full_setup {
+ $Verbose ||= 0;
+
+ my @attrib_help = qw/
+
+ AUTHOR ABSTRACT ABSTRACT_FROM BINARY_LOCATION
+ C CAPI CCFLAGS CONFIG CONFIGURE DEFINE DIR DISTNAME DISTVNAME
+ DL_FUNCS DL_VARS
+ EXCLUDE_EXT EXE_FILES FIRST_MAKEFILE
+ FULLPERL FULLPERLRUN FULLPERLRUNINST
+ FUNCLIST H IMPORTS
+
+ INST_ARCHLIB INST_SCRIPT INST_BIN INST_LIB INST_MAN1DIR INST_MAN3DIR
+ INSTALLDIRS
+ DESTDIR PREFIX INSTALL_BASE
+ PERLPREFIX SITEPREFIX VENDORPREFIX
+ INSTALLPRIVLIB INSTALLSITELIB INSTALLVENDORLIB
+ INSTALLARCHLIB INSTALLSITEARCH INSTALLVENDORARCH
+ INSTALLBIN INSTALLSITEBIN INSTALLVENDORBIN
+ INSTALLMAN1DIR INSTALLMAN3DIR
+ INSTALLSITEMAN1DIR INSTALLSITEMAN3DIR
+ INSTALLVENDORMAN1DIR INSTALLVENDORMAN3DIR
+ INSTALLSCRIPT INSTALLSITESCRIPT INSTALLVENDORSCRIPT
+ PERL_LIB PERL_ARCHLIB
+ SITELIBEXP SITEARCHEXP
+
+ INC INCLUDE_EXT LDFROM LIB LIBPERL_A LIBS LICENSE
+ LINKTYPE MAKE MAKEAPERL MAKEFILE MAKEFILE_OLD MAN1PODS MAN3PODS MAP_TARGET
+ META_ADD META_MERGE MIN_PERL_VERSION BUILD_REQUIRES CONFIGURE_REQUIRES
+ MYEXTLIB NAME NEEDS_LINKING NOECHO NO_META NORECURS NO_VC OBJECT OPTIMIZE
+ PERL_MALLOC_OK PERL PERLMAINCC PERLRUN PERLRUNINST PERL_CORE
+ PERL_SRC PERM_DIR PERM_RW PERM_RWX
+ PL_FILES PM PM_FILTER PMLIBDIRS PMLIBPARENTDIRS POLLUTE PPM_INSTALL_EXEC
+ PPM_INSTALL_SCRIPT PREREQ_FATAL PREREQ_PM PREREQ_PRINT PRINT_PREREQ
+ SIGN SKIP TYPEMAPS VERSION VERSION_FROM XS XSOPT XSPROTOARG
+ XS_VERSION clean depend dist dynamic_lib linkext macro realclean
+ tool_autosplit
+
+ MACPERL_SRC MACPERL_LIB MACLIBS_68K MACLIBS_PPC MACLIBS_SC MACLIBS_MRC
+ MACLIBS_ALL_68K MACLIBS_ALL_PPC MACLIBS_SHARED
+ /;
+
+ # IMPORTS is used under OS/2 and Win32
+
+ # @Overridable is close to @MM_Sections but not identical. The
+ # order is important. Many subroutines declare macros. These
+ # depend on each other. Let's try to collect the macros up front,
+ # then pasthru, then the rules.
+
+ # MM_Sections are the sections we have to call explicitly
+ # in Overridable we have subroutines that are used indirectly
+
+
+ @MM_Sections =
+ qw(
+
+ post_initialize const_config constants platform_constants
+ tool_autosplit tool_xsubpp tools_other
+
+ makemakerdflt
+
+ dist macro depend cflags const_loadlibs const_cccmd
+ post_constants
+
+ pasthru
+
+ special_targets
+ c_o xs_c xs_o
+ top_targets blibdirs linkext dlsyms dynamic dynamic_bs
+ dynamic_lib static static_lib manifypods processPL
+ installbin subdirs
+ clean_subdirs clean realclean_subdirs realclean
+ metafile signature
+ dist_basics dist_core distdir dist_test dist_ci distmeta distsignature
+ install force perldepend makefile staticmake test ppd
+
+ ); # loses section ordering
+
+ @Overridable = @MM_Sections;
+ push @Overridable, qw[
+
+ libscan makeaperl needs_linking
+ subdir_x test_via_harness test_via_script
+
+ init_VERSION init_dist init_INST init_INSTALL init_DEST init_dirscan
+ init_PM init_MANPODS init_xs init_PERL init_DIRFILESEP init_linker
+ ];
+
+ push @MM_Sections, qw[
+
+ pm_to_blib selfdocument
+
+ ];
+
+ # Postamble needs to be the last that was always the case
+ push @MM_Sections, "postamble";
+ push @Overridable, "postamble";
+
+ # All sections are valid keys.
+ @Recognized_Att_Keys{@MM_Sections} = (1) x @MM_Sections;
+
+ # we will use all these variables in the Makefile
+ @Get_from_Config =
+ qw(
+ ar cc cccdlflags ccdlflags dlext dlsrc exe_ext full_ar ld
+ lddlflags ldflags libc lib_ext obj_ext osname osvers ranlib
+ sitelibexp sitearchexp so
+ );
+
+ # 5.5.3 doesn't have any concept of vendor libs
+ push @Get_from_Config, qw( vendorarchexp vendorlibexp ) if $] >= 5.006;
+
+ foreach my $item (@attrib_help){
+ $Recognized_Att_Keys{$item} = 1;
+ }
+ foreach my $item (@Get_from_Config) {
+ $Recognized_Att_Keys{uc $item} = $Config{$item};
+ print "Attribute '\U$item\E' => '$Config{$item}'\n"
+ if ($Verbose >= 2);
+ }
+
+ #
+ # When we eval a Makefile.PL in a subdirectory, that one will ask
+ # us (the parent) for the values and will prepend "..", so that
+ # all files to be installed end up below OUR ./blib
+ #
+ @Prepend_parent = qw(
+ INST_BIN INST_LIB INST_ARCHLIB INST_SCRIPT
+ MAP_TARGET INST_MAN1DIR INST_MAN3DIR PERL_SRC
+ PERL FULLPERL
+ );
+}
+
+sub writeMakefile {
+ die <<END;
+
+The extension you are trying to build apparently is rather old and
+most probably outdated. We detect that from the fact, that a
+subroutine "writeMakefile" is called, and this subroutine is not
+supported anymore since about October 1994.
+
+Please contact the author or look into CPAN (details about CPAN can be
+found in the FAQ and at http:/www.perl.com) for a more recent version
+of the extension. If you're really desperate, you can try to change
+the subroutine name from writeMakefile to WriteMakefile and rerun
+'perl Makefile.PL', but you're most probably left alone, when you do
+so.
+
+The MakeMaker team
+
+END
+}
+
+sub new {
+ my($class,$self) = @_;
+ my($key);
+
+ # Store the original args passed to WriteMakefile()
+ foreach my $k (keys %$self) {
+ $self->{ARGS}{$k} = $self->{$k};
+ }
+
+ $self = {} unless defined $self;
+
+ $self->{PREREQ_PM} ||= {};
+ $self->{BUILD_REQUIRES} ||= {};
+
+ # Temporarily bless it into MM so it can be used as an
+ # object. It will be blessed into a temp package later.
+ bless $self, "MM";
+
+ if ("@ARGV" =~ /\bPREREQ_PRINT\b/) {
+ $self->_PREREQ_PRINT;
+ }
+
+ # PRINT_PREREQ is RedHatism.
+ if ("@ARGV" =~ /\bPRINT_PREREQ\b/) {
+ $self->_PRINT_PREREQ;
+ }
+
+ print STDOUT "MakeMaker (v$VERSION)\n" if $Verbose;
+ if (-f "MANIFEST" && ! -f "Makefile"){
+ check_manifest();
+ }
+
+ check_hints($self);
+
+ # Translate X.Y.Z to X.00Y00Z
+ if( defined $self->{MIN_PERL_VERSION} ) {
+ $self->{MIN_PERL_VERSION} =~ s{ ^ (\d+) \. (\d+) \. (\d+) $ }
+ {sprintf "%d.%03d%03d", $1, $2, $3}ex;
+ }
+
+ my $perl_version_ok = eval {
+ local $SIG{__WARN__} = sub {
+ # simulate "use warnings FATAL => 'all'" for vintage perls
+ die @_;
+ };
+ !$self->{MIN_PERL_VERSION} or $self->{MIN_PERL_VERSION} <= $]
+ };
+ if (!$perl_version_ok) {
+ if (!defined $perl_version_ok) {
+ warn <<'END';
+Warning: MIN_PERL_VERSION is not in a recognized format.
+Recommended is a quoted numerical value like '5.005' or '5.008001'.
+END
+ }
+ elsif ($self->{PREREQ_FATAL}) {
+ die sprintf <<"END", $self->{MIN_PERL_VERSION}, $];
+MakeMaker FATAL: perl version too low for this distribution.
+Required is %s. We run %s.
+END
+ }
+ else {
+ warn sprintf
+ "Warning: Perl version %s or higher required. We run %s.\n",
+ $self->{MIN_PERL_VERSION}, $];
+ }
+ }
+
+ my %configure_att; # record &{$self->{CONFIGURE}} attributes
+ my(%initial_att) = %$self; # record initial attributes
+
+ my(%unsatisfied) = ();
+ my $prereqs = $self->_all_prereqs;
+ foreach my $prereq (sort keys %$prereqs) {
+ my $required_version = $prereqs->{$prereq};
+
+ my $installed_file = MM->_installed_file_for_module($prereq);
+ my $pr_version = 0;
+ $pr_version = MM->parse_version($installed_file) if $installed_file;
+ $pr_version = 0 if $pr_version eq 'undef';
+
+ # convert X.Y_Z alpha version #s to X.YZ for easier comparisons
+ $pr_version =~ s/(\d+)\.(\d+)_(\d+)/$1.$2$3/;
+
+ if (!$installed_file) {
+ warn sprintf "Warning: prerequisite %s %s not found.\n",
+ $prereq, $required_version
+ unless $self->{PREREQ_FATAL};
+
+ $unsatisfied{$prereq} = 'not installed';
+ }
+ elsif ($pr_version < $required_version ){
+ warn sprintf "Warning: prerequisite %s %s not found. We have %s.\n",
+ $prereq, $required_version, ($pr_version || 'unknown version')
+ unless $self->{PREREQ_FATAL};
+
+ $unsatisfied{$prereq} = $required_version ? $required_version : 'unknown version' ;
+ }
+ }
+
+ if (%unsatisfied && $self->{PREREQ_FATAL}){
+ my $failedprereqs = join "\n", map {" $_ $unsatisfied{$_}"}
+ sort { $a cmp $b } keys %unsatisfied;
+ die <<"END";
+MakeMaker FATAL: prerequisites not found.
+$failedprereqs
+
+Please install these modules first and rerun 'perl Makefile.PL'.
+END
+ }
+
+ if (defined $self->{CONFIGURE}) {
+ if (ref $self->{CONFIGURE} eq 'CODE') {
+ %configure_att = %{&{$self->{CONFIGURE}}};
+ $self = { %$self, %configure_att };
+ } else {
+ Carp::croak "Attribute 'CONFIGURE' to WriteMakefile() not a code reference\n";
+ }
+ }
+
+ # This is for old Makefiles written pre 5.00, will go away
+ if ( Carp::longmess("") =~ /runsubdirpl/s ){
+ Carp::carp("WARNING: Please rerun 'perl Makefile.PL' to regenerate your Makefiles\n");
+ }
+
+ my $newclass = ++$PACKNAME;
+ local @Parent = @Parent; # Protect against non-local exits
+ {
+ print "Blessing Object into class [$newclass]\n" if $Verbose>=2;
+ mv_all_methods("MY",$newclass);
+ bless $self, $newclass;
+ push @Parent, $self;
+ require ExtUtils::MY;
+
+ no strict 'refs'; ## no critic;
+ @{"$newclass\:\:ISA"} = 'MM';
+ }
+
+ if (defined $Parent[-2]){
+ $self->{PARENT} = $Parent[-2];
+ for my $key (@Prepend_parent) {
+ next unless defined $self->{PARENT}{$key};
+
+ # Don't stomp on WriteMakefile() args.
+ next if defined $self->{ARGS}{$key} and
+ $self->{ARGS}{$key} eq $self->{$key};
+
+ $self->{$key} = $self->{PARENT}{$key};
+
+ unless ($Is_VMS && $key =~ /PERL$/) {
+ $self->{$key} = $self->catdir("..",$self->{$key})
+ unless $self->file_name_is_absolute($self->{$key});
+ } else {
+ # PERL or FULLPERL will be a command verb or even a
+ # command with an argument instead of a full file
+ # specification under VMS. So, don't turn the command
+ # into a filespec, but do add a level to the path of
+ # the argument if not already absolute.
+ my @cmd = split /\s+/, $self->{$key};
+ $cmd[1] = $self->catfile('[-]',$cmd[1])
+ unless (@cmd < 2) || $self->file_name_is_absolute($cmd[1]);
+ $self->{$key} = join(' ', @cmd);
+ }
+ }
+ if ($self->{PARENT}) {
+ $self->{PARENT}->{CHILDREN}->{$newclass} = $self;
+ foreach my $opt (qw(POLLUTE PERL_CORE LINKTYPE)) {
+ if (exists $self->{PARENT}->{$opt}
+ and not exists $self->{$opt})
+ {
+ # inherit, but only if already unspecified
+ $self->{$opt} = $self->{PARENT}->{$opt};
+ }
+ }
+ }
+ my @fm = grep /^FIRST_MAKEFILE=/, @ARGV;
+ parse_args($self,@fm) if @fm;
+ } else {
+ parse_args($self,split(' ', $ENV{PERL_MM_OPT} || ''),@ARGV);
+ }
+
+
+ $self->{NAME} ||= $self->guess_name;
+
+ ($self->{NAME_SYM} = $self->{NAME}) =~ s/\W+/_/g;
+
+ $self->init_MAKE;
+ $self->init_main;
+ $self->init_VERSION;
+ $self->init_dist;
+ $self->init_INST;
+ $self->init_INSTALL;
+ $self->init_DEST;
+ $self->init_dirscan;
+ $self->init_PM;
+ $self->init_MANPODS;
+ $self->init_xs;
+ $self->init_PERL;
+ $self->init_DIRFILESEP;
+ $self->init_linker;
+ $self->init_ABSTRACT;
+
+ $self->arch_check(
+ $INC{'Config.pm'},
+ $self->catfile($Config{'archlibexp'}, "Config.pm")
+ );
+
+ $self->init_others();
+ $self->init_platform();
+ $self->init_PERM();
+ my($argv) = neatvalue(\@ARGV);
+ $argv =~ s/^\[/(/;
+ $argv =~ s/\]$/)/;
+
+ push @{$self->{RESULT}}, <<END;
+# This Makefile is for the $self->{NAME} extension to perl.
+#
+# It was generated automatically by MakeMaker version
+# $VERSION (Revision: $Revision) from the contents of
+# Makefile.PL. Don't edit this file, edit Makefile.PL instead.
+#
+# ANY CHANGES MADE HERE WILL BE LOST!
+#
+# MakeMaker ARGV: $argv
+#
+END
+
+ push @{$self->{RESULT}}, $self->_MakeMaker_Parameters_section(\%initial_att);
+
+ if (defined $self->{CONFIGURE}) {
+ push @{$self->{RESULT}}, <<END;
+
+# MakeMaker 'CONFIGURE' Parameters:
+END
+ if (scalar(keys %configure_att) > 0) {
+ foreach my $key (sort keys %configure_att){
+ next if $key eq 'ARGS';
+ my($v) = neatvalue($configure_att{$key});
+ $v =~ s/(CODE|HASH|ARRAY|SCALAR)\([\dxa-f]+\)/$1\(...\)/;
+ $v =~ tr/\n/ /s;
+ push @{$self->{RESULT}}, "# $key => $v";
+ }
+ }
+ else
+ {
+ push @{$self->{RESULT}}, "# no values returned";
+ }
+ undef %configure_att; # free memory
+ }
+
+ # turn the SKIP array into a SKIPHASH hash
+ for my $skip (@{$self->{SKIP} || []}) {
+ $self->{SKIPHASH}{$skip} = 1;
+ }
+ delete $self->{SKIP}; # free memory
+
+ if ($self->{PARENT}) {
+ for (qw/install dist dist_basics dist_core distdir dist_test dist_ci/) {
+ $self->{SKIPHASH}{$_} = 1;
+ }
+ }
+
+ # We run all the subdirectories now. They don't have much to query
+ # from the parent, but the parent has to query them: if they need linking!
+ unless ($self->{NORECURS}) {
+ $self->eval_in_subdirs if @{$self->{DIR}};
+ }
+
+ foreach my $section ( @MM_Sections ){
+ # Support for new foo_target() methods.
+ my $method = $section;
+ $method .= '_target' unless $self->can($method);
+
+ print "Processing Makefile '$section' section\n" if ($Verbose >= 2);
+ my($skipit) = $self->skipcheck($section);
+ if ($skipit){
+ push @{$self->{RESULT}}, "\n# --- MakeMaker $section section $skipit.";
+ } else {
+ my(%a) = %{$self->{$section} || {}};
+ push @{$self->{RESULT}}, "\n# --- MakeMaker $section section:";
+ push @{$self->{RESULT}}, "# " . join ", ", %a if $Verbose && %a;
+ push @{$self->{RESULT}}, $self->maketext_filter(
+ $self->$method( %a )
+ );
+ }
+ }
+
+ push @{$self->{RESULT}}, "\n# End.";
+
+ $self;
+}
+
+sub WriteEmptyMakefile {
+ Carp::croak "WriteEmptyMakefile: Need an even number of args" if @_ % 2;
+
+ my %att = @_;
+ my $self = MM->new(\%att);
+
+ my $new = $self->{MAKEFILE};
+ my $old = $self->{MAKEFILE_OLD};
+ if (-f $old) {
+ _unlink($old) or warn "unlink $old: $!";
+ }
+ if ( -f $new ) {
+ _rename($new, $old) or warn "rename $new => $old: $!"
+ }
+ open my $mfh, '>', $new or die "open $new for write: $!";
+ print $mfh <<'EOP';
+all :
+
+clean :
+
+install :
+
+makemakerdflt :
+
+test :
+
+EOP
+ close $mfh or die "close $new for write: $!";
+}
+
+
+=begin private
+
+=head3 _installed_file_for_module
+
+ my $file = MM->_installed_file_for_module($module);
+
+Return the first installed .pm $file associated with the $module. The
+one which will show up when you C<use $module>.
+
+$module is something like "strict" or "Test::More".
+
+=end private
+
+=cut
+
+sub _installed_file_for_module {
+ my $class = shift;
+ my $prereq = shift;
+
+ my $file = "$prereq.pm";
+ $file =~ s{::}{/}g;
+
+ my $path;
+ for my $dir (@INC) {
+ my $tmp = File::Spec->catfile($dir, $file);
+ if ( -r $tmp ) {
+ $path = $tmp;
+ last;
+ }
+ }
+
+ return $path;
+}
+
+
+# Extracted from MakeMaker->new so we can test it
+sub _MakeMaker_Parameters_section {
+ my $self = shift;
+ my $att = shift;
+
+ my @result = <<'END';
+# MakeMaker Parameters:
+END
+
+ foreach my $key (sort keys %$att){
+ next if $key eq 'ARGS';
+ my ($v) = neatvalue($att->{$key});
+ if ($key eq 'PREREQ_PM') {
+ # CPAN.pm takes prereqs from this field in 'Makefile'
+ # and does not know about BUILD_REQUIRES
+ $v = neatvalue({ %{ $att->{PREREQ_PM} || {} }, %{ $att->{BUILD_REQUIRES} || {} } });
+ } else {
+ $v = neatvalue($att->{$key});
+ }
+
+ $v =~ s/(CODE|HASH|ARRAY|SCALAR)\([\dxa-f]+\)/$1\(...\)/;
+ $v =~ tr/\n/ /s;
+ push @result, "# $key => $v";
+ }
+
+ return @result;
+}
+
+
+sub check_manifest {
+ print STDOUT "Checking if your kit is complete...\n";
+ require ExtUtils::Manifest;
+ # avoid warning
+ $ExtUtils::Manifest::Quiet = $ExtUtils::Manifest::Quiet = 1;
+ my(@missed) = ExtUtils::Manifest::manicheck();
+ if (@missed) {
+ print STDOUT "Warning: the following files are missing in your kit:\n";
+ print "\t", join "\n\t", @missed;
+ print STDOUT "\n";
+ print STDOUT "Please inform the author.\n";
+ } else {
+ print STDOUT "Looks good\n";
+ }
+}
+
+sub parse_args{
+ my($self, @args) = @_;
+ foreach (@args) {
+ unless (m/(.*?)=(.*)/) {
+ ++$Verbose if m/^verb/;
+ next;
+ }
+ my($name, $value) = ($1, $2);
+ if ($value =~ m/^~(\w+)?/) { # tilde with optional username
+ $value =~ s [^~(\w*)]
+ [$1 ?
+ ((getpwnam($1))[7] || "~$1") :
+ (getpwuid($>))[7]
+ ]ex;
+ }
+
+ # Remember the original args passed it. It will be useful later.
+ $self->{ARGS}{uc $name} = $self->{uc $name} = $value;
+ }
+
+ # catch old-style 'potential_libs' and inform user how to 'upgrade'
+ if (defined $self->{potential_libs}){
+ my($msg)="'potential_libs' => '$self->{potential_libs}' should be";
+ if ($self->{potential_libs}){
+ print STDOUT "$msg changed to:\n\t'LIBS' => ['$self->{potential_libs}']\n";
+ } else {
+ print STDOUT "$msg deleted.\n";
+ }
+ $self->{LIBS} = [$self->{potential_libs}];
+ delete $self->{potential_libs};
+ }
+ # catch old-style 'ARMAYBE' and inform user how to 'upgrade'
+ if (defined $self->{ARMAYBE}){
+ my($armaybe) = $self->{ARMAYBE};
+ print STDOUT "ARMAYBE => '$armaybe' should be changed to:\n",
+ "\t'dynamic_lib' => {ARMAYBE => '$armaybe'}\n";
+ my(%dl) = %{$self->{dynamic_lib} || {}};
+ $self->{dynamic_lib} = { %dl, ARMAYBE => $armaybe};
+ delete $self->{ARMAYBE};
+ }
+ if (defined $self->{LDTARGET}){
+ print STDOUT "LDTARGET should be changed to LDFROM\n";
+ $self->{LDFROM} = $self->{LDTARGET};
+ delete $self->{LDTARGET};
+ }
+ # Turn a DIR argument on the command line into an array
+ if (defined $self->{DIR} && ref \$self->{DIR} eq 'SCALAR') {
+ # So they can choose from the command line, which extensions they want
+ # the grep enables them to have some colons too much in case they
+ # have to build a list with the shell
+ $self->{DIR} = [grep $_, split ":", $self->{DIR}];
+ }
+ # Turn a INCLUDE_EXT argument on the command line into an array
+ if (defined $self->{INCLUDE_EXT} && ref \$self->{INCLUDE_EXT} eq 'SCALAR') {
+ $self->{INCLUDE_EXT} = [grep $_, split '\s+', $self->{INCLUDE_EXT}];
+ }
+ # Turn a EXCLUDE_EXT argument on the command line into an array
+ if (defined $self->{EXCLUDE_EXT} && ref \$self->{EXCLUDE_EXT} eq 'SCALAR') {
+ $self->{EXCLUDE_EXT} = [grep $_, split '\s+', $self->{EXCLUDE_EXT}];
+ }
+
+ foreach my $mmkey (sort keys %$self){
+ next if $mmkey eq 'ARGS';
+ print STDOUT " $mmkey => ", neatvalue($self->{$mmkey}), "\n" if $Verbose;
+ print STDOUT "'$mmkey' is not a known MakeMaker parameter name.\n"
+ unless exists $Recognized_Att_Keys{$mmkey};
+ }
+ $| = 1 if $Verbose;
+}
+
+sub check_hints {
+ my($self) = @_;
+ # We allow extension-specific hints files.
+
+ require File::Spec;
+ my $curdir = File::Spec->curdir;
+
+ my $hint_dir = File::Spec->catdir($curdir, "hints");
+ return unless -d $hint_dir;
+
+ # First we look for the best hintsfile we have
+ my($hint)="${^O}_$Config{osvers}";
+ $hint =~ s/\./_/g;
+ $hint =~ s/_$//;
+ return unless $hint;
+
+ # Also try without trailing minor version numbers.
+ while (1) {
+ last if -f File::Spec->catfile($hint_dir, "$hint.pl"); # found
+ } continue {
+ last unless $hint =~ s/_[^_]*$//; # nothing to cut off
+ }
+ my $hint_file = File::Spec->catfile($hint_dir, "$hint.pl");
+
+ return unless -f $hint_file; # really there
+
+ _run_hintfile($self, $hint_file);
+}
+
+sub _run_hintfile {
+ our $self;
+ local($self) = shift; # make $self available to the hint file.
+ my($hint_file) = shift;
+
+ local($@, $!);
+ print STDERR "Processing hints file $hint_file\n";
+
+ # Just in case the ./ isn't on the hint file, which File::Spec can
+ # often strip off, we bung the curdir into @INC
+ local @INC = (File::Spec->curdir, @INC);
+ my $ret = do $hint_file;
+ if( !defined $ret ) {
+ my $error = $@ || $!;
+ print STDERR $error;
+ }
+}
+
+sub mv_all_methods {
+ my($from,$to) = @_;
+
+ # Here you see the *current* list of methods that are overridable
+ # from Makefile.PL via MY:: subroutines. As of VERSION 5.07 I'm
+ # still trying to reduce the list to some reasonable minimum --
+ # because I want to make it easier for the user. A.K.
+
+ local $SIG{__WARN__} = sub {
+ # can't use 'no warnings redefined', 5.6 only
+ warn @_ unless $_[0] =~ /^Subroutine .* redefined/
+ };
+ foreach my $method (@Overridable) {
+
+ # We cannot say "next" here. Nick might call MY->makeaperl
+ # which isn't defined right now
+
+ # Above statement was written at 4.23 time when Tk-b8 was
+ # around. As Tk-b9 only builds with 5.002something and MM 5 is
+ # standard, we try to enable the next line again. It was
+ # commented out until MM 5.23
+
+ next unless defined &{"${from}::$method"};
+
+ {
+ no strict 'refs'; ## no critic
+ *{"${to}::$method"} = \&{"${from}::$method"};
+
+ # If we delete a method, then it will be undefined and cannot
+ # be called. But as long as we have Makefile.PLs that rely on
+ # %MY:: being intact, we have to fill the hole with an
+ # inheriting method:
+
+ {
+ package MY;
+ my $super = "SUPER::".$method;
+ *{$method} = sub {
+ shift->$super(@_);
+ };
+ }
+ }
+ }
+
+ # We have to clean out %INC also, because the current directory is
+ # changed frequently and Graham Barr prefers to get his version
+ # out of a History.pl file which is "required" so woudn't get
+ # loaded again in another extension requiring a History.pl
+
+ # With perl5.002_01 the deletion of entries in %INC caused Tk-b11
+ # to core dump in the middle of a require statement. The required
+ # file was Tk/MMutil.pm. The consequence is, we have to be
+ # extremely careful when we try to give perl a reason to reload a
+ # library with same name. The workaround prefers to drop nothing
+ # from %INC and teach the writers not to use such libraries.
+
+# my $inc;
+# foreach $inc (keys %INC) {
+# #warn "***$inc*** deleted";
+# delete $INC{$inc};
+# }
+}
+
+sub skipcheck {
+ my($self) = shift;
+ my($section) = @_;
+ if ($section eq 'dynamic') {
+ print STDOUT "Warning (non-fatal): Target 'dynamic' depends on targets ",
+ "in skipped section 'dynamic_bs'\n"
+ if $self->{SKIPHASH}{dynamic_bs} && $Verbose;
+ print STDOUT "Warning (non-fatal): Target 'dynamic' depends on targets ",
+ "in skipped section 'dynamic_lib'\n"
+ if $self->{SKIPHASH}{dynamic_lib} && $Verbose;
+ }
+ if ($section eq 'dynamic_lib') {
+ print STDOUT "Warning (non-fatal): Target '\$(INST_DYNAMIC)' depends on ",
+ "targets in skipped section 'dynamic_bs'\n"
+ if $self->{SKIPHASH}{dynamic_bs} && $Verbose;
+ }
+ if ($section eq 'static') {
+ print STDOUT "Warning (non-fatal): Target 'static' depends on targets ",
+ "in skipped section 'static_lib'\n"
+ if $self->{SKIPHASH}{static_lib} && $Verbose;
+ }
+ return 'skipped' if $self->{SKIPHASH}{$section};
+ return '';
+}
+
+sub flush {
+ my $self = shift;
+
+ my $finalname = $self->{MAKEFILE};
+ print STDOUT "Writing $finalname for $self->{NAME}\n";
+
+ unlink($finalname, "MakeMaker.tmp", $Is_VMS ? 'Descrip.MMS' : ());
+ open(my $fh,">", "MakeMaker.tmp")
+ or die "Unable to open MakeMaker.tmp: $!";
+
+ for my $chunk (@{$self->{RESULT}}) {
+ print $fh "$chunk\n";
+ }
+
+ close $fh;
+ _rename("MakeMaker.tmp", $finalname) or
+ warn "rename MakeMaker.tmp => $finalname: $!";
+ chmod 0644, $finalname unless $Is_VMS;
+
+ my %keep = map { ($_ => 1) } qw(NEEDS_LINKING HAS_LINK_CODE);
+
+ if ($self->{PARENT} && !$self->{_KEEP_AFTER_FLUSH}) {
+ foreach (keys %$self) { # safe memory
+ delete $self->{$_} unless $keep{$_};
+ }
+ }
+
+ system("$Config::Config{eunicefix} $finalname") unless $Config::Config{eunicefix} eq ":";
+}
+
+
+# This is a rename for OS's where the target must be unlinked first.
+sub _rename {
+ my($src, $dest) = @_;
+ chmod 0666, $dest;
+ unlink $dest;
+ return rename $src, $dest;
+}
+
+# This is an unlink for OS's where the target must be writable first.
+sub _unlink {
+ my @files = @_;
+ chmod 0666, @files;
+ return unlink @files;
+}
+
+
+# The following mkbootstrap() is only for installations that are calling
+# the pre-4.1 mkbootstrap() from their old Makefiles. This MakeMaker
+# writes Makefiles, that use ExtUtils::Mkbootstrap directly.
+sub mkbootstrap {
+ die <<END;
+!!! Your Makefile has been built such a long time ago, !!!
+!!! that is unlikely to work with current MakeMaker. !!!
+!!! Please rebuild your Makefile !!!
+END
+}
+
+# Ditto for mksymlists() as of MakeMaker 5.17
+sub mksymlists {
+ die <<END;
+!!! Your Makefile has been built such a long time ago, !!!
+!!! that is unlikely to work with current MakeMaker. !!!
+!!! Please rebuild your Makefile !!!
+END
+}
+
+sub neatvalue {
+ my($v) = @_;
+ return "undef" unless defined $v;
+ my($t) = ref $v;
+ return "q[$v]" unless $t;
+ if ($t eq 'ARRAY') {
+ my(@m, @neat);
+ push @m, "[";
+ foreach my $elem (@$v) {
+ push @neat, "q[$elem]";
+ }
+ push @m, join ", ", @neat;
+ push @m, "]";
+ return join "", @m;
+ }
+ return "$v" unless $t eq 'HASH';
+ my(@m, $key, $val);
+ while (($key,$val) = each %$v){
+ last unless defined $key; # cautious programming in case (undef,undef) is true
+ push(@m,"$key=>".neatvalue($val)) ;
+ }
+ return "{ ".join(', ',@m)." }";
+}
+
+sub selfdocument {
+ my($self) = @_;
+ my(@m);
+ if ($Verbose){
+ push @m, "\n# Full list of MakeMaker attribute values:";
+ foreach my $key (sort keys %$self){
+ next if $key eq 'RESULT' || $key =~ /^[A-Z][a-z]/;
+ my($v) = neatvalue($self->{$key});
+ $v =~ s/(CODE|HASH|ARRAY|SCALAR)\([\dxa-f]+\)/$1\(...\)/;
+ $v =~ tr/\n/ /s;
+ push @m, "# $key => $v";
+ }
+ }
+ join "\n", @m;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+ExtUtils::MakeMaker - Create a module Makefile
+
+=head1 SYNOPSIS
+
+ use ExtUtils::MakeMaker;
+
+ WriteMakefile( ATTRIBUTE => VALUE [, ...] );
+
+=head1 DESCRIPTION
+
+This utility is designed to write a Makefile for an extension module
+from a Makefile.PL. It is based on the Makefile.SH model provided by
+Andy Dougherty and the perl5-porters.
+
+It splits the task of generating the Makefile into several subroutines
+that can be individually overridden. Each subroutine returns the text
+it wishes to have written to the Makefile.
+
+MakeMaker is object oriented. Each directory below the current
+directory that contains a Makefile.PL is treated as a separate
+object. This makes it possible to write an unlimited number of
+Makefiles with a single invocation of WriteMakefile().
+
+=head2 How To Write A Makefile.PL
+
+See ExtUtils::MakeMaker::Tutorial.
+
+The long answer is the rest of the manpage :-)
+
+=head2 Default Makefile Behaviour
+
+The generated Makefile enables the user of the extension to invoke
+
+ perl Makefile.PL # optionally "perl Makefile.PL verbose"
+ make
+ make test # optionally set TEST_VERBOSE=1
+ make install # See below
+
+The Makefile to be produced may be altered by adding arguments of the
+form C<KEY=VALUE>. E.g.
+
+ perl Makefile.PL INSTALL_BASE=~
+
+Other interesting targets in the generated Makefile are
+
+ make config # to check if the Makefile is up-to-date
+ make clean # delete local temp files (Makefile gets renamed)
+ make realclean # delete derived files (including ./blib)
+ make ci # check in all the files in the MANIFEST file
+ make dist # see below the Distribution Support section
+
+=head2 make test
+
+MakeMaker checks for the existence of a file named F<test.pl> in the
+current directory and if it exists it execute the script with the
+proper set of perl C<-I> options.
+
+MakeMaker also checks for any files matching glob("t/*.t"). It will
+execute all matching files in alphabetical order via the
+L<Test::Harness> module with the C<-I> switches set correctly.
+
+If you'd like to see the raw output of your tests, set the
+C<TEST_VERBOSE> variable to true.
+
+ make test TEST_VERBOSE=1
+
+=head2 make testdb
+
+A useful variation of the above is the target C<testdb>. It runs the
+test under the Perl debugger (see L<perldebug>). If the file
+F<test.pl> exists in the current directory, it is used for the test.
+
+If you want to debug some other testfile, set the C<TEST_FILE> variable
+thusly:
+
+ make testdb TEST_FILE=t/mytest.t
+
+By default the debugger is called using C<-d> option to perl. If you
+want to specify some other option, set the C<TESTDB_SW> variable:
+
+ make testdb TESTDB_SW=-Dx
+
+=head2 make install
+
+make alone puts all relevant files into directories that are named by
+the macros INST_LIB, INST_ARCHLIB, INST_SCRIPT, INST_MAN1DIR and
+INST_MAN3DIR. All these default to something below ./blib if you are
+I<not> building below the perl source directory. If you I<are>
+building below the perl source, INST_LIB and INST_ARCHLIB default to
+../../lib, and INST_SCRIPT is not defined.
+
+The I<install> target of the generated Makefile copies the files found
+below each of the INST_* directories to their INSTALL*
+counterparts. Which counterparts are chosen depends on the setting of
+INSTALLDIRS according to the following table:
+
+ INSTALLDIRS set to
+ perl site vendor
+
+ PERLPREFIX SITEPREFIX VENDORPREFIX
+ INST_ARCHLIB INSTALLARCHLIB INSTALLSITEARCH INSTALLVENDORARCH
+ INST_LIB INSTALLPRIVLIB INSTALLSITELIB INSTALLVENDORLIB
+ INST_BIN INSTALLBIN INSTALLSITEBIN INSTALLVENDORBIN
+ INST_SCRIPT INSTALLSCRIPT INSTALLSITESCRIPT INSTALLVENDORSCRIPT
+ INST_MAN1DIR INSTALLMAN1DIR INSTALLSITEMAN1DIR INSTALLVENDORMAN1DIR
+ INST_MAN3DIR INSTALLMAN3DIR INSTALLSITEMAN3DIR INSTALLVENDORMAN3DIR
+
+The INSTALL... macros in turn default to their %Config
+($Config{installprivlib}, $Config{installarchlib}, etc.) counterparts.
+
+You can check the values of these variables on your system with
+
+ perl '-V:install.*'
+
+And to check the sequence in which the library directories are
+searched by perl, run
+
+ perl -le 'print join $/, @INC'
+
+Sometimes older versions of the module you're installing live in other
+directories in @INC. Because Perl loads the first version of a module it
+finds, not the newest, you might accidentally get one of these older
+versions even after installing a brand new version. To delete I<all other
+versions of the module you're installing> (not simply older ones) set the
+C<UNINST> variable.
+
+ make install UNINST=1
+
+
+=head2 INSTALL_BASE
+
+INSTALL_BASE can be passed into Makefile.PL to change where your
+module will be installed. INSTALL_BASE is more like what everyone
+else calls "prefix" than PREFIX is.
+
+To have everything installed in your home directory, do the following.
+
+ # Unix users, INSTALL_BASE=~ works fine
+ perl Makefile.PL INSTALL_BASE=/path/to/your/home/dir
+
+Like PREFIX, it sets several INSTALL* attributes at once. Unlike
+PREFIX it is easy to predict where the module will end up. The
+installation pattern looks like this:
+
+ INSTALLARCHLIB INSTALL_BASE/lib/perl5/$Config{archname}
+ INSTALLPRIVLIB INSTALL_BASE/lib/perl5
+ INSTALLBIN INSTALL_BASE/bin
+ INSTALLSCRIPT INSTALL_BASE/bin
+ INSTALLMAN1DIR INSTALL_BASE/man/man1
+ INSTALLMAN3DIR INSTALL_BASE/man/man3
+
+INSTALL_BASE in MakeMaker and C<--install_base> in Module::Build (as
+of 0.28) install to the same location. If you want MakeMaker and
+Module::Build to install to the same location simply set INSTALL_BASE
+and C<--install_base> to the same location.
+
+INSTALL_BASE was added in 6.31.
+
+
+=head2 PREFIX and LIB attribute
+
+PREFIX and LIB can be used to set several INSTALL* attributes in one
+go. Here's an example for installing into your home directory.
+
+ # Unix users, PREFIX=~ works fine
+ perl Makefile.PL PREFIX=/path/to/your/home/dir
+
+This will install all files in the module under your home directory,
+with man pages and libraries going into an appropriate place (usually
+~/man and ~/lib). How the exact location is determined is complicated
+and depends on how your Perl was configured. INSTALL_BASE works more
+like what other build systems call "prefix" than PREFIX and we
+recommend you use that instead.
+
+Another way to specify many INSTALL directories with a single
+parameter is LIB.
+
+ perl Makefile.PL LIB=~/lib
+
+This will install the module's architecture-independent files into
+~/lib, the architecture-dependent files into ~/lib/$archname.
+
+Note, that in both cases the tilde expansion is done by MakeMaker, not
+by perl by default, nor by make.
+
+Conflicts between parameters LIB, PREFIX and the various INSTALL*
+arguments are resolved so that:
+
+=over 4
+
+=item *
+
+setting LIB overrides any setting of INSTALLPRIVLIB, INSTALLARCHLIB,
+INSTALLSITELIB, INSTALLSITEARCH (and they are not affected by PREFIX);
+
+=item *
+
+without LIB, setting PREFIX replaces the initial C<$Config{prefix}>
+part of those INSTALL* arguments, even if the latter are explicitly
+set (but are set to still start with C<$Config{prefix}>).
+
+=back
+
+If the user has superuser privileges, and is not working on AFS or
+relatives, then the defaults for INSTALLPRIVLIB, INSTALLARCHLIB,
+INSTALLSCRIPT, etc. will be appropriate, and this incantation will be
+the best:
+
+ perl Makefile.PL;
+ make;
+ make test
+ make install
+
+make install per default writes some documentation of what has been
+done into the file C<$(INSTALLARCHLIB)/perllocal.pod>. This feature
+can be bypassed by calling make pure_install.
+
+=head2 AFS users
+
+will have to specify the installation directories as these most
+probably have changed since perl itself has been installed. They will
+have to do this by calling
+
+ perl Makefile.PL INSTALLSITELIB=/afs/here/today \
+ INSTALLSCRIPT=/afs/there/now INSTALLMAN3DIR=/afs/for/manpages
+ make
+
+Be careful to repeat this procedure every time you recompile an
+extension, unless you are sure the AFS installation directories are
+still valid.
+
+=head2 Static Linking of a new Perl Binary
+
+An extension that is built with the above steps is ready to use on
+systems supporting dynamic loading. On systems that do not support
+dynamic loading, any newly created extension has to be linked together
+with the available resources. MakeMaker supports the linking process
+by creating appropriate targets in the Makefile whenever an extension
+is built. You can invoke the corresponding section of the makefile with
+
+ make perl
+
+That produces a new perl binary in the current directory with all
+extensions linked in that can be found in INST_ARCHLIB, SITELIBEXP,
+and PERL_ARCHLIB. To do that, MakeMaker writes a new Makefile, on
+UNIX, this is called Makefile.aperl (may be system dependent). If you
+want to force the creation of a new perl, it is recommended, that you
+delete this Makefile.aperl, so the directories are searched-through
+for linkable libraries again.
+
+The binary can be installed into the directory where perl normally
+resides on your machine with
+
+ make inst_perl
+
+To produce a perl binary with a different name than C<perl>, either say
+
+ perl Makefile.PL MAP_TARGET=myperl
+ make myperl
+ make inst_perl
+
+or say
+
+ perl Makefile.PL
+ make myperl MAP_TARGET=myperl
+ make inst_perl MAP_TARGET=myperl
+
+In any case you will be prompted with the correct invocation of the
+C<inst_perl> target that installs the new binary into INSTALLBIN.
+
+make inst_perl per default writes some documentation of what has been
+done into the file C<$(INSTALLARCHLIB)/perllocal.pod>. This
+can be bypassed by calling make pure_inst_perl.
+
+Warning: the inst_perl: target will most probably overwrite your
+existing perl binary. Use with care!
+
+Sometimes you might want to build a statically linked perl although
+your system supports dynamic loading. In this case you may explicitly
+set the linktype with the invocation of the Makefile.PL or make:
+
+ perl Makefile.PL LINKTYPE=static # recommended
+
+or
+
+ make LINKTYPE=static # works on most systems
+
+=head2 Determination of Perl Library and Installation Locations
+
+MakeMaker needs to know, or to guess, where certain things are
+located. Especially INST_LIB and INST_ARCHLIB (where to put the files
+during the make(1) run), PERL_LIB and PERL_ARCHLIB (where to read
+existing modules from), and PERL_INC (header files and C<libperl*.*>).
+
+Extensions may be built either using the contents of the perl source
+directory tree or from the installed perl library. The recommended way
+is to build extensions after you have run 'make install' on perl
+itself. You can do that in any directory on your hard disk that is not
+below the perl source tree. The support for extensions below the ext
+directory of the perl distribution is only good for the standard
+extensions that come with perl.
+
+If an extension is being built below the C<ext/> directory of the perl
+source then MakeMaker will set PERL_SRC automatically (e.g.,
+C<../..>). If PERL_SRC is defined and the extension is recognized as
+a standard extension, then other variables default to the following:
+
+ PERL_INC = PERL_SRC
+ PERL_LIB = PERL_SRC/lib
+ PERL_ARCHLIB = PERL_SRC/lib
+ INST_LIB = PERL_LIB
+ INST_ARCHLIB = PERL_ARCHLIB
+
+If an extension is being built away from the perl source then MakeMaker
+will leave PERL_SRC undefined and default to using the installed copy
+of the perl library. The other variables default to the following:
+
+ PERL_INC = $archlibexp/CORE
+ PERL_LIB = $privlibexp
+ PERL_ARCHLIB = $archlibexp
+ INST_LIB = ./blib/lib
+ INST_ARCHLIB = ./blib/arch
+
+If perl has not yet been installed then PERL_SRC can be defined on the
+command line as shown in the previous section.
+
+
+=head2 Which architecture dependent directory?
+
+If you don't want to keep the defaults for the INSTALL* macros,
+MakeMaker helps you to minimize the typing needed: the usual
+relationship between INSTALLPRIVLIB and INSTALLARCHLIB is determined
+by Configure at perl compilation time. MakeMaker supports the user who
+sets INSTALLPRIVLIB. If INSTALLPRIVLIB is set, but INSTALLARCHLIB not,
+then MakeMaker defaults the latter to be the same subdirectory of
+INSTALLPRIVLIB as Configure decided for the counterparts in %Config ,
+otherwise it defaults to INSTALLPRIVLIB. The same relationship holds
+for INSTALLSITELIB and INSTALLSITEARCH.
+
+MakeMaker gives you much more freedom than needed to configure
+internal variables and get different results. It is worth to mention,
+that make(1) also lets you configure most of the variables that are
+used in the Makefile. But in the majority of situations this will not
+be necessary, and should only be done if the author of a package
+recommends it (or you know what you're doing).
+
+=head2 Using Attributes and Parameters
+
+The following attributes may be specified as arguments to WriteMakefile()
+or as NAME=VALUE pairs on the command line.
+
+=over 2
+
+=item ABSTRACT
+
+One line description of the module. Will be included in PPD file.
+
+=item ABSTRACT_FROM
+
+Name of the file that contains the package description. MakeMaker looks
+for a line in the POD matching /^($package\s-\s)(.*)/. This is typically
+the first line in the "=head1 NAME" section. $2 becomes the abstract.
+
+=item AUTHOR
+
+String containing name (and email address) of package author(s). Is used
+in PPD (Perl Package Description) files for PPM (Perl Package Manager).
+
+=item BINARY_LOCATION
+
+Used when creating PPD files for binary packages. It can be set to a
+full or relative path or URL to the binary archive for a particular
+architecture. For example:
+
+ perl Makefile.PL BINARY_LOCATION=x86/Agent.tar.gz
+
+builds a PPD package that references a binary of the C<Agent> package,
+located in the C<x86> directory relative to the PPD itself.
+
+=item BUILD_REQUIRES
+
+A hash of modules that are needed to build your module but not run it.
+
+This will go into the C<build_requires> field of your F<META.yml>.
+
+The format is the same as PREREQ_PM.
+
+=item C
+
+Ref to array of *.c file names. Initialised from a directory scan
+and the values portion of the XS attribute hash. This is not
+currently used by MakeMaker but may be handy in Makefile.PLs.
+
+=item CCFLAGS
+
+String that will be included in the compiler call command line between
+the arguments INC and OPTIMIZE.
+
+=item CONFIG
+
+Arrayref. E.g. [qw(archname manext)] defines ARCHNAME & MANEXT from
+config.sh. MakeMaker will add to CONFIG the following values anyway:
+ar
+cc
+cccdlflags
+ccdlflags
+dlext
+dlsrc
+ld
+lddlflags
+ldflags
+libc
+lib_ext
+obj_ext
+ranlib
+sitelibexp
+sitearchexp
+so
+
+=item CONFIGURE
+
+CODE reference. The subroutine should return a hash reference. The
+hash may contain further attributes, e.g. {LIBS =E<gt> ...}, that have to
+be determined by some evaluation method.
+
+=item CONFIGURE_REQUIRES
+
+A hash of modules that are required to run Makefile.PL itself, but not
+to run your distribution.
+
+This will go into the C<configure_requires> field of your F<META.yml>.
+
+Defaults to C<<< { "ExtUtils::MakeMaker" => 0 } >>>
+
+The format is the same as PREREQ_PM.
+
+=item DEFINE
+
+Something like C<"-DHAVE_UNISTD_H">
+
+=item DESTDIR
+
+This is the root directory into which the code will be installed. It
+I<prepends itself to the normal prefix>. For example, if your code
+would normally go into F</usr/local/lib/perl> you could set DESTDIR=~/tmp/
+and installation would go into F<~/tmp/usr/local/lib/perl>.
+
+This is primarily of use for people who repackage Perl modules.
+
+NOTE: Due to the nature of make, it is important that you put the trailing
+slash on your DESTDIR. F<~/tmp/> not F<~/tmp>.
+
+=item DIR
+
+Ref to array of subdirectories containing Makefile.PLs e.g. ['sdbm']
+in ext/SDBM_File
+
+=item DISTNAME
+
+A safe filename for the package.
+
+Defaults to NAME above but with :: replaced with -.
+
+For example, Foo::Bar becomes Foo-Bar.
+
+=item DISTVNAME
+
+Your name for distributing the package with the version number
+included. This is used by 'make dist' to name the resulting archive
+file.
+
+Defaults to DISTNAME-VERSION.
+
+For example, version 1.04 of Foo::Bar becomes Foo-Bar-1.04.
+
+On some OS's where . has special meaning VERSION_SYM may be used in
+place of VERSION.
+
+=item DL_FUNCS
+
+Hashref of symbol names for routines to be made available as universal
+symbols. Each key/value pair consists of the package name and an
+array of routine names in that package. Used only under AIX, OS/2,
+VMS and Win32 at present. The routine names supplied will be expanded
+in the same way as XSUB names are expanded by the XS() macro.
+Defaults to
+
+ {"$(NAME)" => ["boot_$(NAME)" ] }
+
+e.g.
+
+ {"RPC" => [qw( boot_rpcb rpcb_gettime getnetconfigent )],
+ "NetconfigPtr" => [ 'DESTROY'] }
+
+Please see the L<ExtUtils::Mksymlists> documentation for more information
+about the DL_FUNCS, DL_VARS and FUNCLIST attributes.
+
+=item DL_VARS
+
+Array of symbol names for variables to be made available as universal symbols.
+Used only under AIX, OS/2, VMS and Win32 at present. Defaults to [].
+(e.g. [ qw(Foo_version Foo_numstreams Foo_tree ) ])
+
+=item EXCLUDE_EXT
+
+Array of extension names to exclude when doing a static build. This
+is ignored if INCLUDE_EXT is present. Consult INCLUDE_EXT for more
+details. (e.g. [ qw( Socket POSIX ) ] )
+
+This attribute may be most useful when specified as a string on the
+command line: perl Makefile.PL EXCLUDE_EXT='Socket Safe'
+
+=item EXE_FILES
+
+Ref to array of executable files. The files will be copied to the
+INST_SCRIPT directory. Make realclean will delete them from there
+again.
+
+If your executables start with something like #!perl or
+#!/usr/bin/perl MakeMaker will change this to the path of the perl
+'Makefile.PL' was invoked with so the programs will be sure to run
+properly even if perl is not in /usr/bin/perl.
+
+=item FIRST_MAKEFILE
+
+The name of the Makefile to be produced. This is used for the second
+Makefile that will be produced for the MAP_TARGET.
+
+Defaults to 'Makefile' or 'Descrip.MMS' on VMS.
+
+(Note: we couldn't use MAKEFILE because dmake uses this for something
+else).
+
+=item FULLPERL
+
+Perl binary able to run this extension, load XS modules, etc...
+
+=item FULLPERLRUN
+
+Like PERLRUN, except it uses FULLPERL.
+
+=item FULLPERLRUNINST
+
+Like PERLRUNINST, except it uses FULLPERL.
+
+=item FUNCLIST
+
+This provides an alternate means to specify function names to be
+exported from the extension. Its value is a reference to an
+array of function names to be exported by the extension. These
+names are passed through unaltered to the linker options file.
+
+=item H
+
+Ref to array of *.h file names. Similar to C.
+
+=item IMPORTS
+
+This attribute is used to specify names to be imported into the
+extension. Takes a hash ref.
+
+It is only used on OS/2 and Win32.
+
+=item INC
+
+Include file dirs eg: C<"-I/usr/5include -I/path/to/inc">
+
+=item INCLUDE_EXT
+
+Array of extension names to be included when doing a static build.
+MakeMaker will normally build with all of the installed extensions when
+doing a static build, and that is usually the desired behavior. If
+INCLUDE_EXT is present then MakeMaker will build only with those extensions
+which are explicitly mentioned. (e.g. [ qw( Socket POSIX ) ])
+
+It is not necessary to mention DynaLoader or the current extension when
+filling in INCLUDE_EXT. If the INCLUDE_EXT is mentioned but is empty then
+only DynaLoader and the current extension will be included in the build.
+
+This attribute may be most useful when specified as a string on the
+command line: perl Makefile.PL INCLUDE_EXT='POSIX Socket Devel::Peek'
+
+=item INSTALLARCHLIB
+
+Used by 'make install', which copies files from INST_ARCHLIB to this
+directory if INSTALLDIRS is set to perl.
+
+=item INSTALLBIN
+
+Directory to install binary files (e.g. tkperl) into if
+INSTALLDIRS=perl.
+
+=item INSTALLDIRS
+
+Determines which of the sets of installation directories to choose:
+perl, site or vendor. Defaults to site.
+
+=item INSTALLMAN1DIR
+
+=item INSTALLMAN3DIR
+
+These directories get the man pages at 'make install' time if
+INSTALLDIRS=perl. Defaults to $Config{installman*dir}.
+
+If set to 'none', no man pages will be installed.
+
+=item INSTALLPRIVLIB
+
+Used by 'make install', which copies files from INST_LIB to this
+directory if INSTALLDIRS is set to perl.
+
+Defaults to $Config{installprivlib}.
+
+=item INSTALLSCRIPT
+
+Used by 'make install' which copies files from INST_SCRIPT to this
+directory if INSTALLDIRS=perl.
+
+=item INSTALLSITEARCH
+
+Used by 'make install', which copies files from INST_ARCHLIB to this
+directory if INSTALLDIRS is set to site (default).
+
+=item INSTALLSITEBIN
+
+Used by 'make install', which copies files from INST_BIN to this
+directory if INSTALLDIRS is set to site (default).
+
+=item INSTALLSITELIB
+
+Used by 'make install', which copies files from INST_LIB to this
+directory if INSTALLDIRS is set to site (default).
+
+=item INSTALLSITEMAN1DIR
+
+=item INSTALLSITEMAN3DIR
+
+These directories get the man pages at 'make install' time if
+INSTALLDIRS=site (default). Defaults to
+$(SITEPREFIX)/man/man$(MAN*EXT).
+
+If set to 'none', no man pages will be installed.
+
+=item INSTALLSITESCRIPT
+
+Used by 'make install' which copies files from INST_SCRIPT to this
+directory if INSTALLDIRS is set to site (default).
+
+=item INSTALLVENDORARCH
+
+Used by 'make install', which copies files from INST_ARCHLIB to this
+directory if INSTALLDIRS is set to vendor.
+
+=item INSTALLVENDORBIN
+
+Used by 'make install', which copies files from INST_BIN to this
+directory if INSTALLDIRS is set to vendor.
+
+=item INSTALLVENDORLIB
+
+Used by 'make install', which copies files from INST_LIB to this
+directory if INSTALLDIRS is set to vendor.
+
+=item INSTALLVENDORMAN1DIR
+
+=item INSTALLVENDORMAN3DIR
+
+These directories get the man pages at 'make install' time if
+INSTALLDIRS=vendor. Defaults to $(VENDORPREFIX)/man/man$(MAN*EXT).
+
+If set to 'none', no man pages will be installed.
+
+=item INSTALLVENDORSCRIPT
+
+Used by 'make install' which copies files from INST_SCRIPT to this
+directory if INSTALLDIRS is set to vendor.
+
+=item INST_ARCHLIB
+
+Same as INST_LIB for architecture dependent files.
+
+=item INST_BIN
+
+Directory to put real binary files during 'make'. These will be copied
+to INSTALLBIN during 'make install'
+
+=item INST_LIB
+
+Directory where we put library files of this extension while building
+it.
+
+=item INST_MAN1DIR
+
+Directory to hold the man pages at 'make' time
+
+=item INST_MAN3DIR
+
+Directory to hold the man pages at 'make' time
+
+=item INST_SCRIPT
+
+Directory, where executable files should be installed during
+'make'. Defaults to "./blib/script", just to have a dummy location during
+testing. make install will copy the files in INST_SCRIPT to
+INSTALLSCRIPT.
+
+=item LD
+
+Program to be used to link libraries for dynamic loading.
+
+Defaults to $Config{ld}.
+
+=item LDDLFLAGS
+
+Any special flags that might need to be passed to ld to create a
+shared library suitable for dynamic loading. It is up to the makefile
+to use it. (See L<Config/lddlflags>)
+
+Defaults to $Config{lddlflags}.
+
+=item LDFROM
+
+Defaults to "$(OBJECT)" and is used in the ld command to specify
+what files to link/load from (also see dynamic_lib below for how to
+specify ld flags)
+
+=item LIB
+
+LIB should only be set at C<perl Makefile.PL> time but is allowed as a
+MakeMaker argument. It has the effect of setting both INSTALLPRIVLIB
+and INSTALLSITELIB to that value regardless any explicit setting of
+those arguments (or of PREFIX). INSTALLARCHLIB and INSTALLSITEARCH
+are set to the corresponding architecture subdirectory.
+
+=item LIBPERL_A
+
+The filename of the perllibrary that will be used together with this
+extension. Defaults to libperl.a.
+
+=item LIBS
+
+An anonymous array of alternative library
+specifications to be searched for (in order) until
+at least one library is found. E.g.
+
+ 'LIBS' => ["-lgdbm", "-ldbm -lfoo", "-L/path -ldbm.nfs"]
+
+Mind, that any element of the array
+contains a complete set of arguments for the ld
+command. So do not specify
+
+ 'LIBS' => ["-ltcl", "-ltk", "-lX11"]
+
+See ODBM_File/Makefile.PL for an example, where an array is needed. If
+you specify a scalar as in
+
+ 'LIBS' => "-ltcl -ltk -lX11"
+
+MakeMaker will turn it into an array with one element.
+
+=item LICENSE
+
+The licensing terms of your distribution. Generally its "perl" for the
+same license as Perl itself.
+
+See L<Module::Build::API> for the list of options.
+
+Defaults to "unknown".
+
+=item LINKTYPE
+
+'static' or 'dynamic' (default unless usedl=undef in
+config.sh). Should only be used to force static linking (also see
+linkext below).
+
+=item MAKE
+
+Variant of make you intend to run the generated Makefile with. This
+parameter lets Makefile.PL know what make quirks to account for when
+generating the Makefile.
+
+MakeMaker also honors the MAKE environment variable. This parameter
+takes precedent.
+
+Currently the only significant values are 'dmake' and 'nmake' for Windows
+users.
+
+Defaults to $Config{make}.
+
+=item MAKEAPERL
+
+Boolean which tells MakeMaker, that it should include the rules to
+make a perl. This is handled automatically as a switch by
+MakeMaker. The user normally does not need it.
+
+=item MAKEFILE_OLD
+
+When 'make clean' or similar is run, the $(FIRST_MAKEFILE) will be
+backed up at this location.
+
+Defaults to $(FIRST_MAKEFILE).old or $(FIRST_MAKEFILE)_old on VMS.
+
+=item MAN1PODS
+
+Hashref of pod-containing files. MakeMaker will default this to all
+EXE_FILES files that include POD directives. The files listed
+here will be converted to man pages and installed as was requested
+at Configure time.
+
+This hash should map POD files (or scripts containing POD) to the
+man file names under the C<blib/man1/> directory, as in the following
+example:
+
+ MAN1PODS => {
+ 'doc/command.pod' => 'blib/man1/command.1',
+ 'scripts/script.pl' => 'blib/man1/script.1',
+ }
+
+=item MAN3PODS
+
+Hashref that assigns to *.pm and *.pod files the files into which the
+manpages are to be written. MakeMaker parses all *.pod and *.pm files
+for POD directives. Files that contain POD will be the default keys of
+the MAN3PODS hashref. These will then be converted to man pages during
+C<make> and will be installed during C<make install>.
+
+Example similar to MAN1PODS.
+
+=item MAP_TARGET
+
+If it is intended, that a new perl binary be produced, this variable
+may hold a name for that binary. Defaults to perl
+
+=item META_ADD
+
+=item META_MERGE
+
+A hashrefs of items to add to the F<META.yml>.
+
+They differ in how they behave if they have the same key as the
+default metadata. META_ADD will override the default value with it's
+own. META_MERGE will merge its value with the default.
+
+Unless you want to override the defaults, prefer META_MERGE so as to
+get the advantage of any future defaults.
+
+=item MIN_PERL_VERSION
+
+The minimum required version of Perl for this distribution.
+
+Either 5.006001 or 5.6.1 format is acceptable.
+
+=item MYEXTLIB
+
+If the extension links to a library that it builds set this to the
+name of the library (see SDBM_File)
+
+=item NAME
+
+Perl module name for this extension (DBD::Oracle). This will default
+to the directory name but should be explicitly defined in the
+Makefile.PL.
+
+=item NEEDS_LINKING
+
+MakeMaker will figure out if an extension contains linkable code
+anywhere down the directory tree, and will set this variable
+accordingly, but you can speed it up a very little bit if you define
+this boolean variable yourself.
+
+=item NOECHO
+
+Command so make does not print the literal commands its running.
+
+By setting it to an empty string you can generate a Makefile that
+prints all commands. Mainly used in debugging MakeMaker itself.
+
+Defaults to C<@>.
+
+=item NORECURS
+
+Boolean. Attribute to inhibit descending into subdirectories.
+
+=item NO_META
+
+When true, suppresses the generation and addition to the MANIFEST of
+the META.yml module meta-data file during 'make distdir'.
+
+Defaults to false.
+
+=item NO_VC
+
+In general, any generated Makefile checks for the current version of
+MakeMaker and the version the Makefile was built under. If NO_VC is
+set, the version check is neglected. Do not write this into your
+Makefile.PL, use it interactively instead.
+
+=item OBJECT
+
+List of object files, defaults to '$(BASEEXT)$(OBJ_EXT)', but can be a long
+string containing all object files, e.g. "tkpBind.o
+tkpButton.o tkpCanvas.o"
+
+(Where BASEEXT is the last component of NAME, and OBJ_EXT is $Config{obj_ext}.)
+
+=item OPTIMIZE
+
+Defaults to C<-O>. Set it to C<-g> to turn debugging on. The flag is
+passed to subdirectory makes.
+
+=item PERL
+
+Perl binary for tasks that can be done by miniperl
+
+=item PERL_CORE
+
+Set only when MakeMaker is building the extensions of the Perl core
+distribution.
+
+=item PERLMAINCC
+
+The call to the program that is able to compile perlmain.c. Defaults
+to $(CC).
+
+=item PERL_ARCHLIB
+
+Same as for PERL_LIB, but for architecture dependent files.
+
+Used only when MakeMaker is building the extensions of the Perl core
+distribution (because normally $(PERL_ARCHLIB) is automatically in @INC,
+and adding it would get in the way of PERL5LIB).
+
+=item PERL_LIB
+
+Directory containing the Perl library to use.
+
+Used only when MakeMaker is building the extensions of the Perl core
+distribution (because normally $(PERL_LIB) is automatically in @INC,
+and adding it would get in the way of PERL5LIB).
+
+=item PERL_MALLOC_OK
+
+defaults to 0. Should be set to TRUE if the extension can work with
+the memory allocation routines substituted by the Perl malloc() subsystem.
+This should be applicable to most extensions with exceptions of those
+
+=over 4
+
+=item *
+
+with bugs in memory allocations which are caught by Perl's malloc();
+
+=item *
+
+which interact with the memory allocator in other ways than via
+malloc(), realloc(), free(), calloc(), sbrk() and brk();
+
+=item *
+
+which rely on special alignment which is not provided by Perl's malloc().
+
+=back
+
+B<NOTE.> Negligence to set this flag in I<any one> of loaded extension
+nullifies many advantages of Perl's malloc(), such as better usage of
+system resources, error detection, memory usage reporting, catchable failure
+of memory allocations, etc.
+
+=item PERLPREFIX
+
+Directory under which core modules are to be installed.
+
+Defaults to $Config{installprefixexp} falling back to
+$Config{installprefix}, $Config{prefixexp} or $Config{prefix} should
+$Config{installprefixexp} not exist.
+
+Overridden by PREFIX.
+
+=item PERLRUN
+
+Use this instead of $(PERL) when you wish to run perl. It will set up
+extra necessary flags for you.
+
+=item PERLRUNINST
+
+Use this instead of $(PERL) when you wish to run perl to work with
+modules. It will add things like -I$(INST_ARCH) and other necessary
+flags so perl can see the modules you're about to install.
+
+=item PERL_SRC
+
+Directory containing the Perl source code (use of this should be
+avoided, it may be undefined)
+
+=item PERM_DIR
+
+Desired permission for directories. Defaults to C<755>.
+
+=item PERM_RW
+
+Desired permission for read/writable files. Defaults to C<644>.
+
+=item PERM_RWX
+
+Desired permission for executable files. Defaults to C<755>.
+
+=item PL_FILES
+
+MakeMaker can run programs to generate files for you at build time.
+By default any file named *.PL (except Makefile.PL and Build.PL) in
+the top level directory will be assumed to be a Perl program and run
+passing its own basename in as an argument. For example...
+
+ perl foo.PL foo
+
+This behavior can be overridden by supplying your own set of files to
+search. PL_FILES accepts a hash ref, the key being the file to run
+and the value is passed in as the first argument when the PL file is run.
+
+ PL_FILES => {'bin/foobar.PL' => 'bin/foobar'}
+
+Would run bin/foobar.PL like this:
+
+ perl bin/foobar.PL bin/foobar
+
+If multiple files from one program are desired an array ref can be used.
+
+ PL_FILES => {'bin/foobar.PL' => [qw(bin/foobar1 bin/foobar2)]}
+
+In this case the program will be run multiple times using each target file.
+
+ perl bin/foobar.PL bin/foobar1
+ perl bin/foobar.PL bin/foobar2
+
+PL files are normally run B<after> pm_to_blib and include INST_LIB and
+INST_ARCH in its C<@INC> so the just built modules can be
+accessed... unless the PL file is making a module (or anything else in
+PM) in which case it is run B<before> pm_to_blib and does not include
+INST_LIB and INST_ARCH in its C<@INC>. This apparently odd behavior
+is there for backwards compatibility (and its somewhat DWIM).
+
+
+=item PM
+
+Hashref of .pm files and *.pl files to be installed. e.g.
+
+ {'name_of_file.pm' => '$(INST_LIBDIR)/install_as.pm'}
+
+By default this will include *.pm and *.pl and the files found in
+the PMLIBDIRS directories. Defining PM in the
+Makefile.PL will override PMLIBDIRS.
+
+=item PMLIBDIRS
+
+Ref to array of subdirectories containing library files. Defaults to
+[ 'lib', $(BASEEXT) ]. The directories will be scanned and I<any> files
+they contain will be installed in the corresponding location in the
+library. A libscan() method can be used to alter the behaviour.
+Defining PM in the Makefile.PL will override PMLIBDIRS.
+
+(Where BASEEXT is the last component of NAME.)
+
+=item PM_FILTER
+
+A filter program, in the traditional Unix sense (input from stdin, output
+to stdout) that is passed on each .pm file during the build (in the
+pm_to_blib() phase). It is empty by default, meaning no filtering is done.
+
+Great care is necessary when defining the command if quoting needs to be
+done. For instance, you would need to say:
+
+ {'PM_FILTER' => 'grep -v \\"^\\#\\"'}
+
+to remove all the leading comments on the fly during the build. The
+extra \\ are necessary, unfortunately, because this variable is interpolated
+within the context of a Perl program built on the command line, and double
+quotes are what is used with the -e switch to build that command line. The
+# is escaped for the Makefile, since what is going to be generated will then
+be:
+
+ PM_FILTER = grep -v \"^\#\"
+
+Without the \\ before the #, we'd have the start of a Makefile comment,
+and the macro would be incorrectly defined.
+
+=item POLLUTE
+
+Release 5.005 grandfathered old global symbol names by providing preprocessor
+macros for extension source compatibility. As of release 5.6, these
+preprocessor definitions are not available by default. The POLLUTE flag
+specifies that the old names should still be defined:
+
+ perl Makefile.PL POLLUTE=1
+
+Please inform the module author if this is necessary to successfully install
+a module under 5.6 or later.
+
+=item PPM_INSTALL_EXEC
+
+Name of the executable used to run C<PPM_INSTALL_SCRIPT> below. (e.g. perl)
+
+=item PPM_INSTALL_SCRIPT
+
+Name of the script that gets executed by the Perl Package Manager after
+the installation of a package.
+
+=item PREFIX
+
+This overrides all the default install locations. Man pages,
+libraries, scripts, etc... MakeMaker will try to make an educated
+guess about where to place things under the new PREFIX based on your
+Config defaults. Failing that, it will fall back to a structure
+which should be sensible for your platform.
+
+If you specify LIB or any INSTALL* variables they will not be effected
+by the PREFIX.
+
+=item PREREQ_FATAL
+
+Bool. If this parameter is true, failing to have the required modules
+(or the right versions thereof) will be fatal. C<perl Makefile.PL>
+will C<die> instead of simply informing the user of the missing dependencies.
+
+It is I<extremely> rare to have to use C<PREREQ_FATAL>. Its use by module
+authors is I<strongly discouraged> and should never be used lightly.
+Module installation tools have ways of resolving umet dependencies but
+to do that they need a F<Makefile>. Using C<PREREQ_FATAL> breaks this.
+That's bad.
+
+The only situation where it is appropriate is when you have
+dependencies that are indispensible to actually I<write> a
+F<Makefile>. For example, MakeMaker's F<Makefile.PL> needs L<File::Spec>.
+If its not available it cannot write the F<Makefile>.
+
+Note: see L<Test::Harness> for a shortcut for stopping tests early
+if you are missing dependencies and are afraid that users might
+use your module with an incomplete environment.
+
+=item PREREQ_PM
+
+A hash of modules that are needed to run your module. The keys are
+the module names ie. Test::More, and the minimum version is the
+value. If the required version number is 0 any version will do.
+
+This will go into the C<requires> field of your F<META.yml>.
+
+ PREREQ_PM => {
+ # Require Test::More at least 0.47
+ "Test::More" => "0.47",
+
+ # Require any version of Acme::Buffy
+ "Acme::Buffy" => 0,
+ }
+
+=item PREREQ_PRINT
+
+Bool. If this parameter is true, the prerequisites will be printed to
+stdout and MakeMaker will exit. The output format is an evalable hash
+ref.
+
+ $PREREQ_PM = {
+ 'A::B' => Vers1,
+ 'C::D' => Vers2,
+ ...
+ };
+
+If a distribution defines a minimal required perl version, this is
+added to the output as an additional line of the form:
+
+ $MIN_PERL_VERSION = '5.008001';
+
+If BUILD_REQUIRES is not empty, it will be dumped as $BUILD_REQUIRES hasref.
+
+=item PRINT_PREREQ
+
+RedHatism for C<PREREQ_PRINT>. The output format is different, though:
+
+ perl(A::B)>=Vers1 perl(C::D)>=Vers2 ...
+
+A minimal required perl version, if present, will look like this:
+
+ perl(perl)>=5.008001
+
+=item SITEPREFIX
+
+Like PERLPREFIX, but only for the site install locations.
+
+Defaults to $Config{siteprefixexp}. Perls prior to 5.6.0 didn't have
+an explicit siteprefix in the Config. In those cases
+$Config{installprefix} will be used.
+
+Overridable by PREFIX
+
+=item SIGN
+
+When true, perform the generation and addition to the MANIFEST of the
+SIGNATURE file in the distdir during 'make distdir', via 'cpansign
+-s'.
+
+Note that you need to install the Module::Signature module to
+perform this operation.
+
+Defaults to false.
+
+=item SKIP
+
+Arrayref. E.g. [qw(name1 name2)] skip (do not write) sections of the
+Makefile. Caution! Do not use the SKIP attribute for the negligible
+speedup. It may seriously damage the resulting Makefile. Only use it
+if you really need it.
+
+=item TYPEMAPS
+
+Ref to array of typemap file names. Use this when the typemaps are
+in some directory other than the current directory or when they are
+not named B<typemap>. The last typemap in the list takes
+precedence. A typemap in the current directory has highest
+precedence, even if it isn't listed in TYPEMAPS. The default system
+typemap has lowest precedence.
+
+=item VENDORPREFIX
+
+Like PERLPREFIX, but only for the vendor install locations.
+
+Defaults to $Config{vendorprefixexp}.
+
+Overridable by PREFIX
+
+=item VERBINST
+
+If true, make install will be verbose
+
+=item VERSION
+
+Your version number for distributing the package. This defaults to
+0.1.
+
+=item VERSION_FROM
+
+Instead of specifying the VERSION in the Makefile.PL you can let
+MakeMaker parse a file to determine the version number. The parsing
+routine requires that the file named by VERSION_FROM contains one
+single line to compute the version number. The first line in the file
+that contains something like a $VERSION assignment or C<package Name
+VERSION> will be used. The following lines will be parsed o.k.:
+
+ # Good
+ package Foo::Bar 1.23; # 1.23
+ $VERSION = '1.00'; # 1.00
+ *VERSION = \'1.01'; # 1.01
+ ($VERSION) = q$Revision$ =~ /(\d+)/g; # The digits in $Revision$
+ $FOO::VERSION = '1.10'; # 1.10
+ *FOO::VERSION = \'1.11'; # 1.11
+
+but these will fail:
+
+ # Bad
+ my $VERSION = '1.01';
+ local $VERSION = '1.02';
+ local $FOO::VERSION = '1.30';
+
+"Version strings" are incompatible should not be used.
+
+ # Bad
+ $VERSION = 1.2.3;
+ $VERSION = v1.2.3;
+
+L<version> objects are fine. As of MakeMaker 6.35 version.pm will be
+automatically loaded, but you must declare the dependency on version.pm.
+For compatibility with older MakeMaker you should load on the same line
+as $VERSION is declared.
+
+ # All on one line
+ use version; our $VERSION = qv(1.2.3);
+
+(Putting C<my> or C<local> on the preceding line will work o.k.)
+
+The file named in VERSION_FROM is not added as a dependency to
+Makefile. This is not really correct, but it would be a major pain
+during development to have to rewrite the Makefile for any smallish
+change in that file. If you want to make sure that the Makefile
+contains the correct VERSION macro after any change of the file, you
+would have to do something like
+
+ depend => { Makefile => '$(VERSION_FROM)' }
+
+See attribute C<depend> below.
+
+=item VERSION_SYM
+
+A sanitized VERSION with . replaced by _. For places where . has
+special meaning (some filesystems, RCS labels, etc...)
+
+=item XS
+
+Hashref of .xs files. MakeMaker will default this. e.g.
+
+ {'name_of_file.xs' => 'name_of_file.c'}
+
+The .c files will automatically be included in the list of files
+deleted by a make clean.
+
+=item XSOPT
+
+String of options to pass to xsubpp. This might include C<-C++> or
+C<-extern>. Do not include typemaps here; the TYPEMAP parameter exists for
+that purpose.
+
+=item XSPROTOARG
+
+May be set to an empty string, which is identical to C<-prototypes>, or
+C<-noprototypes>. See the xsubpp documentation for details. MakeMaker
+defaults to the empty string.
+
+=item XS_VERSION
+
+Your version number for the .xs file of this package. This defaults
+to the value of the VERSION attribute.
+
+=back
+
+=head2 Additional lowercase attributes
+
+can be used to pass parameters to the methods which implement that
+part of the Makefile. Parameters are specified as a hash ref but are
+passed to the method as a hash.
+
+=over 2
+
+=item clean
+
+ {FILES => "*.xyz foo"}
+
+=item depend
+
+ {ANY_TARGET => ANY_DEPENDENCY, ...}
+
+(ANY_TARGET must not be given a double-colon rule by MakeMaker.)
+
+=item dist
+
+ {TARFLAGS => 'cvfF', COMPRESS => 'gzip', SUFFIX => '.gz',
+ SHAR => 'shar -m', DIST_CP => 'ln', ZIP => '/bin/zip',
+ ZIPFLAGS => '-rl', DIST_DEFAULT => 'private tardist' }
+
+If you specify COMPRESS, then SUFFIX should also be altered, as it is
+needed to tell make the target file of the compression. Setting
+DIST_CP to ln can be useful, if you need to preserve the timestamps on
+your files. DIST_CP can take the values 'cp', which copies the file,
+'ln', which links the file, and 'best' which copies symbolic links and
+links the rest. Default is 'best'.
+
+=item dynamic_lib
+
+ {ARMAYBE => 'ar', OTHERLDFLAGS => '...', INST_DYNAMIC_DEP => '...'}
+
+=item linkext
+
+ {LINKTYPE => 'static', 'dynamic' or ''}
+
+NB: Extensions that have nothing but *.pm files had to say
+
+ {LINKTYPE => ''}
+
+with Pre-5.0 MakeMakers. Since version 5.00 of MakeMaker such a line
+can be deleted safely. MakeMaker recognizes when there's nothing to
+be linked.
+
+=item macro
+
+ {ANY_MACRO => ANY_VALUE, ...}
+
+=item postamble
+
+Anything put here will be passed to MY::postamble() if you have one.
+
+=item realclean
+
+ {FILES => '$(INST_ARCHAUTODIR)/*.xyz'}
+
+=item test
+
+ {TESTS => 't/*.t'}
+
+=item tool_autosplit
+
+ {MAXLEN => 8}
+
+=back
+
+=head2 Overriding MakeMaker Methods
+
+If you cannot achieve the desired Makefile behaviour by specifying
+attributes you may define private subroutines in the Makefile.PL.
+Each subroutine returns the text it wishes to have written to
+the Makefile. To override a section of the Makefile you can
+either say:
+
+ sub MY::c_o { "new literal text" }
+
+or you can edit the default by saying something like:
+
+ package MY; # so that "SUPER" works right
+ sub c_o {
+ my $inherited = shift->SUPER::c_o(@_);
+ $inherited =~ s/old text/new text/;
+ $inherited;
+ }
+
+If you are running experiments with embedding perl as a library into
+other applications, you might find MakeMaker is not sufficient. You'd
+better have a look at ExtUtils::Embed which is a collection of utilities
+for embedding.
+
+If you still need a different solution, try to develop another
+subroutine that fits your needs and submit the diffs to
+C<makemaker@perl.org>
+
+For a complete description of all MakeMaker methods see
+L<ExtUtils::MM_Unix>.
+
+Here is a simple example of how to add a new target to the generated
+Makefile:
+
+ sub MY::postamble {
+ return <<'MAKE_FRAG';
+ $(MYEXTLIB): sdbm/Makefile
+ cd sdbm && $(MAKE) all
+
+ MAKE_FRAG
+ }
+
+=head2 The End Of Cargo Cult Programming
+
+WriteMakefile() now does some basic sanity checks on its parameters to
+protect against typos and malformatted values. This means some things
+which happened to work in the past will now throw warnings and
+possibly produce internal errors.
+
+Some of the most common mistakes:
+
+=over 2
+
+=item C<< MAN3PODS => ' ' >>
+
+This is commonly used to suppress the creation of man pages. MAN3PODS
+takes a hash ref not a string, but the above worked by accident in old
+versions of MakeMaker.
+
+The correct code is C<< MAN3PODS => { } >>.
+
+=back
+
+
+=head2 Hintsfile support
+
+MakeMaker.pm uses the architecture specific information from
+Config.pm. In addition it evaluates architecture specific hints files
+in a C<hints/> directory. The hints files are expected to be named
+like their counterparts in C<PERL_SRC/hints>, but with an C<.pl> file
+name extension (eg. C<next_3_2.pl>). They are simply C<eval>ed by
+MakeMaker within the WriteMakefile() subroutine, and can be used to
+execute commands as well as to include special variables. The rules
+which hintsfile is chosen are the same as in Configure.
+
+The hintsfile is eval()ed immediately after the arguments given to
+WriteMakefile are stuffed into a hash reference $self but before this
+reference becomes blessed. So if you want to do the equivalent to
+override or create an attribute you would say something like
+
+ $self->{LIBS} = ['-ldbm -lucb -lc'];
+
+=head2 Distribution Support
+
+For authors of extensions MakeMaker provides several Makefile
+targets. Most of the support comes from the ExtUtils::Manifest module,
+where additional documentation can be found.
+
+=over 4
+
+=item make distcheck
+
+reports which files are below the build directory but not in the
+MANIFEST file and vice versa. (See ExtUtils::Manifest::fullcheck() for
+details)
+
+=item make skipcheck
+
+reports which files are skipped due to the entries in the
+C<MANIFEST.SKIP> file (See ExtUtils::Manifest::skipcheck() for
+details)
+
+=item make distclean
+
+does a realclean first and then the distcheck. Note that this is not
+needed to build a new distribution as long as you are sure that the
+MANIFEST file is ok.
+
+=item make manifest
+
+rewrites the MANIFEST file, adding all remaining files found (See
+ExtUtils::Manifest::mkmanifest() for details)
+
+=item make distdir
+
+Copies all the files that are in the MANIFEST file to a newly created
+directory with the name C<$(DISTNAME)-$(VERSION)>. If that directory
+exists, it will be removed first.
+
+Additionally, it will create a META.yml module meta-data file in the
+distdir and add this to the distdir's MANIFEST. You can shut this
+behavior off with the NO_META flag.
+
+=item make disttest
+
+Makes a distdir first, and runs a C<perl Makefile.PL>, a make, and
+a make test in that directory.
+
+=item make tardist
+
+First does a distdir. Then a command $(PREOP) which defaults to a null
+command, followed by $(TO_UNIX), which defaults to a null command under
+UNIX, and will convert files in distribution directory to UNIX format
+otherwise. Next it runs C<tar> on that directory into a tarfile and
+deletes the directory. Finishes with a command $(POSTOP) which
+defaults to a null command.
+
+=item make dist
+
+Defaults to $(DIST_DEFAULT) which in turn defaults to tardist.
+
+=item make uutardist
+
+Runs a tardist first and uuencodes the tarfile.
+
+=item make shdist
+
+First does a distdir. Then a command $(PREOP) which defaults to a null
+command. Next it runs C<shar> on that directory into a sharfile and
+deletes the intermediate directory again. Finishes with a command
+$(POSTOP) which defaults to a null command. Note: For shdist to work
+properly a C<shar> program that can handle directories is mandatory.
+
+=item make zipdist
+
+First does a distdir. Then a command $(PREOP) which defaults to a null
+command. Runs C<$(ZIP) $(ZIPFLAGS)> on that directory into a
+zipfile. Then deletes that directory. Finishes with a command
+$(POSTOP) which defaults to a null command.
+
+=item make ci
+
+Does a $(CI) and a $(RCS_LABEL) on all files in the MANIFEST file.
+
+=back
+
+Customization of the dist targets can be done by specifying a hash
+reference to the dist attribute of the WriteMakefile call. The
+following parameters are recognized:
+
+ CI ('ci -u')
+ COMPRESS ('gzip --best')
+ POSTOP ('@ :')
+ PREOP ('@ :')
+ TO_UNIX (depends on the system)
+ RCS_LABEL ('rcs -q -Nv$(VERSION_SYM):')
+ SHAR ('shar')
+ SUFFIX ('.gz')
+ TAR ('tar')
+ TARFLAGS ('cvf')
+ ZIP ('zip')
+ ZIPFLAGS ('-r')
+
+An example:
+
+ WriteMakefile(
+ ...other options...
+ dist => {
+ COMPRESS => "bzip2",
+ SUFFIX => ".bz2"
+ }
+ );
+
+
+=head2 Module Meta-Data
+
+Long plaguing users of MakeMaker based modules has been the problem of
+getting basic information about the module out of the sources
+I<without> running the F<Makefile.PL> and doing a bunch of messy
+heuristics on the resulting F<Makefile>. To this end a simple module
+meta-data file has been introduced, F<META.yml>.
+
+F<META.yml> is a YAML document (see http://www.yaml.org) containing
+basic information about the module (name, version, prerequisites...)
+in an easy to read format. The format is developed and defined by the
+Module::Build developers (see
+http://module-build.sourceforge.net/META-spec.html)
+
+MakeMaker will automatically generate a F<META.yml> file for you and
+add it to your F<MANIFEST> as part of the 'distdir' target (and thus
+the 'dist' target). This is intended to seamlessly and rapidly
+populate CPAN with module meta-data. If you wish to shut this feature
+off, set the C<NO_META> C<WriteMakefile()> flag to true.
+
+
+=head2 Disabling an extension
+
+If some events detected in F<Makefile.PL> imply that there is no way
+to create the Module, but this is a normal state of things, then you
+can create a F<Makefile> which does nothing, but succeeds on all the
+"usual" build targets. To do so, use
+
+ use ExtUtils::MakeMaker qw(WriteEmptyMakefile);
+ WriteEmptyMakefile();
+
+instead of WriteMakefile().
+
+This may be useful if other modules expect this module to be I<built>
+OK, as opposed to I<work> OK (say, this system-dependent module builds
+in a subdirectory of some other distribution, or is listed as a
+dependency in a CPAN::Bundle, but the functionality is supported by
+different means on the current architecture).
+
+=head2 Other Handy Functions
+
+=over 4
+
+=item prompt
+
+ my $value = prompt($message);
+ my $value = prompt($message, $default);
+
+The C<prompt()> function provides an easy way to request user input
+used to write a makefile. It displays the $message as a prompt for
+input. If a $default is provided it will be used as a default. The
+function returns the $value selected by the user.
+
+If C<prompt()> detects that it is not running interactively and there
+is nothing on STDIN or if the PERL_MM_USE_DEFAULT environment variable
+is set to true, the $default will be used without prompting. This
+prevents automated processes from blocking on user input.
+
+If no $default is provided an empty string will be used instead.
+
+=back
+
+
+=head1 ENVIRONMENT
+
+=over 4
+
+=item PERL_MM_OPT
+
+Command line options used by C<MakeMaker-E<gt>new()>, and thus by
+C<WriteMakefile()>. The string is split on whitespace, and the result
+is processed before any actual command line arguments are processed.
+
+=item PERL_MM_USE_DEFAULT
+
+If set to a true value then MakeMaker's prompt function will
+always return the default without waiting for user input.
+
+=item PERL_CORE
+
+Same as the PERL_CORE parameter. The parameter overrides this.
+
+=back
+
+=head1 SEE ALSO
+
+L<Module::Build> is a pure-Perl alternative to MakeMaker which does
+not rely on make or any other external utility. It is easier to
+extend to suit your needs.
+
+L<Module::Install> is a wrapper around MakeMaker which adds features
+not normally available.
+
+L<ExtUtils::ModuleMaker> and L<Module::Starter> are both modules to
+help you setup your distribution.
+
+=head1 AUTHORS
+
+Andy Dougherty C<doughera@lafayette.edu>, Andreas KE<ouml>nig
+C<andreas.koenig@mind.de>, Tim Bunce C<timb@cpan.org>. VMS
+support by Charles Bailey C<bailey@newman.upenn.edu>. OS/2 support
+by Ilya Zakharevich C<ilya@math.ohio-state.edu>.
+
+Currently maintained by Michael G Schwern C<schwern@pobox.com>
+
+Send patches and ideas to C<makemaker@perl.org>.
+
+Send bug reports via http://rt.cpan.org/. Please send your
+generated Makefile along with your report.
+
+For more up-to-date information, see L<http://www.makemaker.org>.
+
+=head1 LICENSE
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+See L<http://www.perl.com/perl/misc/Artistic.html>
+
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MakeMaker/Config.pm b/Master/tlpkg/tlperl/lib/ExtUtils/MakeMaker/Config.pm
new file mode 100644
index 00000000000..38b60affdda
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MakeMaker/Config.pm
@@ -0,0 +1,39 @@
+package ExtUtils::MakeMaker::Config;
+
+use strict;
+
+our $VERSION = '6.56';
+
+use Config ();
+
+# Give us an overridable config.
+our %Config = %Config::Config;
+
+sub import {
+ my $caller = caller;
+
+ no strict 'refs'; ## no critic
+ *{$caller.'::Config'} = \%Config;
+}
+
+1;
+
+
+=head1 NAME
+
+ExtUtils::MakeMaker::Config - Wrapper around Config.pm
+
+
+=head1 SYNOPSIS
+
+ use ExtUtils::MakeMaker::Config;
+ print $Config{installbin}; # or whatever
+
+
+=head1 DESCRIPTION
+
+B<FOR INTERNAL USE ONLY>
+
+A very thin wrapper around Config.pm so MakeMaker is easier to test.
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MakeMaker/FAQ.pod b/Master/tlpkg/tlperl/lib/ExtUtils/MakeMaker/FAQ.pod
new file mode 100644
index 00000000000..d33f82e53b9
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MakeMaker/FAQ.pod
@@ -0,0 +1,431 @@
+package ExtUtils::MakeMaker::FAQ;
+
+our $VERSION = '1.12';
+
+1;
+__END__
+
+=head1 NAME
+
+ExtUtils::MakeMaker::FAQ - Frequently Asked Questions About MakeMaker
+
+=head1 DESCRIPTION
+
+FAQs, tricks and tips for C<ExtUtils::MakeMaker>.
+
+
+=head2 Module Installation
+
+=over 4
+
+=item How do I install a module into my home directory?
+
+If you're not the Perl administrator you probably don't have
+permission to install a module to its default location. Then you
+should install it for your own use into your home directory like so:
+
+ # Non-unix folks, replace ~ with /path/to/your/home/dir
+ perl Makefile.PL INSTALL_BASE=~
+
+This will put modules into F<~/lib/perl5>, man pages into F<~/man> and
+programs into F<~/bin>.
+
+To ensure your Perl programs can see these newly installed modules,
+set your C<PERL5LIB> environment variable to F<~/lib/perl5> or tell
+each of your programs to look in that directory with the following:
+
+ use lib "$ENV{HOME}/lib/perl5";
+
+or if $ENV{HOME} isn't set and you don't want to set it for some
+reason, do it the long way.
+
+ use lib "/path/to/your/home/dir/lib/perl5";
+
+
+=item How do I get MakeMaker and Module::Build to install to the same place?
+
+Module::Build, as of 0.28, supports two ways to install to the same
+location as MakeMaker.
+
+1) Use INSTALL_BASE / C<--install_base>
+
+MakeMaker (as of 6.31) and Module::Build (as of 0.28) both can install
+to the same locations using the "install_base" concept. See
+L<ExtUtils::MakeMaker/INSTALL_BASE> for details. To get MM and MB to
+install to the same location simply set INSTALL_BASE in MM and
+C<--install_base> in MB to the same location.
+
+ perl Makefile.PL INSTALL_BASE=/whatever
+ perl Build.PL --install_base /whatever
+
+2) Use PREFIX / C<--prefix>
+
+Module::Build 0.28 added support for C<--prefix> which works like
+MakeMaker's PREFIX.
+
+ perl Makefile.PL PREFIX=/whatever
+ perl Build.PL --prefix /whatever
+
+
+=item How do I keep from installing man pages?
+
+Recent versions of MakeMaker will only install man pages on Unix like
+operating systems.
+
+For an individual module:
+
+ perl Makefile.PL INSTALLMAN1DIR=none INSTALLMAN3DIR=none
+
+If you want to suppress man page installation for all modules you have
+to reconfigure Perl and tell it 'none' when it asks where to install
+man pages.
+
+
+=item How do I use a module without installing it?
+
+Two ways. One is to build the module normally...
+
+ perl Makefile.PL
+ make
+ make test
+
+...and then set the PERL5LIB environment variable to point at the
+blib/lib and blib/arch directories.
+
+The other is to install the module in a temporary location.
+
+ perl Makefile.PL INSTALL_BASE=~/tmp
+ make
+ make test
+ make install
+
+And then set PERL5LIB to F<~/tmp/lib/perl5>. This works well when you
+have multiple modules to work with. It also ensures that the module
+goes through its full installation process which may modify it.
+
+=item PREFIX vs INSTALL_BASE from Module::Build::Cookbook
+
+The behavior of PREFIX is complicated and depends closely on how your
+Perl is configured. The resulting installation locations will vary from
+machine to machine and even different installations of Perl on the same machine.
+Because of this, its difficult to document where prefix will place your modules.
+
+In contrast, INSTALL_BASE has predictable, easy to explain installation locations.
+Now that Module::Build and MakeMaker both have INSTALL_BASE there is little reason
+to use PREFIX other than to preserve your existing installation locations. If you
+are starting a fresh Perl installation we encourage you to use INSTALL_BASE. If
+you have an existing installation installed via PREFIX, consider moving it to an
+installation structure matching INSTALL_BASE and using that instead.
+
+=back
+
+
+=head2 Philosophy and History
+
+=over 4
+
+=item Why not just use <insert other build config tool here>?
+
+Why did MakeMaker reinvent the build configuration wheel? Why not
+just use autoconf or automake or ppm or Ant or ...
+
+There are many reasons, but the major one is cross-platform
+compatibility.
+
+Perl is one of the most ported pieces of software ever. It works on
+operating systems I've never even heard of (see perlport for details).
+It needs a build tool that can work on all those platforms and with
+any wacky C compilers and linkers they might have.
+
+No such build tool exists. Even make itself has wildly different
+dialects. So we have to build our own.
+
+
+=item What is Module::Build and how does it relate to MakeMaker?
+
+Module::Build is a project by Ken Williams to supplant MakeMaker.
+Its primary advantages are:
+
+=over 8
+
+=item * pure perl. no make, no shell commands
+
+=item * easier to customize
+
+=item * cleaner internals
+
+=item * less cruft
+
+=back
+
+Module::Build is the official heir apparent to MakeMaker and we
+encourage people to work on M::B rather than spending time adding features
+to MakeMaker.
+
+=back
+
+
+=head2 Module Writing
+
+=over 4
+
+=item How do I keep my $VERSION up to date without resetting it manually?
+
+Often you want to manually set the $VERSION in the main module
+distribution because this is the version that everybody sees on CPAN
+and maybe you want to customize it a bit. But for all the other
+modules in your dist, $VERSION is really just bookkeeping and all that's
+important is it goes up every time the module is changed. Doing this
+by hand is a pain and you often forget.
+
+Simplest way to do it automatically is to use your version control
+system's revision number (you are using version control, right?).
+
+In CVS, RCS and SVN you use $Revision$ (see the documentation of your
+version control system for details). Every time the file is checked
+in the $Revision$ will be updated, updating your $VERSION.
+
+SVN uses a simple integer for $Revision$ so you can adapt it for your
+$VERSION like so:
+
+ ($VERSION) = q$Revision$ =~ /(\d+)/;
+
+In CVS and RCS version 1.9 is followed by 1.10. Since CPAN compares
+version numbers numerically we use a sprintf() to convert 1.9 to 1.009
+and 1.10 to 1.010 which compare properly.
+
+ $VERSION = sprintf "%d.%03d", q$Revision$ =~ /(\d+)\.(\d+)/g;
+
+If branches are involved (ie. $Revision: 1.5.3.4$) its a little more
+complicated.
+
+ # must be all on one line or MakeMaker will get confused.
+ $VERSION = do { my @r = (q$Revision$ =~ /\d+/g); sprintf "%d."."%03d" x $#r, @r };
+
+In SVN, $Revision$ should be the same for every file in the project so
+they would all have the same $VERSION. CVS and RCS have a different
+$Revision$ per file so each file will have a differnt $VERSION.
+Distributed version control systems, such as SVK, may have a different
+$Revision$ based on who checks out the file leading to a different $VERSION
+on each machine! Finally, some distributed version control systems, such
+as darcs, have no concept of revision number at all.
+
+
+=item What's this F<META.yml> thing and how did it get in my F<MANIFEST>?!
+
+F<META.yml> is a module meta-data file pioneered by Module::Build and
+automatically generated as part of the 'distdir' target (and thus
+'dist'). See L<ExtUtils::MakeMaker/"Module Meta-Data">.
+
+To shut off its generation, pass the C<NO_META> flag to C<WriteMakefile()>.
+
+
+=item How do I delete everything not in my F<MANIFEST>?
+
+Some folks are surpried that C<make distclean> does not delete
+everything not listed in their MANIFEST (thus making a clean
+distribution) but only tells them what they need to delete. This is
+done because it is considered too dangerous. While developing your
+module you might write a new file, not add it to the MANIFEST, then
+run a C<distclean> and be sad because your new work was deleted.
+
+If you really want to do this, you can use
+C<ExtUtils::Manifest::manifind()> to read the MANIFEST and File::Find
+to delete the files. But you have to be careful. Here's a script to
+do that. Use at your own risk. Have fun blowing holes in your foot.
+
+ #!/usr/bin/perl -w
+
+ use strict;
+
+ use File::Spec;
+ use File::Find;
+ use ExtUtils::Manifest qw(maniread);
+
+ my %manifest = map {( $_ => 1 )}
+ grep { File::Spec->canonpath($_) }
+ keys %{ maniread() };
+
+ if( !keys %manifest ) {
+ print "No files found in MANIFEST. Stopping.\n";
+ exit;
+ }
+
+ find({
+ wanted => sub {
+ my $path = File::Spec->canonpath($_);
+
+ return unless -f $path;
+ return if exists $manifest{ $path };
+
+ print "unlink $path\n";
+ unlink $path;
+ },
+ no_chdir => 1
+ },
+ "."
+ );
+
+
+=item Which zip should I use on Windows for '[nd]make zipdist'?
+
+We recommend InfoZIP: L<http://www.info-zip.org/Zip.html>
+
+
+=back
+
+=head2 XS
+
+=over 4
+
+=item How to I prevent "object version X.XX does not match bootstrap parameter Y.YY" errors?
+
+XS code is very sensitive to the module version number and will
+complain if the version number in your Perl module doesn't match. If
+you change your module's version # without rerunning Makefile.PL the old
+version number will remain in the Makefile causing the XS code to be built
+with the wrong number.
+
+To avoid this, you can force the Makefile to be rebuilt whenever you
+change the module containing the version number by adding this to your
+WriteMakefile() arguments.
+
+ depend => { '$(FIRST_MAKEFILE)' => '$(VERSION_FROM)' }
+
+
+=item How do I make two or more XS files coexist in the same directory?
+
+Sometimes you need to have two and more XS files in the same package.
+One way to go is to put them into separate directories, but sometimes
+this is not the most suitable solution. The following technique allows
+you to put two (and more) XS files in the same directory.
+
+Let's assume that we have a package C<Cool::Foo>, which includes
+C<Cool::Foo> and C<Cool::Bar> modules each having a separate XS
+file. First we use the following I<Makefile.PL>:
+
+ use ExtUtils::MakeMaker;
+
+ WriteMakefile(
+ NAME => 'Cool::Foo',
+ VERSION_FROM => 'Foo.pm',
+ OBJECT => q/$(O_FILES)/,
+ # ... other attrs ...
+ );
+
+Notice the C<OBJECT> attribute. MakeMaker generates the following
+variables in I<Makefile>:
+
+ # Handy lists of source code files:
+ XS_FILES= Bar.xs \
+ Foo.xs
+ C_FILES = Bar.c \
+ Foo.c
+ O_FILES = Bar.o \
+ Foo.o
+
+Therefore we can use the C<O_FILES> variable to tell MakeMaker to use
+these objects into the shared library.
+
+That's pretty much it. Now write I<Foo.pm> and I<Foo.xs>, I<Bar.pm>
+and I<Bar.xs>, where I<Foo.pm> bootstraps the shared library and
+I<Bar.pm> simply loading I<Foo.pm>.
+
+The only issue left is to how to bootstrap I<Bar.xs>. This is done
+from I<Foo.xs>:
+
+ MODULE = Cool::Foo PACKAGE = Cool::Foo
+
+ BOOT:
+ # boot the second XS file
+ boot_Cool__Bar(aTHX_ cv);
+
+If you have more than two files, this is the place where you should
+boot extra XS files from.
+
+The following four files sum up all the details discussed so far.
+
+ Foo.pm:
+ -------
+ package Cool::Foo;
+
+ require DynaLoader;
+
+ our @ISA = qw(DynaLoader);
+ our $VERSION = '0.01';
+ bootstrap Cool::Foo $VERSION;
+
+ 1;
+
+ Bar.pm:
+ -------
+ package Cool::Bar;
+
+ use Cool::Foo; # bootstraps Bar.xs
+
+ 1;
+
+ Foo.xs:
+ -------
+ #include "EXTERN.h"
+ #include "perl.h"
+ #include "XSUB.h"
+
+ MODULE = Cool::Foo PACKAGE = Cool::Foo
+
+ BOOT:
+ # boot the second XS file
+ boot_Cool__Bar(aTHX_ cv);
+
+ MODULE = Cool::Foo PACKAGE = Cool::Foo PREFIX = cool_foo_
+
+ void
+ cool_foo_perl_rules()
+
+ CODE:
+ fprintf(stderr, "Cool::Foo says: Perl Rules\n");
+
+ Bar.xs:
+ -------
+ #include "EXTERN.h"
+ #include "perl.h"
+ #include "XSUB.h"
+
+ MODULE = Cool::Bar PACKAGE = Cool::Bar PREFIX = cool_bar_
+
+ void
+ cool_bar_perl_rules()
+
+ CODE:
+ fprintf(stderr, "Cool::Bar says: Perl Rules\n");
+
+And of course a very basic test:
+
+ t/cool.t:
+ --------
+ use Test;
+ BEGIN { plan tests => 1 };
+ use Cool::Foo;
+ use Cool::Bar;
+ Cool::Foo::perl_rules();
+ Cool::Bar::perl_rules();
+ ok 1;
+
+This tip has been brought to you by Nick Ing-Simmons and Stas Bekman.
+
+=back
+
+=head1 PATCHING
+
+If you have a question you'd like to see added to the FAQ (whether or
+not you have the answer) please send it to makemaker@perl.org.
+
+=head1 AUTHOR
+
+The denizens of makemaker@perl.org.
+
+=head1 SEE ALSO
+
+L<ExtUtils::MakeMaker>
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/MakeMaker/Tutorial.pod b/Master/tlpkg/tlperl/lib/ExtUtils/MakeMaker/Tutorial.pod
new file mode 100644
index 00000000000..8ad72649b1a
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/MakeMaker/Tutorial.pod
@@ -0,0 +1,180 @@
+package ExtUtils::MakeMaker::Tutorial;
+
+our $VERSION = 0.02;
+
+
+=head1 NAME
+
+ExtUtils::MakeMaker::Tutorial - Writing a module with MakeMaker
+
+=head1 SYNOPSIS
+
+ use ExtUtils::MakeMaker;
+
+ WriteMakefile(
+ NAME => 'Your::Module',
+ VERSION_FROM => 'lib/Your/Module.pm'
+ );
+
+=head1 DESCRIPTION
+
+This is a short tutorial on writing a simple module with MakeMaker.
+Its really not that hard.
+
+
+=head2 The Mantra
+
+MakeMaker modules are installed using this simple mantra
+
+ perl Makefile.PL
+ make
+ make test
+ make install
+
+There are lots more commands and options, but the above will do it.
+
+
+=head2 The Layout
+
+The basic files in a module look something like this.
+
+ Makefile.PL
+ MANIFEST
+ lib/Your/Module.pm
+
+That's all that's strictly necessary. There's additional files you might
+want:
+
+ lib/Your/Other/Module.pm
+ t/some_test.t
+ t/some_other_test.t
+ Changes
+ README
+ INSTALL
+ MANIFEST.SKIP
+ bin/some_program
+
+=over 4
+
+=item Makefile.PL
+
+When you run Makefile.PL, it makes a Makefile. That's the whole point of
+MakeMaker. The Makefile.PL is a simple program which loads
+ExtUtils::MakeMaker and runs the WriteMakefile() function to generate a
+Makefile.
+
+Here's an example of what you need for a simple module:
+
+ use ExtUtils::MakeMaker;
+
+ WriteMakefile(
+ NAME => 'Your::Module',
+ VERSION_FROM => 'lib/Your/Module.pm'
+ );
+
+NAME is the top-level namespace of your module. VERSION_FROM is the file
+which contains the $VERSION variable for the entire distribution. Typically
+this is the same as your top-level module.
+
+
+=item MANIFEST
+
+A simple listing of all the files in your distribution.
+
+ Makefile.PL
+ MANIFEST
+ lib/Your/Module.pm
+
+File paths in a MANIFEST always use Unix conventions (ie. /) even if you're
+not on Unix.
+
+You can write this by hand or generate it with 'make manifest'.
+
+See L<ExtUtils::Manifest> for more details.
+
+
+=item lib/
+
+This is the directory where your .pm and .pod files you wish to have
+installed go. They are layed out according to namespace. So Foo::Bar
+is F<lib/Foo/Bar.pm>.
+
+
+=item t/
+
+Tests for your modules go here. Each test filename ends with a .t.
+So F<t/foo.t>/ 'make test' will run these tests. The directory is flat,
+you cannot, for example, have t/foo/bar.t run by 'make test'.
+
+Tests are run from the top level of your distribution. So inside a test
+you would refer to ./lib to enter the lib directory, for example.
+
+
+=item Changes
+
+A log of changes you've made to this module. The layout is free-form.
+Here's an example:
+
+ 1.01 Fri Apr 11 00:21:25 PDT 2003
+ - thing() does some stuff now
+ - fixed the wiggy bug in withit()
+
+ 1.00 Mon Apr 7 00:57:15 PDT 2003
+ - "Rain of Frogs" now supported
+
+
+=item README
+
+A short description of your module, what it does, why someone would use it
+and its limitations. CPAN automatically pulls your README file out of
+the archive and makes it available to CPAN users, it is the first thing
+they will read to decide if your module is right for them.
+
+
+=item INSTALL
+
+Instructions on how to install your module along with any dependencies.
+Suggested information to include here:
+
+ any extra modules required for use
+ the minimum version of Perl required
+ if only works on certain operating systems
+
+
+=item MANIFEST.SKIP
+
+A file full of regular expressions to exclude when using 'make
+manifest' to generate the MANIFEST. These regular expressions
+are checked against each file path found in the distribution (so
+you're matching against "t/foo.t" not "foo.t").
+
+Here's a sample:
+
+ ~$ # ignore emacs and vim backup files
+ .bak$ # ignore manual backups
+ \# # ignore CVS old revision files and emacs temp files
+
+Since # can be used for comments, # must be escaped.
+
+MakeMaker comes with a default MANIFEST.SKIP to avoid things like
+version control directories and backup files. Specifying your own
+will override this default.
+
+
+=item bin/
+
+
+=back
+
+=head1 SEE ALSO
+
+L<perlmodstyle> gives stylistic help writing a module.
+
+L<perlnewmod> gives more information about how to write a module.
+
+There are modules to help you through the process of writing a module:
+L<ExtUtils::ModuleMaker>, L<Module::Install>, L<PAR>
+
+=cut
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/Manifest.pm b/Master/tlpkg/tlperl/lib/ExtUtils/Manifest.pm
new file mode 100644
index 00000000000..df621d5f435
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/Manifest.pm
@@ -0,0 +1,881 @@
+package ExtUtils::Manifest;
+
+require Exporter;
+use Config;
+use File::Basename;
+use File::Copy 'copy';
+use File::Find;
+use File::Spec;
+use Carp;
+use strict;
+
+use vars qw($VERSION @ISA @EXPORT_OK
+ $Is_MacOS $Is_VMS $Is_VMS_mode $Is_VMS_lc $Is_VMS_nodot
+ $Debug $Verbose $Quiet $MANIFEST $DEFAULT_MSKIP);
+
+$VERSION = '1.57';
+@ISA=('Exporter');
+@EXPORT_OK = qw(mkmanifest
+ manicheck filecheck fullcheck skipcheck
+ manifind maniread manicopy maniadd
+ maniskip
+ );
+
+$Is_MacOS = $^O eq 'MacOS';
+$Is_VMS = $^O eq 'VMS';
+$Is_VMS_mode = 0;
+$Is_VMS_lc = 0;
+$Is_VMS_nodot = 0; # No dots in dir names or double dots in files
+
+if ($Is_VMS) {
+ require VMS::Filespec if $Is_VMS;
+ my $vms_unix_rpt;
+ my $vms_efs;
+ my $vms_case;
+
+ $Is_VMS_mode = 1;
+ $Is_VMS_lc = 1;
+ $Is_VMS_nodot = 1;
+ if (eval { local $SIG{__DIE__}; require VMS::Feature; }) {
+ $vms_unix_rpt = VMS::Feature::current("filename_unix_report");
+ $vms_efs = VMS::Feature::current("efs_charset");
+ $vms_case = VMS::Feature::current("efs_case_preserve");
+ } else {
+ my $unix_rpt = $ENV{'DECC$FILENAME_UNIX_REPORT'} || '';
+ my $efs_charset = $ENV{'DECC$EFS_CHARSET'} || '';
+ my $efs_case = $ENV{'DECC$EFS_CASE_PRESERVE'} || '';
+ $vms_unix_rpt = $unix_rpt =~ /^[ET1]/i;
+ $vms_efs = $efs_charset =~ /^[ET1]/i;
+ $vms_case = $efs_case =~ /^[ET1]/i;
+ }
+ $Is_VMS_lc = 0 if ($vms_case);
+ $Is_VMS_mode = 0 if ($vms_unix_rpt);
+ $Is_VMS_nodot = 0 if ($vms_efs);
+}
+
+$Debug = $ENV{PERL_MM_MANIFEST_DEBUG} || 0;
+$Verbose = defined $ENV{PERL_MM_MANIFEST_VERBOSE} ?
+ $ENV{PERL_MM_MANIFEST_VERBOSE} : 1;
+$Quiet = 0;
+$MANIFEST = 'MANIFEST';
+
+$DEFAULT_MSKIP = File::Spec->catfile( dirname(__FILE__), "$MANIFEST.SKIP" );
+
+
+=head1 NAME
+
+ExtUtils::Manifest - utilities to write and check a MANIFEST file
+
+=head1 SYNOPSIS
+
+ use ExtUtils::Manifest qw(...funcs to import...);
+
+ mkmanifest();
+
+ my @missing_files = manicheck;
+ my @skipped = skipcheck;
+ my @extra_files = filecheck;
+ my($missing, $extra) = fullcheck;
+
+ my $found = manifind();
+
+ my $manifest = maniread();
+
+ manicopy($read,$target);
+
+ maniadd({$file => $comment, ...});
+
+
+=head1 DESCRIPTION
+
+=head2 Functions
+
+ExtUtils::Manifest exports no functions by default. The following are
+exported on request
+
+=over 4
+
+=item mkmanifest
+
+ mkmanifest();
+
+Writes all files in and below the current directory to your F<MANIFEST>.
+It works similar to the result of the Unix command
+
+ find . > MANIFEST
+
+All files that match any regular expression in a file F<MANIFEST.SKIP>
+(if it exists) are ignored.
+
+Any existing F<MANIFEST> file will be saved as F<MANIFEST.bak>.
+
+=cut
+
+sub _sort {
+ return sort { lc $a cmp lc $b } @_;
+}
+
+sub mkmanifest {
+ my $manimiss = 0;
+ my $read = (-r 'MANIFEST' && maniread()) or $manimiss++;
+ $read = {} if $manimiss;
+ local *M;
+ my $bakbase = $MANIFEST;
+ $bakbase =~ s/\./_/g if $Is_VMS_nodot; # avoid double dots
+ rename $MANIFEST, "$bakbase.bak" unless $manimiss;
+ open M, "> $MANIFEST" or die "Could not open $MANIFEST: $!";
+ my $skip = maniskip();
+ my $found = manifind();
+ my($key,$val,$file,%all);
+ %all = (%$found, %$read);
+ $all{$MANIFEST} = ($Is_VMS_mode ? "$MANIFEST\t\t" : '') .
+ 'This list of files'
+ if $manimiss; # add new MANIFEST to known file list
+ foreach $file (_sort keys %all) {
+ if ($skip->($file)) {
+ # Policy: only remove files if they're listed in MANIFEST.SKIP.
+ # Don't remove files just because they don't exist.
+ warn "Removed from $MANIFEST: $file\n" if $Verbose and exists $read->{$file};
+ next;
+ }
+ if ($Verbose){
+ warn "Added to $MANIFEST: $file\n" unless exists $read->{$file};
+ }
+ my $text = $all{$file};
+ $file = _unmacify($file);
+ my $tabs = (5 - (length($file)+1)/8);
+ $tabs = 1 if $tabs < 1;
+ $tabs = 0 unless $text;
+ if ($file =~ /\s/) {
+ $file =~ s/([\\'])/\\$1/g;
+ $file = "'$file'";
+ }
+ print M $file, "\t" x $tabs, $text, "\n";
+ }
+ close M;
+}
+
+# Geez, shouldn't this use File::Spec or File::Basename or something?
+# Why so careful about dependencies?
+sub clean_up_filename {
+ my $filename = shift;
+ $filename =~ s|^\./||;
+ $filename =~ s/^:([^:]+)$/$1/ if $Is_MacOS;
+ return $filename;
+}
+
+
+=item manifind
+
+ my $found = manifind();
+
+returns a hash reference. The keys of the hash are the files found
+below the current directory.
+
+=cut
+
+sub manifind {
+ my $p = shift || {};
+ my $found = {};
+
+ my $wanted = sub {
+ my $name = clean_up_filename($File::Find::name);
+ warn "Debug: diskfile $name\n" if $Debug;
+ return if -d $_;
+
+ if( $Is_VMS_lc ) {
+ $name =~ s#(.*)\.$#\L$1#;
+ $name = uc($name) if $name =~ /^MANIFEST(\.SKIP)?$/i;
+ }
+ $found->{$name} = "";
+ };
+
+ # We have to use "$File::Find::dir/$_" in preprocess, because
+ # $File::Find::name is unavailable.
+ # Also, it's okay to use / here, because MANIFEST files use Unix-style
+ # paths.
+ find({wanted => $wanted},
+ $Is_MacOS ? ":" : ".");
+
+ return $found;
+}
+
+
+=item manicheck
+
+ my @missing_files = manicheck();
+
+checks if all the files within a C<MANIFEST> in the current directory
+really do exist. If C<MANIFEST> and the tree below the current
+directory are in sync it silently returns an empty list.
+Otherwise it returns a list of files which are listed in the
+C<MANIFEST> but missing from the directory, and by default also
+outputs these names to STDERR.
+
+=cut
+
+sub manicheck {
+ return _check_files();
+}
+
+
+=item filecheck
+
+ my @extra_files = filecheck();
+
+finds files below the current directory that are not mentioned in the
+C<MANIFEST> file. An optional file C<MANIFEST.SKIP> will be
+consulted. Any file matching a regular expression in such a file will
+not be reported as missing in the C<MANIFEST> file. The list of any
+extraneous files found is returned, and by default also reported to
+STDERR.
+
+=cut
+
+sub filecheck {
+ return _check_manifest();
+}
+
+
+=item fullcheck
+
+ my($missing, $extra) = fullcheck();
+
+does both a manicheck() and a filecheck(), returning then as two array
+refs.
+
+=cut
+
+sub fullcheck {
+ return [_check_files()], [_check_manifest()];
+}
+
+
+=item skipcheck
+
+ my @skipped = skipcheck();
+
+lists all the files that are skipped due to your C<MANIFEST.SKIP>
+file.
+
+=cut
+
+sub skipcheck {
+ my($p) = @_;
+ my $found = manifind();
+ my $matches = maniskip();
+
+ my @skipped = ();
+ foreach my $file (_sort keys %$found){
+ if (&$matches($file)){
+ warn "Skipping $file\n" unless $Quiet;
+ push @skipped, $file;
+ next;
+ }
+ }
+
+ return @skipped;
+}
+
+
+sub _check_files {
+ my $p = shift;
+ my $dosnames=(defined(&Dos::UseLFN) && Dos::UseLFN()==0);
+ my $read = maniread() || {};
+ my $found = manifind($p);
+
+ my(@missfile) = ();
+ foreach my $file (_sort keys %$read){
+ warn "Debug: manicheck checking from $MANIFEST $file\n" if $Debug;
+ if ($dosnames){
+ $file = lc $file;
+ $file =~ s=(\.(\w|-)+)=substr ($1,0,4)=ge;
+ $file =~ s=((\w|-)+)=substr ($1,0,8)=ge;
+ }
+ unless ( exists $found->{$file} ) {
+ warn "No such file: $file\n" unless $Quiet;
+ push @missfile, $file;
+ }
+ }
+
+ return @missfile;
+}
+
+
+sub _check_manifest {
+ my($p) = @_;
+ my $read = maniread() || {};
+ my $found = manifind($p);
+ my $skip = maniskip();
+
+ my @missentry = ();
+ foreach my $file (_sort keys %$found){
+ next if $skip->($file);
+ warn "Debug: manicheck checking from disk $file\n" if $Debug;
+ unless ( exists $read->{$file} ) {
+ my $canon = $Is_MacOS ? "\t" . _unmacify($file) : '';
+ warn "Not in $MANIFEST: $file$canon\n" unless $Quiet;
+ push @missentry, $file;
+ }
+ }
+
+ return @missentry;
+}
+
+
+=item maniread
+
+ my $manifest = maniread();
+ my $manifest = maniread($manifest_file);
+
+reads a named C<MANIFEST> file (defaults to C<MANIFEST> in the current
+directory) and returns a HASH reference with files being the keys and
+comments being the values of the HASH. Blank lines and lines which
+start with C<#> in the C<MANIFEST> file are discarded.
+
+=cut
+
+sub maniread {
+ my ($mfile) = @_;
+ $mfile ||= $MANIFEST;
+ my $read = {};
+ local *M;
+ unless (open M, "< $mfile"){
+ warn "Problem opening $mfile: $!";
+ return $read;
+ }
+ local $_;
+ while (<M>){
+ chomp;
+ next if /^\s*#/;
+
+ my($file, $comment);
+
+ # filename may contain spaces if enclosed in ''
+ # (in which case, \\ and \' are escapes)
+ if (($file, $comment) = /^'(\\[\\']|.+)+'\s*(.*)/) {
+ $file =~ s/\\([\\'])/$1/g;
+ }
+ else {
+ ($file, $comment) = /^(\S+)\s*(.*)/;
+ }
+ next unless $file;
+
+ if ($Is_MacOS) {
+ $file = _macify($file);
+ $file =~ s/\\([0-3][0-7][0-7])/sprintf("%c", oct($1))/ge;
+ }
+ elsif ($Is_VMS_mode) {
+ require File::Basename;
+ my($base,$dir) = File::Basename::fileparse($file);
+ # Resolve illegal file specifications in the same way as tar
+ if ($Is_VMS_nodot) {
+ $dir =~ tr/./_/;
+ my(@pieces) = split(/\./,$base);
+ if (@pieces > 2)
+ { $base = shift(@pieces) . '.' . join('_',@pieces); }
+ my $okfile = "$dir$base";
+ warn "Debug: Illegal name $file changed to $okfile\n" if $Debug;
+ $file = $okfile;
+ }
+ $file = lc($file)
+ unless $Is_VMS_lc &&($file =~ /^MANIFEST(\.SKIP)?$/);
+ }
+
+ $read->{$file} = $comment;
+ }
+ close M;
+ $read;
+}
+
+=item maniskip
+
+ my $skipchk = maniskip();
+ my $skipchk = maniskip($manifest_skip_file);
+
+ if ($skipchk->($file)) { .. }
+
+reads a named C<MANIFEST.SKIP> file (defaults to C<MANIFEST.SKIP> in
+the current directory) and returns a CODE reference that tests whether
+a given filename should be skipped.
+
+=cut
+
+# returns an anonymous sub that decides if an argument matches
+sub maniskip {
+ my @skip ;
+ my $mfile = shift || "$MANIFEST.SKIP";
+ _check_mskip_directives($mfile) if -f $mfile;
+ local(*M, $_);
+ open M, "< $mfile" or open M, "< $DEFAULT_MSKIP" or return sub {0};
+ while (<M>){
+ chomp;
+ s/\r//;
+ $_ =~ qr{^\s*(?:(?:'([^\\']*(?:\\.[^\\']*)*)')|([^#\s]\S*))?(?:(?:\s*)|(?:\s+(.*?)\s*))$};
+ #my $comment = $3;
+ my $filename = $2;
+ if ( defined($1) ) {
+ $filename = $1;
+ $filename =~ s/\\(['\\])/$1/g;
+ }
+ next if (not defined($filename) or not $filename);
+ push @skip, _macify($filename);
+ }
+ close M;
+ return sub {0} unless (scalar @skip > 0);
+
+ my $opts = $Is_VMS_mode ? '(?i)' : '';
+
+ # Make sure each entry is isolated in its own parentheses, in case
+ # any of them contain alternations
+ my $regex = join '|', map "(?:$_)", @skip;
+
+ return sub { $_[0] =~ qr{$opts$regex} };
+}
+
+# checks for the special directives
+# #!include_default
+# #!include /path/to/some/manifest.skip
+# in a custom MANIFEST.SKIP for, for including
+# the content of, respectively, the default MANIFEST.SKIP
+# and an external manifest.skip file
+sub _check_mskip_directives {
+ my $mfile = shift;
+ local (*M, $_);
+ my @lines = ();
+ my $flag = 0;
+ unless (open M, "< $mfile") {
+ warn "Problem opening $mfile: $!";
+ return;
+ }
+ while (<M>) {
+ if (/^#!include_default\s*$/) {
+ if (my @default = _include_mskip_file()) {
+ push @lines, @default;
+ warn "Debug: Including default MANIFEST.SKIP\n" if $Debug;
+ $flag++;
+ }
+ next;
+ }
+ if (/^#!include\s+(.*)\s*$/) {
+ my $external_file = $1;
+ if (my @external = _include_mskip_file($external_file)) {
+ push @lines, @external;
+ warn "Debug: Including external $external_file\n" if $Debug;
+ $flag++;
+ }
+ next;
+ }
+ push @lines, $_;
+ }
+ close M;
+ return unless $flag;
+ my $bakbase = $mfile;
+ $bakbase =~ s/\./_/g if $Is_VMS_nodot; # avoid double dots
+ rename $mfile, "$bakbase.bak";
+ warn "Debug: Saving original $mfile as $bakbase.bak\n" if $Debug;
+ unless (open M, "> $mfile") {
+ warn "Problem opening $mfile: $!";
+ return;
+ }
+ print M $_ for (@lines);
+ close M;
+ return;
+}
+
+# returns an array containing the lines of an external
+# manifest.skip file, if given, or $DEFAULT_MSKIP
+sub _include_mskip_file {
+ my $mskip = shift || $DEFAULT_MSKIP;
+ unless (-f $mskip) {
+ warn qq{Included file "$mskip" not found - skipping};
+ return;
+ }
+ local (*M, $_);
+ unless (open M, "< $mskip") {
+ warn "Problem opening $mskip: $!";
+ return;
+ }
+ my @lines = ();
+ push @lines, "\n#!start included $mskip\n";
+ push @lines, $_ while <M>;
+ close M;
+ push @lines, "#!end included $mskip\n\n";
+ return @lines;
+}
+
+=item manicopy
+
+ manicopy(\%src, $dest_dir);
+ manicopy(\%src, $dest_dir, $how);
+
+Copies the files that are the keys in %src to the $dest_dir. %src is
+typically returned by the maniread() function.
+
+ manicopy( maniread(), $dest_dir );
+
+This function is useful for producing a directory tree identical to the
+intended distribution tree.
+
+$how can be used to specify a different methods of "copying". Valid
+values are C<cp>, which actually copies the files, C<ln> which creates
+hard links, and C<best> which mostly links the files but copies any
+symbolic link to make a tree without any symbolic link. C<cp> is the
+default.
+
+=cut
+
+sub manicopy {
+ my($read,$target,$how)=@_;
+ croak "manicopy() called without target argument" unless defined $target;
+ $how ||= 'cp';
+ require File::Path;
+ require File::Basename;
+
+ $target = VMS::Filespec::unixify($target) if $Is_VMS_mode;
+ File::Path::mkpath([ $target ],! $Quiet,$Is_VMS ? undef : 0755);
+ foreach my $file (keys %$read){
+ if ($Is_MacOS) {
+ if ($file =~ m!:!) {
+ my $dir = _maccat($target, $file);
+ $dir =~ s/[^:]+$//;
+ File::Path::mkpath($dir,1,0755);
+ }
+ cp_if_diff($file, _maccat($target, $file), $how);
+ } else {
+ $file = VMS::Filespec::unixify($file) if $Is_VMS_mode;
+ if ($file =~ m!/!) { # Ilya, that hurts, I fear, or maybe not?
+ my $dir = File::Basename::dirname($file);
+ $dir = VMS::Filespec::unixify($dir) if $Is_VMS_mode;
+ File::Path::mkpath(["$target/$dir"],! $Quiet,$Is_VMS ? undef : 0755);
+ }
+ cp_if_diff($file, "$target/$file", $how);
+ }
+ }
+}
+
+sub cp_if_diff {
+ my($from, $to, $how)=@_;
+ if (! -f $from) {
+ carp "$from not found";
+ return;
+ }
+ my($diff) = 0;
+ local(*F,*T);
+ open(F,"< $from\0") or die "Can't read $from: $!\n";
+ if (open(T,"< $to\0")) {
+ local $_;
+ while (<F>) { $diff++,last if $_ ne <T>; }
+ $diff++ unless eof(T);
+ close T;
+ }
+ else { $diff++; }
+ close F;
+ if ($diff) {
+ if (-e $to) {
+ unlink($to) or confess "unlink $to: $!";
+ }
+ STRICT_SWITCH: {
+ best($from,$to), last STRICT_SWITCH if $how eq 'best';
+ cp($from,$to), last STRICT_SWITCH if $how eq 'cp';
+ ln($from,$to), last STRICT_SWITCH if $how eq 'ln';
+ croak("ExtUtils::Manifest::cp_if_diff " .
+ "called with illegal how argument [$how]. " .
+ "Legal values are 'best', 'cp', and 'ln'.");
+ }
+ }
+}
+
+sub cp {
+ my ($srcFile, $dstFile) = @_;
+ my ($access,$mod) = (stat $srcFile)[8,9];
+
+ copy($srcFile,$dstFile);
+ utime $access, $mod + ($Is_VMS ? 1 : 0), $dstFile;
+ _manicopy_chmod($srcFile, $dstFile);
+}
+
+
+sub ln {
+ my ($srcFile, $dstFile) = @_;
+ # Fix-me - VMS can support links.
+ return &cp if $Is_VMS or ($^O eq 'MSWin32' and Win32::IsWin95());
+ link($srcFile, $dstFile);
+
+ unless( _manicopy_chmod($srcFile, $dstFile) ) {
+ unlink $dstFile;
+ return;
+ }
+ 1;
+}
+
+# 1) Strip off all group and world permissions.
+# 2) Let everyone read it.
+# 3) If the owner can execute it, everyone can.
+sub _manicopy_chmod {
+ my($srcFile, $dstFile) = @_;
+
+ my $perm = 0444 | (stat $srcFile)[2] & 0700;
+ chmod( $perm | ( $perm & 0100 ? 0111 : 0 ), $dstFile );
+}
+
+# Files that are often modified in the distdir. Don't hard link them.
+my @Exceptions = qw(MANIFEST META.yml SIGNATURE);
+sub best {
+ my ($srcFile, $dstFile) = @_;
+
+ my $is_exception = grep $srcFile =~ /$_/, @Exceptions;
+ if ($is_exception or !$Config{d_link} or -l $srcFile) {
+ cp($srcFile, $dstFile);
+ } else {
+ ln($srcFile, $dstFile) or cp($srcFile, $dstFile);
+ }
+}
+
+sub _macify {
+ my($file) = @_;
+
+ return $file unless $Is_MacOS;
+
+ $file =~ s|^\./||;
+ if ($file =~ m|/|) {
+ $file =~ s|/+|:|g;
+ $file = ":$file";
+ }
+
+ $file;
+}
+
+sub _maccat {
+ my($f1, $f2) = @_;
+
+ return "$f1/$f2" unless $Is_MacOS;
+
+ $f1 .= ":$f2";
+ $f1 =~ s/([^:]:):/$1/g;
+ return $f1;
+}
+
+sub _unmacify {
+ my($file) = @_;
+
+ return $file unless $Is_MacOS;
+
+ $file =~ s|^:||;
+ $file =~ s|([/ \n])|sprintf("\\%03o", unpack("c", $1))|ge;
+ $file =~ y|:|/|;
+
+ $file;
+}
+
+
+=item maniadd
+
+ maniadd({ $file => $comment, ...});
+
+Adds an entry to an existing F<MANIFEST> unless its already there.
+
+$file will be normalized (ie. Unixified). B<UNIMPLEMENTED>
+
+=cut
+
+sub maniadd {
+ my($additions) = shift;
+
+ _normalize($additions);
+ _fix_manifest($MANIFEST);
+
+ my $manifest = maniread();
+ my @needed = grep { !exists $manifest->{$_} } keys %$additions;
+ return 1 unless @needed;
+
+ open(MANIFEST, ">>$MANIFEST") or
+ die "maniadd() could not open $MANIFEST: $!";
+
+ foreach my $file (_sort @needed) {
+ my $comment = $additions->{$file} || '';
+ if ($file =~ /\s/) {
+ $file =~ s/([\\'])/\\$1/g;
+ $file = "'$file'";
+ }
+ printf MANIFEST "%-40s %s\n", $file, $comment;
+ }
+ close MANIFEST or die "Error closing $MANIFEST: $!";
+
+ return 1;
+}
+
+
+# Sometimes MANIFESTs are missing a trailing newline. Fix this.
+sub _fix_manifest {
+ my $manifest_file = shift;
+
+ open MANIFEST, $MANIFEST or die "Could not open $MANIFEST: $!";
+
+ # Yes, we should be using seek(), but I'd like to avoid loading POSIX
+ # to get SEEK_*
+ my @manifest = <MANIFEST>;
+ close MANIFEST;
+
+ unless( $manifest[-1] =~ /\n\z/ ) {
+ open MANIFEST, ">>$MANIFEST" or die "Could not open $MANIFEST: $!";
+ print MANIFEST "\n";
+ close MANIFEST;
+ }
+}
+
+
+# UNIMPLEMENTED
+sub _normalize {
+ return;
+}
+
+
+=back
+
+=head2 MANIFEST
+
+A list of files in the distribution, one file per line. The MANIFEST
+always uses Unix filepath conventions even if you're not on Unix. This
+means F<foo/bar> style not F<foo\bar>.
+
+Anything between white space and an end of line within a C<MANIFEST>
+file is considered to be a comment. Any line beginning with # is also
+a comment. Beginning with ExtUtils::Manifest 1.52, a filename may
+contain whitespace characters if it is enclosed in single quotes; single
+quotes or backslashes in that filename must be backslash-escaped.
+
+ # this a comment
+ some/file
+ some/other/file comment about some/file
+ 'some/third file' comment
+
+
+=head2 MANIFEST.SKIP
+
+The file MANIFEST.SKIP may contain regular expressions of files that
+should be ignored by mkmanifest() and filecheck(). The regular
+expressions should appear one on each line. Blank lines and lines
+which start with C<#> are skipped. Use C<\#> if you need a regular
+expression to start with a C<#>.
+
+For example:
+
+ # Version control files and dirs.
+ \bRCS\b
+ \bCVS\b
+ ,v$
+ \B\.svn\b
+
+ # Makemaker generated files and dirs.
+ ^MANIFEST\.
+ ^Makefile$
+ ^blib/
+ ^MakeMaker-\d
+
+ # Temp, old and emacs backup files.
+ ~$
+ \.old$
+ ^#.*#$
+ ^\.#
+
+If no MANIFEST.SKIP file is found, a default set of skips will be
+used, similar to the example above. If you want nothing skipped,
+simply make an empty MANIFEST.SKIP file.
+
+In one's own MANIFEST.SKIP file, certain directives
+can be used to include the contents of other MANIFEST.SKIP
+files. At present two such directives are recognized.
+
+=over 4
+
+=item #!include_default
+
+This inserts the contents of the default MANIFEST.SKIP file
+
+=item #!include /Path/to/another/manifest.skip
+
+This inserts the contents of the specified external file
+
+=back
+
+The included contents will be inserted into the MANIFEST.SKIP
+file in between I<#!start included /path/to/manifest.skip>
+and I<#!end included /path/to/manifest.skip> markers.
+The original MANIFEST.SKIP is saved as MANIFEST.SKIP.bak.
+
+=head2 EXPORT_OK
+
+C<&mkmanifest>, C<&manicheck>, C<&filecheck>, C<&fullcheck>,
+C<&maniread>, and C<&manicopy> are exportable.
+
+=head2 GLOBAL VARIABLES
+
+C<$ExtUtils::Manifest::MANIFEST> defaults to C<MANIFEST>. Changing it
+results in both a different C<MANIFEST> and a different
+C<MANIFEST.SKIP> file. This is useful if you want to maintain
+different distributions for different audiences (say a user version
+and a developer version including RCS).
+
+C<$ExtUtils::Manifest::Quiet> defaults to 0. If set to a true value,
+all functions act silently.
+
+C<$ExtUtils::Manifest::Debug> defaults to 0. If set to a true value,
+or if PERL_MM_MANIFEST_DEBUG is true, debugging output will be
+produced.
+
+=head1 DIAGNOSTICS
+
+All diagnostic output is sent to C<STDERR>.
+
+=over 4
+
+=item C<Not in MANIFEST:> I<file>
+
+is reported if a file is found which is not in C<MANIFEST>.
+
+=item C<Skipping> I<file>
+
+is reported if a file is skipped due to an entry in C<MANIFEST.SKIP>.
+
+=item C<No such file:> I<file>
+
+is reported if a file mentioned in a C<MANIFEST> file does not
+exist.
+
+=item C<MANIFEST:> I<$!>
+
+is reported if C<MANIFEST> could not be opened.
+
+=item C<Added to MANIFEST:> I<file>
+
+is reported by mkmanifest() if $Verbose is set and a file is added
+to MANIFEST. $Verbose is set to 1 by default.
+
+=back
+
+=head1 ENVIRONMENT
+
+=over 4
+
+=item B<PERL_MM_MANIFEST_DEBUG>
+
+Turns on debugging
+
+=back
+
+=head1 SEE ALSO
+
+L<ExtUtils::MakeMaker> which has handy targets for most of the functionality.
+
+=head1 AUTHOR
+
+Andreas Koenig C<andreas.koenig@anima.de>
+
+Maintained by Michael G Schwern C<schwern@pobox.com> within the
+ExtUtils-MakeMaker package and, as a separate CPAN package, by
+Randy Kobes C<r.kobes@uwinnipeg.ca>.
+
+=cut
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/Miniperl.pm b/Master/tlpkg/tlperl/lib/ExtUtils/Miniperl.pm
new file mode 100644
index 00000000000..493cb347e44
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/Miniperl.pm
@@ -0,0 +1,280 @@
+# This File keeps the contents of miniperlmain.c.
+#
+# It was generated automatically by minimod.PL from the contents
+# of miniperlmain.c. Don't edit this file!
+#
+# ANY CHANGES MADE HERE WILL BE LOST!
+#
+
+
+package ExtUtils::Miniperl;
+require Exporter;
+@ISA = qw(Exporter);
+@EXPORT = qw(&writemain);
+
+$head= <<'EOF!HEAD';
+/* miniperlmain.c
+ *
+ * Copyright (C) 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003,
+ * 2004, 2005, 2006, 2007, by Larry Wall and others
+ *
+ * You may distribute under the terms of either the GNU General Public
+ * License or the Artistic License, as specified in the README file.
+ *
+ */
+
+/*
+ * The Road goes ever on and on
+ * Down from the door where it began.
+ *
+ * [Bilbo on p.35 of _The Lord of the Rings_, I/i: "A Long-Expected Party"]
+ * [Frodo on p.73 of _The Lord of the Rings_, I/iii: "Three Is Company"]
+ */
+
+/* This file contains the main() function for the perl interpreter.
+ * Note that miniperlmain.c contains main() for the 'miniperl' binary,
+ * while perlmain.c contains main() for the 'perl' binary.
+ *
+ * Miniperl is like perl except that it does not support dynamic loading,
+ * and in fact is used to build the dynamic modules needed for the 'real'
+ * perl executable.
+ */
+
+#ifdef OEMVS
+#ifdef MYMALLOC
+/* sbrk is limited to first heap segment so make it big */
+#pragma runopts(HEAP(8M,500K,ANYWHERE,KEEP,8K,4K) STACK(,,ANY,) ALL31(ON))
+#else
+#pragma runopts(HEAP(2M,500K,ANYWHERE,KEEP,8K,4K) STACK(,,ANY,) ALL31(ON))
+#endif
+#endif
+
+
+#include "EXTERN.h"
+#define PERL_IN_MINIPERLMAIN_C
+#include "perl.h"
+#include "XSUB.h"
+
+static void xs_init (pTHX);
+static PerlInterpreter *my_perl;
+
+#if defined (atarist)
+/* The Atari operating system doesn't have a dynamic stack. The
+ stack size is determined from this value. */
+long _stksize = 64 * 1024;
+#endif
+
+#if defined(PERL_GLOBAL_STRUCT_PRIVATE)
+/* The static struct perl_vars* may seem counterproductive since the
+ * whole idea PERL_GLOBAL_STRUCT_PRIVATE was to avoid statics, but note
+ * that this static is not in the shared perl library, the globals PL_Vars
+ * and PL_VarsPtr will stay away. */
+static struct perl_vars* my_plvarsp;
+struct perl_vars* Perl_GetVarsPrivate(void) { return my_plvarsp; }
+#endif
+
+#ifdef NO_ENV_ARRAY_IN_MAIN
+extern char **environ;
+int
+main(int argc, char **argv)
+#else
+int
+main(int argc, char **argv, char **env)
+#endif
+{
+ dVAR;
+ int exitstatus, i;
+#ifdef PERL_GLOBAL_STRUCT
+ struct perl_vars *plvarsp = init_global_struct();
+# ifdef PERL_GLOBAL_STRUCT_PRIVATE
+ my_vars = my_plvarsp = plvarsp;
+# endif
+#endif /* PERL_GLOBAL_STRUCT */
+ (void)env;
+#ifndef PERL_USE_SAFE_PUTENV
+ PL_use_safe_putenv = 0;
+#endif /* PERL_USE_SAFE_PUTENV */
+
+ /* if user wants control of gprof profiling off by default */
+ /* noop unless Configure is given -Accflags=-DPERL_GPROF_CONTROL */
+ PERL_GPROF_MONCONTROL(0);
+
+#ifdef NO_ENV_ARRAY_IN_MAIN
+ PERL_SYS_INIT3(&argc,&argv,&environ);
+#else
+ PERL_SYS_INIT3(&argc,&argv,&env);
+#endif
+
+#if defined(USE_ITHREADS)
+ /* XXX Ideally, this should really be happening in perl_alloc() or
+ * perl_construct() to keep libperl.a transparently fork()-safe.
+ * It is currently done here only because Apache/mod_perl have
+ * problems due to lack of a call to cancel pthread_atfork()
+ * handlers when shared objects that contain the handlers may
+ * be dlclose()d. This forces applications that embed perl to
+ * call PTHREAD_ATFORK() explicitly, but if and only if it hasn't
+ * been called at least once before in the current process.
+ * --GSAR 2001-07-20 */
+ PTHREAD_ATFORK(Perl_atfork_lock,
+ Perl_atfork_unlock,
+ Perl_atfork_unlock);
+#endif
+
+ if (!PL_do_undump) {
+ my_perl = perl_alloc();
+ if (!my_perl)
+ exit(1);
+ perl_construct(my_perl);
+ PL_perl_destruct_level = 0;
+ }
+ PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
+ exitstatus = perl_parse(my_perl, xs_init, argc, argv, (char **)NULL);
+ if (!exitstatus)
+ perl_run(my_perl);
+
+ /* Unregister our signal handler before destroying my_perl */
+ for (i = 0; PL_sig_name[i]; i++) {
+ if (rsignal_state(PL_sig_num[i]) == (Sighandler_t) PL_csighandlerp) {
+ rsignal(PL_sig_num[i], (Sighandler_t) SIG_DFL);
+ }
+ }
+
+ exitstatus = perl_destruct(my_perl);
+
+ perl_free(my_perl);
+
+#if defined(USE_ENVIRON_ARRAY) && defined(PERL_TRACK_MEMPOOL) && !defined(NO_ENV_ARRAY_IN_MAIN)
+ /*
+ * The old environment may have been freed by perl_free()
+ * when PERL_TRACK_MEMPOOL is defined, but without having
+ * been restored by perl_destruct() before (this is only
+ * done if destruct_level > 0).
+ *
+ * It is important to have a valid environment for atexit()
+ * routines that are eventually called.
+ */
+ environ = env;
+#endif
+
+#ifdef PERL_GLOBAL_STRUCT
+ free_global_struct(plvarsp);
+#endif /* PERL_GLOBAL_STRUCT */
+
+ PERL_SYS_TERM();
+
+ exit(exitstatus);
+ return exitstatus;
+}
+
+/* Register any extra external extensions */
+
+EOF!HEAD
+$tail=<<'EOF!TAIL';
+
+static void
+xs_init(pTHX)
+{
+ PERL_UNUSED_CONTEXT;
+}
+
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ *
+ * ex: set ts=8 sts=4 sw=4 noet:
+ */
+EOF!TAIL
+
+sub writemain{
+ my(@exts) = @_;
+
+ my($pname);
+ my($dl) = canon('/','DynaLoader');
+ print $head;
+
+ foreach $_ (@exts){
+ my($pname) = canon('/', $_);
+ my($mname, $cname);
+ ($mname = $pname) =~ s!/!::!g;
+ ($cname = $pname) =~ s!/!__!g;
+ print "EXTERN_C void boot_${cname} (pTHX_ CV* cv);\n";
+ }
+
+ my ($tail1,$tail2,$tail3) = ( $tail =~ /\A(.*{\s*\n)(.*\n)(\s*\}.*)\Z/s );
+
+ print $tail1;
+ print "\tconst char file[] = __FILE__;\n";
+ print "\tdXSUB_SYS;\n" if $] > 5.002;
+ print $tail2;
+
+ foreach $_ (@exts){
+ my($pname) = canon('/', $_);
+ my($mname, $cname, $ccode);
+ ($mname = $pname) =~ s!/!::!g;
+ ($cname = $pname) =~ s!/!__!g;
+ print "\t{\n";
+ if ($pname eq $dl){
+ # Must NOT install 'DynaLoader::boot_DynaLoader' as 'bootstrap'!
+ # boot_DynaLoader is called directly in DynaLoader.pm
+ $ccode = "\t/* DynaLoader is a special case */\n
+\tnewXS(\"${mname}::boot_${cname}\", boot_${cname}, file);\n";
+ print $ccode unless $SEEN{$ccode}++;
+ } else {
+ $ccode = "\tnewXS(\"${mname}::bootstrap\", boot_${cname}, file);\n";
+ print $ccode unless $SEEN{$ccode}++;
+ }
+ print "\t}\n";
+ }
+ print $tail3;
+}
+
+sub canon{
+ my($as, @ext) = @_;
+ foreach(@ext){
+ # might be X::Y or lib/auto/X/Y/Y.a
+ next if s!::!/!g;
+ s:^(lib|ext)/(auto/)?::;
+ s:/\w+\.\w+$::;
+ }
+ grep(s:/:$as:, @ext) if ($as ne '/');
+ @ext;
+}
+
+1;
+__END__
+
+=head1 NAME
+
+ExtUtils::Miniperl, writemain - write the C code for perlmain.c
+
+=head1 SYNOPSIS
+
+C<use ExtUtils::Miniperl;>
+
+C<writemain(@directories);>
+
+=head1 DESCRIPTION
+
+This whole module is written when perl itself is built from a script
+called minimod.PL. In case you want to patch it, please patch
+minimod.PL in the perl distribution instead.
+
+writemain() takes an argument list of directories containing archive
+libraries that relate to perl modules and should be linked into a new
+perl binary. It writes to STDOUT a corresponding perlmain.c file that
+is a plain C file containing all the bootstrap code to make the
+modules associated with the libraries available from within perl.
+
+The typical usage is from within a Makefile generated by
+ExtUtils::MakeMaker. So under normal circumstances you won't have to
+deal with this module directly.
+
+=head1 SEE ALSO
+
+L<ExtUtils::MakeMaker>
+
+=cut
+
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/Mkbootstrap.pm b/Master/tlpkg/tlperl/lib/ExtUtils/Mkbootstrap.pm
new file mode 100644
index 00000000000..707466a98dd
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/Mkbootstrap.pm
@@ -0,0 +1,109 @@
+package ExtUtils::Mkbootstrap;
+
+# There's just too much Dynaloader incest here to turn on strict vars.
+use strict 'refs';
+
+our $VERSION = '6.56';
+
+require Exporter;
+our @ISA = ('Exporter');
+our @EXPORT = ('&Mkbootstrap');
+
+use Config;
+
+our $Verbose = 0;
+
+
+sub Mkbootstrap {
+ my($baseext, @bsloadlibs)=@_;
+ @bsloadlibs = grep($_, @bsloadlibs); # strip empty libs
+
+ print STDOUT " bsloadlibs=@bsloadlibs\n" if $Verbose;
+
+ # We need DynaLoader here because we and/or the *_BS file may
+ # call dl_findfile(). We don't say `use' here because when
+ # first building perl extensions the DynaLoader will not have
+ # been built when MakeMaker gets first used.
+ require DynaLoader;
+
+ rename "$baseext.bs", "$baseext.bso"
+ if -s "$baseext.bs";
+
+ if (-f "${baseext}_BS"){
+ $_ = "${baseext}_BS";
+ package DynaLoader; # execute code as if in DynaLoader
+ local($osname, $dlsrc) = (); # avoid warnings
+ ($osname, $dlsrc) = @Config::Config{qw(osname dlsrc)};
+ $bscode = "";
+ unshift @INC, ".";
+ require $_;
+ shift @INC;
+ }
+
+ if ($Config{'dlsrc'} =~ /^dl_dld/){
+ package DynaLoader;
+ push(@dl_resolve_using, dl_findfile('-lc'));
+ }
+
+ my(@all) = (@bsloadlibs, @DynaLoader::dl_resolve_using);
+ my($method) = '';
+ if (@all){
+ open my $bs, ">", "$baseext.bs"
+ or die "Unable to open $baseext.bs: $!";
+ print STDOUT "Writing $baseext.bs\n";
+ print STDOUT " containing: @all" if $Verbose;
+ print $bs "# $baseext DynaLoader bootstrap file for $^O architecture.\n";
+ print $bs "# Do not edit this file, changes will be lost.\n";
+ print $bs "# This file was automatically generated by the\n";
+ print $bs "# Mkbootstrap routine in ExtUtils::Mkbootstrap (v$VERSION).\n";
+ print $bs "\@DynaLoader::dl_resolve_using = ";
+ # If @all contains names in the form -lxxx or -Lxxx then it's asking for
+ # runtime library location so we automatically add a call to dl_findfile()
+ if (" @all" =~ m/ -[lLR]/){
+ print $bs " dl_findfile(qw(\n @all\n ));\n";
+ }else{
+ print $bs " qw(@all);\n";
+ }
+ # write extra code if *_BS says so
+ print $bs $DynaLoader::bscode if $DynaLoader::bscode;
+ print $bs "\n1;\n";
+ close $bs;
+ }
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+ExtUtils::Mkbootstrap - make a bootstrap file for use by DynaLoader
+
+=head1 SYNOPSIS
+
+C<Mkbootstrap>
+
+=head1 DESCRIPTION
+
+Mkbootstrap typically gets called from an extension Makefile.
+
+There is no C<*.bs> file supplied with the extension. Instead, there may
+be a C<*_BS> file which has code for the special cases, like posix for
+berkeley db on the NeXT.
+
+This file will get parsed, and produce a maybe empty
+C<@DynaLoader::dl_resolve_using> array for the current architecture.
+That will be extended by $BSLOADLIBS, which was computed by
+ExtUtils::Liblist::ext(). If this array still is empty, we do nothing,
+else we write a .bs file with an C<@DynaLoader::dl_resolve_using>
+array.
+
+The C<*_BS> file can put some code into the generated C<*.bs> file by
+placing it in C<$bscode>. This is a handy 'escape' mechanism that may
+prove useful in complex situations.
+
+If @DynaLoader::dl_resolve_using contains C<-L*> or C<-l*> entries then
+Mkbootstrap will automatically add a dl_findfile() call to the
+generated C<*.bs> file.
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/Mksymlists.pm b/Master/tlpkg/tlperl/lib/ExtUtils/Mksymlists.pm
new file mode 100644
index 00000000000..962c67fd57f
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/Mksymlists.pm
@@ -0,0 +1,312 @@
+package ExtUtils::Mksymlists;
+
+use 5.006;
+use strict qw[ subs refs ];
+# no strict 'vars'; # until filehandles are exempted
+
+use Carp;
+use Exporter;
+use Config;
+
+our @ISA = qw(Exporter);
+our @EXPORT = qw(&Mksymlists);
+our $VERSION = '6.56';
+
+sub Mksymlists {
+ my(%spec) = @_;
+ my($osname) = $^O;
+
+ croak("Insufficient information specified to Mksymlists")
+ unless ( $spec{NAME} or
+ ($spec{FILE} and ($spec{DL_FUNCS} or $spec{FUNCLIST})) );
+
+ $spec{DL_VARS} = [] unless $spec{DL_VARS};
+ ($spec{FILE} = $spec{NAME}) =~ s/.*::// unless $spec{FILE};
+ $spec{FUNCLIST} = [] unless $spec{FUNCLIST};
+ $spec{DL_FUNCS} = { $spec{NAME} => [] }
+ unless ( ($spec{DL_FUNCS} and keys %{$spec{DL_FUNCS}}) or
+ @{$spec{FUNCLIST}});
+ if (defined $spec{DL_FUNCS}) {
+ foreach my $package (keys %{$spec{DL_FUNCS}}) {
+ my($packprefix,$bootseen);
+ ($packprefix = $package) =~ s/\W/_/g;
+ foreach my $sym (@{$spec{DL_FUNCS}->{$package}}) {
+ if ($sym =~ /^boot_/) {
+ push(@{$spec{FUNCLIST}},$sym);
+ $bootseen++;
+ }
+ else {
+ push(@{$spec{FUNCLIST}},"XS_${packprefix}_$sym");
+ }
+ }
+ push(@{$spec{FUNCLIST}},"boot_$packprefix") unless $bootseen;
+ }
+ }
+
+# We'll need this if we ever add any OS which uses mod2fname
+# not as pseudo-builtin.
+# require DynaLoader;
+ if (defined &DynaLoader::mod2fname and not $spec{DLBASE}) {
+ $spec{DLBASE} = DynaLoader::mod2fname([ split(/::/,$spec{NAME}) ]);
+ }
+
+ if ($osname eq 'aix') { _write_aix(\%spec); }
+ elsif ($osname eq 'MacOS'){ _write_aix(\%spec) }
+ elsif ($osname eq 'VMS') { _write_vms(\%spec) }
+ elsif ($osname eq 'os2') { _write_os2(\%spec) }
+ elsif ($osname eq 'MSWin32') { _write_win32(\%spec) }
+ else {
+ croak("Don't know how to create linker option file for $osname\n");
+ }
+}
+
+
+sub _write_aix {
+ my($data) = @_;
+
+ rename "$data->{FILE}.exp", "$data->{FILE}.exp_old";
+
+ open( my $exp, ">", "$data->{FILE}.exp")
+ or croak("Can't create $data->{FILE}.exp: $!\n");
+ print $exp join("\n",@{$data->{DL_VARS}}, "\n") if @{$data->{DL_VARS}};
+ print $exp join("\n",@{$data->{FUNCLIST}}, "\n") if @{$data->{FUNCLIST}};
+ close $exp;
+}
+
+
+sub _write_os2 {
+ my($data) = @_;
+ require Config;
+ my $threaded = ($Config::Config{archname} =~ /-thread/ ? " threaded" : "");
+
+ if (not $data->{DLBASE}) {
+ ($data->{DLBASE} = $data->{NAME}) =~ s/.*:://;
+ $data->{DLBASE} = substr($data->{DLBASE},0,7) . '_';
+ }
+ my $distname = $data->{DISTNAME} || $data->{NAME};
+ $distname = "Distribution $distname";
+ my $patchlevel = " pl$Config{perl_patchlevel}" || '';
+ my $comment = sprintf "Perl (v%s%s%s) module %s",
+ $Config::Config{version}, $threaded, $patchlevel, $data->{NAME};
+ chomp $comment;
+ if ($data->{INSTALLDIRS} and $data->{INSTALLDIRS} eq 'perl') {
+ $distname = 'perl5-porters@perl.org';
+ $comment = "Core $comment";
+ }
+ $comment = "$comment (Perl-config: $Config{config_args})";
+ $comment = substr($comment, 0, 200) . "...)" if length $comment > 203;
+ rename "$data->{FILE}.def", "$data->{FILE}_def.old";
+
+ open(my $def, ">", "$data->{FILE}.def")
+ or croak("Can't create $data->{FILE}.def: $!\n");
+ print $def "LIBRARY '$data->{DLBASE}' INITINSTANCE TERMINSTANCE\n";
+ print $def "DESCRIPTION '\@#$distname:$data->{VERSION}#\@ $comment'\n";
+ print $def "CODE LOADONCALL\n";
+ print $def "DATA LOADONCALL NONSHARED MULTIPLE\n";
+ print $def "EXPORTS\n ";
+ print $def join("\n ",@{$data->{DL_VARS}}, "\n") if @{$data->{DL_VARS}};
+ print $def join("\n ",@{$data->{FUNCLIST}}, "\n") if @{$data->{FUNCLIST}};
+ if (%{$data->{IMPORTS}}) {
+ print $def "IMPORTS\n";
+ my ($name, $exp);
+ while (($name, $exp)= each %{$data->{IMPORTS}}) {
+ print $def " $name=$exp\n";
+ }
+ }
+ close $def;
+}
+
+sub _write_win32 {
+ my($data) = @_;
+
+ require Config;
+ if (not $data->{DLBASE}) {
+ ($data->{DLBASE} = $data->{NAME}) =~ s/.*:://;
+ $data->{DLBASE} = substr($data->{DLBASE},0,7) . '_';
+ }
+ rename "$data->{FILE}.def", "$data->{FILE}_def.old";
+
+ open( my $def, ">", "$data->{FILE}.def" )
+ or croak("Can't create $data->{FILE}.def: $!\n");
+ # put library name in quotes (it could be a keyword, like 'Alias')
+ if ($Config::Config{'cc'} !~ /^gcc/i) {
+ print $def "LIBRARY \"$data->{DLBASE}\"\n";
+ }
+ print $def "EXPORTS\n ";
+ my @syms;
+ # Export public symbols both with and without underscores to
+ # ensure compatibility between DLLs from different compilers
+ # NOTE: DynaLoader itself only uses the names without underscores,
+ # so this is only to cover the case when the extension DLL may be
+ # linked to directly from C. GSAR 97-07-10
+ if ($Config::Config{'cc'} =~ /^bcc/i) {
+ for (@{$data->{DL_VARS}}, @{$data->{FUNCLIST}}) {
+ push @syms, "_$_", "$_ = _$_";
+ }
+ }
+ else {
+ for (@{$data->{DL_VARS}}, @{$data->{FUNCLIST}}) {
+ push @syms, "$_", "_$_ = $_";
+ }
+ }
+ print $def join("\n ",@syms, "\n") if @syms;
+ if (%{$data->{IMPORTS}}) {
+ print $def "IMPORTS\n";
+ my ($name, $exp);
+ while (($name, $exp)= each %{$data->{IMPORTS}}) {
+ print $def " $name=$exp\n";
+ }
+ }
+ close $def;
+}
+
+
+sub _write_vms {
+ my($data) = @_;
+
+ require Config; # a reminder for once we do $^O
+ require ExtUtils::XSSymSet;
+
+ my($isvax) = $Config::Config{'archname'} =~ /VAX/i;
+ my($set) = new ExtUtils::XSSymSet;
+
+ rename "$data->{FILE}.opt", "$data->{FILE}.opt_old";
+
+ open(my $opt,">", "$data->{FILE}.opt")
+ or croak("Can't create $data->{FILE}.opt: $!\n");
+
+ # Options file declaring universal symbols
+ # Used when linking shareable image for dynamic extension,
+ # or when linking PerlShr into which we've added this package
+ # as a static extension
+ # We don't do anything to preserve order, so we won't relax
+ # the GSMATCH criteria for a dynamic extension
+
+ print $opt "case_sensitive=yes\n"
+ if $Config::Config{d_vms_case_sensitive_symbols};
+
+ foreach my $sym (@{$data->{FUNCLIST}}) {
+ my $safe = $set->addsym($sym);
+ if ($isvax) { print $opt "UNIVERSAL=$safe\n" }
+ else { print $opt "SYMBOL_VECTOR=($safe=PROCEDURE)\n"; }
+ }
+
+ foreach my $sym (@{$data->{DL_VARS}}) {
+ my $safe = $set->addsym($sym);
+ print $opt "PSECT_ATTR=${sym},PIC,OVR,RD,NOEXE,WRT,NOSHR\n";
+ if ($isvax) { print $opt "UNIVERSAL=$safe\n" }
+ else { print $opt "SYMBOL_VECTOR=($safe=DATA)\n"; }
+ }
+
+ close $opt;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+ExtUtils::Mksymlists - write linker options files for dynamic extension
+
+=head1 SYNOPSIS
+
+ use ExtUtils::Mksymlists;
+ Mksymlists({ NAME => $name ,
+ DL_VARS => [ $var1, $var2, $var3 ],
+ DL_FUNCS => { $pkg1 => [ $func1, $func2 ],
+ $pkg2 => [ $func3 ] });
+
+=head1 DESCRIPTION
+
+C<ExtUtils::Mksymlists> produces files used by the linker under some OSs
+during the creation of shared libraries for dynamic extensions. It is
+normally called from a MakeMaker-generated Makefile when the extension
+is built. The linker option file is generated by calling the function
+C<Mksymlists>, which is exported by default from C<ExtUtils::Mksymlists>.
+It takes one argument, a list of key-value pairs, in which the following
+keys are recognized:
+
+=over 4
+
+=item DLBASE
+
+This item specifies the name by which the linker knows the
+extension, which may be different from the name of the
+extension itself (for instance, some linkers add an '_' to the
+name of the extension). If it is not specified, it is derived
+from the NAME attribute. It is presently used only by OS2 and Win32.
+
+=item DL_FUNCS
+
+This is identical to the DL_FUNCS attribute available via MakeMaker,
+from which it is usually taken. Its value is a reference to an
+associative array, in which each key is the name of a package, and
+each value is an a reference to an array of function names which
+should be exported by the extension. For instance, one might say
+C<DL_FUNCS =E<gt> { Homer::Iliad =E<gt> [ qw(trojans greeks) ],
+Homer::Odyssey =E<gt> [ qw(travellers family suitors) ] }>. The
+function names should be identical to those in the XSUB code;
+C<Mksymlists> will alter the names written to the linker option
+file to match the changes made by F<xsubpp>. In addition, if
+none of the functions in a list begin with the string B<boot_>,
+C<Mksymlists> will add a bootstrap function for that package,
+just as xsubpp does. (If a B<boot_E<lt>pkgE<gt>> function is
+present in the list, it is passed through unchanged.) If
+DL_FUNCS is not specified, it defaults to the bootstrap
+function for the extension specified in NAME.
+
+=item DL_VARS
+
+This is identical to the DL_VARS attribute available via MakeMaker,
+and, like DL_FUNCS, it is usually specified via MakeMaker. Its
+value is a reference to an array of variable names which should
+be exported by the extension.
+
+=item FILE
+
+This key can be used to specify the name of the linker option file
+(minus the OS-specific extension), if for some reason you do not
+want to use the default value, which is the last word of the NAME
+attribute (I<e.g.> for C<Tk::Canvas>, FILE defaults to C<Canvas>).
+
+=item FUNCLIST
+
+This provides an alternate means to specify function names to be
+exported from the extension. Its value is a reference to an
+array of function names to be exported by the extension. These
+names are passed through unaltered to the linker options file.
+Specifying a value for the FUNCLIST attribute suppresses automatic
+generation of the bootstrap function for the package. To still create
+the bootstrap name you have to specify the package name in the
+DL_FUNCS hash:
+
+ Mksymlists({ NAME => $name ,
+ FUNCLIST => [ $func1, $func2 ],
+ DL_FUNCS => { $pkg => [] } });
+
+
+=item IMPORTS
+
+This attribute is used to specify names to be imported into the
+extension. It is currently only used by OS/2 and Win32.
+
+=item NAME
+
+This gives the name of the extension (I<e.g.> C<Tk::Canvas>) for which
+the linker option file will be produced.
+
+=back
+
+When calling C<Mksymlists>, one should always specify the NAME
+attribute. In most cases, this is all that's necessary. In
+the case of unusual extensions, however, the other attributes
+can be used to provide additional information to the linker.
+
+=head1 AUTHOR
+
+Charles Bailey I<E<lt>bailey@newman.upenn.eduE<gt>>
+
+=head1 REVISION
+
+Last revised 14-Feb-1996, for Perl 5.002.
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/Packlist.pm b/Master/tlpkg/tlperl/lib/ExtUtils/Packlist.pm
new file mode 100644
index 00000000000..b77a556be50
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/Packlist.pm
@@ -0,0 +1,352 @@
+package ExtUtils::Packlist;
+
+use 5.00503;
+use strict;
+use Carp qw();
+use Config;
+use vars qw($VERSION $Relocations);
+$VERSION = '1.44';
+$VERSION = eval $VERSION;
+
+# Used for generating filehandle globs. IO::File might not be available!
+my $fhname = "FH1";
+
+=begin _undocumented
+
+=over
+
+=item mkfh()
+
+Make a filehandle. Same kind of idea as Symbol::gensym().
+
+=cut
+
+sub mkfh()
+{
+no strict;
+my $fh = \*{$fhname++};
+use strict;
+return($fh);
+}
+
+=item __find_relocations
+
+Works out what absolute paths in the configuration have been located at run
+time relative to $^X, and generates a regexp that matches them
+
+=end _undocumented
+
+=back
+
+=cut
+
+sub __find_relocations
+{
+ my %paths;
+ while (my ($raw_key, $raw_val) = each %Config) {
+ my $exp_key = $raw_key . "exp";
+ next unless exists $Config{$exp_key};
+ next unless $raw_val =~ m!\.\.\./!;
+ $paths{$Config{$exp_key}}++;
+ }
+ # Longest prefixes go first in the alternatives
+ my $alternations = join "|", map {quotemeta $_}
+ sort {length $b <=> length $a} keys %paths;
+ qr/^($alternations)/o;
+}
+
+sub new($$)
+{
+my ($class, $packfile) = @_;
+$class = ref($class) || $class;
+my %self;
+tie(%self, $class, $packfile);
+return(bless(\%self, $class));
+}
+
+sub TIEHASH
+{
+my ($class, $packfile) = @_;
+my $self = { packfile => $packfile };
+bless($self, $class);
+$self->read($packfile) if (defined($packfile) && -f $packfile);
+return($self);
+}
+
+sub STORE
+{
+$_[0]->{data}->{$_[1]} = $_[2];
+}
+
+sub FETCH
+{
+return($_[0]->{data}->{$_[1]});
+}
+
+sub FIRSTKEY
+{
+my $reset = scalar(keys(%{$_[0]->{data}}));
+return(each(%{$_[0]->{data}}));
+}
+
+sub NEXTKEY
+{
+return(each(%{$_[0]->{data}}));
+}
+
+sub EXISTS
+{
+return(exists($_[0]->{data}->{$_[1]}));
+}
+
+sub DELETE
+{
+return(delete($_[0]->{data}->{$_[1]}));
+}
+
+sub CLEAR
+{
+%{$_[0]->{data}} = ();
+}
+
+sub DESTROY
+{
+}
+
+sub read($;$)
+{
+my ($self, $packfile) = @_;
+$self = tied(%$self) || $self;
+
+if (defined($packfile)) { $self->{packfile} = $packfile; }
+else { $packfile = $self->{packfile}; }
+Carp::croak("No packlist filename specified") if (! defined($packfile));
+my $fh = mkfh();
+open($fh, "<$packfile") || Carp::croak("Can't open file $packfile: $!");
+$self->{data} = {};
+my ($line);
+while (defined($line = <$fh>))
+ {
+ chomp $line;
+ my ($key, $data) = $line;
+ if ($key =~ /^(.*?)( \w+=.*)$/)
+ {
+ $key = $1;
+ $data = { map { split('=', $_) } split(' ', $2)};
+
+ if ($Config{userelocatableinc} && $data->{relocate_as})
+ {
+ require File::Spec;
+ require Cwd;
+ my ($vol, $dir) = File::Spec->splitpath($packfile);
+ my $newpath = File::Spec->catpath($vol, $dir, $data->{relocate_as});
+ $key = Cwd::realpath($newpath);
+ }
+ }
+ $key =~ s!/\./!/!g; # Some .packlists have spurious '/./' bits in the paths
+ $self->{data}->{$key} = $data;
+ }
+close($fh);
+}
+
+sub write($;$)
+{
+my ($self, $packfile) = @_;
+$self = tied(%$self) || $self;
+if (defined($packfile)) { $self->{packfile} = $packfile; }
+else { $packfile = $self->{packfile}; }
+Carp::croak("No packlist filename specified") if (! defined($packfile));
+my $fh = mkfh();
+open($fh, ">$packfile") || Carp::croak("Can't open file $packfile: $!");
+foreach my $key (sort(keys(%{$self->{data}})))
+ {
+ my $data = $self->{data}->{$key};
+ if ($Config{userelocatableinc}) {
+ $Relocations ||= __find_relocations();
+ if ($packfile =~ $Relocations) {
+ # We are writing into a subdirectory of a run-time relocated
+ # path. Figure out if the this file is also within a subdir.
+ my $prefix = $1;
+ if (File::Spec->no_upwards(File::Spec->abs2rel($key, $prefix)))
+ {
+ # The relocated path is within the found prefix
+ my $packfile_prefix;
+ (undef, $packfile_prefix)
+ = File::Spec->splitpath($packfile);
+
+ my $relocate_as
+ = File::Spec->abs2rel($key, $packfile_prefix);
+
+ if (!ref $data) {
+ $data = {};
+ }
+ $data->{relocate_as} = $relocate_as;
+ }
+ }
+ }
+ print $fh ("$key");
+ if (ref($data))
+ {
+ foreach my $k (sort(keys(%$data)))
+ {
+ print $fh (" $k=$data->{$k}");
+ }
+ }
+ print $fh ("\n");
+ }
+close($fh);
+}
+
+sub validate($;$)
+{
+my ($self, $remove) = @_;
+$self = tied(%$self) || $self;
+my @missing;
+foreach my $key (sort(keys(%{$self->{data}})))
+ {
+ if (! -e $key)
+ {
+ push(@missing, $key);
+ delete($self->{data}{$key}) if ($remove);
+ }
+ }
+return(@missing);
+}
+
+sub packlist_file($)
+{
+my ($self) = @_;
+$self = tied(%$self) || $self;
+return($self->{packfile});
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+ExtUtils::Packlist - manage .packlist files
+
+=head1 SYNOPSIS
+
+ use ExtUtils::Packlist;
+ my ($pl) = ExtUtils::Packlist->new('.packlist');
+ $pl->read('/an/old/.packlist');
+ my @missing_files = $pl->validate();
+ $pl->write('/a/new/.packlist');
+
+ $pl->{'/some/file/name'}++;
+ or
+ $pl->{'/some/other/file/name'} = { type => 'file',
+ from => '/some/file' };
+
+=head1 DESCRIPTION
+
+ExtUtils::Packlist provides a standard way to manage .packlist files.
+Functions are provided to read and write .packlist files. The original
+.packlist format is a simple list of absolute pathnames, one per line. In
+addition, this package supports an extended format, where as well as a filename
+each line may contain a list of attributes in the form of a space separated
+list of key=value pairs. This is used by the installperl script to
+differentiate between files and links, for example.
+
+=head1 USAGE
+
+The hash reference returned by the new() function can be used to examine and
+modify the contents of the .packlist. Items may be added/deleted from the
+.packlist by modifying the hash. If the value associated with a hash key is a
+scalar, the entry written to the .packlist by any subsequent write() will be a
+simple filename. If the value is a hash, the entry written will be the
+filename followed by the key=value pairs from the hash. Reading back the
+.packlist will recreate the original entries.
+
+=head1 FUNCTIONS
+
+=over 4
+
+=item new()
+
+This takes an optional parameter, the name of a .packlist. If the file exists,
+it will be opened and the contents of the file will be read. The new() method
+returns a reference to a hash. This hash holds an entry for each line in the
+.packlist. In the case of old-style .packlists, the value associated with each
+key is undef. In the case of new-style .packlists, the value associated with
+each key is a hash containing the key=value pairs following the filename in the
+.packlist.
+
+=item read()
+
+This takes an optional parameter, the name of the .packlist to be read. If
+no file is specified, the .packlist specified to new() will be read. If the
+.packlist does not exist, Carp::croak will be called.
+
+=item write()
+
+This takes an optional parameter, the name of the .packlist to be written. If
+no file is specified, the .packlist specified to new() will be overwritten.
+
+=item validate()
+
+This checks that every file listed in the .packlist actually exists. If an
+argument which evaluates to true is given, any missing files will be removed
+from the internal hash. The return value is a list of the missing files, which
+will be empty if they all exist.
+
+=item packlist_file()
+
+This returns the name of the associated .packlist file
+
+=back
+
+=head1 EXAMPLE
+
+Here's C<modrm>, a little utility to cleanly remove an installed module.
+
+ #!/usr/local/bin/perl -w
+
+ use strict;
+ use IO::Dir;
+ use ExtUtils::Packlist;
+ use ExtUtils::Installed;
+
+ sub emptydir($) {
+ my ($dir) = @_;
+ my $dh = IO::Dir->new($dir) || return(0);
+ my @count = $dh->read();
+ $dh->close();
+ return(@count == 2 ? 1 : 0);
+ }
+
+ # Find all the installed packages
+ print("Finding all installed modules...\n");
+ my $installed = ExtUtils::Installed->new();
+
+ foreach my $module (grep(!/^Perl$/, $installed->modules())) {
+ my $version = $installed->version($module) || "???";
+ print("Found module $module Version $version\n");
+ print("Do you want to delete $module? [n] ");
+ my $r = <STDIN>; chomp($r);
+ if ($r && $r =~ /^y/i) {
+ # Remove all the files
+ foreach my $file (sort($installed->files($module))) {
+ print("rm $file\n");
+ unlink($file);
+ }
+ my $pf = $installed->packlist($module)->packlist_file();
+ print("rm $pf\n");
+ unlink($pf);
+ foreach my $dir (sort($installed->directory_tree($module))) {
+ if (emptydir($dir)) {
+ print("rmdir $dir\n");
+ rmdir($dir);
+ }
+ }
+ }
+ }
+
+=head1 AUTHOR
+
+Alan Burlison <Alan.Burlison@uk.sun.com>
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/ParseXS.pm b/Master/tlpkg/tlperl/lib/ExtUtils/ParseXS.pm
new file mode 100644
index 00000000000..05c3e690027
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/ParseXS.pm
@@ -0,0 +1,2111 @@
+package ExtUtils::ParseXS;
+
+use 5.006; # We use /??{}/ in regexes
+use Cwd;
+use Config;
+use File::Basename;
+use File::Spec;
+use Symbol;
+
+require Exporter;
+
+@ISA = qw(Exporter);
+@EXPORT_OK = qw(process_file);
+
+# use strict; # One of these days...
+
+my(@XSStack); # Stack of conditionals and INCLUDEs
+my($XSS_work_idx, $cpp_next_tmp);
+
+use vars qw($VERSION);
+$VERSION = '2.21';
+$VERSION = eval $VERSION if $VERSION =~ /_/;
+
+use vars qw(%input_expr %output_expr $ProtoUsed @InitFileCode $FH $proto_re $Overload $errors $Fallback
+ $cplusplus $hiertype $WantPrototypes $WantVersionChk $except $WantLineNumbers
+ $WantOptimize $process_inout $process_argtypes @tm
+ $dir $filename $filepathname %IncludedFiles
+ %type_kind %proto_letter
+ %targetable $BLOCK_re $lastline $lastline_no
+ $Package $Prefix @line @BootCode %args_match %defaults %var_types %arg_list @proto_arg
+ $processing_arg_with_types %argtype_seen @outlist %in_out %lengthof
+ $proto_in_this_xsub $scope_in_this_xsub $interface $prepush_done $interface_macro $interface_macro_set
+ $ProtoThisXSUB $ScopeThisXSUB $xsreturn
+ @line_no $ret_type $func_header $orig_args
+ ); # Add these just to get compilation to happen.
+
+
+sub process_file {
+
+ # Allow for $package->process_file(%hash) in the future
+ my ($pkg, %args) = @_ % 2 ? @_ : (__PACKAGE__, @_);
+
+ $ProtoUsed = exists $args{prototypes};
+
+ # Set defaults.
+ %args = (
+ # 'C++' => 0, # Doesn't seem to *do* anything...
+ hiertype => 0,
+ except => 0,
+ prototypes => 0,
+ versioncheck => 1,
+ linenumbers => 1,
+ optimize => 1,
+ prototypes => 0,
+ inout => 1,
+ argtypes => 1,
+ typemap => [],
+ output => \*STDOUT,
+ csuffix => '.c',
+ %args,
+ );
+
+ # Global Constants
+
+ my ($Is_VMS, $SymSet);
+ if ($^O eq 'VMS') {
+ $Is_VMS = 1;
+ # Establish set of global symbols with max length 28, since xsubpp
+ # will later add the 'XS_' prefix.
+ require ExtUtils::XSSymSet;
+ $SymSet = new ExtUtils::XSSymSet 28;
+ }
+ @XSStack = ({type => 'none'});
+ ($XSS_work_idx, $cpp_next_tmp) = (0, "XSubPPtmpAAAA");
+ @InitFileCode = ();
+ $FH = Symbol::gensym();
+ $proto_re = "[" . quotemeta('\$%&*@;[]') . "]" ;
+ $Overload = 0;
+ $errors = 0;
+ $Fallback = '&PL_sv_undef';
+
+ # Most of the 1500 lines below uses these globals. We'll have to
+ # clean this up sometime, probably. For now, we just pull them out
+ # of %args. -Ken
+
+ $cplusplus = $args{'C++'};
+ $hiertype = $args{hiertype};
+ $WantPrototypes = $args{prototypes};
+ $WantVersionChk = $args{versioncheck};
+ $except = $args{except} ? ' TRY' : '';
+ $WantLineNumbers = $args{linenumbers};
+ $WantOptimize = $args{optimize};
+ $process_inout = $args{inout};
+ $process_argtypes = $args{argtypes};
+ @tm = ref $args{typemap} ? @{$args{typemap}} : ($args{typemap});
+
+ for ($args{filename}) {
+ die "Missing required parameter 'filename'" unless $_;
+ $filepathname = $_;
+ ($dir, $filename) = (dirname($_), basename($_));
+ $filepathname =~ s/\\/\\\\/g;
+ $IncludedFiles{$_}++;
+ }
+
+ # Open the input file
+ open($FH, $args{filename}) or die "cannot open $args{filename}: $!\n";
+
+ # Open the output file if given as a string. If they provide some
+ # other kind of reference, trust them that we can print to it.
+ if (not ref $args{output}) {
+ open my($fh), "> $args{output}" or die "Can't create $args{output}: $!";
+ $args{outfile} = $args{output};
+ $args{output} = $fh;
+ }
+
+ # Really, we shouldn't have to chdir() or select() in the first
+ # place. For now, just save & restore.
+ my $orig_cwd = cwd();
+ my $orig_fh = select();
+
+ chdir($dir);
+ my $pwd = cwd();
+ my $csuffix = $args{csuffix};
+
+ if ($WantLineNumbers) {
+ my $cfile;
+ if ( $args{outfile} ) {
+ $cfile = $args{outfile};
+ } else {
+ $cfile = $args{filename};
+ $cfile =~ s/\.xs$/$csuffix/i or $cfile .= $csuffix;
+ }
+ tie(*PSEUDO_STDOUT, 'ExtUtils::ParseXS::CountLines', $cfile, $args{output});
+ select PSEUDO_STDOUT;
+ } else {
+ select $args{output};
+ }
+
+ foreach my $typemap (@tm) {
+ die "Can't find $typemap in $pwd\n" unless -r $typemap;
+ }
+
+ push @tm, standard_typemap_locations();
+
+ foreach my $typemap (@tm) {
+ next unless -f $typemap ;
+ # skip directories, binary files etc.
+ warn("Warning: ignoring non-text typemap file '$typemap'\n"), next
+ unless -T $typemap ;
+ open(TYPEMAP, $typemap)
+ or warn ("Warning: could not open typemap file '$typemap': $!\n"), next;
+ my $mode = 'Typemap';
+ my $junk = "" ;
+ my $current = \$junk;
+ while (<TYPEMAP>) {
+ next if /^\s* #/;
+ my $line_no = $. + 1;
+ if (/^INPUT\s*$/) {
+ $mode = 'Input'; $current = \$junk; next;
+ }
+ if (/^OUTPUT\s*$/) {
+ $mode = 'Output'; $current = \$junk; next;
+ }
+ if (/^TYPEMAP\s*$/) {
+ $mode = 'Typemap'; $current = \$junk; next;
+ }
+ if ($mode eq 'Typemap') {
+ chomp;
+ my $line = $_ ;
+ TrimWhitespace($_) ;
+ # skip blank lines and comment lines
+ next if /^$/ or /^#/ ;
+ my($type,$kind, $proto) = /^\s*(.*?\S)\s+(\S+)\s*($proto_re*)\s*$/ or
+ warn("Warning: File '$typemap' Line $. '$line' TYPEMAP entry needs 2 or 3 columns\n"), next;
+ $type = TidyType($type) ;
+ $type_kind{$type} = $kind ;
+ # prototype defaults to '$'
+ $proto = "\$" unless $proto ;
+ warn("Warning: File '$typemap' Line $. '$line' Invalid prototype '$proto'\n")
+ unless ValidProtoString($proto) ;
+ $proto_letter{$type} = C_string($proto) ;
+ } elsif (/^\s/) {
+ $$current .= $_;
+ } elsif ($mode eq 'Input') {
+ s/\s+$//;
+ $input_expr{$_} = '';
+ $current = \$input_expr{$_};
+ } else {
+ s/\s+$//;
+ $output_expr{$_} = '';
+ $current = \$output_expr{$_};
+ }
+ }
+ close(TYPEMAP);
+ }
+
+ foreach my $value (values %input_expr) {
+ $value =~ s/;*\s+\z//;
+ # Move C pre-processor instructions to column 1 to be strictly ANSI
+ # conformant. Some pre-processors are fussy about this.
+ $value =~ s/^\s+#/#/mg;
+ }
+ foreach my $value (values %output_expr) {
+ # And again.
+ $value =~ s/^\s+#/#/mg;
+ }
+
+ my ($cast, $size);
+ our $bal = qr[(?:(?>[^()]+)|\((??{ $bal })\))*]; # ()-balanced
+ $cast = qr[(?:\(\s*SV\s*\*\s*\)\s*)?]; # Optional (SV*) cast
+ $size = qr[,\s* (??{ $bal }) ]x; # Third arg (to setpvn)
+
+ foreach my $key (keys %output_expr) {
+ # We can still bootstrap compile 're', because in code re.pm is
+ # available to miniperl, and does not attempt to load the XS code.
+ use re 'eval';
+
+ my ($t, $with_size, $arg, $sarg) =
+ ($output_expr{$key} =~
+ m[^ \s+ sv_set ( [iunp] ) v (n)? # Type, is_setpvn
+ \s* \( \s* $cast \$arg \s* ,
+ \s* ( (??{ $bal }) ) # Set from
+ ( (??{ $size }) )? # Possible sizeof set-from
+ \) \s* ; \s* $
+ ]x);
+ $targetable{$key} = [$t, $with_size, $arg, $sarg] if $t;
+ }
+
+ my $END = "!End!\n\n"; # "impossible" keyword (multiple newline)
+
+ # Match an XS keyword
+ $BLOCK_re= '\s*(' . join('|', qw(
+ REQUIRE BOOT CASE PREINIT INPUT INIT CODE PPCODE OUTPUT
+ CLEANUP ALIAS ATTRS PROTOTYPES PROTOTYPE VERSIONCHECK INCLUDE
+ SCOPE INTERFACE INTERFACE_MACRO C_ARGS POSTCALL OVERLOAD FALLBACK
+ )) . "|$END)\\s*:";
+
+
+ our ($C_group_rex, $C_arg);
+ # Group in C (no support for comments or literals)
+ $C_group_rex = qr/ [({\[]
+ (?: (?> [^()\[\]{}]+ ) | (??{ $C_group_rex }) )*
+ [)}\]] /x ;
+ # Chunk in C without comma at toplevel (no comments):
+ $C_arg = qr/ (?: (?> [^()\[\]{},"']+ )
+ | (??{ $C_group_rex })
+ | " (?: (?> [^\\"]+ )
+ | \\.
+ )* " # String literal
+ | ' (?: (?> [^\\']+ ) | \\. )* ' # Char literal
+ )* /xs;
+
+ # Identify the version of xsubpp used
+ print <<EOM ;
+/*
+ * This file was generated automatically by ExtUtils::ParseXS version $VERSION from the
+ * contents of $filename. Do not edit this file, edit $filename instead.
+ *
+ * ANY CHANGES MADE HERE WILL BE LOST!
+ *
+ */
+
+EOM
+
+
+ print("#line 1 \"$filepathname\"\n")
+ if $WantLineNumbers;
+
+ firstmodule:
+ while (<$FH>) {
+ if (/^=/) {
+ my $podstartline = $.;
+ do {
+ if (/^=cut\s*$/) {
+ # We can't just write out a /* */ comment, as our embedded
+ # POD might itself be in a comment. We can't put a /**/
+ # comment inside #if 0, as the C standard says that the source
+ # file is decomposed into preprocessing characters in the stage
+ # before preprocessing commands are executed.
+ # I don't want to leave the text as barewords, because the spec
+ # isn't clear whether macros are expanded before or after
+ # preprocessing commands are executed, and someone pathological
+ # may just have defined one of the 3 words as a macro that does
+ # something strange. Multiline strings are illegal in C, so
+ # the "" we write must be a string literal. And they aren't
+ # concatenated until 2 steps later, so we are safe.
+ # - Nicholas Clark
+ print("#if 0\n \"Skipped embedded POD.\"\n#endif\n");
+ printf("#line %d \"$filepathname\"\n", $. + 1)
+ if $WantLineNumbers;
+ next firstmodule
+ }
+
+ } while (<$FH>);
+ # At this point $. is at end of file so die won't state the start
+ # of the problem, and as we haven't yet read any lines &death won't
+ # show the correct line in the message either.
+ die ("Error: Unterminated pod in $filename, line $podstartline\n")
+ unless $lastline;
+ }
+ last if ($Package, $Prefix) =
+ /^MODULE\s*=\s*[\w:]+(?:\s+PACKAGE\s*=\s*([\w:]+))?(?:\s+PREFIX\s*=\s*(\S+))?\s*$/;
+
+ print $_;
+ }
+ unless (defined $_) {
+ warn "Didn't find a 'MODULE ... PACKAGE ... PREFIX' line\n";
+ exit 0; # Not a fatal error for the caller process
+ }
+
+ print 'ExtUtils::ParseXS::CountLines'->end_marker, "\n" if $WantLineNumbers;
+
+ print <<"EOF";
+#ifndef PERL_UNUSED_VAR
+# define PERL_UNUSED_VAR(var) if (0) var = var
+#endif
+
+EOF
+
+ print <<"EOF";
+#ifndef PERL_ARGS_ASSERT_CROAK_XS_USAGE
+#define PERL_ARGS_ASSERT_CROAK_XS_USAGE assert(cv); assert(params)
+
+/* prototype to pass -Wmissing-prototypes */
+STATIC void
+S_croak_xs_usage(pTHX_ const CV *const cv, const char *const params);
+
+STATIC void
+S_croak_xs_usage(pTHX_ const CV *const cv, const char *const params)
+{
+ const GV *const gv = CvGV(cv);
+
+ PERL_ARGS_ASSERT_CROAK_XS_USAGE;
+
+ if (gv) {
+ const char *const gvname = GvNAME(gv);
+ const HV *const stash = GvSTASH(gv);
+ const char *const hvname = stash ? HvNAME(stash) : NULL;
+
+ if (hvname)
+ Perl_croak(aTHX_ "Usage: %s::%s(%s)", hvname, gvname, params);
+ else
+ Perl_croak(aTHX_ "Usage: %s(%s)", gvname, params);
+ } else {
+ /* Pants. I don't think that it should be possible to get here. */
+ Perl_croak(aTHX_ "Usage: CODE(0x%"UVxf")(%s)", PTR2UV(cv), params);
+ }
+}
+#undef PERL_ARGS_ASSERT_CROAK_XS_USAGE
+
+#ifdef PERL_IMPLICIT_CONTEXT
+#define croak_xs_usage(a,b) S_croak_xs_usage(aTHX_ a,b)
+#else
+#define croak_xs_usage S_croak_xs_usage
+#endif
+
+#endif
+
+/* NOTE: the prototype of newXSproto() is different in versions of perls,
+ * so we define a portable version of newXSproto()
+ */
+#ifdef newXS_flags
+#define newXSproto_portable(name, c_impl, file, proto) newXS_flags(name, c_impl, file, proto, 0)
+#else
+#define newXSproto_portable(name, c_impl, file, proto) (PL_Sv=(SV*)newXS(name, c_impl, file), sv_setpv(PL_Sv, proto), (CV*)PL_Sv)
+#endif /* !defined(newXS_flags) */
+
+EOF
+
+ print 'ExtUtils::ParseXS::CountLines'->end_marker, "\n" if $WantLineNumbers;
+
+ $lastline = $_;
+ $lastline_no = $.;
+
+ PARAGRAPH:
+ while (fetch_para()) {
+ # Print initial preprocessor statements and blank lines
+ while (@line && $line[0] !~ /^[^\#]/) {
+ my $line = shift(@line);
+ print $line, "\n";
+ next unless $line =~ /^\#\s*((if)(?:n?def)?|elsif|else|endif)\b/;
+ my $statement = $+;
+ if ($statement eq 'if') {
+ $XSS_work_idx = @XSStack;
+ push(@XSStack, {type => 'if'});
+ } else {
+ death ("Error: `$statement' with no matching `if'")
+ if $XSStack[-1]{type} ne 'if';
+ if ($XSStack[-1]{varname}) {
+ push(@InitFileCode, "#endif\n");
+ push(@BootCode, "#endif");
+ }
+
+ my(@fns) = keys %{$XSStack[-1]{functions}};
+ if ($statement ne 'endif') {
+ # Hide the functions defined in other #if branches, and reset.
+ @{$XSStack[-1]{other_functions}}{@fns} = (1) x @fns;
+ @{$XSStack[-1]}{qw(varname functions)} = ('', {});
+ } else {
+ my($tmp) = pop(@XSStack);
+ 0 while (--$XSS_work_idx
+ && $XSStack[$XSS_work_idx]{type} ne 'if');
+ # Keep all new defined functions
+ push(@fns, keys %{$tmp->{other_functions}});
+ @{$XSStack[$XSS_work_idx]{functions}}{@fns} = (1) x @fns;
+ }
+ }
+ }
+
+ next PARAGRAPH unless @line;
+
+ if ($XSS_work_idx && !$XSStack[$XSS_work_idx]{varname}) {
+ # We are inside an #if, but have not yet #defined its xsubpp variable.
+ print "#define $cpp_next_tmp 1\n\n";
+ push(@InitFileCode, "#if $cpp_next_tmp\n");
+ push(@BootCode, "#if $cpp_next_tmp");
+ $XSStack[$XSS_work_idx]{varname} = $cpp_next_tmp++;
+ }
+
+ death ("Code is not inside a function"
+ ." (maybe last function was ended by a blank line "
+ ." followed by a statement on column one?)")
+ if $line[0] =~ /^\s/;
+
+ my ($class, $externC, $static, $ellipsis, $wantRETVAL, $RETVAL_no_return);
+ my (@fake_INPUT_pre); # For length(s) generated variables
+ my (@fake_INPUT);
+
+ # initialize info arrays
+ undef(%args_match);
+ undef(%var_types);
+ undef(%defaults);
+ undef(%arg_list) ;
+ undef(@proto_arg) ;
+ undef($processing_arg_with_types) ;
+ undef(%argtype_seen) ;
+ undef(@outlist) ;
+ undef(%in_out) ;
+ undef(%lengthof) ;
+ undef($proto_in_this_xsub) ;
+ undef($scope_in_this_xsub) ;
+ undef($interface);
+ undef($prepush_done);
+ $interface_macro = 'XSINTERFACE_FUNC' ;
+ $interface_macro_set = 'XSINTERFACE_FUNC_SET' ;
+ $ProtoThisXSUB = $WantPrototypes ;
+ $ScopeThisXSUB = 0;
+ $xsreturn = 0;
+
+ $_ = shift(@line);
+ while (my $kwd = check_keyword("REQUIRE|PROTOTYPES|FALLBACK|VERSIONCHECK|INCLUDE|SCOPE")) {
+ &{"${kwd}_handler"}() ;
+ next PARAGRAPH unless @line ;
+ $_ = shift(@line);
+ }
+
+ if (check_keyword("BOOT")) {
+ &check_cpp;
+ push (@BootCode, "#line $line_no[@line_no - @line] \"$filepathname\"")
+ if $WantLineNumbers && $line[0] !~ /^\s*#\s*line\b/;
+ push (@BootCode, @line, "") ;
+ next PARAGRAPH ;
+ }
+
+
+ # extract return type, function name and arguments
+ ($ret_type) = TidyType($_);
+ $RETVAL_no_return = 1 if $ret_type =~ s/^NO_OUTPUT\s+//;
+
+ # Allow one-line ANSI-like declaration
+ unshift @line, $2
+ if $process_argtypes
+ and $ret_type =~ s/^(.*?\w.*?)\s*\b(\w+\s*\(.*)/$1/s;
+
+ # a function definition needs at least 2 lines
+ blurt ("Error: Function definition too short '$ret_type'"), next PARAGRAPH
+ unless @line ;
+
+ $externC = 1 if $ret_type =~ s/^extern "C"\s+//;
+ $static = 1 if $ret_type =~ s/^static\s+//;
+
+ $func_header = shift(@line);
+ blurt ("Error: Cannot parse function definition from '$func_header'"), next PARAGRAPH
+ unless $func_header =~ /^(?:([\w:]*)::)?(\w+)\s*\(\s*(.*?)\s*\)\s*(const)?\s*(;\s*)?$/s;
+
+ ($class, $func_name, $orig_args) = ($1, $2, $3) ;
+ $class = "$4 $class" if $4;
+ ($pname = $func_name) =~ s/^($Prefix)?/$Packprefix/;
+ ($clean_func_name = $func_name) =~ s/^$Prefix//;
+ $Full_func_name = "${Packid}_$clean_func_name";
+ if ($Is_VMS) {
+ $Full_func_name = $SymSet->addsym($Full_func_name);
+ }
+
+ # Check for duplicate function definition
+ for my $tmp (@XSStack) {
+ next unless defined $tmp->{functions}{$Full_func_name};
+ Warn("Warning: duplicate function definition '$clean_func_name' detected");
+ last;
+ }
+ $XSStack[$XSS_work_idx]{functions}{$Full_func_name} ++ ;
+ %XsubAliases = %XsubAliasValues = %Interfaces = @Attributes = ();
+ $DoSetMagic = 1;
+
+ $orig_args =~ s/\\\s*/ /g; # process line continuations
+ my @args;
+
+ my %only_C_inlist; # Not in the signature of Perl function
+ if ($process_argtypes and $orig_args =~ /\S/) {
+ my $args = "$orig_args ,";
+ if ($args =~ /^( (??{ $C_arg }) , )* $ /x) {
+ @args = ($args =~ /\G ( (??{ $C_arg }) ) , /xg);
+ for ( @args ) {
+ s/^\s+//;
+ s/\s+$//;
+ my ($arg, $default) = / ( [^=]* ) ( (?: = .* )? ) /x;
+ my ($pre, $name) = ($arg =~ /(.*?) \s*
+ \b ( \w+ | length\( \s*\w+\s* \) )
+ \s* $ /x);
+ next unless defined($pre) && length($pre);
+ my $out_type = '';
+ my $inout_var;
+ if ($process_inout and s/^(IN|IN_OUTLIST|OUTLIST|OUT|IN_OUT)\s+//) {
+ my $type = $1;
+ $out_type = $type if $type ne 'IN';
+ $arg =~ s/^(IN|IN_OUTLIST|OUTLIST|OUT|IN_OUT)\s+//;
+ $pre =~ s/^(IN|IN_OUTLIST|OUTLIST|OUT|IN_OUT)\s+//;
+ }
+ my $islength;
+ if ($name =~ /^length\( \s* (\w+) \s* \)\z/x) {
+ $name = "XSauto_length_of_$1";
+ $islength = 1;
+ die "Default value on length() argument: `$_'"
+ if length $default;
+ }
+ if (length $pre or $islength) { # Has a type
+ if ($islength) {
+ push @fake_INPUT_pre, $arg;
+ } else {
+ push @fake_INPUT, $arg;
+ }
+ # warn "pushing '$arg'\n";
+ $argtype_seen{$name}++;
+ $_ = "$name$default"; # Assigns to @args
+ }
+ $only_C_inlist{$_} = 1 if $out_type eq "OUTLIST" or $islength;
+ push @outlist, $name if $out_type =~ /OUTLIST$/;
+ $in_out{$name} = $out_type if $out_type;
+ }
+ } else {
+ @args = split(/\s*,\s*/, $orig_args);
+ Warn("Warning: cannot parse argument list '$orig_args', fallback to split");
+ }
+ } else {
+ @args = split(/\s*,\s*/, $orig_args);
+ for (@args) {
+ if ($process_inout and s/^(IN|IN_OUTLIST|OUTLIST|IN_OUT|OUT)\s+//) {
+ my $out_type = $1;
+ next if $out_type eq 'IN';
+ $only_C_inlist{$_} = 1 if $out_type eq "OUTLIST";
+ push @outlist, $name if $out_type =~ /OUTLIST$/;
+ $in_out{$_} = $out_type;
+ }
+ }
+ }
+ if (defined($class)) {
+ my $arg0 = ((defined($static) or $func_name eq 'new')
+ ? "CLASS" : "THIS");
+ unshift(@args, $arg0);
+ }
+ my $extra_args = 0;
+ @args_num = ();
+ $num_args = 0;
+ my $report_args = '';
+ foreach my $i (0 .. $#args) {
+ if ($args[$i] =~ s/\.\.\.//) {
+ $ellipsis = 1;
+ if ($args[$i] eq '' && $i == $#args) {
+ $report_args .= ", ...";
+ pop(@args);
+ last;
+ }
+ }
+ if ($only_C_inlist{$args[$i]}) {
+ push @args_num, undef;
+ } else {
+ push @args_num, ++$num_args;
+ $report_args .= ", $args[$i]";
+ }
+ if ($args[$i] =~ /^([^=]*[^\s=])\s*=\s*(.*)/s) {
+ $extra_args++;
+ $args[$i] = $1;
+ $defaults{$args[$i]} = $2;
+ $defaults{$args[$i]} =~ s/"/\\"/g;
+ }
+ $proto_arg[$i+1] = '$' ;
+ }
+ $min_args = $num_args - $extra_args;
+ $report_args =~ s/"/\\"/g;
+ $report_args =~ s/^,\s+//;
+ my @func_args = @args;
+ shift @func_args if defined($class);
+
+ for (@func_args) {
+ s/^/&/ if $in_out{$_};
+ }
+ $func_args = join(", ", @func_args);
+ @args_match{@args} = @args_num;
+
+ $PPCODE = grep(/^\s*PPCODE\s*:/, @line);
+ $CODE = grep(/^\s*CODE\s*:/, @line);
+ # Detect CODE: blocks which use ST(n)= or XST_m*(n,v)
+ # to set explicit return values.
+ $EXPLICIT_RETURN = ($CODE &&
+ ("@line" =~ /(\bST\s*\([^;]*=) | (\bXST_m\w+\s*\()/x ));
+ $ALIAS = grep(/^\s*ALIAS\s*:/, @line);
+ $INTERFACE = grep(/^\s*INTERFACE\s*:/, @line);
+
+ $xsreturn = 1 if $EXPLICIT_RETURN;
+
+ $externC = $externC ? qq[extern "C"] : "";
+
+ # print function header
+ print Q(<<"EOF");
+#$externC
+#XS(XS_${Full_func_name}); /* prototype to pass -Wmissing-prototypes */
+#XS(XS_${Full_func_name})
+#[[
+##ifdef dVAR
+# dVAR; dXSARGS;
+##else
+# dXSARGS;
+##endif
+EOF
+ print Q(<<"EOF") if $ALIAS ;
+# dXSI32;
+EOF
+ print Q(<<"EOF") if $INTERFACE ;
+# dXSFUNCTION($ret_type);
+EOF
+ if ($ellipsis) {
+ $cond = ($min_args ? qq(items < $min_args) : 0);
+ } elsif ($min_args == $num_args) {
+ $cond = qq(items != $min_args);
+ } else {
+ $cond = qq(items < $min_args || items > $num_args);
+ }
+
+ print Q(<<"EOF") if $except;
+# char errbuf[1024];
+# *errbuf = '\0';
+EOF
+
+ if($cond) {
+ print Q(<<"EOF");
+# if ($cond)
+# croak_xs_usage(cv, "$report_args");
+EOF
+ } else {
+ # cv likely to be unused
+ print Q(<<"EOF");
+# PERL_UNUSED_VAR(cv); /* -W */
+EOF
+ }
+
+ #gcc -Wall: if an xsub has PPCODE is used
+ #it is possible none of ST, XSRETURN or XSprePUSH macros are used
+ #hence `ax' (setup by dXSARGS) is unused
+ #XXX: could breakup the dXSARGS; into dSP;dMARK;dITEMS
+ #but such a move could break third-party extensions
+ print Q(<<"EOF") if $PPCODE;
+# PERL_UNUSED_VAR(ax); /* -Wall */
+EOF
+
+ print Q(<<"EOF") if $PPCODE;
+# SP -= items;
+EOF
+
+ # Now do a block of some sort.
+
+ $condnum = 0;
+ $cond = ''; # last CASE: condidional
+ push(@line, "$END:");
+ push(@line_no, $line_no[-1]);
+ $_ = '';
+ &check_cpp;
+ while (@line) {
+ &CASE_handler if check_keyword("CASE");
+ print Q(<<"EOF");
+# $except [[
+EOF
+
+ # do initialization of input variables
+ $thisdone = 0;
+ $retvaldone = 0;
+ $deferred = "";
+ %arg_list = () ;
+ $gotRETVAL = 0;
+
+ INPUT_handler() ;
+ process_keyword("INPUT|PREINIT|INTERFACE_MACRO|C_ARGS|ALIAS|ATTRS|PROTOTYPE|SCOPE|OVERLOAD") ;
+
+ print Q(<<"EOF") if $ScopeThisXSUB;
+# ENTER;
+# [[
+EOF
+
+ if (!$thisdone && defined($class)) {
+ if (defined($static) or $func_name eq 'new') {
+ print "\tchar *";
+ $var_types{"CLASS"} = "char *";
+ &generate_init("char *", 1, "CLASS");
+ }
+ else {
+ print "\t$class *";
+ $var_types{"THIS"} = "$class *";
+ &generate_init("$class *", 1, "THIS");
+ }
+ }
+
+ # do code
+ if (/^\s*NOT_IMPLEMENTED_YET/) {
+ print "\n\tPerl_croak(aTHX_ \"$pname: not implemented yet\");\n";
+ $_ = '' ;
+ } else {
+ if ($ret_type ne "void") {
+ print "\t" . &map_type($ret_type, 'RETVAL') . ";\n"
+ if !$retvaldone;
+ $args_match{"RETVAL"} = 0;
+ $var_types{"RETVAL"} = $ret_type;
+ print "\tdXSTARG;\n"
+ if $WantOptimize and $targetable{$type_kind{$ret_type}};
+ }
+
+ if (@fake_INPUT or @fake_INPUT_pre) {
+ unshift @line, @fake_INPUT_pre, @fake_INPUT, $_;
+ $_ = "";
+ $processing_arg_with_types = 1;
+ INPUT_handler() ;
+ }
+ print $deferred;
+
+ process_keyword("INIT|ALIAS|ATTRS|PROTOTYPE|INTERFACE_MACRO|INTERFACE|C_ARGS|OVERLOAD") ;
+
+ if (check_keyword("PPCODE")) {
+ print_section();
+ death ("PPCODE must be last thing") if @line;
+ print "\tLEAVE;\n" if $ScopeThisXSUB;
+ print "\tPUTBACK;\n\treturn;\n";
+ } elsif (check_keyword("CODE")) {
+ print_section() ;
+ } elsif (defined($class) and $func_name eq "DESTROY") {
+ print "\n\t";
+ print "delete THIS;\n";
+ } else {
+ print "\n\t";
+ if ($ret_type ne "void") {
+ print "RETVAL = ";
+ $wantRETVAL = 1;
+ }
+ if (defined($static)) {
+ if ($func_name eq 'new') {
+ $func_name = "$class";
+ } else {
+ print "${class}::";
+ }
+ } elsif (defined($class)) {
+ if ($func_name eq 'new') {
+ $func_name .= " $class";
+ } else {
+ print "THIS->";
+ }
+ }
+ $func_name =~ s/^\Q$args{'s'}//
+ if exists $args{'s'};
+ $func_name = 'XSFUNCTION' if $interface;
+ print "$func_name($func_args);\n";
+ }
+ }
+
+ # do output variables
+ $gotRETVAL = 0; # 1 if RETVAL seen in OUTPUT section;
+ undef $RETVAL_code ; # code to set RETVAL (from OUTPUT section);
+ # $wantRETVAL set if 'RETVAL =' autogenerated
+ ($wantRETVAL, $ret_type) = (0, 'void') if $RETVAL_no_return;
+ undef %outargs ;
+ process_keyword("POSTCALL|OUTPUT|ALIAS|ATTRS|PROTOTYPE|OVERLOAD");
+
+ &generate_output($var_types{$_}, $args_match{$_}, $_, $DoSetMagic)
+ for grep $in_out{$_} =~ /OUT$/, keys %in_out;
+
+ # all OUTPUT done, so now push the return value on the stack
+ if ($gotRETVAL && $RETVAL_code) {
+ print "\t$RETVAL_code\n";
+ } elsif ($gotRETVAL || $wantRETVAL) {
+ my $t = $WantOptimize && $targetable{$type_kind{$ret_type}};
+ my $var = 'RETVAL';
+ my $type = $ret_type;
+
+ # 0: type, 1: with_size, 2: how, 3: how_size
+ if ($t and not $t->[1] and $t->[0] eq 'p') {
+ # PUSHp corresponds to setpvn. Treate setpv directly
+ my $what = eval qq("$t->[2]");
+ warn $@ if $@;
+
+ print "\tsv_setpv(TARG, $what); XSprePUSH; PUSHTARG;\n";
+ $prepush_done = 1;
+ }
+ elsif ($t) {
+ my $what = eval qq("$t->[2]");
+ warn $@ if $@;
+
+ my $size = $t->[3];
+ $size = '' unless defined $size;
+ $size = eval qq("$size");
+ warn $@ if $@;
+ print "\tXSprePUSH; PUSH$t->[0]($what$size);\n";
+ $prepush_done = 1;
+ }
+ else {
+ # RETVAL almost never needs SvSETMAGIC()
+ &generate_output($ret_type, 0, 'RETVAL', 0);
+ }
+ }
+
+ $xsreturn = 1 if $ret_type ne "void";
+ my $num = $xsreturn;
+ my $c = @outlist;
+ print "\tXSprePUSH;" if $c and not $prepush_done;
+ print "\tEXTEND(SP,$c);\n" if $c;
+ $xsreturn += $c;
+ generate_output($var_types{$_}, $num++, $_, 0, 1) for @outlist;
+
+ # do cleanup
+ process_keyword("CLEANUP|ALIAS|ATTRS|PROTOTYPE|OVERLOAD") ;
+
+ print Q(<<"EOF") if $ScopeThisXSUB;
+# ]]
+EOF
+ print Q(<<"EOF") if $ScopeThisXSUB and not $PPCODE;
+# LEAVE;
+EOF
+
+ # print function trailer
+ print Q(<<"EOF");
+# ]]
+EOF
+ print Q(<<"EOF") if $except;
+# BEGHANDLERS
+# CATCHALL
+# sprintf(errbuf, "%s: %s\\tpropagated", Xname, Xreason);
+# ENDHANDLERS
+EOF
+ if (check_keyword("CASE")) {
+ blurt ("Error: No `CASE:' at top of function")
+ unless $condnum;
+ $_ = "CASE: $_"; # Restore CASE: label
+ next;
+ }
+ last if $_ eq "$END:";
+ death(/^$BLOCK_re/o ? "Misplaced `$1:'" : "Junk at end of function ($_)");
+ }
+
+ print Q(<<"EOF") if $except;
+# if (errbuf[0])
+# Perl_croak(aTHX_ errbuf);
+EOF
+
+ if ($xsreturn) {
+ print Q(<<"EOF") unless $PPCODE;
+# XSRETURN($xsreturn);
+EOF
+ } else {
+ print Q(<<"EOF") unless $PPCODE;
+# XSRETURN_EMPTY;
+EOF
+ }
+
+ print Q(<<"EOF");
+#]]
+#
+EOF
+
+ our $newXS = "newXS" ;
+ our $proto = "" ;
+
+ # Build the prototype string for the xsub
+ if ($ProtoThisXSUB) {
+ $newXS = "newXSproto_portable";
+
+ if ($ProtoThisXSUB eq 2) {
+ # User has specified empty prototype
+ }
+ elsif ($ProtoThisXSUB eq 1) {
+ my $s = ';';
+ if ($min_args < $num_args) {
+ $s = '';
+ $proto_arg[$min_args] .= ";" ;
+ }
+ push @proto_arg, "$s\@"
+ if $ellipsis ;
+
+ $proto = join ("", grep defined, @proto_arg);
+ }
+ else {
+ # User has specified a prototype
+ $proto = $ProtoThisXSUB;
+ }
+ $proto = qq{, "$proto"};
+ }
+
+ if (%XsubAliases) {
+ $XsubAliases{$pname} = 0
+ unless defined $XsubAliases{$pname} ;
+ while ( ($name, $value) = each %XsubAliases) {
+ push(@InitFileCode, Q(<<"EOF"));
+# cv = ${newXS}(\"$name\", XS_$Full_func_name, file$proto);
+# XSANY.any_i32 = $value ;
+EOF
+ }
+ }
+ elsif (@Attributes) {
+ push(@InitFileCode, Q(<<"EOF"));
+# cv = ${newXS}(\"$pname\", XS_$Full_func_name, file$proto);
+# apply_attrs_string("$Package", cv, "@Attributes", 0);
+EOF
+ }
+ elsif ($interface) {
+ while ( ($name, $value) = each %Interfaces) {
+ $name = "$Package\::$name" unless $name =~ /::/;
+ push(@InitFileCode, Q(<<"EOF"));
+# cv = ${newXS}(\"$name\", XS_$Full_func_name, file$proto);
+# $interface_macro_set(cv,$value) ;
+EOF
+ }
+ }
+ else {
+ push(@InitFileCode,
+ " (void)${newXS}(\"$pname\", XS_$Full_func_name, file$proto);\n");
+ }
+ }
+
+ if ($Overload) # make it findable with fetchmethod
+ {
+ print Q(<<"EOF");
+#XS(XS_${Packid}_nil); /* prototype to pass -Wmissing-prototypes */
+#XS(XS_${Packid}_nil)
+#{
+# dXSARGS;
+# XSRETURN_EMPTY;
+#}
+#
+EOF
+ unshift(@InitFileCode, <<"MAKE_FETCHMETHOD_WORK");
+ /* Making a sub named "${Package}::()" allows the package */
+ /* to be findable via fetchmethod(), and causes */
+ /* overload::Overloaded("${Package}") to return true. */
+ (void)${newXS}("${Package}::()", XS_${Packid}_nil, file$proto);
+MAKE_FETCHMETHOD_WORK
+ }
+
+ # print initialization routine
+
+ print Q(<<"EOF");
+##ifdef __cplusplus
+#extern "C"
+##endif
+EOF
+
+ print Q(<<"EOF");
+#XS(boot_$Module_cname); /* prototype to pass -Wmissing-prototypes */
+#XS(boot_$Module_cname)
+EOF
+
+ print Q(<<"EOF");
+#[[
+##ifdef dVAR
+# dVAR; dXSARGS;
+##else
+# dXSARGS;
+##endif
+EOF
+
+ #Under 5.8.x and lower, newXS is declared in proto.h as expecting a non-const
+ #file name argument. If the wrong qualifier is used, it causes breakage with
+ #C++ compilers and warnings with recent gcc.
+ #-Wall: if there is no $Full_func_name there are no xsubs in this .xs
+ #so `file' is unused
+ print Q(<<"EOF") if $Full_func_name;
+##if (PERL_REVISION == 5 && PERL_VERSION < 9)
+# char* file = __FILE__;
+##else
+# const char* file = __FILE__;
+##endif
+EOF
+
+ print Q("#\n");
+
+ print Q(<<"EOF");
+# PERL_UNUSED_VAR(cv); /* -W */
+# PERL_UNUSED_VAR(items); /* -W */
+EOF
+
+ print Q(<<"EOF") if $WantVersionChk ;
+# XS_VERSION_BOOTCHECK ;
+#
+EOF
+
+ print Q(<<"EOF") if defined $XsubAliases or defined $Interfaces ;
+# {
+# CV * cv ;
+#
+EOF
+
+ print Q(<<"EOF") if ($Overload);
+# /* register the overloading (type 'A') magic */
+# PL_amagic_generation++;
+# /* The magic for overload gets a GV* via gv_fetchmeth as */
+# /* mentioned above, and looks in the SV* slot of it for */
+# /* the "fallback" status. */
+# sv_setsv(
+# get_sv( "${Package}::()", TRUE ),
+# $Fallback
+# );
+EOF
+
+ print @InitFileCode;
+
+ print Q(<<"EOF") if defined $XsubAliases or defined $Interfaces ;
+# }
+EOF
+
+ if (@BootCode)
+ {
+ print "\n /* Initialisation Section */\n\n" ;
+ @line = @BootCode;
+ print_section();
+ print "\n /* End of Initialisation Section */\n\n" ;
+ }
+
+ print Q(<<'EOF');
+##if (PERL_REVISION == 5 && PERL_VERSION >= 9)
+# if (PL_unitcheckav)
+# call_list(PL_scopestack_ix, PL_unitcheckav);
+##endif
+EOF
+
+ print Q(<<"EOF");
+# XSRETURN_YES;
+#]]
+#
+EOF
+
+ warn("Please specify prototyping behavior for $filename (see perlxs manual)\n")
+ unless $ProtoUsed ;
+
+ chdir($orig_cwd);
+ select($orig_fh);
+ untie *PSEUDO_STDOUT if tied *PSEUDO_STDOUT;
+ close $FH;
+
+ return 1;
+}
+
+sub errors { $errors }
+
+sub standard_typemap_locations {
+ # Add all the default typemap locations to the search path
+ my @tm = qw(typemap);
+
+ my $updir = File::Spec->updir;
+ foreach my $dir (File::Spec->catdir(($updir) x 1), File::Spec->catdir(($updir) x 2),
+ File::Spec->catdir(($updir) x 3), File::Spec->catdir(($updir) x 4)) {
+
+ unshift @tm, File::Spec->catfile($dir, 'typemap');
+ unshift @tm, File::Spec->catfile($dir, lib => ExtUtils => 'typemap');
+ }
+ foreach my $dir (@INC) {
+ my $file = File::Spec->catfile($dir, ExtUtils => 'typemap');
+ unshift @tm, $file if -e $file;
+ }
+ return @tm;
+}
+
+sub TrimWhitespace
+{
+ $_[0] =~ s/^\s+|\s+$//go ;
+}
+
+sub TidyType
+ {
+ local ($_) = @_ ;
+
+ # rationalise any '*' by joining them into bunches and removing whitespace
+ s#\s*(\*+)\s*#$1#g;
+ s#(\*+)# $1 #g ;
+
+ # change multiple whitespace into a single space
+ s/\s+/ /g ;
+
+ # trim leading & trailing whitespace
+ TrimWhitespace($_) ;
+
+ $_ ;
+}
+
+# Input: ($_, @line) == unparsed input.
+# Output: ($_, @line) == (rest of line, following lines).
+# Return: the matched keyword if found, otherwise 0
+sub check_keyword {
+ $_ = shift(@line) while !/\S/ && @line;
+ s/^(\s*)($_[0])\s*:\s*(?:#.*)?/$1/s && $2;
+}
+
+sub print_section {
+ # the "do" is required for right semantics
+ do { $_ = shift(@line) } while !/\S/ && @line;
+
+ print("#line ", $line_no[@line_no - @line -1], " \"$filepathname\"\n")
+ if $WantLineNumbers && !/^\s*#\s*line\b/ && !/^#if XSubPPtmp/;
+ for (; defined($_) && !/^$BLOCK_re/o; $_ = shift(@line)) {
+ print "$_\n";
+ }
+ print 'ExtUtils::ParseXS::CountLines'->end_marker, "\n" if $WantLineNumbers;
+}
+
+sub merge_section {
+ my $in = '';
+
+ while (!/\S/ && @line) {
+ $_ = shift(@line);
+ }
+
+ for (; defined($_) && !/^$BLOCK_re/o; $_ = shift(@line)) {
+ $in .= "$_\n";
+ }
+ chomp $in;
+ return $in;
+ }
+
+sub process_keyword($)
+ {
+ my($pattern) = @_ ;
+ my $kwd ;
+
+ &{"${kwd}_handler"}()
+ while $kwd = check_keyword($pattern) ;
+ }
+
+sub CASE_handler {
+ blurt ("Error: `CASE:' after unconditional `CASE:'")
+ if $condnum && $cond eq '';
+ $cond = $_;
+ TrimWhitespace($cond);
+ print " ", ($condnum++ ? " else" : ""), ($cond ? " if ($cond)\n" : "\n");
+ $_ = '' ;
+}
+
+sub INPUT_handler {
+ for (; !/^$BLOCK_re/o; $_ = shift(@line)) {
+ last if /^\s*NOT_IMPLEMENTED_YET/;
+ next unless /\S/; # skip blank lines
+
+ TrimWhitespace($_) ;
+ my $line = $_ ;
+
+ # remove trailing semicolon if no initialisation
+ s/\s*;$//g unless /[=;+].*\S/ ;
+
+ # Process the length(foo) declarations
+ if (s/^([^=]*)\blength\(\s*(\w+)\s*\)\s*$/$1 XSauto_length_of_$2=NO_INIT/x) {
+ print "\tSTRLEN\tSTRLEN_length_of_$2;\n";
+ $lengthof{$2} = $name;
+ # $islengthof{$name} = $1;
+ $deferred .= "\n\tXSauto_length_of_$2 = STRLEN_length_of_$2;\n";
+ }
+
+ # check for optional initialisation code
+ my $var_init = '' ;
+ $var_init = $1 if s/\s*([=;+].*)$//s ;
+ $var_init =~ s/"/\\"/g;
+
+ s/\s+/ /g;
+ my ($var_type, $var_addr, $var_name) = /^(.*?[^&\s])\s*(\&?)\s*\b(\w+)$/s
+ or blurt("Error: invalid argument declaration '$line'"), next;
+
+ # Check for duplicate definitions
+ blurt ("Error: duplicate definition of argument '$var_name' ignored"), next
+ if $arg_list{$var_name}++
+ or defined $argtype_seen{$var_name} and not $processing_arg_with_types;
+
+ $thisdone |= $var_name eq "THIS";
+ $retvaldone |= $var_name eq "RETVAL";
+ $var_types{$var_name} = $var_type;
+ # XXXX This check is a safeguard against the unfinished conversion of
+ # generate_init(). When generate_init() is fixed,
+ # one can use 2-args map_type() unconditionally.
+ if ($var_type =~ / \( \s* \* \s* \) /x) {
+ # Function pointers are not yet supported with &output_init!
+ print "\t" . &map_type($var_type, $var_name);
+ $name_printed = 1;
+ } else {
+ print "\t" . &map_type($var_type);
+ $name_printed = 0;
+ }
+ $var_num = $args_match{$var_name};
+
+ $proto_arg[$var_num] = ProtoString($var_type)
+ if $var_num ;
+ $func_args =~ s/\b($var_name)\b/&$1/ if $var_addr;
+ if ($var_init =~ /^[=;]\s*NO_INIT\s*;?\s*$/
+ or $in_out{$var_name} and $in_out{$var_name} =~ /^OUT/
+ and $var_init !~ /\S/) {
+ if ($name_printed) {
+ print ";\n";
+ } else {
+ print "\t$var_name;\n";
+ }
+ } elsif ($var_init =~ /\S/) {
+ &output_init($var_type, $var_num, $var_name, $var_init, $name_printed);
+ } elsif ($var_num) {
+ # generate initialization code
+ &generate_init($var_type, $var_num, $var_name, $name_printed);
+ } else {
+ print ";\n";
+ }
+ }
+}
+
+sub OUTPUT_handler {
+ for (; !/^$BLOCK_re/o; $_ = shift(@line)) {
+ next unless /\S/;
+ if (/^\s*SETMAGIC\s*:\s*(ENABLE|DISABLE)\s*/) {
+ $DoSetMagic = ($1 eq "ENABLE" ? 1 : 0);
+ next;
+ }
+ my ($outarg, $outcode) = /^\s*(\S+)\s*(.*?)\s*$/s ;
+ blurt ("Error: duplicate OUTPUT argument '$outarg' ignored"), next
+ if $outargs{$outarg} ++ ;
+ if (!$gotRETVAL and $outarg eq 'RETVAL') {
+ # deal with RETVAL last
+ $RETVAL_code = $outcode ;
+ $gotRETVAL = 1 ;
+ next ;
+ }
+ blurt ("Error: OUTPUT $outarg not an argument"), next
+ unless defined($args_match{$outarg});
+ blurt("Error: No input definition for OUTPUT argument '$outarg' - ignored"), next
+ unless defined $var_types{$outarg} ;
+ $var_num = $args_match{$outarg};
+ if ($outcode) {
+ print "\t$outcode\n";
+ print "\tSvSETMAGIC(ST(" , $var_num-1 , "));\n" if $DoSetMagic;
+ } else {
+ &generate_output($var_types{$outarg}, $var_num, $outarg, $DoSetMagic);
+ }
+ delete $in_out{$outarg} # No need to auto-OUTPUT
+ if exists $in_out{$outarg} and $in_out{$outarg} =~ /OUT$/;
+ }
+}
+
+sub C_ARGS_handler() {
+ my $in = merge_section();
+
+ TrimWhitespace($in);
+ $func_args = $in;
+}
+
+sub INTERFACE_MACRO_handler() {
+ my $in = merge_section();
+
+ TrimWhitespace($in);
+ if ($in =~ /\s/) { # two
+ ($interface_macro, $interface_macro_set) = split ' ', $in;
+ } else {
+ $interface_macro = $in;
+ $interface_macro_set = 'UNKNOWN_CVT'; # catch later
+ }
+ $interface = 1; # local
+ $Interfaces = 1; # global
+}
+
+sub INTERFACE_handler() {
+ my $in = merge_section();
+
+ TrimWhitespace($in);
+
+ foreach (split /[\s,]+/, $in) {
+ my $name = $_;
+ $name =~ s/^$Prefix//;
+ $Interfaces{$name} = $_;
+ }
+ print Q(<<"EOF");
+# XSFUNCTION = $interface_macro($ret_type,cv,XSANY.any_dptr);
+EOF
+ $interface = 1; # local
+ $Interfaces = 1; # global
+}
+
+sub CLEANUP_handler() { print_section() }
+sub PREINIT_handler() { print_section() }
+sub POSTCALL_handler() { print_section() }
+sub INIT_handler() { print_section() }
+
+sub GetAliases
+ {
+ my ($line) = @_ ;
+ my ($orig) = $line ;
+ my ($alias) ;
+ my ($value) ;
+
+ # Parse alias definitions
+ # format is
+ # alias = value alias = value ...
+
+ while ($line =~ s/^\s*([\w:]+)\s*=\s*(\w+)\s*//) {
+ $alias = $1 ;
+ $orig_alias = $alias ;
+ $value = $2 ;
+
+ # check for optional package definition in the alias
+ $alias = $Packprefix . $alias if $alias !~ /::/ ;
+
+ # check for duplicate alias name & duplicate value
+ Warn("Warning: Ignoring duplicate alias '$orig_alias'")
+ if defined $XsubAliases{$alias} ;
+
+ Warn("Warning: Aliases '$orig_alias' and '$XsubAliasValues{$value}' have identical values")
+ if $XsubAliasValues{$value} ;
+
+ $XsubAliases = 1;
+ $XsubAliases{$alias} = $value ;
+ $XsubAliasValues{$value} = $orig_alias ;
+ }
+
+ blurt("Error: Cannot parse ALIAS definitions from '$orig'")
+ if $line ;
+ }
+
+sub ATTRS_handler ()
+ {
+ for (; !/^$BLOCK_re/o; $_ = shift(@line)) {
+ next unless /\S/;
+ TrimWhitespace($_) ;
+ push @Attributes, $_;
+ }
+ }
+
+sub ALIAS_handler ()
+ {
+ for (; !/^$BLOCK_re/o; $_ = shift(@line)) {
+ next unless /\S/;
+ TrimWhitespace($_) ;
+ GetAliases($_) if $_ ;
+ }
+ }
+
+sub OVERLOAD_handler()
+{
+ for (; !/^$BLOCK_re/o; $_ = shift(@line)) {
+ next unless /\S/;
+ TrimWhitespace($_) ;
+ while ( s/^\s*([\w:"\\)\+\-\*\/\%\<\>\.\&\|\^\!\~\{\}\=]+)\s*//) {
+ $Overload = 1 unless $Overload;
+ my $overload = "$Package\::(".$1 ;
+ push(@InitFileCode,
+ " (void)${newXS}(\"$overload\", XS_$Full_func_name, file$proto);\n");
+ }
+ }
+}
+
+sub FALLBACK_handler()
+{
+ # the rest of the current line should contain either TRUE,
+ # FALSE or UNDEF
+
+ TrimWhitespace($_) ;
+ my %map = (
+ TRUE => "&PL_sv_yes", 1 => "&PL_sv_yes",
+ FALSE => "&PL_sv_no", 0 => "&PL_sv_no",
+ UNDEF => "&PL_sv_undef",
+ ) ;
+
+ # check for valid FALLBACK value
+ death ("Error: FALLBACK: TRUE/FALSE/UNDEF") unless exists $map{uc $_} ;
+
+ $Fallback = $map{uc $_} ;
+}
+
+
+sub REQUIRE_handler ()
+ {
+ # the rest of the current line should contain a version number
+ my ($Ver) = $_ ;
+
+ TrimWhitespace($Ver) ;
+
+ death ("Error: REQUIRE expects a version number")
+ unless $Ver ;
+
+ # check that the version number is of the form n.n
+ death ("Error: REQUIRE: expected a number, got '$Ver'")
+ unless $Ver =~ /^\d+(\.\d*)?/ ;
+
+ death ("Error: xsubpp $Ver (or better) required--this is only $VERSION.")
+ unless $VERSION >= $Ver ;
+ }
+
+sub VERSIONCHECK_handler ()
+ {
+ # the rest of the current line should contain either ENABLE or
+ # DISABLE
+
+ TrimWhitespace($_) ;
+
+ # check for ENABLE/DISABLE
+ death ("Error: VERSIONCHECK: ENABLE/DISABLE")
+ unless /^(ENABLE|DISABLE)/i ;
+
+ $WantVersionChk = 1 if $1 eq 'ENABLE' ;
+ $WantVersionChk = 0 if $1 eq 'DISABLE' ;
+
+ }
+
+sub PROTOTYPE_handler ()
+ {
+ my $specified ;
+
+ death("Error: Only 1 PROTOTYPE definition allowed per xsub")
+ if $proto_in_this_xsub ++ ;
+
+ for (; !/^$BLOCK_re/o; $_ = shift(@line)) {
+ next unless /\S/;
+ $specified = 1 ;
+ TrimWhitespace($_) ;
+ if ($_ eq 'DISABLE') {
+ $ProtoThisXSUB = 0
+ } elsif ($_ eq 'ENABLE') {
+ $ProtoThisXSUB = 1
+ } else {
+ # remove any whitespace
+ s/\s+//g ;
+ death("Error: Invalid prototype '$_'")
+ unless ValidProtoString($_) ;
+ $ProtoThisXSUB = C_string($_) ;
+ }
+ }
+
+ # If no prototype specified, then assume empty prototype ""
+ $ProtoThisXSUB = 2 unless $specified ;
+
+ $ProtoUsed = 1 ;
+
+ }
+
+sub SCOPE_handler ()
+ {
+ death("Error: Only 1 SCOPE declaration allowed per xsub")
+ if $scope_in_this_xsub ++ ;
+
+ TrimWhitespace($_);
+ death ("Error: SCOPE: ENABLE/DISABLE")
+ unless /^(ENABLE|DISABLE)\b/i;
+ $ScopeThisXSUB = ( uc($1) eq 'ENABLE' );
+ }
+
+sub PROTOTYPES_handler ()
+ {
+ # the rest of the current line should contain either ENABLE or
+ # DISABLE
+
+ TrimWhitespace($_) ;
+
+ # check for ENABLE/DISABLE
+ death ("Error: PROTOTYPES: ENABLE/DISABLE")
+ unless /^(ENABLE|DISABLE)/i ;
+
+ $WantPrototypes = 1 if $1 eq 'ENABLE' ;
+ $WantPrototypes = 0 if $1 eq 'DISABLE' ;
+ $ProtoUsed = 1 ;
+
+ }
+
+sub INCLUDE_handler ()
+ {
+ # the rest of the current line should contain a valid filename
+
+ TrimWhitespace($_) ;
+
+ death("INCLUDE: filename missing")
+ unless $_ ;
+
+ death("INCLUDE: output pipe is illegal")
+ if /^\s*\|/ ;
+
+ # simple minded recursion detector
+ death("INCLUDE loop detected")
+ if $IncludedFiles{$_} ;
+
+ ++ $IncludedFiles{$_} unless /\|\s*$/ ;
+
+ # Save the current file context.
+ push(@XSStack, {
+ type => 'file',
+ LastLine => $lastline,
+ LastLineNo => $lastline_no,
+ Line => \@line,
+ LineNo => \@line_no,
+ Filename => $filename,
+ Filepathname => $filepathname,
+ Handle => $FH,
+ }) ;
+
+ $FH = Symbol::gensym();
+
+ # open the new file
+ open ($FH, "$_") or death("Cannot open '$_': $!") ;
+
+ print Q(<<"EOF");
+#
+#/* INCLUDE: Including '$_' from '$filename' */
+#
+EOF
+
+ $filename = $_ ;
+ $filepathname = "$dir/$filename";
+
+ # Prime the pump by reading the first
+ # non-blank line
+
+ # skip leading blank lines
+ while (<$FH>) {
+ last unless /^\s*$/ ;
+ }
+
+ $lastline = $_ ;
+ $lastline_no = $. ;
+
+ }
+
+sub PopFile()
+ {
+ return 0 unless $XSStack[-1]{type} eq 'file' ;
+
+ my $data = pop @XSStack ;
+ my $ThisFile = $filename ;
+ my $isPipe = ($filename =~ /\|\s*$/) ;
+
+ -- $IncludedFiles{$filename}
+ unless $isPipe ;
+
+ close $FH ;
+
+ $FH = $data->{Handle} ;
+ # $filename is the leafname, which for some reason isused for diagnostic
+ # messages, whereas $filepathname is the full pathname, and is used for
+ # #line directives.
+ $filename = $data->{Filename} ;
+ $filepathname = $data->{Filepathname} ;
+ $lastline = $data->{LastLine} ;
+ $lastline_no = $data->{LastLineNo} ;
+ @line = @{ $data->{Line} } ;
+ @line_no = @{ $data->{LineNo} } ;
+
+ if ($isPipe and $? ) {
+ -- $lastline_no ;
+ print STDERR "Error reading from pipe '$ThisFile': $! in $filename, line $lastline_no\n" ;
+ exit 1 ;
+ }
+
+ print Q(<<"EOF");
+#
+#/* INCLUDE: Returning to '$filename' from '$ThisFile' */
+#
+EOF
+
+ return 1 ;
+ }
+
+sub ValidProtoString ($)
+ {
+ my($string) = @_ ;
+
+ if ( $string =~ /^$proto_re+$/ ) {
+ return $string ;
+ }
+
+ return 0 ;
+ }
+
+sub C_string ($)
+ {
+ my($string) = @_ ;
+
+ $string =~ s[\\][\\\\]g ;
+ $string ;
+ }
+
+sub ProtoString ($)
+ {
+ my ($type) = @_ ;
+
+ $proto_letter{$type} or "\$" ;
+ }
+
+sub check_cpp {
+ my @cpp = grep(/^\#\s*(?:if|e\w+)/, @line);
+ if (@cpp) {
+ my ($cpp, $cpplevel);
+ for $cpp (@cpp) {
+ if ($cpp =~ /^\#\s*if/) {
+ $cpplevel++;
+ } elsif (!$cpplevel) {
+ Warn("Warning: #else/elif/endif without #if in this function");
+ print STDERR " (precede it with a blank line if the matching #if is outside the function)\n"
+ if $XSStack[-1]{type} eq 'if';
+ return;
+ } elsif ($cpp =~ /^\#\s*endif/) {
+ $cpplevel--;
+ }
+ }
+ Warn("Warning: #if without #endif in this function") if $cpplevel;
+ }
+}
+
+
+sub Q {
+ my($text) = @_;
+ $text =~ s/^#//gm;
+ $text =~ s/\[\[/{/g;
+ $text =~ s/\]\]/}/g;
+ $text;
+}
+
+# Read next xsub into @line from ($lastline, <$FH>).
+sub fetch_para {
+ # parse paragraph
+ death ("Error: Unterminated `#if/#ifdef/#ifndef'")
+ if !defined $lastline && $XSStack[-1]{type} eq 'if';
+ @line = ();
+ @line_no = () ;
+ return PopFile() if !defined $lastline;
+
+ if ($lastline =~
+ /^MODULE\s*=\s*([\w:]+)(?:\s+PACKAGE\s*=\s*([\w:]+))?(?:\s+PREFIX\s*=\s*(\S+))?\s*$/) {
+ $Module = $1;
+ $Package = defined($2) ? $2 : ''; # keep -w happy
+ $Prefix = defined($3) ? $3 : ''; # keep -w happy
+ $Prefix = quotemeta $Prefix ;
+ ($Module_cname = $Module) =~ s/\W/_/g;
+ ($Packid = $Package) =~ tr/:/_/;
+ $Packprefix = $Package;
+ $Packprefix .= "::" if $Packprefix ne "";
+ $lastline = "";
+ }
+
+ for (;;) {
+ # Skip embedded PODs
+ while ($lastline =~ /^=/) {
+ while ($lastline = <$FH>) {
+ last if ($lastline =~ /^=cut\s*$/);
+ }
+ death ("Error: Unterminated pod") unless $lastline;
+ $lastline = <$FH>;
+ chomp $lastline;
+ $lastline =~ s/^\s+$//;
+ }
+ if ($lastline !~ /^\s*#/ ||
+ # CPP directives:
+ # ANSI: if ifdef ifndef elif else endif define undef
+ # line error pragma
+ # gcc: warning include_next
+ # obj-c: import
+ # others: ident (gcc notes that some cpps have this one)
+ $lastline =~ /^#[ \t]*(?:(?:if|ifn?def|elif|else|endif|define|undef|pragma|error|warning|line\s+\d+|ident)\b|(?:include(?:_next)?|import)\s*["<].*[>"])/) {
+ last if $lastline =~ /^\S/ && @line && $line[-1] eq "";
+ push(@line, $lastline);
+ push(@line_no, $lastline_no) ;
+ }
+
+ # Read next line and continuation lines
+ last unless defined($lastline = <$FH>);
+ $lastline_no = $.;
+ my $tmp_line;
+ $lastline .= $tmp_line
+ while ($lastline =~ /\\$/ && defined($tmp_line = <$FH>));
+
+ chomp $lastline;
+ $lastline =~ s/^\s+$//;
+ }
+ pop(@line), pop(@line_no) while @line && $line[-1] eq "";
+ 1;
+}
+
+sub output_init {
+ local($type, $num, $var, $init, $name_printed) = @_;
+ local($arg) = "ST(" . ($num - 1) . ")";
+
+ if ( $init =~ /^=/ ) {
+ if ($name_printed) {
+ eval qq/print " $init\\n"/;
+ } else {
+ eval qq/print "\\t$var $init\\n"/;
+ }
+ warn $@ if $@;
+ } else {
+ if ( $init =~ s/^\+// && $num ) {
+ &generate_init($type, $num, $var, $name_printed);
+ } elsif ($name_printed) {
+ print ";\n";
+ $init =~ s/^;//;
+ } else {
+ eval qq/print "\\t$var;\\n"/;
+ warn $@ if $@;
+ $init =~ s/^;//;
+ }
+ $deferred .= eval qq/"\\n\\t$init\\n"/;
+ warn $@ if $@;
+ }
+}
+
+sub Warn
+ {
+ # work out the line number
+ my $line_no = $line_no[@line_no - @line -1] ;
+
+ print STDERR "@_ in $filename, line $line_no\n" ;
+ }
+
+sub blurt
+ {
+ Warn @_ ;
+ $errors ++
+ }
+
+sub death
+ {
+ Warn @_ ;
+ exit 1 ;
+ }
+
+sub generate_init {
+ local($type, $num, $var) = @_;
+ local($arg) = "ST(" . ($num - 1) . ")";
+ local($argoff) = $num - 1;
+ local($ntype);
+ local($tk);
+
+ $type = TidyType($type) ;
+ blurt("Error: '$type' not in typemap"), return
+ unless defined($type_kind{$type});
+
+ ($ntype = $type) =~ s/\s*\*/Ptr/g;
+ ($subtype = $ntype) =~ s/(?:Array)?(?:Ptr)?$//;
+ $tk = $type_kind{$type};
+ $tk =~ s/OBJ$/REF/ if $func_name =~ /DESTROY$/;
+ if ($tk eq 'T_PV' and exists $lengthof{$var}) {
+ print "\t$var" unless $name_printed;
+ print " = ($type)SvPV($arg, STRLEN_length_of_$var);\n";
+ die "default value not supported with length(NAME) supplied"
+ if defined $defaults{$var};
+ return;
+ }
+ $type =~ tr/:/_/ unless $hiertype;
+ blurt("Error: No INPUT definition for type '$type', typekind '$type_kind{$type}' found"), return
+ unless defined $input_expr{$tk} ;
+ $expr = $input_expr{$tk};
+ if ($expr =~ /DO_ARRAY_ELEM/) {
+ blurt("Error: '$subtype' not in typemap"), return
+ unless defined($type_kind{$subtype});
+ blurt("Error: No INPUT definition for type '$subtype', typekind '$type_kind{$subtype}' found"), return
+ unless defined $input_expr{$type_kind{$subtype}} ;
+ $subexpr = $input_expr{$type_kind{$subtype}};
+ $subexpr =~ s/\$type/\$subtype/g;
+ $subexpr =~ s/ntype/subtype/g;
+ $subexpr =~ s/\$arg/ST(ix_$var)/g;
+ $subexpr =~ s/\n\t/\n\t\t/g;
+ $subexpr =~ s/is not of (.*\")/[arg %d] is not of $1, ix_$var + 1/g;
+ $subexpr =~ s/\$var/${var}[ix_$var - $argoff]/;
+ $expr =~ s/DO_ARRAY_ELEM/$subexpr/;
+ }
+ if ($expr =~ m#/\*.*scope.*\*/#i) { # "scope" in C comments
+ $ScopeThisXSUB = 1;
+ }
+ if (defined($defaults{$var})) {
+ $expr =~ s/(\t+)/$1 /g;
+ $expr =~ s/ /\t/g;
+ if ($name_printed) {
+ print ";\n";
+ } else {
+ eval qq/print "\\t$var;\\n"/;
+ warn $@ if $@;
+ }
+ if ($defaults{$var} eq 'NO_INIT') {
+ $deferred .= eval qq/"\\n\\tif (items >= $num) {\\n$expr;\\n\\t}\\n"/;
+ } else {
+ $deferred .= eval qq/"\\n\\tif (items < $num)\\n\\t $var = $defaults{$var};\\n\\telse {\\n$expr;\\n\\t}\\n"/;
+ }
+ warn $@ if $@;
+ } elsif ($ScopeThisXSUB or $expr !~ /^\s*\$var =/) {
+ if ($name_printed) {
+ print ";\n";
+ } else {
+ eval qq/print "\\t$var;\\n"/;
+ warn $@ if $@;
+ }
+ $deferred .= eval qq/"\\n$expr;\\n"/;
+ warn $@ if $@;
+ } else {
+ die "panic: do not know how to handle this branch for function pointers"
+ if $name_printed;
+ eval qq/print "$expr;\\n"/;
+ warn $@ if $@;
+ }
+}
+
+sub generate_output {
+ local($type, $num, $var, $do_setmagic, $do_push) = @_;
+ local($arg) = "ST(" . ($num - ($num != 0)) . ")";
+ local($argoff) = $num - 1;
+ local($ntype);
+
+ $type = TidyType($type) ;
+ if ($type =~ /^array\(([^,]*),(.*)\)/) {
+ print "\t$arg = sv_newmortal();\n";
+ print "\tsv_setpvn($arg, (char *)$var, $2 * sizeof($1));\n";
+ print "\tSvSETMAGIC($arg);\n" if $do_setmagic;
+ } else {
+ blurt("Error: '$type' not in typemap"), return
+ unless defined($type_kind{$type});
+ blurt("Error: No OUTPUT definition for type '$type', typekind '$type_kind{$type}' found"), return
+ unless defined $output_expr{$type_kind{$type}} ;
+ ($ntype = $type) =~ s/\s*\*/Ptr/g;
+ $ntype =~ s/\(\)//g;
+ ($subtype = $ntype) =~ s/(?:Array)?(?:Ptr)?$//;
+ $expr = $output_expr{$type_kind{$type}};
+ if ($expr =~ /DO_ARRAY_ELEM/) {
+ blurt("Error: '$subtype' not in typemap"), return
+ unless defined($type_kind{$subtype});
+ blurt("Error: No OUTPUT definition for type '$subtype', typekind '$type_kind{$subtype}' found"), return
+ unless defined $output_expr{$type_kind{$subtype}} ;
+ $subexpr = $output_expr{$type_kind{$subtype}};
+ $subexpr =~ s/ntype/subtype/g;
+ $subexpr =~ s/\$arg/ST(ix_$var)/g;
+ $subexpr =~ s/\$var/${var}[ix_$var]/g;
+ $subexpr =~ s/\n\t/\n\t\t/g;
+ $expr =~ s/DO_ARRAY_ELEM\n/$subexpr/;
+ eval "print qq\a$expr\a";
+ warn $@ if $@;
+ print "\t\tSvSETMAGIC(ST(ix_$var));\n" if $do_setmagic;
+ } elsif ($var eq 'RETVAL') {
+ if ($expr =~ /^\t\$arg = new/) {
+ # We expect that $arg has refcnt 1, so we need to
+ # mortalize it.
+ eval "print qq\a$expr\a";
+ warn $@ if $@;
+ print "\tsv_2mortal(ST($num));\n";
+ print "\tSvSETMAGIC(ST($num));\n" if $do_setmagic;
+ } elsif ($expr =~ /^\s*\$arg\s*=/) {
+ # We expect that $arg has refcnt >=1, so we need
+ # to mortalize it!
+ eval "print qq\a$expr\a";
+ warn $@ if $@;
+ print "\tsv_2mortal(ST(0));\n";
+ print "\tSvSETMAGIC(ST(0));\n" if $do_setmagic;
+ } else {
+ # Just hope that the entry would safely write it
+ # over an already mortalized value. By
+ # coincidence, something like $arg = &sv_undef
+ # works too.
+ print "\tST(0) = sv_newmortal();\n";
+ eval "print qq\a$expr\a";
+ warn $@ if $@;
+ # new mortals don't have set magic
+ }
+ } elsif ($do_push) {
+ print "\tPUSHs(sv_newmortal());\n";
+ $arg = "ST($num)";
+ eval "print qq\a$expr\a";
+ warn $@ if $@;
+ print "\tSvSETMAGIC($arg);\n" if $do_setmagic;
+ } elsif ($arg =~ /^ST\(\d+\)$/) {
+ eval "print qq\a$expr\a";
+ warn $@ if $@;
+ print "\tSvSETMAGIC($arg);\n" if $do_setmagic;
+ }
+ }
+}
+
+sub map_type {
+ my($type, $varname) = @_;
+
+ # C++ has :: in types too so skip this
+ $type =~ tr/:/_/ unless $hiertype;
+ $type =~ s/^array\(([^,]*),(.*)\).*/$1 */s;
+ if ($varname) {
+ if ($varname && $type =~ / \( \s* \* (?= \s* \) ) /xg) {
+ (substr $type, pos $type, 0) = " $varname ";
+ } else {
+ $type .= "\t$varname";
+ }
+ }
+ $type;
+}
+
+
+#########################################################
+package
+ ExtUtils::ParseXS::CountLines;
+use strict;
+use vars qw($SECTION_END_MARKER);
+
+sub TIEHANDLE {
+ my ($class, $cfile, $fh) = @_;
+ $cfile =~ s/\\/\\\\/g;
+ $SECTION_END_MARKER = qq{#line --- "$cfile"};
+
+ return bless {buffer => '',
+ fh => $fh,
+ line_no => 1,
+ }, $class;
+}
+
+sub PRINT {
+ my $self = shift;
+ for (@_) {
+ $self->{buffer} .= $_;
+ while ($self->{buffer} =~ s/^([^\n]*\n)//) {
+ my $line = $1;
+ ++ $self->{line_no};
+ $line =~ s|^\#line\s+---(?=\s)|#line $self->{line_no}|;
+ print {$self->{fh}} $line;
+ }
+ }
+}
+
+sub PRINTF {
+ my $self = shift;
+ my $fmt = shift;
+ $self->PRINT(sprintf($fmt, @_));
+}
+
+sub DESTROY {
+ # Not necessary if we're careful to end with a "\n"
+ my $self = shift;
+ print {$self->{fh}} $self->{buffer};
+}
+
+sub UNTIE {
+ # This sub does nothing, but is neccessary for references to be released.
+}
+
+sub end_marker {
+ return $SECTION_END_MARKER;
+}
+
+
+1;
+__END__
+
+=head1 NAME
+
+ExtUtils::ParseXS - converts Perl XS code into C code
+
+=head1 SYNOPSIS
+
+ use ExtUtils::ParseXS qw(process_file);
+
+ process_file( filename => 'foo.xs' );
+
+ process_file( filename => 'foo.xs',
+ output => 'bar.c',
+ 'C++' => 1,
+ typemap => 'path/to/typemap',
+ hiertype => 1,
+ except => 1,
+ prototypes => 1,
+ versioncheck => 1,
+ linenumbers => 1,
+ optimize => 1,
+ prototypes => 1,
+ );
+=head1 DESCRIPTION
+
+C<ExtUtils::ParseXS> will compile XS code into C code by embedding the constructs
+necessary to let C functions manipulate Perl values and creates the glue
+necessary to let Perl access those functions. The compiler uses typemaps to
+determine how to map C function parameters and variables to Perl values.
+
+The compiler will search for typemap files called I<typemap>. It will use
+the following search path to find default typemaps, with the rightmost
+typemap taking precedence.
+
+ ../../../typemap:../../typemap:../typemap:typemap
+
+=head1 EXPORT
+
+None by default. C<process_file()> may be exported upon request.
+
+
+=head1 FUNCTIONS
+
+=over 4
+
+=item process_xs()
+
+This function processes an XS file and sends output to a C file.
+Named parameters control how the processing is done. The following
+parameters are accepted:
+
+=over 4
+
+=item B<C++>
+
+Adds C<extern "C"> to the C code. Default is false.
+
+=item B<hiertype>
+
+Retains C<::> in type names so that C++ hierachical types can be
+mapped. Default is false.
+
+=item B<except>
+
+Adds exception handling stubs to the C code. Default is false.
+
+=item B<typemap>
+
+Indicates that a user-supplied typemap should take precedence over the
+default typemaps. A single typemap may be specified as a string, or
+multiple typemaps can be specified in an array reference, with the
+last typemap having the highest precedence.
+
+=item B<prototypes>
+
+Generates prototype code for all xsubs. Default is false.
+
+=item B<versioncheck>
+
+Makes sure at run time that the object file (derived from the C<.xs>
+file) and the C<.pm> files have the same version number. Default is
+true.
+
+=item B<linenumbers>
+
+Adds C<#line> directives to the C output so error messages will look
+like they came from the original XS file. Default is true.
+
+=item B<optimize>
+
+Enables certain optimizations. The only optimization that is currently
+affected is the use of I<target>s by the output C code (see L<perlguts>).
+Not optimizing may significantly slow down the generated code, but this is the way
+B<xsubpp> of 5.005 and earlier operated. Default is to optimize.
+
+=item B<inout>
+
+Enable recognition of C<IN>, C<OUT_LIST> and C<INOUT_LIST>
+declarations. Default is true.
+
+=item B<argtypes>
+
+Enable recognition of ANSI-like descriptions of function signature.
+Default is true.
+
+=item B<s>
+
+I have no clue what this does. Strips function prefixes?
+
+=back
+
+=item errors()
+
+This function returns the number of [a certain kind of] errors
+encountered during processing of the XS file.
+
+=back
+
+=head1 AUTHOR
+
+Based on xsubpp code, written by Larry Wall.
+
+Maintained by:
+
+=over 4
+
+=item *
+
+Ken Williams, <ken@mathforum.org>
+
+=item *
+
+David Golden, <dagolden@cpan.org>
+
+=back
+
+=head1 COPYRIGHT
+
+Copyright 2002-2009 by Ken Williams, David Golden and other contributors. All
+rights reserved.
+
+This library is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+Based on the ExtUtils::xsubpp code by Larry Wall and the Perl 5
+Porters, which was released under the same license terms.
+
+=head1 SEE ALSO
+
+L<perl>, ExtUtils::xsubpp, ExtUtils::MakeMaker, L<perlxs>, L<perlxstut>.
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/testlib.pm b/Master/tlpkg/tlperl/lib/ExtUtils/testlib.pm
new file mode 100644
index 00000000000..fe01beb0e1e
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/testlib.pm
@@ -0,0 +1,41 @@
+package ExtUtils::testlib;
+
+use strict;
+use warnings;
+
+our $VERSION = 6.56;
+
+use Cwd;
+use File::Spec;
+
+# So the tests can chdir around and not break @INC.
+# We use getcwd() because otherwise rel2abs will blow up under taint
+# mode pre-5.8. We detaint is so @INC won't be tainted. This is
+# no worse, and probably better, than just shoving an untainted,
+# relative "blib/lib" onto @INC.
+my $cwd;
+BEGIN {
+ ($cwd) = getcwd() =~ /(.*)/;
+}
+use lib map { File::Spec->rel2abs($_, $cwd) } qw(blib/arch blib/lib);
+1;
+__END__
+
+=head1 NAME
+
+ExtUtils::testlib - add blib/* directories to @INC
+
+=head1 SYNOPSIS
+
+ use ExtUtils::testlib;
+
+=head1 DESCRIPTION
+
+After an extension has been built and before it is installed it may be
+desirable to test it bypassing C<make test>. By adding
+
+ use ExtUtils::testlib;
+
+to a test program the intermediate directories used by C<make> are
+added to @INC.
+
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/typemap b/Master/tlpkg/tlperl/lib/ExtUtils/typemap
new file mode 100644
index 00000000000..f88858762d5
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/typemap
@@ -0,0 +1,336 @@
+# basic C types
+int T_IV
+unsigned T_UV
+unsigned int T_UV
+long T_IV
+unsigned long T_UV
+short T_IV
+unsigned short T_UV
+char T_CHAR
+unsigned char T_U_CHAR
+char * T_PV
+unsigned char * T_PV
+const char * T_PV
+caddr_t T_PV
+wchar_t * T_PV
+wchar_t T_IV
+# bool_t is defined in <rpc/rpc.h>
+bool_t T_IV
+size_t T_UV
+ssize_t T_IV
+time_t T_NV
+unsigned long * T_OPAQUEPTR
+char ** T_PACKEDARRAY
+void * T_PTR
+Time_t * T_PV
+SV * T_SV
+SVREF T_SVREF
+AV * T_AVREF
+HV * T_HVREF
+CV * T_CVREF
+
+IV T_IV
+UV T_UV
+NV T_NV
+I32 T_IV
+I16 T_IV
+I8 T_IV
+STRLEN T_UV
+U32 T_U_LONG
+U16 T_U_SHORT
+U8 T_UV
+Result T_U_CHAR
+Boolean T_BOOL
+float T_FLOAT
+double T_DOUBLE
+SysRet T_SYSRET
+SysRetLong T_SYSRET
+FILE * T_STDIO
+PerlIO * T_INOUT
+FileHandle T_PTROBJ
+InputStream T_IN
+InOutStream T_INOUT
+OutputStream T_OUT
+bool T_BOOL
+
+#############################################################################
+INPUT
+T_SV
+ $var = $arg
+T_SVREF
+ if (SvROK($arg))
+ $var = (SV*)SvRV($arg);
+ else
+ Perl_croak(aTHX_ \"%s: %s is not a reference\",
+ ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
+ \"$var\")
+T_AVREF
+ if (SvROK($arg) && SvTYPE(SvRV($arg))==SVt_PVAV)
+ $var = (AV*)SvRV($arg);
+ else
+ Perl_croak(aTHX_ \"%s: %s is not an array reference\",
+ ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
+ \"$var\")
+T_HVREF
+ if (SvROK($arg) && SvTYPE(SvRV($arg))==SVt_PVHV)
+ $var = (HV*)SvRV($arg);
+ else
+ Perl_croak(aTHX_ \"%s: %s is not a hash reference\",
+ ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
+ \"$var\")
+T_CVREF
+ if (SvROK($arg) && SvTYPE(SvRV($arg))==SVt_PVCV)
+ $var = (CV*)SvRV($arg);
+ else
+ Perl_croak(aTHX_ \"%s: %s is not a code reference\",
+ ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
+ \"$var\")
+T_SYSRET
+ $var NOT IMPLEMENTED
+T_UV
+ $var = ($type)SvUV($arg)
+T_IV
+ $var = ($type)SvIV($arg)
+T_INT
+ $var = (int)SvIV($arg)
+T_ENUM
+ $var = ($type)SvIV($arg)
+T_BOOL
+ $var = (bool)SvTRUE($arg)
+T_U_INT
+ $var = (unsigned int)SvUV($arg)
+T_SHORT
+ $var = (short)SvIV($arg)
+T_U_SHORT
+ $var = (unsigned short)SvUV($arg)
+T_LONG
+ $var = (long)SvIV($arg)
+T_U_LONG
+ $var = (unsigned long)SvUV($arg)
+T_CHAR
+ $var = (char)*SvPV_nolen($arg)
+T_U_CHAR
+ $var = (unsigned char)SvUV($arg)
+T_FLOAT
+ $var = (float)SvNV($arg)
+T_NV
+ $var = ($type)SvNV($arg)
+T_DOUBLE
+ $var = (double)SvNV($arg)
+T_PV
+ $var = ($type)SvPV_nolen($arg)
+T_PTR
+ $var = INT2PTR($type,SvIV($arg))
+T_PTRREF
+ if (SvROK($arg)) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ $var = INT2PTR($type,tmp);
+ }
+ else
+ Perl_croak(aTHX_ \"%s: %s is not a reference\",
+ ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
+ \"$var\")
+T_REF_IV_REF
+ if (sv_isa($arg, \"${ntype}\")) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ $var = *INT2PTR($type *, tmp);
+ }
+ else
+ Perl_croak(aTHX_ \"%s: %s is not of type %s\",
+ ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
+ \"$var\", \"$ntype\")
+T_REF_IV_PTR
+ if (sv_isa($arg, \"${ntype}\")) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ $var = INT2PTR($type, tmp);
+ }
+ else
+ Perl_croak(aTHX_ \"%s: %s is not of type %s\",
+ ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
+ \"$var\", \"$ntype\")
+T_PTROBJ
+ if (SvROK($arg) && sv_derived_from($arg, \"${ntype}\")) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ $var = INT2PTR($type,tmp);
+ }
+ else
+ Perl_croak(aTHX_ \"%s: %s is not of type %s\",
+ ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
+ \"$var\", \"$ntype\")
+T_PTRDESC
+ if (sv_isa($arg, \"${ntype}\")) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ ${type}_desc = (\U${type}_DESC\E*) tmp;
+ $var = ${type}_desc->ptr;
+ }
+ else
+ Perl_croak(aTHX_ \"%s: %s is not of type %s\",
+ ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
+ \"$var\", \"$ntype\")
+T_REFREF
+ if (SvROK($arg)) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ $var = *INT2PTR($type,tmp);
+ }
+ else
+ Perl_croak(aTHX_ \"%s: %s is not a reference\",
+ ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
+ \"$var\")
+T_REFOBJ
+ if (sv_isa($arg, \"${ntype}\")) {
+ IV tmp = SvIV((SV*)SvRV($arg));
+ $var = *INT2PTR($type,tmp);
+ }
+ else
+ Perl_croak(aTHX_ \"%s: %s is not of type %s\",
+ ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
+ \"$var\", \"$ntype\")
+T_OPAQUE
+ $var = *($type *)SvPV_nolen($arg)
+T_OPAQUEPTR
+ $var = ($type)SvPV_nolen($arg)
+T_PACKED
+ $var = XS_unpack_$ntype($arg)
+T_PACKEDARRAY
+ $var = XS_unpack_$ntype($arg)
+T_CALLBACK
+ $var = make_perl_cb_$type($arg)
+T_ARRAY
+ U32 ix_$var = $argoff;
+ $var = $ntype(items -= $argoff);
+ while (items--) {
+ DO_ARRAY_ELEM;
+ ix_$var++;
+ }
+ /* this is the number of elements in the array */
+ ix_$var -= $argoff
+T_STDIO
+ $var = PerlIO_findFILE(IoIFP(sv_2io($arg)))
+T_IN
+ $var = IoIFP(sv_2io($arg))
+T_INOUT
+ $var = IoIFP(sv_2io($arg))
+T_OUT
+ $var = IoOFP(sv_2io($arg))
+#############################################################################
+OUTPUT
+T_SV
+ $arg = $var;
+T_SVREF
+ $arg = newRV((SV*)$var);
+T_AVREF
+ $arg = newRV((SV*)$var);
+T_HVREF
+ $arg = newRV((SV*)$var);
+T_CVREF
+ $arg = newRV((SV*)$var);
+T_IV
+ sv_setiv($arg, (IV)$var);
+T_UV
+ sv_setuv($arg, (UV)$var);
+T_INT
+ sv_setiv($arg, (IV)$var);
+T_SYSRET
+ if ($var != -1) {
+ if ($var == 0)
+ sv_setpvn($arg, "0 but true", 10);
+ else
+ sv_setiv($arg, (IV)$var);
+ }
+T_ENUM
+ sv_setiv($arg, (IV)$var);
+T_BOOL
+ $arg = boolSV($var);
+T_U_INT
+ sv_setuv($arg, (UV)$var);
+T_SHORT
+ sv_setiv($arg, (IV)$var);
+T_U_SHORT
+ sv_setuv($arg, (UV)$var);
+T_LONG
+ sv_setiv($arg, (IV)$var);
+T_U_LONG
+ sv_setuv($arg, (UV)$var);
+T_CHAR
+ sv_setpvn($arg, (char *)&$var, 1);
+T_U_CHAR
+ sv_setuv($arg, (UV)$var);
+T_FLOAT
+ sv_setnv($arg, (double)$var);
+T_NV
+ sv_setnv($arg, (NV)$var);
+T_DOUBLE
+ sv_setnv($arg, (double)$var);
+T_PV
+ sv_setpv((SV*)$arg, $var);
+T_PTR
+ sv_setiv($arg, PTR2IV($var));
+T_PTRREF
+ sv_setref_pv($arg, Nullch, (void*)$var);
+T_REF_IV_REF
+ sv_setref_pv($arg, \"${ntype}\", (void*)new $ntype($var));
+T_REF_IV_PTR
+ sv_setref_pv($arg, \"${ntype}\", (void*)$var);
+T_PTROBJ
+ sv_setref_pv($arg, \"${ntype}\", (void*)$var);
+T_PTRDESC
+ sv_setref_pv($arg, \"${ntype}\", (void*)new\U${type}_DESC\E($var));
+T_REFREF
+ NOT_IMPLEMENTED
+T_REFOBJ
+ NOT IMPLEMENTED
+T_OPAQUE
+ sv_setpvn($arg, (char *)&$var, sizeof($var));
+T_OPAQUEPTR
+ sv_setpvn($arg, (char *)$var, sizeof(*$var));
+T_PACKED
+ XS_pack_$ntype($arg, $var);
+T_PACKEDARRAY
+ XS_pack_$ntype($arg, $var, count_$ntype);
+T_DATAUNIT
+ sv_setpvn($arg, $var.chp(), $var.size());
+T_CALLBACK
+ sv_setpvn($arg, $var.context.value().chp(),
+ $var.context.value().size());
+T_ARRAY
+ {
+ U32 ix_$var;
+ EXTEND(SP,size_$var);
+ for (ix_$var = 0; ix_$var < size_$var; ix_$var++) {
+ ST(ix_$var) = sv_newmortal();
+ DO_ARRAY_ELEM
+ }
+ }
+T_STDIO
+ {
+ GV *gv = newGVgen("$Package");
+ PerlIO *fp = PerlIO_importFILE($var,0);
+ if ( fp && do_open(gv, "+<&", 3, FALSE, 0, 0, fp) )
+ sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1)));
+ else
+ $arg = &PL_sv_undef;
+ }
+T_IN
+ {
+ GV *gv = newGVgen("$Package");
+ if ( do_open(gv, "<&", 2, FALSE, 0, 0, $var) )
+ sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1)));
+ else
+ $arg = &PL_sv_undef;
+ }
+T_INOUT
+ {
+ GV *gv = newGVgen("$Package");
+ if ( do_open(gv, "+<&", 3, FALSE, 0, 0, $var) )
+ sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1)));
+ else
+ $arg = &PL_sv_undef;
+ }
+T_OUT
+ {
+ GV *gv = newGVgen("$Package");
+ if ( do_open(gv, "+>&", 3, FALSE, 0, 0, $var) )
+ sv_setsv($arg, sv_bless(newRV((SV*)gv), gv_stashpv("$Package",1)));
+ else
+ $arg = &PL_sv_undef;
+ }
diff --git a/Master/tlpkg/tlperl/lib/ExtUtils/xsubpp b/Master/tlpkg/tlperl/lib/ExtUtils/xsubpp
new file mode 100644
index 00000000000..e4e5b774d82
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/ExtUtils/xsubpp
@@ -0,0 +1,156 @@
+#!./miniperl
+
+require 5.002;
+use ExtUtils::ParseXS qw(process_file);
+use Getopt::Long;
+
+my %args = ();
+
+my $usage = "Usage: xsubpp [-v] [-csuffix csuffix] [-except] [-prototypes] [-noversioncheck] [-nolinenumbers] [-nooptimize] [-noinout] [-noargtypes] [-s pattern] [-typemap typemap]... file.xs\n";
+
+Getopt::Long::Configure qw(no_auto_abbrev no_ignore_case);
+
+@ARGV = grep {$_ ne '-C++'} @ARGV; # Allow -C++ for backward compatibility
+GetOptions(\%args, qw(hiertype!
+ prototypes!
+ versioncheck!
+ linenumbers!
+ optimize!
+ inout!
+ argtypes!
+ object_capi!
+ except!
+ v
+ typemap=s@
+ output=s
+ s=s
+ csuffix=s
+ ))
+ or die $usage;
+
+if ($args{v}) {
+ print "xsubpp version $ExtUtils::ParseXS::VERSION\n";
+ exit;
+}
+
+@ARGV == 1 or die $usage;
+
+$args{filename} = shift @ARGV;
+
+process_file(%args);
+exit( ExtUtils::ParseXS::errors() ? 1 : 0 );
+
+__END__
+
+=head1 NAME
+
+xsubpp - compiler to convert Perl XS code into C code
+
+=head1 SYNOPSIS
+
+B<xsubpp> [B<-v>] [B<-except>] [B<-s pattern>] [B<-prototypes>] [B<-noversioncheck>] [B<-nolinenumbers>] [B<-nooptimize>] [B<-typemap typemap>] [B<-output filename>]... file.xs
+
+=head1 DESCRIPTION
+
+This compiler is typically run by the makefiles created by L<ExtUtils::MakeMaker>.
+
+I<xsubpp> will compile XS code into C code by embedding the constructs
+necessary to let C functions manipulate Perl values and creates the glue
+necessary to let Perl access those functions. The compiler uses typemaps to
+determine how to map C function parameters and variables to Perl values.
+
+The compiler will search for typemap files called I<typemap>. It will use
+the following search path to find default typemaps, with the rightmost
+typemap taking precedence.
+
+ ../../../typemap:../../typemap:../typemap:typemap
+
+It will also use a default typemap installed as C<ExtUtils::typemap>.
+
+=head1 OPTIONS
+
+Note that the C<XSOPT> MakeMaker option may be used to add these options to
+any makefiles generated by MakeMaker.
+
+=over 5
+
+=item B<-hiertype>
+
+Retains '::' in type names so that C++ hierarchical types can be mapped.
+
+=item B<-except>
+
+Adds exception handling stubs to the C code.
+
+=item B<-typemap typemap>
+
+Indicates that a user-supplied typemap should take precedence over the
+default typemaps. This option may be used multiple times, with the last
+typemap having the highest precedence.
+
+=item B<-output filename>
+
+Specifies the name of the output file to generate. If no file is
+specified, output will be written to standard output.
+
+=item B<-v>
+
+Prints the I<xsubpp> version number to standard output, then exits.
+
+=item B<-prototypes>
+
+By default I<xsubpp> will not automatically generate prototype code for
+all xsubs. This flag will enable prototypes.
+
+=item B<-noversioncheck>
+
+Disables the run time test that determines if the object file (derived
+from the C<.xs> file) and the C<.pm> files have the same version
+number.
+
+=item B<-nolinenumbers>
+
+Prevents the inclusion of `#line' directives in the output.
+
+=item B<-nooptimize>
+
+Disables certain optimizations. The only optimization that is currently
+affected is the use of I<target>s by the output C code (see L<perlguts>).
+This may significantly slow down the generated code, but this is the way
+B<xsubpp> of 5.005 and earlier operated.
+
+=item B<-noinout>
+
+Disable recognition of C<IN>, C<OUT_LIST> and C<INOUT_LIST> declarations.
+
+=item B<-noargtypes>
+
+Disable recognition of ANSI-like descriptions of function signature.
+
+=item B<-C++>
+
+Currently doesn't do anything at all. This flag has been a no-op for
+many versions of perl, at least as far back as perl5.003_07. It's
+allowed here for backwards compatibility.
+
+=back
+
+=head1 ENVIRONMENT
+
+No environment variables are used.
+
+=head1 AUTHOR
+
+Originally by Larry Wall. Turned into the C<ExtUtils::ParseXS> module
+by Ken Williams.
+
+=head1 MODIFICATION HISTORY
+
+See the file F<Changes>.
+
+=head1 SEE ALSO
+
+perl(1), perlxs(1), perlxstut(1), ExtUtils::ParseXS
+
+=cut
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Compress/Adapter/Bzip2.pm b/Master/tlpkg/tlperl/lib/IO/Compress/Adapter/Bzip2.pm
new file mode 100644
index 00000000000..3e2e89f8e12
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Compress/Adapter/Bzip2.pm
@@ -0,0 +1,162 @@
+package IO::Compress::Adapter::Bzip2 ;
+
+use strict;
+use warnings;
+use bytes;
+
+use IO::Compress::Base::Common 2.024 qw(:Status);
+
+#use Compress::Bzip2 ;
+use Compress::Raw::Bzip2 2.024 ;
+
+our ($VERSION);
+$VERSION = '2.024';
+
+sub mkCompObject
+{
+ my $BlockSize100K = shift ;
+ my $WorkFactor = shift ;
+ my $Verbosity = shift ;
+
+ my ($def, $status) = new Compress::Raw::Bzip2(1, $BlockSize100K,
+ $WorkFactor, $Verbosity);
+ #my ($def, $status) = bzdeflateInit();
+ #-BlockSize100K => $params->value('BlockSize100K'),
+ #-WorkFactor => $params->value('WorkFactor');
+
+ return (undef, "Could not create Deflate object: $status", $status)
+ if $status != BZ_OK ;
+
+ return bless {'Def' => $def,
+ 'Error' => '',
+ 'ErrorNo' => 0,
+ } ;
+}
+
+sub compr
+{
+ my $self = shift ;
+
+ my $def = $self->{Def};
+
+ #my ($out, $status) = $def->bzdeflate(defined ${$_[0]} ? ${$_[0]} : "") ;
+ my $status = $def->bzdeflate($_[0], $_[1]) ;
+ $self->{ErrorNo} = $status;
+
+ if ($status != BZ_RUN_OK)
+ {
+ $self->{Error} = "Deflate Error: $status";
+ return STATUS_ERROR;
+ }
+
+ #${ $_[1] } .= $out if defined $out;
+
+ return STATUS_OK;
+}
+
+sub flush
+{
+ my $self = shift ;
+
+ my $def = $self->{Def};
+
+ #my ($out, $status) = $def->bzflush($opt);
+ #my $status = $def->bzflush($_[0], $opt);
+ my $status = $def->bzflush($_[0]);
+ $self->{ErrorNo} = $status;
+
+ if ($status != BZ_RUN_OK)
+ {
+ $self->{Error} = "Deflate Error: $status";
+ return STATUS_ERROR;
+ }
+
+ #${ $_[0] } .= $out if defined $out ;
+ return STATUS_OK;
+
+}
+
+sub close
+{
+ my $self = shift ;
+
+ my $def = $self->{Def};
+
+ #my ($out, $status) = $def->bzclose();
+ my $status = $def->bzclose($_[0]);
+ $self->{ErrorNo} = $status;
+
+ if ($status != BZ_STREAM_END)
+ {
+ $self->{Error} = "Deflate Error: $status";
+ return STATUS_ERROR;
+ }
+
+ #${ $_[0] } .= $out if defined $out ;
+ return STATUS_OK;
+
+}
+
+
+sub reset
+{
+ my $self = shift ;
+
+ my $outer = $self->{Outer};
+
+ my ($def, $status) = new Compress::Raw::Bzip2();
+ $self->{ErrorNo} = ($status == BZ_OK) ? 0 : $status ;
+
+ if ($status != BZ_OK)
+ {
+ $self->{Error} = "Cannot create Deflate object: $status";
+ return STATUS_ERROR;
+ }
+
+ $self->{Def} = $def;
+
+ return STATUS_OK;
+}
+
+sub compressedBytes
+{
+ my $self = shift ;
+ $self->{Def}->compressedBytes();
+}
+
+sub uncompressedBytes
+{
+ my $self = shift ;
+ $self->{Def}->uncompressedBytes();
+}
+
+#sub total_out
+#{
+# my $self = shift ;
+# 0;
+#}
+#
+
+#sub total_in
+#{
+# my $self = shift ;
+# $self->{Def}->total_in();
+#}
+#
+#sub crc32
+#{
+# my $self = shift ;
+# $self->{Def}->crc32();
+#}
+#
+#sub adler32
+#{
+# my $self = shift ;
+# $self->{Def}->adler32();
+#}
+
+
+1;
+
+__END__
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Compress/Adapter/Deflate.pm b/Master/tlpkg/tlperl/lib/IO/Compress/Adapter/Deflate.pm
new file mode 100644
index 00000000000..f23a9819c67
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Compress/Adapter/Deflate.pm
@@ -0,0 +1,165 @@
+package IO::Compress::Adapter::Deflate ;
+
+use strict;
+use warnings;
+use bytes;
+
+use IO::Compress::Base::Common 2.024 qw(:Status);
+
+use Compress::Raw::Zlib 2.024 qw(Z_OK Z_FINISH MAX_WBITS) ;
+our ($VERSION);
+
+$VERSION = '2.024';
+
+sub mkCompObject
+{
+ my $crc32 = shift ;
+ my $adler32 = shift ;
+ my $level = shift ;
+ my $strategy = shift ;
+
+ my ($def, $status) = new Compress::Raw::Zlib::Deflate
+ -AppendOutput => 1,
+ -CRC32 => $crc32,
+ -ADLER32 => $adler32,
+ -Level => $level,
+ -Strategy => $strategy,
+ -WindowBits => - MAX_WBITS;
+
+ return (undef, "Cannot create Deflate object: $status", $status)
+ if $status != Z_OK;
+
+ return bless {'Def' => $def,
+ 'Error' => '',
+ } ;
+}
+
+sub compr
+{
+ my $self = shift ;
+
+ my $def = $self->{Def};
+
+ my $status = $def->deflate($_[0], $_[1]) ;
+ $self->{ErrorNo} = $status;
+
+ if ($status != Z_OK)
+ {
+ $self->{Error} = "Deflate Error: $status";
+ return STATUS_ERROR;
+ }
+
+ return STATUS_OK;
+}
+
+sub flush
+{
+ my $self = shift ;
+
+ my $def = $self->{Def};
+
+ my $opt = $_[1] || Z_FINISH;
+ my $status = $def->flush($_[0], $opt);
+ $self->{ErrorNo} = $status;
+
+ if ($status != Z_OK)
+ {
+ $self->{Error} = "Deflate Error: $status";
+ return STATUS_ERROR;
+ }
+
+ return STATUS_OK;
+
+}
+
+sub close
+{
+ my $self = shift ;
+
+ my $def = $self->{Def};
+
+ $def->flush($_[0], Z_FINISH)
+ if defined $def ;
+}
+
+sub reset
+{
+ my $self = shift ;
+
+ my $def = $self->{Def};
+
+ my $status = $def->deflateReset() ;
+ $self->{ErrorNo} = $status;
+ if ($status != Z_OK)
+ {
+ $self->{Error} = "Deflate Error: $status";
+ return STATUS_ERROR;
+ }
+
+ return STATUS_OK;
+}
+
+sub deflateParams
+{
+ my $self = shift ;
+
+ my $def = $self->{Def};
+
+ my $status = $def->deflateParams(@_);
+ $self->{ErrorNo} = $status;
+ if ($status != Z_OK)
+ {
+ $self->{Error} = "deflateParams Error: $status";
+ return STATUS_ERROR;
+ }
+
+ return STATUS_OK;
+}
+
+
+
+#sub total_out
+#{
+# my $self = shift ;
+# $self->{Def}->total_out();
+#}
+#
+#sub total_in
+#{
+# my $self = shift ;
+# $self->{Def}->total_in();
+#}
+
+sub compressedBytes
+{
+ my $self = shift ;
+
+ $self->{Def}->compressedBytes();
+}
+
+sub uncompressedBytes
+{
+ my $self = shift ;
+ $self->{Def}->uncompressedBytes();
+}
+
+
+
+
+sub crc32
+{
+ my $self = shift ;
+ $self->{Def}->crc32();
+}
+
+sub adler32
+{
+ my $self = shift ;
+ $self->{Def}->adler32();
+}
+
+
+1;
+
+__END__
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Compress/Adapter/Identity.pm b/Master/tlpkg/tlperl/lib/IO/Compress/Adapter/Identity.pm
new file mode 100644
index 00000000000..16f14d8e7f3
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Compress/Adapter/Identity.pm
@@ -0,0 +1,101 @@
+package IO::Compress::Adapter::Identity ;
+
+use strict;
+use warnings;
+use bytes;
+
+use IO::Compress::Base::Common 2.024 qw(:Status);
+our ($VERSION);
+
+$VERSION = '2.024';
+
+sub mkCompObject
+{
+ my $level = shift ;
+ my $strategy = shift ;
+
+ return bless {
+ 'CompSize' => 0,
+ 'UnCompSize' => 0,
+ 'Error' => '',
+ 'ErrorNo' => 0,
+ } ;
+}
+
+sub compr
+{
+ my $self = shift ;
+
+ if (defined ${ $_[0] } && length ${ $_[0] }) {
+ $self->{CompSize} += length ${ $_[0] } ;
+ $self->{UnCompSize} = $self->{CompSize} ;
+
+ if ( ref $_[1] )
+ { ${ $_[1] } .= ${ $_[0] } }
+ else
+ { $_[1] .= ${ $_[0] } }
+ }
+
+ return STATUS_OK ;
+}
+
+sub flush
+{
+ my $self = shift ;
+
+ return STATUS_OK;
+}
+
+sub close
+{
+ my $self = shift ;
+
+ return STATUS_OK;
+}
+
+sub reset
+{
+ my $self = shift ;
+
+ $self->{CompSize} = 0;
+ $self->{UnCompSize} = 0;
+
+ return STATUS_OK;
+}
+
+sub deflateParams
+{
+ my $self = shift ;
+
+ return STATUS_OK;
+}
+
+#sub total_out
+#{
+# my $self = shift ;
+# return $self->{UnCompSize} ;
+#}
+#
+#sub total_in
+#{
+# my $self = shift ;
+# return $self->{UnCompSize} ;
+#}
+
+sub compressedBytes
+{
+ my $self = shift ;
+ return $self->{UnCompSize} ;
+}
+
+sub uncompressedBytes
+{
+ my $self = shift ;
+ return $self->{UnCompSize} ;
+}
+
+1;
+
+
+__END__
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Compress/Base.pm b/Master/tlpkg/tlperl/lib/IO/Compress/Base.pm
new file mode 100644
index 00000000000..5a20f60007b
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Compress/Base.pm
@@ -0,0 +1,981 @@
+
+package IO::Compress::Base ;
+
+require 5.004 ;
+
+use strict ;
+use warnings;
+
+use IO::Compress::Base::Common 2.024 ;
+
+use IO::File ;
+use Scalar::Util qw(blessed readonly);
+
+#use File::Glob;
+#require Exporter ;
+use Carp ;
+use Symbol;
+use bytes;
+
+our (@ISA, $VERSION);
+@ISA = qw(Exporter IO::File);
+
+$VERSION = '2.024';
+
+#Can't locate object method "SWASHNEW" via package "utf8" (perhaps you forgot to load "utf8"?) at .../ext/Compress-Zlib/Gzip/blib/lib/Compress/Zlib/Common.pm line 16.
+
+sub saveStatus
+{
+ my $self = shift ;
+ ${ *$self->{ErrorNo} } = shift() + 0 ;
+ ${ *$self->{Error} } = '' ;
+
+ return ${ *$self->{ErrorNo} } ;
+}
+
+
+sub saveErrorString
+{
+ my $self = shift ;
+ my $retval = shift ;
+ ${ *$self->{Error} } = shift ;
+ ${ *$self->{ErrorNo} } = shift() + 0 if @_ ;
+
+ return $retval;
+}
+
+sub croakError
+{
+ my $self = shift ;
+ $self->saveErrorString(0, $_[0]);
+ croak $_[0];
+}
+
+sub closeError
+{
+ my $self = shift ;
+ my $retval = shift ;
+
+ my $errno = *$self->{ErrorNo};
+ my $error = ${ *$self->{Error} };
+
+ $self->close();
+
+ *$self->{ErrorNo} = $errno ;
+ ${ *$self->{Error} } = $error ;
+
+ return $retval;
+}
+
+
+
+sub error
+{
+ my $self = shift ;
+ return ${ *$self->{Error} } ;
+}
+
+sub errorNo
+{
+ my $self = shift ;
+ return ${ *$self->{ErrorNo} } ;
+}
+
+
+sub writeAt
+{
+ my $self = shift ;
+ my $offset = shift;
+ my $data = shift;
+
+ if (defined *$self->{FH}) {
+ my $here = tell(*$self->{FH});
+ return $self->saveErrorString(undef, "Cannot seek to end of output filehandle: $!", $!)
+ if $here < 0 ;
+ seek(*$self->{FH}, $offset, SEEK_SET)
+ or return $self->saveErrorString(undef, "Cannot seek to end of output filehandle: $!", $!) ;
+ defined *$self->{FH}->write($data, length $data)
+ or return $self->saveErrorString(undef, $!, $!) ;
+ seek(*$self->{FH}, $here, SEEK_SET)
+ or return $self->saveErrorString(undef, "Cannot seek to end of output filehandle: $!", $!) ;
+ }
+ else {
+ substr(${ *$self->{Buffer} }, $offset, length($data)) = $data ;
+ }
+
+ return 1;
+}
+
+sub output
+{
+ my $self = shift ;
+ my $data = shift ;
+ my $last = shift ;
+
+ return 1
+ if length $data == 0 && ! $last ;
+
+ if ( *$self->{FilterEnvelope} ) {
+ *_ = \$data;
+ &{ *$self->{FilterEnvelope} }();
+ }
+
+ if (length $data) {
+ if ( defined *$self->{FH} ) {
+ defined *$self->{FH}->write( $data, length $data )
+ or return $self->saveErrorString(0, $!, $!);
+ }
+ else {
+ ${ *$self->{Buffer} } .= $data ;
+ }
+ }
+
+ return 1;
+}
+
+sub getOneShotParams
+{
+ return ( 'MultiStream' => [1, 1, Parse_boolean, 1],
+ );
+}
+
+sub checkParams
+{
+ my $self = shift ;
+ my $class = shift ;
+
+ my $got = shift || IO::Compress::Base::Parameters::new();
+
+ $got->parse(
+ {
+ # Generic Parameters
+ 'AutoClose' => [1, 1, Parse_boolean, 0],
+ #'Encode' => [1, 1, Parse_any, undef],
+ 'Strict' => [0, 1, Parse_boolean, 1],
+ 'Append' => [1, 1, Parse_boolean, 0],
+ 'BinModeIn' => [1, 1, Parse_boolean, 0],
+
+ 'FilterEnvelope' => [1, 1, Parse_any, undef],
+
+ $self->getExtraParams(),
+ *$self->{OneShot} ? $self->getOneShotParams()
+ : (),
+ },
+ @_) or $self->croakError("${class}: $got->{Error}") ;
+
+ return $got ;
+}
+
+sub _create
+{
+ my $obj = shift;
+ my $got = shift;
+
+ *$obj->{Closed} = 1 ;
+
+ my $class = ref $obj;
+ $obj->croakError("$class: Missing Output parameter")
+ if ! @_ && ! $got ;
+
+ my $outValue = shift ;
+ my $oneShot = 1 ;
+
+ if (! $got)
+ {
+ $oneShot = 0 ;
+ $got = $obj->checkParams($class, undef, @_)
+ or return undef ;
+ }
+
+ my $lax = ! $got->value('Strict') ;
+
+ my $outType = whatIsOutput($outValue);
+
+ $obj->ckOutputParam($class, $outValue)
+ or return undef ;
+
+ if ($outType eq 'buffer') {
+ *$obj->{Buffer} = $outValue;
+ }
+ else {
+ my $buff = "" ;
+ *$obj->{Buffer} = \$buff ;
+ }
+
+ # Merge implies Append
+ my $merge = $got->value('Merge') ;
+ my $appendOutput = $got->value('Append') || $merge ;
+ *$obj->{Append} = $appendOutput;
+ *$obj->{FilterEnvelope} = $got->value('FilterEnvelope') ;
+
+ if ($merge)
+ {
+ # Switch off Merge mode if output file/buffer is empty/doesn't exist
+ if (($outType eq 'buffer' && length $$outValue == 0 ) ||
+ ($outType ne 'buffer' && (! -e $outValue || (-w _ && -z _))) )
+ { $merge = 0 }
+ }
+
+ # If output is a file, check that it is writable
+ #no warnings;
+ #if ($outType eq 'filename' && -e $outValue && ! -w _)
+ # { return $obj->saveErrorString(undef, "Output file '$outValue' is not writable" ) }
+
+
+
+ if ($got->parsed('Encode')) {
+ my $want_encoding = $got->value('Encode');
+ *$obj->{Encoding} = getEncoding($obj, $class, $want_encoding);
+ }
+
+ $obj->ckParams($got)
+ or $obj->croakError("${class}: " . $obj->error());
+
+
+ $obj->saveStatus(STATUS_OK) ;
+
+ my $status ;
+ if (! $merge)
+ {
+ *$obj->{Compress} = $obj->mkComp($got)
+ or return undef;
+
+ *$obj->{UnCompSize} = new U64 ;
+ *$obj->{CompSize} = new U64 ;
+
+ if ( $outType eq 'buffer') {
+ ${ *$obj->{Buffer} } = ''
+ unless $appendOutput ;
+ }
+ else {
+ if ($outType eq 'handle') {
+ *$obj->{FH} = $outValue ;
+ setBinModeOutput(*$obj->{FH}) ;
+ $outValue->flush() ;
+ *$obj->{Handle} = 1 ;
+ if ($appendOutput)
+ {
+ seek(*$obj->{FH}, 0, SEEK_END)
+ or return $obj->saveErrorString(undef, "Cannot seek to end of output filehandle: $!", $!) ;
+
+ }
+ }
+ elsif ($outType eq 'filename') {
+ no warnings;
+ my $mode = '>' ;
+ $mode = '>>'
+ if $appendOutput;
+ *$obj->{FH} = new IO::File "$mode $outValue"
+ or return $obj->saveErrorString(undef, "cannot open file '$outValue': $!", $!) ;
+ *$obj->{StdIO} = ($outValue eq '-');
+ setBinModeOutput(*$obj->{FH}) ;
+ }
+ }
+
+ *$obj->{Header} = $obj->mkHeader($got) ;
+ $obj->output( *$obj->{Header} )
+ or return undef;
+ }
+ else
+ {
+ *$obj->{Compress} = $obj->createMerge($outValue, $outType)
+ or return undef;
+ }
+
+ *$obj->{Closed} = 0 ;
+ *$obj->{AutoClose} = $got->value('AutoClose') ;
+ *$obj->{Output} = $outValue;
+ *$obj->{ClassName} = $class;
+ *$obj->{Got} = $got;
+ *$obj->{OneShot} = 0 ;
+
+ return $obj ;
+}
+
+sub ckOutputParam
+{
+ my $self = shift ;
+ my $from = shift ;
+ my $outType = whatIsOutput($_[0]);
+
+ $self->croakError("$from: output parameter not a filename, filehandle or scalar ref")
+ if ! $outType ;
+
+ #$self->croakError("$from: output filename is undef or null string")
+ #if $outType eq 'filename' && (! defined $_[0] || $_[0] eq '') ;
+
+ $self->croakError("$from: output buffer is read-only")
+ if $outType eq 'buffer' && readonly(${ $_[0] });
+
+ return 1;
+}
+
+
+sub _def
+{
+ my $obj = shift ;
+
+ my $class= (caller)[0] ;
+ my $name = (caller(1))[3] ;
+
+ $obj->croakError("$name: expected at least 1 parameters\n")
+ unless @_ >= 1 ;
+
+ my $input = shift ;
+ my $haveOut = @_ ;
+ my $output = shift ;
+
+ my $x = new IO::Compress::Base::Validator($class, *$obj->{Error}, $name, $input, $output)
+ or return undef ;
+
+ push @_, $output if $haveOut && $x->{Hash};
+
+ *$obj->{OneShot} = 1 ;
+
+ my $got = $obj->checkParams($name, undef, @_)
+ or return undef ;
+
+ $x->{Got} = $got ;
+
+# if ($x->{Hash})
+# {
+# while (my($k, $v) = each %$input)
+# {
+# $v = \$input->{$k}
+# unless defined $v ;
+#
+# $obj->_singleTarget($x, 1, $k, $v, @_)
+# or return undef ;
+# }
+#
+# return keys %$input ;
+# }
+
+ if ($x->{GlobMap})
+ {
+ $x->{oneInput} = 1 ;
+ foreach my $pair (@{ $x->{Pairs} })
+ {
+ my ($from, $to) = @$pair ;
+ $obj->_singleTarget($x, 1, $from, $to, @_)
+ or return undef ;
+ }
+
+ return scalar @{ $x->{Pairs} } ;
+ }
+
+ if (! $x->{oneOutput} )
+ {
+ my $inFile = ($x->{inType} eq 'filenames'
+ || $x->{inType} eq 'filename');
+
+ $x->{inType} = $inFile ? 'filename' : 'buffer';
+
+ foreach my $in ($x->{oneInput} ? $input : @$input)
+ {
+ my $out ;
+ $x->{oneInput} = 1 ;
+
+ $obj->_singleTarget($x, $inFile, $in, \$out, @_)
+ or return undef ;
+
+ push @$output, \$out ;
+ #if ($x->{outType} eq 'array')
+ # { push @$output, \$out }
+ #else
+ # { $output->{$in} = \$out }
+ }
+
+ return 1 ;
+ }
+
+ # finally the 1 to 1 and n to 1
+ return $obj->_singleTarget($x, 1, $input, $output, @_);
+
+ croak "should not be here" ;
+}
+
+sub _singleTarget
+{
+ my $obj = shift ;
+ my $x = shift ;
+ my $inputIsFilename = shift;
+ my $input = shift;
+
+ if ($x->{oneInput})
+ {
+ $obj->getFileInfo($x->{Got}, $input)
+ if isaFilename($input) and $inputIsFilename ;
+
+ my $z = $obj->_create($x->{Got}, @_)
+ or return undef ;
+
+
+ defined $z->_wr2($input, $inputIsFilename)
+ or return $z->closeError(undef) ;
+
+ return $z->close() ;
+ }
+ else
+ {
+ my $afterFirst = 0 ;
+ my $inputIsFilename = ($x->{inType} ne 'array');
+ my $keep = $x->{Got}->clone();
+
+ #for my $element ( ($x->{inType} eq 'hash') ? keys %$input : @$input)
+ for my $element ( @$input)
+ {
+ my $isFilename = isaFilename($element);
+
+ if ( $afterFirst ++ )
+ {
+ defined addInterStream($obj, $element, $isFilename)
+ or return $obj->closeError(undef) ;
+ }
+ else
+ {
+ $obj->getFileInfo($x->{Got}, $element)
+ if $isFilename;
+
+ $obj->_create($x->{Got}, @_)
+ or return undef ;
+ }
+
+ defined $obj->_wr2($element, $isFilename)
+ or return $obj->closeError(undef) ;
+
+ *$obj->{Got} = $keep->clone();
+ }
+ return $obj->close() ;
+ }
+
+}
+
+sub _wr2
+{
+ my $self = shift ;
+
+ my $source = shift ;
+ my $inputIsFilename = shift;
+
+ my $input = $source ;
+ if (! $inputIsFilename)
+ {
+ $input = \$source
+ if ! ref $source;
+ }
+
+ if ( ref $input && ref $input eq 'SCALAR' )
+ {
+ return $self->syswrite($input, @_) ;
+ }
+
+ if ( ! ref $input || isaFilehandle($input))
+ {
+ my $isFilehandle = isaFilehandle($input) ;
+
+ my $fh = $input ;
+
+ if ( ! $isFilehandle )
+ {
+ $fh = new IO::File "<$input"
+ or return $self->saveErrorString(undef, "cannot open file '$input': $!", $!) ;
+ }
+ binmode $fh if *$self->{Got}->valueOrDefault('BinModeIn') ;
+
+ my $status ;
+ my $buff ;
+ my $count = 0 ;
+ while ($status = read($fh, $buff, 16 * 1024)) {
+ $count += length $buff;
+ defined $self->syswrite($buff, @_)
+ or return undef ;
+ }
+
+ return $self->saveErrorString(undef, $!, $!)
+ if ! defined $status ;
+
+ if ( (!$isFilehandle || *$self->{AutoClose}) && $input ne '-')
+ {
+ $fh->close()
+ or return undef ;
+ }
+
+ return $count ;
+ }
+
+ croak "Should not be here";
+ return undef;
+}
+
+sub addInterStream
+{
+ my $self = shift ;
+ my $input = shift ;
+ my $inputIsFilename = shift ;
+
+ if (*$self->{Got}->value('MultiStream'))
+ {
+ $self->getFileInfo(*$self->{Got}, $input)
+ #if isaFilename($input) and $inputIsFilename ;
+ if isaFilename($input) ;
+
+ # TODO -- newStream needs to allow gzip/zip header to be modified
+ return $self->newStream();
+ }
+ elsif (*$self->{Got}->value('AutoFlush'))
+ {
+ #return $self->flush(Z_FULL_FLUSH);
+ }
+
+ return 1 ;
+}
+
+sub getFileInfo
+{
+}
+
+sub TIEHANDLE
+{
+ return $_[0] if ref($_[0]);
+ die "OOPS\n" ;
+}
+
+sub UNTIE
+{
+ my $self = shift ;
+}
+
+sub DESTROY
+{
+ my $self = shift ;
+ local ($., $@, $!, $^E, $?);
+
+ $self->close() ;
+
+ # TODO - memory leak with 5.8.0 - this isn't called until
+ # global destruction
+ #
+ %{ *$self } = () ;
+ undef $self ;
+}
+
+
+
+sub filterUncompressed
+{
+}
+
+sub syswrite
+{
+ my $self = shift ;
+
+ my $buffer ;
+ if (ref $_[0] ) {
+ $self->croakError( *$self->{ClassName} . "::write: not a scalar reference" )
+ unless ref $_[0] eq 'SCALAR' ;
+ $buffer = $_[0] ;
+ }
+ else {
+ $buffer = \$_[0] ;
+ }
+
+ $] >= 5.008 and ( utf8::downgrade($$buffer, 1)
+ or croak "Wide character in " . *$self->{ClassName} . "::write:");
+
+
+ if (@_ > 1) {
+ my $slen = defined $$buffer ? length($$buffer) : 0;
+ my $len = $slen;
+ my $offset = 0;
+ $len = $_[1] if $_[1] < $len;
+
+ if (@_ > 2) {
+ $offset = $_[2] || 0;
+ $self->croakError(*$self->{ClassName} . "::write: offset outside string")
+ if $offset > $slen;
+ if ($offset < 0) {
+ $offset += $slen;
+ $self->croakError( *$self->{ClassName} . "::write: offset outside string") if $offset < 0;
+ }
+ my $rem = $slen - $offset;
+ $len = $rem if $rem < $len;
+ }
+
+ $buffer = \substr($$buffer, $offset, $len) ;
+ }
+
+ return 0 if ! defined $$buffer || length $$buffer == 0 ;
+
+ if (*$self->{Encoding}) {
+ $$buffer = *$self->{Encoding}->encode($$buffer);
+ }
+
+ $self->filterUncompressed($buffer);
+
+ my $buffer_length = defined $$buffer ? length($$buffer) : 0 ;
+ *$self->{UnCompSize}->add($buffer_length) ;
+
+ my $outBuffer='';
+ my $status = *$self->{Compress}->compr($buffer, $outBuffer) ;
+
+ return $self->saveErrorString(undef, *$self->{Compress}{Error},
+ *$self->{Compress}{ErrorNo})
+ if $status == STATUS_ERROR;
+
+ *$self->{CompSize}->add(length $outBuffer) ;
+
+ $self->output($outBuffer)
+ or return undef;
+
+ return $buffer_length;
+}
+
+sub print
+{
+ my $self = shift;
+
+ #if (ref $self) {
+ # $self = *$self{GLOB} ;
+ #}
+
+ if (defined $\) {
+ if (defined $,) {
+ defined $self->syswrite(join($,, @_) . $\);
+ } else {
+ defined $self->syswrite(join("", @_) . $\);
+ }
+ } else {
+ if (defined $,) {
+ defined $self->syswrite(join($,, @_));
+ } else {
+ defined $self->syswrite(join("", @_));
+ }
+ }
+}
+
+sub printf
+{
+ my $self = shift;
+ my $fmt = shift;
+ defined $self->syswrite(sprintf($fmt, @_));
+}
+
+
+
+sub flush
+{
+ my $self = shift ;
+
+ my $outBuffer='';
+ my $status = *$self->{Compress}->flush($outBuffer, @_) ;
+ return $self->saveErrorString(0, *$self->{Compress}{Error},
+ *$self->{Compress}{ErrorNo})
+ if $status == STATUS_ERROR;
+
+ if ( defined *$self->{FH} ) {
+ *$self->{FH}->clearerr();
+ }
+
+ *$self->{CompSize}->add(length $outBuffer) ;
+
+ $self->output($outBuffer)
+ or return 0;
+
+ if ( defined *$self->{FH} ) {
+ defined *$self->{FH}->flush()
+ or return $self->saveErrorString(0, $!, $!);
+ }
+
+ return 1;
+}
+
+sub newStream
+{
+ my $self = shift ;
+
+ $self->_writeTrailer()
+ or return 0 ;
+
+ my $got = $self->checkParams('newStream', *$self->{Got}, @_)
+ or return 0 ;
+
+ $self->ckParams($got)
+ or $self->croakError("newStream: $self->{Error}");
+
+ *$self->{Compress} = $self->mkComp($got)
+ or return 0;
+
+ *$self->{Header} = $self->mkHeader($got) ;
+ $self->output(*$self->{Header} )
+ or return 0;
+
+ *$self->{UnCompSize}->reset();
+ *$self->{CompSize}->reset();
+
+ return 1 ;
+}
+
+sub reset
+{
+ my $self = shift ;
+ return *$self->{Compress}->reset() ;
+}
+
+sub _writeTrailer
+{
+ my $self = shift ;
+
+ my $trailer = '';
+
+ my $status = *$self->{Compress}->close($trailer) ;
+ return $self->saveErrorString(0, *$self->{Compress}{Error}, *$self->{Compress}{ErrorNo})
+ if $status == STATUS_ERROR;
+
+ *$self->{CompSize}->add(length $trailer) ;
+
+ $trailer .= $self->mkTrailer();
+ defined $trailer
+ or return 0;
+
+ return $self->output($trailer);
+}
+
+sub _writeFinalTrailer
+{
+ my $self = shift ;
+
+ return $self->output($self->mkFinalTrailer());
+}
+
+sub close
+{
+ my $self = shift ;
+
+ return 1 if *$self->{Closed} || ! *$self->{Compress} ;
+ *$self->{Closed} = 1 ;
+
+ untie *$self
+ if $] >= 5.008 ;
+
+ $self->_writeTrailer()
+ or return 0 ;
+
+ $self->_writeFinalTrailer()
+ or return 0 ;
+
+ $self->output( "", 1 )
+ or return 0;
+
+ if (defined *$self->{FH}) {
+
+ #if (! *$self->{Handle} || *$self->{AutoClose}) {
+ if ((! *$self->{Handle} || *$self->{AutoClose}) && ! *$self->{StdIO}) {
+ $! = 0 ;
+ *$self->{FH}->close()
+ or return $self->saveErrorString(0, $!, $!);
+ }
+ delete *$self->{FH} ;
+ # This delete can set $! in older Perls, so reset the errno
+ $! = 0 ;
+ }
+
+ return 1;
+}
+
+
+#sub total_in
+#sub total_out
+#sub msg
+#
+#sub crc
+#{
+# my $self = shift ;
+# return *$self->{Compress}->crc32() ;
+#}
+#
+#sub msg
+#{
+# my $self = shift ;
+# return *$self->{Compress}->msg() ;
+#}
+#
+#sub dict_adler
+#{
+# my $self = shift ;
+# return *$self->{Compress}->dict_adler() ;
+#}
+#
+#sub get_Level
+#{
+# my $self = shift ;
+# return *$self->{Compress}->get_Level() ;
+#}
+#
+#sub get_Strategy
+#{
+# my $self = shift ;
+# return *$self->{Compress}->get_Strategy() ;
+#}
+
+
+sub tell
+{
+ my $self = shift ;
+
+ return *$self->{UnCompSize}->get32bit() ;
+}
+
+sub eof
+{
+ my $self = shift ;
+
+ return *$self->{Closed} ;
+}
+
+
+sub seek
+{
+ my $self = shift ;
+ my $position = shift;
+ my $whence = shift ;
+
+ my $here = $self->tell() ;
+ my $target = 0 ;
+
+ #use IO::Handle qw(SEEK_SET SEEK_CUR SEEK_END);
+ use IO::Handle ;
+
+ if ($whence == IO::Handle::SEEK_SET) {
+ $target = $position ;
+ }
+ elsif ($whence == IO::Handle::SEEK_CUR || $whence == IO::Handle::SEEK_END) {
+ $target = $here + $position ;
+ }
+ else {
+ $self->croakError(*$self->{ClassName} . "::seek: unknown value, $whence, for whence parameter");
+ }
+
+ # short circuit if seeking to current offset
+ return 1 if $target == $here ;
+
+ # Outlaw any attempt to seek backwards
+ $self->croakError(*$self->{ClassName} . "::seek: cannot seek backwards")
+ if $target < $here ;
+
+ # Walk the file to the new offset
+ my $offset = $target - $here ;
+
+ my $buffer ;
+ defined $self->syswrite("\x00" x $offset)
+ or return 0;
+
+ return 1 ;
+}
+
+sub binmode
+{
+ 1;
+# my $self = shift ;
+# return defined *$self->{FH}
+# ? binmode *$self->{FH}
+# : 1 ;
+}
+
+sub fileno
+{
+ my $self = shift ;
+ return defined *$self->{FH}
+ ? *$self->{FH}->fileno()
+ : undef ;
+}
+
+sub opened
+{
+ my $self = shift ;
+ return ! *$self->{Closed} ;
+}
+
+sub autoflush
+{
+ my $self = shift ;
+ return defined *$self->{FH}
+ ? *$self->{FH}->autoflush(@_)
+ : undef ;
+}
+
+sub input_line_number
+{
+ return undef ;
+}
+
+
+sub _notAvailable
+{
+ my $name = shift ;
+ return sub { croak "$name Not Available: File opened only for output" ; } ;
+}
+
+*read = _notAvailable('read');
+*READ = _notAvailable('read');
+*readline = _notAvailable('readline');
+*READLINE = _notAvailable('readline');
+*getc = _notAvailable('getc');
+*GETC = _notAvailable('getc');
+
+*FILENO = \&fileno;
+*PRINT = \&print;
+*PRINTF = \&printf;
+*WRITE = \&syswrite;
+*write = \&syswrite;
+*SEEK = \&seek;
+*TELL = \&tell;
+*EOF = \&eof;
+*CLOSE = \&close;
+*BINMODE = \&binmode;
+
+#*sysread = \&_notAvailable;
+#*syswrite = \&_write;
+
+1;
+
+__END__
+
+=head1 NAME
+
+IO::Compress::Base - Base Class for IO::Compress modules
+
+=head1 SYNOPSIS
+
+ use IO::Compress::Base ;
+
+=head1 DESCRIPTION
+
+This module is not intended for direct use in application code. Its sole
+purpose if to to be sub-classed by IO::Compress modules.
+
+=head1 SEE ALSO
+
+L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Compress::Deflate>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Compress::Bzip2>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
+
+L<Compress::Zlib::FAQ|Compress::Zlib::FAQ>
+
+L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
+L<Archive::Tar|Archive::Tar>,
+L<IO::Zlib|IO::Zlib>
+
+=head1 AUTHOR
+
+This module was written by Paul Marquess, F<pmqs@cpan.org>.
+
+=head1 MODIFICATION HISTORY
+
+See the Changes file.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2005-2010 Paul Marquess. All rights reserved.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Compress/Base/Common.pm b/Master/tlpkg/tlperl/lib/IO/Compress/Base/Common.pm
new file mode 100644
index 00000000000..4f8b4dadc36
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Compress/Base/Common.pm
@@ -0,0 +1,956 @@
+package IO::Compress::Base::Common;
+
+use strict ;
+use warnings;
+use bytes;
+
+use Carp;
+use Scalar::Util qw(blessed readonly);
+use File::GlobMapper;
+
+require Exporter;
+our ($VERSION, @ISA, @EXPORT, %EXPORT_TAGS, $HAS_ENCODE);
+@ISA = qw(Exporter);
+$VERSION = '2.024';
+
+@EXPORT = qw( isaFilehandle isaFilename whatIsInput whatIsOutput
+ isaFileGlobString cleanFileGlobString oneTarget
+ setBinModeInput setBinModeOutput
+ ckInOutParams
+ createSelfTiedObject
+ getEncoding
+
+ WANT_CODE
+ WANT_EXT
+ WANT_UNDEF
+ WANT_HASH
+
+ STATUS_OK
+ STATUS_ENDSTREAM
+ STATUS_EOF
+ STATUS_ERROR
+ );
+
+%EXPORT_TAGS = ( Status => [qw( STATUS_OK
+ STATUS_ENDSTREAM
+ STATUS_EOF
+ STATUS_ERROR
+ )]);
+
+
+use constant STATUS_OK => 0;
+use constant STATUS_ENDSTREAM => 1;
+use constant STATUS_EOF => 2;
+use constant STATUS_ERROR => -1;
+
+sub hasEncode()
+{
+ if (! defined $HAS_ENCODE) {
+ eval
+ {
+ require Encode;
+ Encode->import();
+ };
+
+ $HAS_ENCODE = $@ ? 0 : 1 ;
+ }
+
+ return $HAS_ENCODE;
+}
+
+sub getEncoding($$$)
+{
+ my $obj = shift;
+ my $class = shift ;
+ my $want_encoding = shift ;
+
+ $obj->croakError("$class: Encode module needed to use -Encode")
+ if ! hasEncode();
+
+ my $encoding = Encode::find_encoding($want_encoding);
+
+ $obj->croakError("$class: Encoding '$want_encoding' is not available")
+ if ! $encoding;
+
+ return $encoding;
+}
+
+our ($needBinmode);
+$needBinmode = ($^O eq 'MSWin32' ||
+ ($] >= 5.006 && eval ' ${^UNICODE} || ${^UTF8LOCALE} '))
+ ? 1 : 1 ;
+
+sub setBinModeInput($)
+{
+ my $handle = shift ;
+
+ binmode $handle
+ if $needBinmode;
+}
+
+sub setBinModeOutput($)
+{
+ my $handle = shift ;
+
+ binmode $handle
+ if $needBinmode;
+}
+
+sub isaFilehandle($)
+{
+ use utf8; # Pragma needed to keep Perl 5.6.0 happy
+ return (defined $_[0] and
+ (UNIVERSAL::isa($_[0],'GLOB') or
+ UNIVERSAL::isa($_[0],'IO::Handle') or
+ UNIVERSAL::isa(\$_[0],'GLOB'))
+ )
+}
+
+sub isaFilename($)
+{
+ return (defined $_[0] and
+ ! ref $_[0] and
+ UNIVERSAL::isa(\$_[0], 'SCALAR'));
+}
+
+sub isaFileGlobString
+{
+ return defined $_[0] && $_[0] =~ /^<.*>$/;
+}
+
+sub cleanFileGlobString
+{
+ my $string = shift ;
+
+ $string =~ s/^\s*<\s*(.*)\s*>\s*$/$1/;
+
+ return $string;
+}
+
+use constant WANT_CODE => 1 ;
+use constant WANT_EXT => 2 ;
+use constant WANT_UNDEF => 4 ;
+#use constant WANT_HASH => 8 ;
+use constant WANT_HASH => 0 ;
+
+sub whatIsInput($;$)
+{
+ my $got = whatIs(@_);
+
+ if (defined $got && $got eq 'filename' && defined $_[0] && $_[0] eq '-')
+ {
+ #use IO::File;
+ $got = 'handle';
+ $_[0] = *STDIN;
+ #$_[0] = new IO::File("<-");
+ }
+
+ return $got;
+}
+
+sub whatIsOutput($;$)
+{
+ my $got = whatIs(@_);
+
+ if (defined $got && $got eq 'filename' && defined $_[0] && $_[0] eq '-')
+ {
+ $got = 'handle';
+ $_[0] = *STDOUT;
+ #$_[0] = new IO::File(">-");
+ }
+
+ return $got;
+}
+
+sub whatIs ($;$)
+{
+ return 'handle' if isaFilehandle($_[0]);
+
+ my $wantCode = defined $_[1] && $_[1] & WANT_CODE ;
+ my $extended = defined $_[1] && $_[1] & WANT_EXT ;
+ my $undef = defined $_[1] && $_[1] & WANT_UNDEF ;
+ my $hash = defined $_[1] && $_[1] & WANT_HASH ;
+
+ return 'undef' if ! defined $_[0] && $undef ;
+
+ if (ref $_[0]) {
+ return '' if blessed($_[0]); # is an object
+ #return '' if UNIVERSAL::isa($_[0], 'UNIVERSAL'); # is an object
+ return 'buffer' if UNIVERSAL::isa($_[0], 'SCALAR');
+ return 'array' if UNIVERSAL::isa($_[0], 'ARRAY') && $extended ;
+ return 'hash' if UNIVERSAL::isa($_[0], 'HASH') && $hash ;
+ return 'code' if UNIVERSAL::isa($_[0], 'CODE') && $wantCode ;
+ return '';
+ }
+
+ return 'fileglob' if $extended && isaFileGlobString($_[0]);
+ return 'filename';
+}
+
+sub oneTarget
+{
+ return $_[0] =~ /^(code|handle|buffer|filename)$/;
+}
+
+sub IO::Compress::Base::Validator::new
+{
+ my $class = shift ;
+
+ my $Class = shift ;
+ my $error_ref = shift ;
+ my $reportClass = shift ;
+
+ my %data = (Class => $Class,
+ Error => $error_ref,
+ reportClass => $reportClass,
+ ) ;
+
+ my $obj = bless \%data, $class ;
+
+ local $Carp::CarpLevel = 1;
+
+ my $inType = $data{inType} = whatIsInput($_[0], WANT_EXT|WANT_HASH);
+ my $outType = $data{outType} = whatIsOutput($_[1], WANT_EXT|WANT_HASH);
+
+ my $oneInput = $data{oneInput} = oneTarget($inType);
+ my $oneOutput = $data{oneOutput} = oneTarget($outType);
+
+ if (! $inType)
+ {
+ $obj->croakError("$reportClass: illegal input parameter") ;
+ #return undef ;
+ }
+
+# if ($inType eq 'hash')
+# {
+# $obj->{Hash} = 1 ;
+# $obj->{oneInput} = 1 ;
+# return $obj->validateHash($_[0]);
+# }
+
+ if (! $outType)
+ {
+ $obj->croakError("$reportClass: illegal output parameter") ;
+ #return undef ;
+ }
+
+
+ if ($inType ne 'fileglob' && $outType eq 'fileglob')
+ {
+ $obj->croakError("Need input fileglob for outout fileglob");
+ }
+
+# if ($inType ne 'fileglob' && $outType eq 'hash' && $inType ne 'filename' )
+# {
+# $obj->croakError("input must ne filename or fileglob when output is a hash");
+# }
+
+ if ($inType eq 'fileglob' && $outType eq 'fileglob')
+ {
+ $data{GlobMap} = 1 ;
+ $data{inType} = $data{outType} = 'filename';
+ my $mapper = new File::GlobMapper($_[0], $_[1]);
+ if ( ! $mapper )
+ {
+ return $obj->saveErrorString($File::GlobMapper::Error) ;
+ }
+ $data{Pairs} = $mapper->getFileMap();
+
+ return $obj;
+ }
+
+ $obj->croakError("$reportClass: input and output $inType are identical")
+ if $inType eq $outType && $_[0] eq $_[1] && $_[0] ne '-' ;
+
+ if ($inType eq 'fileglob') # && $outType ne 'fileglob'
+ {
+ my $glob = cleanFileGlobString($_[0]);
+ my @inputs = glob($glob);
+
+ if (@inputs == 0)
+ {
+ # TODO -- legal or die?
+ die "globmap matched zero file -- legal or die???" ;
+ }
+ elsif (@inputs == 1)
+ {
+ $obj->validateInputFilenames($inputs[0])
+ or return undef;
+ $_[0] = $inputs[0] ;
+ $data{inType} = 'filename' ;
+ $data{oneInput} = 1;
+ }
+ else
+ {
+ $obj->validateInputFilenames(@inputs)
+ or return undef;
+ $_[0] = [ @inputs ] ;
+ $data{inType} = 'filenames' ;
+ }
+ }
+ elsif ($inType eq 'filename')
+ {
+ $obj->validateInputFilenames($_[0])
+ or return undef;
+ }
+ elsif ($inType eq 'array')
+ {
+ $data{inType} = 'filenames' ;
+ $obj->validateInputArray($_[0])
+ or return undef ;
+ }
+
+ return $obj->saveErrorString("$reportClass: output buffer is read-only")
+ if $outType eq 'buffer' && readonly(${ $_[1] });
+
+ if ($outType eq 'filename' )
+ {
+ $obj->croakError("$reportClass: output filename is undef or null string")
+ if ! defined $_[1] || $_[1] eq '' ;
+
+ if (-e $_[1])
+ {
+ if (-d _ )
+ {
+ return $obj->saveErrorString("output file '$_[1]' is a directory");
+ }
+ }
+ }
+
+ return $obj ;
+}
+
+sub IO::Compress::Base::Validator::saveErrorString
+{
+ my $self = shift ;
+ ${ $self->{Error} } = shift ;
+ return undef;
+
+}
+
+sub IO::Compress::Base::Validator::croakError
+{
+ my $self = shift ;
+ $self->saveErrorString($_[0]);
+ croak $_[0];
+}
+
+
+
+sub IO::Compress::Base::Validator::validateInputFilenames
+{
+ my $self = shift ;
+
+ foreach my $filename (@_)
+ {
+ $self->croakError("$self->{reportClass}: input filename is undef or null string")
+ if ! defined $filename || $filename eq '' ;
+
+ next if $filename eq '-';
+
+ if (! -e $filename )
+ {
+ return $self->saveErrorString("input file '$filename' does not exist");
+ }
+
+ if (-d _ )
+ {
+ return $self->saveErrorString("input file '$filename' is a directory");
+ }
+
+ if (! -r _ )
+ {
+ return $self->saveErrorString("cannot open file '$filename': $!");
+ }
+ }
+
+ return 1 ;
+}
+
+sub IO::Compress::Base::Validator::validateInputArray
+{
+ my $self = shift ;
+
+ if ( @{ $_[0] } == 0 )
+ {
+ return $self->saveErrorString("empty array reference") ;
+ }
+
+ foreach my $element ( @{ $_[0] } )
+ {
+ my $inType = whatIsInput($element);
+
+ if (! $inType)
+ {
+ $self->croakError("unknown input parameter") ;
+ }
+ elsif($inType eq 'filename')
+ {
+ $self->validateInputFilenames($element)
+ or return undef ;
+ }
+ else
+ {
+ $self->croakError("not a filename") ;
+ }
+ }
+
+ return 1 ;
+}
+
+#sub IO::Compress::Base::Validator::validateHash
+#{
+# my $self = shift ;
+# my $href = shift ;
+#
+# while (my($k, $v) = each %$href)
+# {
+# my $ktype = whatIsInput($k);
+# my $vtype = whatIsOutput($v, WANT_EXT|WANT_UNDEF) ;
+#
+# if ($ktype ne 'filename')
+# {
+# return $self->saveErrorString("hash key not filename") ;
+# }
+#
+# my %valid = map { $_ => 1 } qw(filename buffer array undef handle) ;
+# if (! $valid{$vtype})
+# {
+# return $self->saveErrorString("hash value not ok") ;
+# }
+# }
+#
+# return $self ;
+#}
+
+sub createSelfTiedObject
+{
+ my $class = shift || (caller)[0] ;
+ my $error_ref = shift ;
+
+ my $obj = bless Symbol::gensym(), ref($class) || $class;
+ tie *$obj, $obj if $] >= 5.005;
+ *$obj->{Closed} = 1 ;
+ $$error_ref = '';
+ *$obj->{Error} = $error_ref ;
+ my $errno = 0 ;
+ *$obj->{ErrorNo} = \$errno ;
+
+ return $obj;
+}
+
+
+
+#package Parse::Parameters ;
+#
+#
+#require Exporter;
+#our ($VERSION, @ISA, @EXPORT);
+#$VERSION = '2.000_08';
+#@ISA = qw(Exporter);
+
+$EXPORT_TAGS{Parse} = [qw( ParseParameters
+ Parse_any Parse_unsigned Parse_signed
+ Parse_boolean Parse_custom Parse_string
+ Parse_multiple Parse_writable_scalar
+ )
+ ];
+
+push @EXPORT, @{ $EXPORT_TAGS{Parse} } ;
+
+use constant Parse_any => 0x01;
+use constant Parse_unsigned => 0x02;
+use constant Parse_signed => 0x04;
+use constant Parse_boolean => 0x08;
+use constant Parse_string => 0x10;
+use constant Parse_custom => 0x12;
+
+#use constant Parse_store_ref => 0x100 ;
+use constant Parse_multiple => 0x100 ;
+use constant Parse_writable => 0x200 ;
+use constant Parse_writable_scalar => 0x400 | Parse_writable ;
+
+use constant OFF_PARSED => 0 ;
+use constant OFF_TYPE => 1 ;
+use constant OFF_DEFAULT => 2 ;
+use constant OFF_FIXED => 3 ;
+use constant OFF_FIRST_ONLY => 4 ;
+use constant OFF_STICKY => 5 ;
+
+
+
+sub ParseParameters
+{
+ my $level = shift || 0 ;
+
+ my $sub = (caller($level + 1))[3] ;
+ local $Carp::CarpLevel = 1 ;
+
+ return $_[1]
+ if @_ == 2 && defined $_[1] && UNIVERSAL::isa($_[1], "IO::Compress::Base::Parameters");
+
+ my $p = new IO::Compress::Base::Parameters() ;
+ $p->parse(@_)
+ or croak "$sub: $p->{Error}" ;
+
+ return $p;
+}
+
+#package IO::Compress::Base::Parameters;
+
+use strict;
+use warnings;
+use Carp;
+
+sub IO::Compress::Base::Parameters::new
+{
+ my $class = shift ;
+
+ my $obj = { Error => '',
+ Got => {},
+ } ;
+
+ #return bless $obj, ref($class) || $class || __PACKAGE__ ;
+ return bless $obj, 'IO::Compress::Base::Parameters' ;
+}
+
+sub IO::Compress::Base::Parameters::setError
+{
+ my $self = shift ;
+ my $error = shift ;
+ my $retval = @_ ? shift : undef ;
+
+ $self->{Error} = $error ;
+ return $retval;
+}
+
+#sub getError
+#{
+# my $self = shift ;
+# return $self->{Error} ;
+#}
+
+sub IO::Compress::Base::Parameters::parse
+{
+ my $self = shift ;
+
+ my $default = shift ;
+
+ my $got = $self->{Got} ;
+ my $firstTime = keys %{ $got } == 0 ;
+ my $other;
+
+ my (@Bad) ;
+ my @entered = () ;
+
+ # Allow the options to be passed as a hash reference or
+ # as the complete hash.
+ if (@_ == 0) {
+ @entered = () ;
+ }
+ elsif (@_ == 1) {
+ my $href = $_[0] ;
+
+ return $self->setError("Expected even number of parameters, got 1")
+ if ! defined $href or ! ref $href or ref $href ne "HASH" ;
+
+ foreach my $key (keys %$href) {
+ push @entered, $key ;
+ push @entered, \$href->{$key} ;
+ }
+ }
+ else {
+ my $count = @_;
+ return $self->setError("Expected even number of parameters, got $count")
+ if $count % 2 != 0 ;
+
+ for my $i (0.. $count / 2 - 1) {
+ if ($_[2 * $i] eq '__xxx__') {
+ $other = $_[2 * $i + 1] ;
+ }
+ else {
+ push @entered, $_[2 * $i] ;
+ push @entered, \$_[2 * $i + 1] ;
+ }
+ }
+ }
+
+
+ while (my ($key, $v) = each %$default)
+ {
+ croak "need 4 params [@$v]"
+ if @$v != 4 ;
+
+ my ($first_only, $sticky, $type, $value) = @$v ;
+ my $x ;
+ $self->_checkType($key, \$value, $type, 0, \$x)
+ or return undef ;
+
+ $key = lc $key;
+
+ if ($firstTime || ! $sticky) {
+ $x = []
+ if $type & Parse_multiple;
+
+ $got->{$key} = [0, $type, $value, $x, $first_only, $sticky] ;
+ }
+
+ $got->{$key}[OFF_PARSED] = 0 ;
+ }
+
+ my %parsed = ();
+
+ if ($other)
+ {
+ for my $key (keys %$default)
+ {
+ my $canonkey = lc $key;
+ if ($other->parsed($canonkey))
+ {
+ my $value = $other->value($canonkey);
+#print "SET '$canonkey' to $value [$$value]\n";
+ ++ $parsed{$canonkey};
+ $got->{$canonkey}[OFF_PARSED] = 1;
+ $got->{$canonkey}[OFF_DEFAULT] = $value;
+ $got->{$canonkey}[OFF_FIXED] = $value;
+ }
+ }
+ }
+
+ for my $i (0.. @entered / 2 - 1) {
+ my $key = $entered[2* $i] ;
+ my $value = $entered[2* $i+1] ;
+
+ #print "Key [$key] Value [$value]" ;
+ #print defined $$value ? "[$$value]\n" : "[undef]\n";
+
+ $key =~ s/^-// ;
+ my $canonkey = lc $key;
+
+ if ($got->{$canonkey} && ($firstTime ||
+ ! $got->{$canonkey}[OFF_FIRST_ONLY] ))
+ {
+ my $type = $got->{$canonkey}[OFF_TYPE] ;
+ my $parsed = $parsed{$canonkey};
+ ++ $parsed{$canonkey};
+
+ return $self->setError("Muliple instances of '$key' found")
+ if $parsed && $type & Parse_multiple == 0 ;
+
+ my $s ;
+ $self->_checkType($key, $value, $type, 1, \$s)
+ or return undef ;
+
+ $value = $$value ;
+ if ($type & Parse_multiple) {
+ $got->{$canonkey}[OFF_PARSED] = 1;
+ push @{ $got->{$canonkey}[OFF_FIXED] }, $s ;
+ }
+ else {
+ $got->{$canonkey} = [1, $type, $value, $s] ;
+ }
+ }
+ else
+ { push (@Bad, $key) }
+ }
+
+ if (@Bad) {
+ my ($bad) = join(", ", @Bad) ;
+ return $self->setError("unknown key value(s) $bad") ;
+ }
+
+ return 1;
+}
+
+sub IO::Compress::Base::Parameters::_checkType
+{
+ my $self = shift ;
+
+ my $key = shift ;
+ my $value = shift ;
+ my $type = shift ;
+ my $validate = shift ;
+ my $output = shift;
+
+ #local $Carp::CarpLevel = $level ;
+ #print "PARSE $type $key $value $validate $sub\n" ;
+
+ if ($type & Parse_writable_scalar)
+ {
+ return $self->setError("Parameter '$key' not writable")
+ if $validate && readonly $$value ;
+
+ if (ref $$value)
+ {
+ return $self->setError("Parameter '$key' not a scalar reference")
+ if $validate && ref $$value ne 'SCALAR' ;
+
+ $$output = $$value ;
+ }
+ else
+ {
+ return $self->setError("Parameter '$key' not a scalar")
+ if $validate && ref $value ne 'SCALAR' ;
+
+ $$output = $value ;
+ }
+
+ return 1;
+ }
+
+# if ($type & Parse_store_ref)
+# {
+# #$value = $$value
+# # if ref ${ $value } ;
+#
+# $$output = $value ;
+# return 1;
+# }
+
+ $value = $$value ;
+
+ if ($type & Parse_any)
+ {
+ $$output = $value ;
+ return 1;
+ }
+ elsif ($type & Parse_unsigned)
+ {
+ return $self->setError("Parameter '$key' must be an unsigned int, got 'undef'")
+ if $validate && ! defined $value ;
+ return $self->setError("Parameter '$key' must be an unsigned int, got '$value'")
+ if $validate && $value !~ /^\d+$/;
+
+ $$output = defined $value ? $value : 0 ;
+ return 1;
+ }
+ elsif ($type & Parse_signed)
+ {
+ return $self->setError("Parameter '$key' must be a signed int, got 'undef'")
+ if $validate && ! defined $value ;
+ return $self->setError("Parameter '$key' must be a signed int, got '$value'")
+ if $validate && $value !~ /^-?\d+$/;
+
+ $$output = defined $value ? $value : 0 ;
+ return 1 ;
+ }
+ elsif ($type & Parse_boolean)
+ {
+ return $self->setError("Parameter '$key' must be an int, got '$value'")
+ if $validate && defined $value && $value !~ /^\d*$/;
+ $$output = defined $value ? $value != 0 : 0 ;
+ return 1;
+ }
+ elsif ($type & Parse_string)
+ {
+ $$output = defined $value ? $value : "" ;
+ return 1;
+ }
+
+ $$output = $value ;
+ return 1;
+}
+
+
+
+sub IO::Compress::Base::Parameters::parsed
+{
+ my $self = shift ;
+ my $name = shift ;
+
+ return $self->{Got}{lc $name}[OFF_PARSED] ;
+}
+
+sub IO::Compress::Base::Parameters::value
+{
+ my $self = shift ;
+ my $name = shift ;
+
+ if (@_)
+ {
+ $self->{Got}{lc $name}[OFF_PARSED] = 1;
+ $self->{Got}{lc $name}[OFF_DEFAULT] = $_[0] ;
+ $self->{Got}{lc $name}[OFF_FIXED] = $_[0] ;
+ }
+
+ return $self->{Got}{lc $name}[OFF_FIXED] ;
+}
+
+sub IO::Compress::Base::Parameters::valueOrDefault
+{
+ my $self = shift ;
+ my $name = shift ;
+ my $default = shift ;
+
+ my $value = $self->{Got}{lc $name}[OFF_DEFAULT] ;
+
+ return $value if defined $value ;
+ return $default ;
+}
+
+sub IO::Compress::Base::Parameters::wantValue
+{
+ my $self = shift ;
+ my $name = shift ;
+
+ return defined $self->{Got}{lc $name}[OFF_DEFAULT] ;
+
+}
+
+sub IO::Compress::Base::Parameters::clone
+{
+ my $self = shift ;
+ my $obj = { };
+ my %got ;
+
+ while (my ($k, $v) = each %{ $self->{Got} }) {
+ $got{$k} = [ @$v ];
+ }
+
+ $obj->{Error} = $self->{Error};
+ $obj->{Got} = \%got ;
+
+ return bless $obj, 'IO::Compress::Base::Parameters' ;
+}
+
+package U64;
+
+use constant MAX32 => 0xFFFFFFFF ;
+use constant HI_1 => MAX32 + 1 ;
+use constant LOW => 0 ;
+use constant HIGH => 1;
+
+sub new
+{
+ my $class = shift ;
+
+ my $high = 0 ;
+ my $low = 0 ;
+
+ if (@_ == 2) {
+ $high = shift ;
+ $low = shift ;
+ }
+ elsif (@_ == 1) {
+ $low = shift ;
+ }
+
+ bless [$low, $high], $class;
+}
+
+sub newUnpack_V64
+{
+ my $string = shift;
+
+ my ($low, $hi) = unpack "V V", $string ;
+ bless [ $low, $hi ], "U64";
+}
+
+sub newUnpack_V32
+{
+ my $string = shift;
+
+ my $low = unpack "V", $string ;
+ bless [ $low, 0 ], "U64";
+}
+
+sub reset
+{
+ my $self = shift;
+ $self->[HIGH] = $self->[LOW] = 0;
+}
+
+sub clone
+{
+ my $self = shift;
+ bless [ @$self ], ref $self ;
+}
+
+sub getHigh
+{
+ my $self = shift;
+ return $self->[HIGH];
+}
+
+sub getLow
+{
+ my $self = shift;
+ return $self->[LOW];
+}
+
+sub get32bit
+{
+ my $self = shift;
+ return $self->[LOW];
+}
+
+sub get64bit
+{
+ my $self = shift;
+ # Not using << here because the result will still be
+ # a 32-bit value on systems where int size is 32-bits
+ return $self->[HIGH] * HI_1 + $self->[LOW];
+}
+
+sub add
+{
+ my $self = shift;
+ my $value = shift;
+
+ if (ref $value eq 'U64') {
+ $self->[HIGH] += $value->[HIGH] ;
+ $value = $value->[LOW];
+ }
+
+ my $available = MAX32 - $self->[LOW] ;
+
+ if ($value > $available) {
+ ++ $self->[HIGH] ;
+ $self->[LOW] = $value - $available - 1;
+ }
+ else {
+ $self->[LOW] += $value ;
+ }
+
+}
+
+sub equal
+{
+ my $self = shift;
+ my $other = shift;
+
+ return $self->[LOW] == $other->[LOW] &&
+ $self->[HIGH] == $other->[HIGH] ;
+}
+
+sub is64bit
+{
+ my $self = shift;
+ return $self->[HIGH] > 0 ;
+}
+
+sub getPacked_V64
+{
+ my $self = shift;
+
+ return pack "V V", @$self ;
+}
+
+sub getPacked_V32
+{
+ my $self = shift;
+
+ return pack "V", $self->[LOW] ;
+}
+
+sub pack_V64
+{
+ my $low = shift;
+
+ return pack "V V", $low, 0;
+}
+
+
+package IO::Compress::Base::Common;
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/IO/Compress/Bzip2.pm b/Master/tlpkg/tlperl/lib/IO/Compress/Bzip2.pm
new file mode 100644
index 00000000000..2a85ef55b19
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Compress/Bzip2.pm
@@ -0,0 +1,758 @@
+package IO::Compress::Bzip2 ;
+
+use strict ;
+use warnings;
+use bytes;
+require Exporter ;
+
+use IO::Compress::Base 2.024 ;
+
+use IO::Compress::Base::Common 2.024 qw(createSelfTiedObject);
+use IO::Compress::Adapter::Bzip2 2.024 ;
+
+
+
+our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $Bzip2Error);
+
+$VERSION = '2.024';
+$Bzip2Error = '';
+
+@ISA = qw(Exporter IO::Compress::Base);
+@EXPORT_OK = qw( $Bzip2Error bzip2 ) ;
+%EXPORT_TAGS = %IO::Compress::Base::EXPORT_TAGS ;
+push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
+Exporter::export_ok_tags('all');
+
+
+
+sub new
+{
+ my $class = shift ;
+
+ my $obj = createSelfTiedObject($class, \$Bzip2Error);
+ return $obj->_create(undef, @_);
+}
+
+sub bzip2
+{
+ my $obj = createSelfTiedObject(undef, \$Bzip2Error);
+ $obj->_def(@_);
+}
+
+
+sub mkHeader
+{
+ my $self = shift ;
+ return '';
+
+}
+
+sub getExtraParams
+{
+ my $self = shift ;
+
+ use IO::Compress::Base::Common 2.024 qw(:Parse);
+
+ return (
+ 'BlockSize100K' => [0, 1, Parse_unsigned, 1],
+ 'WorkFactor' => [0, 1, Parse_unsigned, 0],
+ 'Verbosity' => [0, 1, Parse_boolean, 0],
+ );
+}
+
+
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift;
+
+ # check that BlockSize100K is a number between 1 & 9
+ if ($got->parsed('BlockSize100K')) {
+ my $value = $got->value('BlockSize100K');
+ return $self->saveErrorString(undef, "Parameter 'BlockSize100K' not between 1 and 9, got $value")
+ unless defined $value && $value >= 1 && $value <= 9;
+
+ }
+
+ # check that WorkFactor between 0 & 250
+ if ($got->parsed('WorkFactor')) {
+ my $value = $got->value('WorkFactor');
+ return $self->saveErrorString(undef, "Parameter 'WorkFactor' not between 0 and 250, got $value")
+ unless $value >= 0 && $value <= 250;
+ }
+
+ return 1 ;
+}
+
+
+sub mkComp
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ my $BlockSize100K = $got->value('BlockSize100K');
+ my $WorkFactor = $got->value('WorkFactor');
+ my $Verbosity = $got->value('Verbosity');
+
+ my ($obj, $errstr, $errno) = IO::Compress::Adapter::Bzip2::mkCompObject(
+ $BlockSize100K, $WorkFactor,
+ $Verbosity);
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ return $obj;
+}
+
+
+sub mkTrailer
+{
+ my $self = shift ;
+ return '';
+}
+
+sub mkFinalTrailer
+{
+ return '';
+}
+
+#sub newHeader
+#{
+# my $self = shift ;
+# return '';
+#}
+
+sub getInverseClass
+{
+ return ('IO::Uncompress::Bunzip2');
+}
+
+sub getFileInfo
+{
+ my $self = shift ;
+ my $params = shift;
+ my $file = shift ;
+
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+IO::Compress::Bzip2 - Write bzip2 files/buffers
+
+
+
+=head1 SYNOPSIS
+
+ use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error) ;
+
+ my $status = bzip2 $input => $output [,OPTS]
+ or die "bzip2 failed: $Bzip2Error\n";
+
+ my $z = new IO::Compress::Bzip2 $output [,OPTS]
+ or die "bzip2 failed: $Bzip2Error\n";
+
+ $z->print($string);
+ $z->printf($format, $string);
+ $z->write($string);
+ $z->syswrite($string [, $length, $offset]);
+ $z->flush();
+ $z->tell();
+ $z->eof();
+ $z->seek($position, $whence);
+ $z->binmode();
+ $z->fileno();
+ $z->opened();
+ $z->autoflush();
+ $z->input_line_number();
+ $z->newStream( [OPTS] );
+
+ $z->close() ;
+
+ $Bzip2Error ;
+
+ # IO::File mode
+
+ print $z $string;
+ printf $z $format, $string;
+ tell $z
+ eof $z
+ seek $z, $position, $whence
+ binmode $z
+ fileno $z
+ close $z ;
+
+
+=head1 DESCRIPTION
+
+This module provides a Perl interface that allows writing bzip2
+compressed data to files or buffer.
+
+For reading bzip2 files/buffers, see the companion module
+L<IO::Uncompress::Bunzip2|IO::Uncompress::Bunzip2>.
+
+=head1 Functional Interface
+
+A top-level function, C<bzip2>, is provided to carry out
+"one-shot" compression between buffers and/or files. For finer
+control over the compression process, see the L</"OO Interface">
+section.
+
+ use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error) ;
+
+ bzip2 $input => $output [,OPTS]
+ or die "bzip2 failed: $Bzip2Error\n";
+
+The functional interface needs Perl5.005 or better.
+
+=head2 bzip2 $input => $output [, OPTS]
+
+C<bzip2> expects at least two parameters, C<$input> and C<$output>.
+
+=head3 The C<$input> parameter
+
+The parameter, C<$input>, is used to define the source of
+the uncompressed data.
+
+It can take one of the following forms:
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for reading and the input data
+will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the input data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the input data will be read
+from C<$$input>.
+
+=item An array reference
+
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
+The complete array will be walked to ensure that it only
+contains valid filenames before any data is compressed.
+
+=item An Input FileGlob string
+
+If C<$input> is a string that is delimited by the characters "<" and ">"
+C<bzip2> will assume that it is an I<input fileglob string>. The
+input is the list of files that match the fileglob.
+
+If the fileglob does not match any files ...
+
+See L<File::GlobMapper|File::GlobMapper> for more details.
+
+=back
+
+If the C<$input> parameter is any other type, C<undef> will be returned.
+
+=head3 The C<$output> parameter
+
+The parameter C<$output> is used to control the destination of the
+compressed data. This parameter can take one of these forms.
+
+=over 5
+
+=item A filename
+
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the compressed
+data will be written to it.
+
+=item A filehandle
+
+If the C<$output> parameter is a filehandle, the compressed data
+will be written to it.
+The string '-' can be used as an alias for standard output.
+
+=item A scalar reference
+
+If C<$output> is a scalar reference, the compressed data will be
+stored in C<$$output>.
+
+=item An Array Reference
+
+If C<$output> is an array reference, the compressed data will be
+pushed onto the array.
+
+=item An Output FileGlob
+
+If C<$output> is a string that is delimited by the characters "<" and ">"
+C<bzip2> will assume that it is an I<output fileglob string>. The
+output is the list of files that match the fileglob.
+
+When C<$output> is an fileglob string, C<$input> must also be a fileglob
+string. Anything else is an error.
+
+=back
+
+If the C<$output> parameter is any other type, C<undef> will be returned.
+
+=head2 Notes
+
+When C<$input> maps to multiple files/buffers and C<$output> is a single
+file/buffer the input files/buffers will be stored
+in C<$output> as a concatenated series of compressed data streams.
+
+=head2 Optional Parameters
+
+Unless specified below, the optional parameters for C<bzip2>,
+C<OPTS>, are the same as those used with the OO interface defined in the
+L</"Constructor Options"> section below.
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option applies to any input or output data streams to
+C<bzip2> that are filehandles.
+
+If C<AutoClose> is specified, and the value is true, it will result in all
+input and/or output filehandles being closed once C<bzip2> has
+completed.
+
+This parameter defaults to 0.
+
+=item C<< BinModeIn => 0|1 >>
+
+When reading from a file or filehandle, set C<binmode> before reading.
+
+Defaults to 0.
+
+=item C<< Append => 0|1 >>
+
+TODO
+
+=back
+
+=head2 Examples
+
+To read the contents of the file C<file1.txt> and write the compressed
+data to the file C<file1.txt.bz2>.
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error) ;
+
+ my $input = "file1.txt";
+ bzip2 $input => "$input.bz2"
+ or die "bzip2 failed: $Bzip2Error\n";
+
+To read from an existing Perl filehandle, C<$input>, and write the
+compressed data to a buffer, C<$buffer>.
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error) ;
+ use IO::File ;
+
+ my $input = new IO::File "<file1.txt"
+ or die "Cannot open 'file1.txt': $!\n" ;
+ my $buffer ;
+ bzip2 $input => \$buffer
+ or die "bzip2 failed: $Bzip2Error\n";
+
+To compress all files in the directory "/my/home" that match "*.txt"
+and store the compressed data in the same directory
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error) ;
+
+ bzip2 '</my/home/*.txt>' => '<*.bz2>'
+ or die "bzip2 failed: $Bzip2Error\n";
+
+and if you want to compress each file one at a time, this will do the trick
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error) ;
+
+ for my $input ( glob "/my/home/*.txt" )
+ {
+ my $output = "$input.bz2" ;
+ bzip2 $input => $output
+ or die "Error compressing '$input': $Bzip2Error\n";
+ }
+
+=head1 OO Interface
+
+=head2 Constructor
+
+The format of the constructor for C<IO::Compress::Bzip2> is shown below
+
+ my $z = new IO::Compress::Bzip2 $output [,OPTS]
+ or die "IO::Compress::Bzip2 failed: $Bzip2Error\n";
+
+It returns an C<IO::Compress::Bzip2> object on success and undef on failure.
+The variable C<$Bzip2Error> will contain an error message on failure.
+
+If you are running Perl 5.005 or better the object, C<$z>, returned from
+IO::Compress::Bzip2 can be used exactly like an L<IO::File|IO::File> filehandle.
+This means that all normal output file operations can be carried out
+with C<$z>.
+For example, to write to a compressed file/buffer you can use either of
+these forms
+
+ $z->print("hello world\n");
+ print $z "hello world\n";
+
+The mandatory parameter C<$output> is used to control the destination
+of the compressed data. This parameter can take one of these forms.
+
+=over 5
+
+=item A filename
+
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the compressed data
+will be written to it.
+
+=item A filehandle
+
+If the C<$output> parameter is a filehandle, the compressed data will be
+written to it.
+The string '-' can be used as an alias for standard output.
+
+=item A scalar reference
+
+If C<$output> is a scalar reference, the compressed data will be stored
+in C<$$output>.
+
+=back
+
+If the C<$output> parameter is any other type, C<IO::Compress::Bzip2>::new will
+return undef.
+
+=head2 Constructor Options
+
+C<OPTS> is any combination of the following options:
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option is only valid when the C<$output> parameter is a filehandle. If
+specified, and the value is true, it will result in the C<$output> being
+closed once either the C<close> method is called or the C<IO::Compress::Bzip2>
+object is destroyed.
+
+This parameter defaults to 0.
+
+=item C<< Append => 0|1 >>
+
+Opens C<$output> in append mode.
+
+The behaviour of this option is dependent on the type of C<$output>.
+
+=over 5
+
+=item * A Buffer
+
+If C<$output> is a buffer and C<Append> is enabled, all compressed data
+will be append to the end if C<$output>. Otherwise C<$output> will be
+cleared before any data is written to it.
+
+=item * A Filename
+
+If C<$output> is a filename and C<Append> is enabled, the file will be
+opened in append mode. Otherwise the contents of the file, if any, will be
+truncated before any compressed data is written to it.
+
+=item * A Filehandle
+
+If C<$output> is a filehandle, the file pointer will be positioned to the
+end of the file via a call to C<seek> before any compressed data is written
+to it. Otherwise the file pointer will not be moved.
+
+=back
+
+This parameter defaults to 0.
+
+=item C<< BlockSize100K => number >>
+
+Specify the number of 100K blocks bzip2 uses during compression.
+
+Valid values are from 1 to 9, where 9 is best compression.
+
+The default is 1.
+
+=item C<< WorkFactor => number >>
+
+Specifies how much effort bzip2 should take before resorting to a slower
+fallback compression algorithm.
+
+Valid values range from 0 to 250, where 0 means use the default value 30.
+
+The default is 0.
+
+=item C<< Strict => 0|1 >>
+
+This is a placeholder option.
+
+=back
+
+=head2 Examples
+
+TODO
+
+=head1 Methods
+
+=head2 print
+
+Usage is
+
+ $z->print($data)
+ print $z $data
+
+Compresses and outputs the contents of the C<$data> parameter. This
+has the same behaviour as the C<print> built-in.
+
+Returns true if successful.
+
+=head2 printf
+
+Usage is
+
+ $z->printf($format, $data)
+ printf $z $format, $data
+
+Compresses and outputs the contents of the C<$data> parameter.
+
+Returns true if successful.
+
+=head2 syswrite
+
+Usage is
+
+ $z->syswrite $data
+ $z->syswrite $data, $length
+ $z->syswrite $data, $length, $offset
+
+Compresses and outputs the contents of the C<$data> parameter.
+
+Returns the number of uncompressed bytes written, or C<undef> if
+unsuccessful.
+
+=head2 write
+
+Usage is
+
+ $z->write $data
+ $z->write $data, $length
+ $z->write $data, $length, $offset
+
+Compresses and outputs the contents of the C<$data> parameter.
+
+Returns the number of uncompressed bytes written, or C<undef> if
+unsuccessful.
+
+=head2 flush
+
+Usage is
+
+ $z->flush;
+
+Flushes any pending compressed data to the output file/buffer.
+
+TODO
+
+Returns true on success.
+
+=head2 tell
+
+Usage is
+
+ $z->tell()
+ tell $z
+
+Returns the uncompressed file offset.
+
+=head2 eof
+
+Usage is
+
+ $z->eof();
+ eof($z);
+
+Returns true if the C<close> method has been called.
+
+=head2 seek
+
+ $z->seek($position, $whence);
+ seek($z, $position, $whence);
+
+Provides a sub-set of the C<seek> functionality, with the restriction
+that it is only legal to seek forward in the output file/buffer.
+It is a fatal error to attempt to seek backward.
+
+Empty parts of the file/buffer will have NULL (0x00) bytes written to them.
+
+The C<$whence> parameter takes one the usual values, namely SEEK_SET,
+SEEK_CUR or SEEK_END.
+
+Returns 1 on success, 0 on failure.
+
+=head2 binmode
+
+Usage is
+
+ $z->binmode
+ binmode $z ;
+
+This is a noop provided for completeness.
+
+=head2 opened
+
+ $z->opened()
+
+Returns true if the object currently refers to a opened file/buffer.
+
+=head2 autoflush
+
+ my $prev = $z->autoflush()
+ my $prev = $z->autoflush(EXPR)
+
+If the C<$z> object is associated with a file or a filehandle, this method
+returns the current autoflush setting for the underlying filehandle. If
+C<EXPR> is present, and is non-zero, it will enable flushing after every
+write/print operation.
+
+If C<$z> is associated with a buffer, this method has no effect and always
+returns C<undef>.
+
+B<Note> that the special variable C<$|> B<cannot> be used to set or
+retrieve the autoflush setting.
+
+=head2 input_line_number
+
+ $z->input_line_number()
+ $z->input_line_number(EXPR)
+
+This method always returns C<undef> when compressing.
+
+=head2 fileno
+
+ $z->fileno()
+ fileno($z)
+
+If the C<$z> object is associated with a file or a filehandle, C<fileno>
+will return the underlying file descriptor. Once the C<close> method is
+called C<fileno> will return C<undef>.
+
+If the C<$z> object is is associated with a buffer, this method will return
+C<undef>.
+
+=head2 close
+
+ $z->close() ;
+ close $z ;
+
+Flushes any pending compressed data and then closes the output file/buffer.
+
+For most versions of Perl this method will be automatically invoked if
+the IO::Compress::Bzip2 object is destroyed (either explicitly or by the
+variable with the reference to the object going out of scope). The
+exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In
+these cases, the C<close> method will be called automatically, but
+not until global destruction of all live objects when the program is
+terminating.
+
+Therefore, if you want your scripts to be able to run on all versions
+of Perl, you should call C<close> explicitly and not rely on automatic
+closing.
+
+Returns true on success, otherwise 0.
+
+If the C<AutoClose> option has been enabled when the IO::Compress::Bzip2
+object was created, and the object is associated with a file, the
+underlying file will also be closed.
+
+=head2 newStream([OPTS])
+
+Usage is
+
+ $z->newStream( [OPTS] )
+
+Closes the current compressed data stream and starts a new one.
+
+OPTS consists of any of the the options that are available when creating
+the C<$z> object.
+
+See the L</"Constructor Options"> section for more details.
+
+=head1 Importing
+
+No symbolic constants are required by this IO::Compress::Bzip2 at present.
+
+=over 5
+
+=item :all
+
+Imports C<bzip2> and C<$Bzip2Error>.
+Same as doing this
+
+ use IO::Compress::Bzip2 qw(bzip2 $Bzip2Error) ;
+
+
+
+=back
+
+=head1 EXAMPLES
+
+=head2 Apache::GZip Revisited
+
+See L<IO::Compress::Bzip2::FAQ|IO::Compress::Bzip2::FAQ/"Apache::GZip Revisited">
+
+
+
+=head2 Working with Net::FTP
+
+See L<IO::Compress::Bzip2::FAQ|IO::Compress::Bzip2::FAQ/"Compressed files and Net::FTP">
+
+=head1 SEE ALSO
+
+L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Compress::Deflate>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
+
+L<Compress::Zlib::FAQ|Compress::Zlib::FAQ>
+
+L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
+L<Archive::Tar|Archive::Tar>,
+L<IO::Zlib|IO::Zlib>
+
+The primary site for the bzip2 program is F<http://www.bzip.org>.
+
+See the module L<Compress::Bzip2|Compress::Bzip2>
+
+=head1 AUTHOR
+
+This module was written by Paul Marquess, F<pmqs@cpan.org>.
+
+=head1 MODIFICATION HISTORY
+
+See the Changes file.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2005-2008 Paul Marquess. All rights reserved.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Compress/Deflate.pm b/Master/tlpkg/tlperl/lib/IO/Compress/Deflate.pm
new file mode 100644
index 00000000000..0f46e59d3a4
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Compress/Deflate.pm
@@ -0,0 +1,930 @@
+package IO::Compress::Deflate ;
+
+use strict ;
+use warnings;
+use bytes;
+
+require Exporter ;
+
+use IO::Compress::RawDeflate 2.024 ;
+
+use Compress::Raw::Zlib 2.024 ;
+use IO::Compress::Zlib::Constants 2.024 ;
+use IO::Compress::Base::Common 2.024 qw(createSelfTiedObject);
+
+
+our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $DeflateError);
+
+$VERSION = '2.024';
+$DeflateError = '';
+
+@ISA = qw(Exporter IO::Compress::RawDeflate);
+@EXPORT_OK = qw( $DeflateError deflate ) ;
+%EXPORT_TAGS = %IO::Compress::RawDeflate::DEFLATE_CONSTANTS ;
+push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
+Exporter::export_ok_tags('all');
+
+
+sub new
+{
+ my $class = shift ;
+
+ my $obj = createSelfTiedObject($class, \$DeflateError);
+ return $obj->_create(undef, @_);
+}
+
+sub deflate
+{
+ my $obj = createSelfTiedObject(undef, \$DeflateError);
+ return $obj->_def(@_);
+}
+
+
+sub bitmask($$$$)
+{
+ my $into = shift ;
+ my $value = shift ;
+ my $offset = shift ;
+ my $mask = shift ;
+
+ return $into | (($value & $mask) << $offset ) ;
+}
+
+sub mkDeflateHdr($$$;$)
+{
+ my $method = shift ;
+ my $cinfo = shift;
+ my $level = shift;
+ my $fdict_adler = shift ;
+
+ my $cmf = 0;
+ my $flg = 0;
+ my $fdict = 0;
+ $fdict = 1 if defined $fdict_adler;
+
+ $cmf = bitmask($cmf, $method, ZLIB_CMF_CM_OFFSET, ZLIB_CMF_CM_BITS);
+ $cmf = bitmask($cmf, $cinfo, ZLIB_CMF_CINFO_OFFSET, ZLIB_CMF_CINFO_BITS);
+
+ $flg = bitmask($flg, $fdict, ZLIB_FLG_FDICT_OFFSET, ZLIB_FLG_FDICT_BITS);
+ $flg = bitmask($flg, $level, ZLIB_FLG_LEVEL_OFFSET, ZLIB_FLG_LEVEL_BITS);
+
+ my $fcheck = 31 - ($cmf * 256 + $flg) % 31 ;
+ $flg = bitmask($flg, $fcheck, ZLIB_FLG_FCHECK_OFFSET, ZLIB_FLG_FCHECK_BITS);
+
+ my $hdr = pack("CC", $cmf, $flg) ;
+ $hdr .= pack("N", $fdict_adler) if $fdict ;
+
+ return $hdr;
+}
+
+sub mkHeader
+{
+ my $self = shift ;
+ my $param = shift ;
+
+ my $level = $param->value('Level');
+ my $strategy = $param->value('Strategy');
+
+ my $lflag ;
+ $level = 6
+ if $level == Z_DEFAULT_COMPRESSION ;
+
+ if (ZLIB_VERNUM >= 0x1210)
+ {
+ if ($strategy >= Z_HUFFMAN_ONLY || $level < 2)
+ { $lflag = ZLIB_FLG_LEVEL_FASTEST }
+ elsif ($level < 6)
+ { $lflag = ZLIB_FLG_LEVEL_FAST }
+ elsif ($level == 6)
+ { $lflag = ZLIB_FLG_LEVEL_DEFAULT }
+ else
+ { $lflag = ZLIB_FLG_LEVEL_SLOWEST }
+ }
+ else
+ {
+ $lflag = ($level - 1) >> 1 ;
+ $lflag = 3 if $lflag > 3 ;
+ }
+
+ #my $wbits = (MAX_WBITS - 8) << 4 ;
+ my $wbits = 7;
+ mkDeflateHdr(ZLIB_CMF_CM_DEFLATED, $wbits, $lflag);
+}
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift;
+
+ $got->value('ADLER32' => 1);
+ return 1 ;
+}
+
+
+sub mkTrailer
+{
+ my $self = shift ;
+ return pack("N", *$self->{Compress}->adler32()) ;
+}
+
+sub mkFinalTrailer
+{
+ return '';
+}
+
+#sub newHeader
+#{
+# my $self = shift ;
+# return *$self->{Header};
+#}
+
+sub getExtraParams
+{
+ my $self = shift ;
+ return $self->getZlibParams(),
+}
+
+sub getInverseClass
+{
+ return ('IO::Uncompress::Inflate',
+ \$IO::Uncompress::Inflate::InflateError);
+}
+
+sub getFileInfo
+{
+ my $self = shift ;
+ my $params = shift;
+ my $file = shift ;
+
+}
+
+
+
+1;
+
+__END__
+
+=head1 NAME
+
+IO::Compress::Deflate - Write RFC 1950 files/buffers
+
+
+
+=head1 SYNOPSIS
+
+ use IO::Compress::Deflate qw(deflate $DeflateError) ;
+
+ my $status = deflate $input => $output [,OPTS]
+ or die "deflate failed: $DeflateError\n";
+
+ my $z = new IO::Compress::Deflate $output [,OPTS]
+ or die "deflate failed: $DeflateError\n";
+
+ $z->print($string);
+ $z->printf($format, $string);
+ $z->write($string);
+ $z->syswrite($string [, $length, $offset]);
+ $z->flush();
+ $z->tell();
+ $z->eof();
+ $z->seek($position, $whence);
+ $z->binmode();
+ $z->fileno();
+ $z->opened();
+ $z->autoflush();
+ $z->input_line_number();
+ $z->newStream( [OPTS] );
+
+ $z->deflateParams();
+
+ $z->close() ;
+
+ $DeflateError ;
+
+ # IO::File mode
+
+ print $z $string;
+ printf $z $format, $string;
+ tell $z
+ eof $z
+ seek $z, $position, $whence
+ binmode $z
+ fileno $z
+ close $z ;
+
+
+=head1 DESCRIPTION
+
+This module provides a Perl interface that allows writing compressed
+data to files or buffer as defined in RFC 1950.
+
+For reading RFC 1950 files/buffers, see the companion module
+L<IO::Uncompress::Inflate|IO::Uncompress::Inflate>.
+
+=head1 Functional Interface
+
+A top-level function, C<deflate>, is provided to carry out
+"one-shot" compression between buffers and/or files. For finer
+control over the compression process, see the L</"OO Interface">
+section.
+
+ use IO::Compress::Deflate qw(deflate $DeflateError) ;
+
+ deflate $input => $output [,OPTS]
+ or die "deflate failed: $DeflateError\n";
+
+The functional interface needs Perl5.005 or better.
+
+=head2 deflate $input => $output [, OPTS]
+
+C<deflate> expects at least two parameters, C<$input> and C<$output>.
+
+=head3 The C<$input> parameter
+
+The parameter, C<$input>, is used to define the source of
+the uncompressed data.
+
+It can take one of the following forms:
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for reading and the input data
+will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the input data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the input data will be read
+from C<$$input>.
+
+=item An array reference
+
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
+The complete array will be walked to ensure that it only
+contains valid filenames before any data is compressed.
+
+=item An Input FileGlob string
+
+If C<$input> is a string that is delimited by the characters "<" and ">"
+C<deflate> will assume that it is an I<input fileglob string>. The
+input is the list of files that match the fileglob.
+
+If the fileglob does not match any files ...
+
+See L<File::GlobMapper|File::GlobMapper> for more details.
+
+=back
+
+If the C<$input> parameter is any other type, C<undef> will be returned.
+
+=head3 The C<$output> parameter
+
+The parameter C<$output> is used to control the destination of the
+compressed data. This parameter can take one of these forms.
+
+=over 5
+
+=item A filename
+
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the compressed
+data will be written to it.
+
+=item A filehandle
+
+If the C<$output> parameter is a filehandle, the compressed data
+will be written to it.
+The string '-' can be used as an alias for standard output.
+
+=item A scalar reference
+
+If C<$output> is a scalar reference, the compressed data will be
+stored in C<$$output>.
+
+=item An Array Reference
+
+If C<$output> is an array reference, the compressed data will be
+pushed onto the array.
+
+=item An Output FileGlob
+
+If C<$output> is a string that is delimited by the characters "<" and ">"
+C<deflate> will assume that it is an I<output fileglob string>. The
+output is the list of files that match the fileglob.
+
+When C<$output> is an fileglob string, C<$input> must also be a fileglob
+string. Anything else is an error.
+
+=back
+
+If the C<$output> parameter is any other type, C<undef> will be returned.
+
+=head2 Notes
+
+When C<$input> maps to multiple files/buffers and C<$output> is a single
+file/buffer the input files/buffers will be stored
+in C<$output> as a concatenated series of compressed data streams.
+
+=head2 Optional Parameters
+
+Unless specified below, the optional parameters for C<deflate>,
+C<OPTS>, are the same as those used with the OO interface defined in the
+L</"Constructor Options"> section below.
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option applies to any input or output data streams to
+C<deflate> that are filehandles.
+
+If C<AutoClose> is specified, and the value is true, it will result in all
+input and/or output filehandles being closed once C<deflate> has
+completed.
+
+This parameter defaults to 0.
+
+=item C<< BinModeIn => 0|1 >>
+
+When reading from a file or filehandle, set C<binmode> before reading.
+
+Defaults to 0.
+
+=item C<< Append => 0|1 >>
+
+The behaviour of this option is dependent on the type of output data
+stream.
+
+=over 5
+
+=item * A Buffer
+
+If C<Append> is enabled, all compressed data will be append to the end of
+the output buffer. Otherwise the output buffer will be cleared before any
+compressed data is written to it.
+
+=item * A Filename
+
+If C<Append> is enabled, the file will be opened in append mode. Otherwise
+the contents of the file, if any, will be truncated before any compressed
+data is written to it.
+
+=item * A Filehandle
+
+If C<Append> is enabled, the filehandle will be positioned to the end of
+the file via a call to C<seek> before any compressed data is
+written to it. Otherwise the file pointer will not be moved.
+
+=back
+
+When C<Append> is specified, and set to true, it will I<append> all compressed
+data to the output data stream.
+
+So when the output is a filehandle it will carry out a seek to the eof
+before writing any compressed data. If the output is a filename, it will be opened for
+appending. If the output is a buffer, all compressed data will be appened to
+the existing buffer.
+
+Conversely when C<Append> is not specified, or it is present and is set to
+false, it will operate as follows.
+
+When the output is a filename, it will truncate the contents of the file
+before writing any compressed data. If the output is a filehandle
+its position will not be changed. If the output is a buffer, it will be
+wiped before any compressed data is output.
+
+Defaults to 0.
+
+=back
+
+=head2 Examples
+
+To read the contents of the file C<file1.txt> and write the compressed
+data to the file C<file1.txt.1950>.
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::Deflate qw(deflate $DeflateError) ;
+
+ my $input = "file1.txt";
+ deflate $input => "$input.1950"
+ or die "deflate failed: $DeflateError\n";
+
+To read from an existing Perl filehandle, C<$input>, and write the
+compressed data to a buffer, C<$buffer>.
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::Deflate qw(deflate $DeflateError) ;
+ use IO::File ;
+
+ my $input = new IO::File "<file1.txt"
+ or die "Cannot open 'file1.txt': $!\n" ;
+ my $buffer ;
+ deflate $input => \$buffer
+ or die "deflate failed: $DeflateError\n";
+
+To compress all files in the directory "/my/home" that match "*.txt"
+and store the compressed data in the same directory
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::Deflate qw(deflate $DeflateError) ;
+
+ deflate '</my/home/*.txt>' => '<*.1950>'
+ or die "deflate failed: $DeflateError\n";
+
+and if you want to compress each file one at a time, this will do the trick
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::Deflate qw(deflate $DeflateError) ;
+
+ for my $input ( glob "/my/home/*.txt" )
+ {
+ my $output = "$input.1950" ;
+ deflate $input => $output
+ or die "Error compressing '$input': $DeflateError\n";
+ }
+
+=head1 OO Interface
+
+=head2 Constructor
+
+The format of the constructor for C<IO::Compress::Deflate> is shown below
+
+ my $z = new IO::Compress::Deflate $output [,OPTS]
+ or die "IO::Compress::Deflate failed: $DeflateError\n";
+
+It returns an C<IO::Compress::Deflate> object on success and undef on failure.
+The variable C<$DeflateError> will contain an error message on failure.
+
+If you are running Perl 5.005 or better the object, C<$z>, returned from
+IO::Compress::Deflate can be used exactly like an L<IO::File|IO::File> filehandle.
+This means that all normal output file operations can be carried out
+with C<$z>.
+For example, to write to a compressed file/buffer you can use either of
+these forms
+
+ $z->print("hello world\n");
+ print $z "hello world\n";
+
+The mandatory parameter C<$output> is used to control the destination
+of the compressed data. This parameter can take one of these forms.
+
+=over 5
+
+=item A filename
+
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the compressed data
+will be written to it.
+
+=item A filehandle
+
+If the C<$output> parameter is a filehandle, the compressed data will be
+written to it.
+The string '-' can be used as an alias for standard output.
+
+=item A scalar reference
+
+If C<$output> is a scalar reference, the compressed data will be stored
+in C<$$output>.
+
+=back
+
+If the C<$output> parameter is any other type, C<IO::Compress::Deflate>::new will
+return undef.
+
+=head2 Constructor Options
+
+C<OPTS> is any combination of the following options:
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option is only valid when the C<$output> parameter is a filehandle. If
+specified, and the value is true, it will result in the C<$output> being
+closed once either the C<close> method is called or the C<IO::Compress::Deflate>
+object is destroyed.
+
+This parameter defaults to 0.
+
+=item C<< Append => 0|1 >>
+
+Opens C<$output> in append mode.
+
+The behaviour of this option is dependent on the type of C<$output>.
+
+=over 5
+
+=item * A Buffer
+
+If C<$output> is a buffer and C<Append> is enabled, all compressed data
+will be append to the end of C<$output>. Otherwise C<$output> will be
+cleared before any data is written to it.
+
+=item * A Filename
+
+If C<$output> is a filename and C<Append> is enabled, the file will be
+opened in append mode. Otherwise the contents of the file, if any, will be
+truncated before any compressed data is written to it.
+
+=item * A Filehandle
+
+If C<$output> is a filehandle, the file pointer will be positioned to the
+end of the file via a call to C<seek> before any compressed data is written
+to it. Otherwise the file pointer will not be moved.
+
+=back
+
+This parameter defaults to 0.
+
+=item C<< Merge => 0|1 >>
+
+This option is used to compress input data and append it to an existing
+compressed data stream in C<$output>. The end result is a single compressed
+data stream stored in C<$output>.
+
+It is a fatal error to attempt to use this option when C<$output> is not an
+RFC 1950 data stream.
+
+There are a number of other limitations with the C<Merge> option:
+
+=over 5
+
+=item 1
+
+This module needs to have been built with zlib 1.2.1 or better to work. A
+fatal error will be thrown if C<Merge> is used with an older version of
+zlib.
+
+=item 2
+
+If C<$output> is a file or a filehandle, it must be seekable.
+
+=back
+
+This parameter defaults to 0.
+
+=item -Level
+
+Defines the compression level used by zlib. The value should either be
+a number between 0 and 9 (0 means no compression and 9 is maximum
+compression), or one of the symbolic constants defined below.
+
+ Z_NO_COMPRESSION
+ Z_BEST_SPEED
+ Z_BEST_COMPRESSION
+ Z_DEFAULT_COMPRESSION
+
+The default is Z_DEFAULT_COMPRESSION.
+
+Note, these constants are not imported by C<IO::Compress::Deflate> by default.
+
+ use IO::Compress::Deflate qw(:strategy);
+ use IO::Compress::Deflate qw(:constants);
+ use IO::Compress::Deflate qw(:all);
+
+=item -Strategy
+
+Defines the strategy used to tune the compression. Use one of the symbolic
+constants defined below.
+
+ Z_FILTERED
+ Z_HUFFMAN_ONLY
+ Z_RLE
+ Z_FIXED
+ Z_DEFAULT_STRATEGY
+
+The default is Z_DEFAULT_STRATEGY.
+
+=item C<< Strict => 0|1 >>
+
+This is a placeholder option.
+
+=back
+
+=head2 Examples
+
+TODO
+
+=head1 Methods
+
+=head2 print
+
+Usage is
+
+ $z->print($data)
+ print $z $data
+
+Compresses and outputs the contents of the C<$data> parameter. This
+has the same behaviour as the C<print> built-in.
+
+Returns true if successful.
+
+=head2 printf
+
+Usage is
+
+ $z->printf($format, $data)
+ printf $z $format, $data
+
+Compresses and outputs the contents of the C<$data> parameter.
+
+Returns true if successful.
+
+=head2 syswrite
+
+Usage is
+
+ $z->syswrite $data
+ $z->syswrite $data, $length
+ $z->syswrite $data, $length, $offset
+
+Compresses and outputs the contents of the C<$data> parameter.
+
+Returns the number of uncompressed bytes written, or C<undef> if
+unsuccessful.
+
+=head2 write
+
+Usage is
+
+ $z->write $data
+ $z->write $data, $length
+ $z->write $data, $length, $offset
+
+Compresses and outputs the contents of the C<$data> parameter.
+
+Returns the number of uncompressed bytes written, or C<undef> if
+unsuccessful.
+
+=head2 flush
+
+Usage is
+
+ $z->flush;
+ $z->flush($flush_type);
+
+Flushes any pending compressed data to the output file/buffer.
+
+This method takes an optional parameter, C<$flush_type>, that controls
+how the flushing will be carried out. By default the C<$flush_type>
+used is C<Z_FINISH>. Other valid values for C<$flush_type> are
+C<Z_NO_FLUSH>, C<Z_SYNC_FLUSH>, C<Z_FULL_FLUSH> and C<Z_BLOCK>. It is
+strongly recommended that you only set the C<flush_type> parameter if
+you fully understand the implications of what it does - overuse of C<flush>
+can seriously degrade the level of compression achieved. See the C<zlib>
+documentation for details.
+
+Returns true on success.
+
+=head2 tell
+
+Usage is
+
+ $z->tell()
+ tell $z
+
+Returns the uncompressed file offset.
+
+=head2 eof
+
+Usage is
+
+ $z->eof();
+ eof($z);
+
+Returns true if the C<close> method has been called.
+
+=head2 seek
+
+ $z->seek($position, $whence);
+ seek($z, $position, $whence);
+
+Provides a sub-set of the C<seek> functionality, with the restriction
+that it is only legal to seek forward in the output file/buffer.
+It is a fatal error to attempt to seek backward.
+
+Empty parts of the file/buffer will have NULL (0x00) bytes written to them.
+
+The C<$whence> parameter takes one the usual values, namely SEEK_SET,
+SEEK_CUR or SEEK_END.
+
+Returns 1 on success, 0 on failure.
+
+=head2 binmode
+
+Usage is
+
+ $z->binmode
+ binmode $z ;
+
+This is a noop provided for completeness.
+
+=head2 opened
+
+ $z->opened()
+
+Returns true if the object currently refers to a opened file/buffer.
+
+=head2 autoflush
+
+ my $prev = $z->autoflush()
+ my $prev = $z->autoflush(EXPR)
+
+If the C<$z> object is associated with a file or a filehandle, this method
+returns the current autoflush setting for the underlying filehandle. If
+C<EXPR> is present, and is non-zero, it will enable flushing after every
+write/print operation.
+
+If C<$z> is associated with a buffer, this method has no effect and always
+returns C<undef>.
+
+B<Note> that the special variable C<$|> B<cannot> be used to set or
+retrieve the autoflush setting.
+
+=head2 input_line_number
+
+ $z->input_line_number()
+ $z->input_line_number(EXPR)
+
+This method always returns C<undef> when compressing.
+
+=head2 fileno
+
+ $z->fileno()
+ fileno($z)
+
+If the C<$z> object is associated with a file or a filehandle, C<fileno>
+will return the underlying file descriptor. Once the C<close> method is
+called C<fileno> will return C<undef>.
+
+If the C<$z> object is is associated with a buffer, this method will return
+C<undef>.
+
+=head2 close
+
+ $z->close() ;
+ close $z ;
+
+Flushes any pending compressed data and then closes the output file/buffer.
+
+For most versions of Perl this method will be automatically invoked if
+the IO::Compress::Deflate object is destroyed (either explicitly or by the
+variable with the reference to the object going out of scope). The
+exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In
+these cases, the C<close> method will be called automatically, but
+not until global destruction of all live objects when the program is
+terminating.
+
+Therefore, if you want your scripts to be able to run on all versions
+of Perl, you should call C<close> explicitly and not rely on automatic
+closing.
+
+Returns true on success, otherwise 0.
+
+If the C<AutoClose> option has been enabled when the IO::Compress::Deflate
+object was created, and the object is associated with a file, the
+underlying file will also be closed.
+
+=head2 newStream([OPTS])
+
+Usage is
+
+ $z->newStream( [OPTS] )
+
+Closes the current compressed data stream and starts a new one.
+
+OPTS consists of any of the the options that are available when creating
+the C<$z> object.
+
+See the L</"Constructor Options"> section for more details.
+
+=head2 deflateParams
+
+Usage is
+
+ $z->deflateParams
+
+TODO
+
+=head1 Importing
+
+A number of symbolic constants are required by some methods in
+C<IO::Compress::Deflate>. None are imported by default.
+
+=over 5
+
+=item :all
+
+Imports C<deflate>, C<$DeflateError> and all symbolic
+constants that can be used by C<IO::Compress::Deflate>. Same as doing this
+
+ use IO::Compress::Deflate qw(deflate $DeflateError :constants) ;
+
+=item :constants
+
+Import all symbolic constants. Same as doing this
+
+ use IO::Compress::Deflate qw(:flush :level :strategy) ;
+
+=item :flush
+
+These symbolic constants are used by the C<flush> method.
+
+ Z_NO_FLUSH
+ Z_PARTIAL_FLUSH
+ Z_SYNC_FLUSH
+ Z_FULL_FLUSH
+ Z_FINISH
+ Z_BLOCK
+
+=item :level
+
+These symbolic constants are used by the C<Level> option in the constructor.
+
+ Z_NO_COMPRESSION
+ Z_BEST_SPEED
+ Z_BEST_COMPRESSION
+ Z_DEFAULT_COMPRESSION
+
+=item :strategy
+
+These symbolic constants are used by the C<Strategy> option in the constructor.
+
+ Z_FILTERED
+ Z_HUFFMAN_ONLY
+ Z_RLE
+ Z_FIXED
+ Z_DEFAULT_STRATEGY
+
+
+
+
+=back
+
+=head1 EXAMPLES
+
+=head2 Apache::GZip Revisited
+
+See L<IO::Compress::FAQ|IO::Compress::FAQ/"Apache::GZip Revisited">
+
+
+
+=head2 Working with Net::FTP
+
+See L<IO::Compress::FAQ|IO::Compress::FAQ/"Compressed files and Net::FTP">
+
+=head1 SEE ALSO
+
+L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Compress::Bzip2>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
+
+L<Compress::Zlib::FAQ|Compress::Zlib::FAQ>
+
+L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
+L<Archive::Tar|Archive::Tar>,
+L<IO::Zlib|IO::Zlib>
+
+For RFC 1950, 1951 and 1952 see
+F<http://www.faqs.org/rfcs/rfc1950.html>,
+F<http://www.faqs.org/rfcs/rfc1951.html> and
+F<http://www.faqs.org/rfcs/rfc1952.html>
+
+The I<zlib> compression library was written by Jean-loup Gailly
+F<gzip@prep.ai.mit.edu> and Mark Adler F<madler@alumni.caltech.edu>.
+
+The primary site for the I<zlib> compression library is
+F<http://www.zlib.org>.
+
+The primary site for gzip is F<http://www.gzip.org>.
+
+=head1 AUTHOR
+
+This module was written by Paul Marquess, F<pmqs@cpan.org>.
+
+=head1 MODIFICATION HISTORY
+
+See the Changes file.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2005-2010 Paul Marquess. All rights reserved.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Compress/Gzip.pm b/Master/tlpkg/tlperl/lib/IO/Compress/Gzip.pm
new file mode 100644
index 00000000000..1978b91b283
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Compress/Gzip.pm
@@ -0,0 +1,1242 @@
+
+package IO::Compress::Gzip ;
+
+require 5.004 ;
+
+use strict ;
+use warnings;
+use bytes;
+
+
+use IO::Compress::RawDeflate 2.024 ;
+
+use Compress::Raw::Zlib 2.024 ;
+use IO::Compress::Base::Common 2.024 qw(:Status :Parse createSelfTiedObject);
+use IO::Compress::Gzip::Constants 2.024 ;
+use IO::Compress::Zlib::Extra 2.024 ;
+
+BEGIN
+{
+ if (defined &utf8::downgrade )
+ { *noUTF8 = \&utf8::downgrade }
+ else
+ { *noUTF8 = sub {} }
+}
+
+require Exporter ;
+
+our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $GzipError);
+
+$VERSION = '2.024';
+$GzipError = '' ;
+
+@ISA = qw(Exporter IO::Compress::RawDeflate);
+@EXPORT_OK = qw( $GzipError gzip ) ;
+%EXPORT_TAGS = %IO::Compress::RawDeflate::DEFLATE_CONSTANTS ;
+push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
+Exporter::export_ok_tags('all');
+
+sub new
+{
+ my $class = shift ;
+
+ my $obj = createSelfTiedObject($class, \$GzipError);
+
+ $obj->_create(undef, @_);
+}
+
+
+sub gzip
+{
+ my $obj = createSelfTiedObject(undef, \$GzipError);
+ return $obj->_def(@_);
+}
+
+#sub newHeader
+#{
+# my $self = shift ;
+# #return GZIP_MINIMUM_HEADER ;
+# return $self->mkHeader(*$self->{Got});
+#}
+
+sub getExtraParams
+{
+ my $self = shift ;
+
+ return (
+ # zlib behaviour
+ $self->getZlibParams(),
+
+ # Gzip header fields
+ 'Minimal' => [0, 1, Parse_boolean, 0],
+ 'Comment' => [0, 1, Parse_any, undef],
+ 'Name' => [0, 1, Parse_any, undef],
+ 'Time' => [0, 1, Parse_any, undef],
+ 'TextFlag' => [0, 1, Parse_boolean, 0],
+ 'HeaderCRC' => [0, 1, Parse_boolean, 0],
+ 'OS_Code' => [0, 1, Parse_unsigned, $Compress::Raw::Zlib::gzip_os_code],
+ 'ExtraField'=> [0, 1, Parse_any, undef],
+ 'ExtraFlags'=> [0, 1, Parse_any, undef],
+
+ );
+}
+
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ # gzip always needs crc32
+ $got->value('CRC32' => 1);
+
+ return 1
+ if $got->value('Merge') ;
+
+ my $strict = $got->value('Strict') ;
+
+
+ {
+ if (! $got->parsed('Time') ) {
+ # Modification time defaults to now.
+ $got->value('Time' => time) ;
+ }
+
+ # Check that the Name & Comment don't have embedded NULLs
+ # Also check that they only contain ISO 8859-1 chars.
+ if ($got->parsed('Name') && defined $got->value('Name')) {
+ my $name = $got->value('Name');
+
+ return $self->saveErrorString(undef, "Null Character found in Name",
+ Z_DATA_ERROR)
+ if $strict && $name =~ /\x00/ ;
+
+ return $self->saveErrorString(undef, "Non ISO 8859-1 Character found in Name",
+ Z_DATA_ERROR)
+ if $strict && $name =~ /$GZIP_FNAME_INVALID_CHAR_RE/o ;
+ }
+
+ if ($got->parsed('Comment') && defined $got->value('Comment')) {
+ my $comment = $got->value('Comment');
+
+ return $self->saveErrorString(undef, "Null Character found in Comment",
+ Z_DATA_ERROR)
+ if $strict && $comment =~ /\x00/ ;
+
+ return $self->saveErrorString(undef, "Non ISO 8859-1 Character found in Comment",
+ Z_DATA_ERROR)
+ if $strict && $comment =~ /$GZIP_FCOMMENT_INVALID_CHAR_RE/o;
+ }
+
+ if ($got->parsed('OS_Code') ) {
+ my $value = $got->value('OS_Code');
+
+ return $self->saveErrorString(undef, "OS_Code must be between 0 and 255, got '$value'")
+ if $value < 0 || $value > 255 ;
+
+ }
+
+ # gzip only supports Deflate at present
+ $got->value('Method' => Z_DEFLATED) ;
+
+ if ( ! $got->parsed('ExtraFlags')) {
+ $got->value('ExtraFlags' => 2)
+ if $got->value('Level') == Z_BEST_SPEED ;
+ $got->value('ExtraFlags' => 4)
+ if $got->value('Level') == Z_BEST_COMPRESSION ;
+ }
+
+ my $data = $got->value('ExtraField') ;
+ if (defined $data) {
+ my $bad = IO::Compress::Zlib::Extra::parseExtraField($data, $strict, 1) ;
+ return $self->saveErrorString(undef, "Error with ExtraField Parameter: $bad", Z_DATA_ERROR)
+ if $bad ;
+
+ $got->value('ExtraField', $data) ;
+ }
+ }
+
+ return 1;
+}
+
+sub mkTrailer
+{
+ my $self = shift ;
+ return pack("V V", *$self->{Compress}->crc32(),
+ *$self->{UnCompSize}->get32bit());
+}
+
+sub getInverseClass
+{
+ return ('IO::Uncompress::Gunzip',
+ \$IO::Uncompress::Gunzip::GunzipError);
+}
+
+sub getFileInfo
+{
+ my $self = shift ;
+ my $params = shift;
+ my $filename = shift ;
+
+ my $defaultTime = (stat($filename))[9] ;
+
+ $params->value('Name' => $filename)
+ if ! $params->parsed('Name') ;
+
+ $params->value('Time' => $defaultTime)
+ if ! $params->parsed('Time') ;
+}
+
+
+sub mkHeader
+{
+ my $self = shift ;
+ my $param = shift ;
+
+ # stort-circuit if a minimal header is requested.
+ return GZIP_MINIMUM_HEADER if $param->value('Minimal') ;
+
+ # METHOD
+ my $method = $param->valueOrDefault('Method', GZIP_CM_DEFLATED) ;
+
+ # FLAGS
+ my $flags = GZIP_FLG_DEFAULT ;
+ $flags |= GZIP_FLG_FTEXT if $param->value('TextFlag') ;
+ $flags |= GZIP_FLG_FHCRC if $param->value('HeaderCRC') ;
+ $flags |= GZIP_FLG_FEXTRA if $param->wantValue('ExtraField') ;
+ $flags |= GZIP_FLG_FNAME if $param->wantValue('Name') ;
+ $flags |= GZIP_FLG_FCOMMENT if $param->wantValue('Comment') ;
+
+ # MTIME
+ my $time = $param->valueOrDefault('Time', GZIP_MTIME_DEFAULT) ;
+
+ # EXTRA FLAGS
+ my $extra_flags = $param->valueOrDefault('ExtraFlags', GZIP_XFL_DEFAULT);
+
+ # OS CODE
+ my $os_code = $param->valueOrDefault('OS_Code', GZIP_OS_DEFAULT) ;
+
+
+ my $out = pack("C4 V C C",
+ GZIP_ID1, # ID1
+ GZIP_ID2, # ID2
+ $method, # Compression Method
+ $flags, # Flags
+ $time, # Modification Time
+ $extra_flags, # Extra Flags
+ $os_code, # Operating System Code
+ ) ;
+
+ # EXTRA
+ if ($flags & GZIP_FLG_FEXTRA) {
+ my $extra = $param->value('ExtraField') ;
+ $out .= pack("v", length $extra) . $extra ;
+ }
+
+ # NAME
+ if ($flags & GZIP_FLG_FNAME) {
+ my $name .= $param->value('Name') ;
+ $name =~ s/\x00.*$//;
+ $out .= $name ;
+ # Terminate the filename with NULL unless it already is
+ $out .= GZIP_NULL_BYTE
+ if !length $name or
+ substr($name, 1, -1) ne GZIP_NULL_BYTE ;
+ }
+
+ # COMMENT
+ if ($flags & GZIP_FLG_FCOMMENT) {
+ my $comment .= $param->value('Comment') ;
+ $comment =~ s/\x00.*$//;
+ $out .= $comment ;
+ # Terminate the comment with NULL unless it already is
+ $out .= GZIP_NULL_BYTE
+ if ! length $comment or
+ substr($comment, 1, -1) ne GZIP_NULL_BYTE;
+ }
+
+ # HEADER CRC
+ $out .= pack("v", crc32($out) & 0x00FF ) if $param->value('HeaderCRC') ;
+
+ noUTF8($out);
+
+ return $out ;
+}
+
+sub mkFinalTrailer
+{
+ return '';
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+IO::Compress::Gzip - Write RFC 1952 files/buffers
+
+
+
+=head1 SYNOPSIS
+
+ use IO::Compress::Gzip qw(gzip $GzipError) ;
+
+ my $status = gzip $input => $output [,OPTS]
+ or die "gzip failed: $GzipError\n";
+
+ my $z = new IO::Compress::Gzip $output [,OPTS]
+ or die "gzip failed: $GzipError\n";
+
+ $z->print($string);
+ $z->printf($format, $string);
+ $z->write($string);
+ $z->syswrite($string [, $length, $offset]);
+ $z->flush();
+ $z->tell();
+ $z->eof();
+ $z->seek($position, $whence);
+ $z->binmode();
+ $z->fileno();
+ $z->opened();
+ $z->autoflush();
+ $z->input_line_number();
+ $z->newStream( [OPTS] );
+
+ $z->deflateParams();
+
+ $z->close() ;
+
+ $GzipError ;
+
+ # IO::File mode
+
+ print $z $string;
+ printf $z $format, $string;
+ tell $z
+ eof $z
+ seek $z, $position, $whence
+ binmode $z
+ fileno $z
+ close $z ;
+
+
+=head1 DESCRIPTION
+
+This module provides a Perl interface that allows writing compressed
+data to files or buffer as defined in RFC 1952.
+
+All the gzip headers defined in RFC 1952 can be created using
+this module.
+
+For reading RFC 1952 files/buffers, see the companion module
+L<IO::Uncompress::Gunzip|IO::Uncompress::Gunzip>.
+
+=head1 Functional Interface
+
+A top-level function, C<gzip>, is provided to carry out
+"one-shot" compression between buffers and/or files. For finer
+control over the compression process, see the L</"OO Interface">
+section.
+
+ use IO::Compress::Gzip qw(gzip $GzipError) ;
+
+ gzip $input => $output [,OPTS]
+ or die "gzip failed: $GzipError\n";
+
+The functional interface needs Perl5.005 or better.
+
+=head2 gzip $input => $output [, OPTS]
+
+C<gzip> expects at least two parameters, C<$input> and C<$output>.
+
+=head3 The C<$input> parameter
+
+The parameter, C<$input>, is used to define the source of
+the uncompressed data.
+
+It can take one of the following forms:
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for reading and the input data
+will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the input data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the input data will be read
+from C<$$input>.
+
+=item An array reference
+
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
+The complete array will be walked to ensure that it only
+contains valid filenames before any data is compressed.
+
+=item An Input FileGlob string
+
+If C<$input> is a string that is delimited by the characters "<" and ">"
+C<gzip> will assume that it is an I<input fileglob string>. The
+input is the list of files that match the fileglob.
+
+If the fileglob does not match any files ...
+
+See L<File::GlobMapper|File::GlobMapper> for more details.
+
+=back
+
+If the C<$input> parameter is any other type, C<undef> will be returned.
+
+In addition, if C<$input> is a simple filename, the default values for
+the C<Name> and C<Time> options will be sourced from that file.
+
+If you do not want to use these defaults they can be overridden by
+explicitly setting the C<Name> and C<Time> options or by setting the
+C<Minimal> parameter.
+
+=head3 The C<$output> parameter
+
+The parameter C<$output> is used to control the destination of the
+compressed data. This parameter can take one of these forms.
+
+=over 5
+
+=item A filename
+
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the compressed
+data will be written to it.
+
+=item A filehandle
+
+If the C<$output> parameter is a filehandle, the compressed data
+will be written to it.
+The string '-' can be used as an alias for standard output.
+
+=item A scalar reference
+
+If C<$output> is a scalar reference, the compressed data will be
+stored in C<$$output>.
+
+=item An Array Reference
+
+If C<$output> is an array reference, the compressed data will be
+pushed onto the array.
+
+=item An Output FileGlob
+
+If C<$output> is a string that is delimited by the characters "<" and ">"
+C<gzip> will assume that it is an I<output fileglob string>. The
+output is the list of files that match the fileglob.
+
+When C<$output> is an fileglob string, C<$input> must also be a fileglob
+string. Anything else is an error.
+
+=back
+
+If the C<$output> parameter is any other type, C<undef> will be returned.
+
+=head2 Notes
+
+When C<$input> maps to multiple files/buffers and C<$output> is a single
+file/buffer the input files/buffers will be stored
+in C<$output> as a concatenated series of compressed data streams.
+
+=head2 Optional Parameters
+
+Unless specified below, the optional parameters for C<gzip>,
+C<OPTS>, are the same as those used with the OO interface defined in the
+L</"Constructor Options"> section below.
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option applies to any input or output data streams to
+C<gzip> that are filehandles.
+
+If C<AutoClose> is specified, and the value is true, it will result in all
+input and/or output filehandles being closed once C<gzip> has
+completed.
+
+This parameter defaults to 0.
+
+=item C<< BinModeIn => 0|1 >>
+
+When reading from a file or filehandle, set C<binmode> before reading.
+
+Defaults to 0.
+
+=item C<< Append => 0|1 >>
+
+The behaviour of this option is dependent on the type of output data
+stream.
+
+=over 5
+
+=item * A Buffer
+
+If C<Append> is enabled, all compressed data will be append to the end of
+the output buffer. Otherwise the output buffer will be cleared before any
+compressed data is written to it.
+
+=item * A Filename
+
+If C<Append> is enabled, the file will be opened in append mode. Otherwise
+the contents of the file, if any, will be truncated before any compressed
+data is written to it.
+
+=item * A Filehandle
+
+If C<Append> is enabled, the filehandle will be positioned to the end of
+the file via a call to C<seek> before any compressed data is
+written to it. Otherwise the file pointer will not be moved.
+
+=back
+
+When C<Append> is specified, and set to true, it will I<append> all compressed
+data to the output data stream.
+
+So when the output is a filehandle it will carry out a seek to the eof
+before writing any compressed data. If the output is a filename, it will be opened for
+appending. If the output is a buffer, all compressed data will be appened to
+the existing buffer.
+
+Conversely when C<Append> is not specified, or it is present and is set to
+false, it will operate as follows.
+
+When the output is a filename, it will truncate the contents of the file
+before writing any compressed data. If the output is a filehandle
+its position will not be changed. If the output is a buffer, it will be
+wiped before any compressed data is output.
+
+Defaults to 0.
+
+=back
+
+=head2 Examples
+
+To read the contents of the file C<file1.txt> and write the compressed
+data to the file C<file1.txt.gz>.
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::Gzip qw(gzip $GzipError) ;
+
+ my $input = "file1.txt";
+ gzip $input => "$input.gz"
+ or die "gzip failed: $GzipError\n";
+
+To read from an existing Perl filehandle, C<$input>, and write the
+compressed data to a buffer, C<$buffer>.
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::Gzip qw(gzip $GzipError) ;
+ use IO::File ;
+
+ my $input = new IO::File "<file1.txt"
+ or die "Cannot open 'file1.txt': $!\n" ;
+ my $buffer ;
+ gzip $input => \$buffer
+ or die "gzip failed: $GzipError\n";
+
+To compress all files in the directory "/my/home" that match "*.txt"
+and store the compressed data in the same directory
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::Gzip qw(gzip $GzipError) ;
+
+ gzip '</my/home/*.txt>' => '<*.gz>'
+ or die "gzip failed: $GzipError\n";
+
+and if you want to compress each file one at a time, this will do the trick
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::Gzip qw(gzip $GzipError) ;
+
+ for my $input ( glob "/my/home/*.txt" )
+ {
+ my $output = "$input.gz" ;
+ gzip $input => $output
+ or die "Error compressing '$input': $GzipError\n";
+ }
+
+=head1 OO Interface
+
+=head2 Constructor
+
+The format of the constructor for C<IO::Compress::Gzip> is shown below
+
+ my $z = new IO::Compress::Gzip $output [,OPTS]
+ or die "IO::Compress::Gzip failed: $GzipError\n";
+
+It returns an C<IO::Compress::Gzip> object on success and undef on failure.
+The variable C<$GzipError> will contain an error message on failure.
+
+If you are running Perl 5.005 or better the object, C<$z>, returned from
+IO::Compress::Gzip can be used exactly like an L<IO::File|IO::File> filehandle.
+This means that all normal output file operations can be carried out
+with C<$z>.
+For example, to write to a compressed file/buffer you can use either of
+these forms
+
+ $z->print("hello world\n");
+ print $z "hello world\n";
+
+The mandatory parameter C<$output> is used to control the destination
+of the compressed data. This parameter can take one of these forms.
+
+=over 5
+
+=item A filename
+
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the compressed data
+will be written to it.
+
+=item A filehandle
+
+If the C<$output> parameter is a filehandle, the compressed data will be
+written to it.
+The string '-' can be used as an alias for standard output.
+
+=item A scalar reference
+
+If C<$output> is a scalar reference, the compressed data will be stored
+in C<$$output>.
+
+=back
+
+If the C<$output> parameter is any other type, C<IO::Compress::Gzip>::new will
+return undef.
+
+=head2 Constructor Options
+
+C<OPTS> is any combination of the following options:
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option is only valid when the C<$output> parameter is a filehandle. If
+specified, and the value is true, it will result in the C<$output> being
+closed once either the C<close> method is called or the C<IO::Compress::Gzip>
+object is destroyed.
+
+This parameter defaults to 0.
+
+=item C<< Append => 0|1 >>
+
+Opens C<$output> in append mode.
+
+The behaviour of this option is dependent on the type of C<$output>.
+
+=over 5
+
+=item * A Buffer
+
+If C<$output> is a buffer and C<Append> is enabled, all compressed data
+will be append to the end of C<$output>. Otherwise C<$output> will be
+cleared before any data is written to it.
+
+=item * A Filename
+
+If C<$output> is a filename and C<Append> is enabled, the file will be
+opened in append mode. Otherwise the contents of the file, if any, will be
+truncated before any compressed data is written to it.
+
+=item * A Filehandle
+
+If C<$output> is a filehandle, the file pointer will be positioned to the
+end of the file via a call to C<seek> before any compressed data is written
+to it. Otherwise the file pointer will not be moved.
+
+=back
+
+This parameter defaults to 0.
+
+=item C<< Merge => 0|1 >>
+
+This option is used to compress input data and append it to an existing
+compressed data stream in C<$output>. The end result is a single compressed
+data stream stored in C<$output>.
+
+It is a fatal error to attempt to use this option when C<$output> is not an
+RFC 1952 data stream.
+
+There are a number of other limitations with the C<Merge> option:
+
+=over 5
+
+=item 1
+
+This module needs to have been built with zlib 1.2.1 or better to work. A
+fatal error will be thrown if C<Merge> is used with an older version of
+zlib.
+
+=item 2
+
+If C<$output> is a file or a filehandle, it must be seekable.
+
+=back
+
+This parameter defaults to 0.
+
+=item -Level
+
+Defines the compression level used by zlib. The value should either be
+a number between 0 and 9 (0 means no compression and 9 is maximum
+compression), or one of the symbolic constants defined below.
+
+ Z_NO_COMPRESSION
+ Z_BEST_SPEED
+ Z_BEST_COMPRESSION
+ Z_DEFAULT_COMPRESSION
+
+The default is Z_DEFAULT_COMPRESSION.
+
+Note, these constants are not imported by C<IO::Compress::Gzip> by default.
+
+ use IO::Compress::Gzip qw(:strategy);
+ use IO::Compress::Gzip qw(:constants);
+ use IO::Compress::Gzip qw(:all);
+
+=item -Strategy
+
+Defines the strategy used to tune the compression. Use one of the symbolic
+constants defined below.
+
+ Z_FILTERED
+ Z_HUFFMAN_ONLY
+ Z_RLE
+ Z_FIXED
+ Z_DEFAULT_STRATEGY
+
+The default is Z_DEFAULT_STRATEGY.
+
+=item C<< Minimal => 0|1 >>
+
+If specified, this option will force the creation of the smallest possible
+compliant gzip header (which is exactly 10 bytes long) as defined in
+RFC 1952.
+
+See the section titled "Compliance" in RFC 1952 for a definition
+of the values used for the fields in the gzip header.
+
+All other parameters that control the content of the gzip header will
+be ignored if this parameter is set to 1.
+
+This parameter defaults to 0.
+
+=item C<< Comment => $comment >>
+
+Stores the contents of C<$comment> in the COMMENT field in
+the gzip header.
+By default, no comment field is written to the gzip file.
+
+If the C<-Strict> option is enabled, the comment can only consist of ISO
+8859-1 characters plus line feed.
+
+If the C<-Strict> option is disabled, the comment field can contain any
+character except NULL. If any null characters are present, the field
+will be truncated at the first NULL.
+
+=item C<< Name => $string >>
+
+Stores the contents of C<$string> in the gzip NAME header field. If
+C<Name> is not specified, no gzip NAME field will be created.
+
+If the C<-Strict> option is enabled, C<$string> can only consist of ISO
+8859-1 characters.
+
+If C<-Strict> is disabled, then C<$string> can contain any character
+except NULL. If any null characters are present, the field will be
+truncated at the first NULL.
+
+=item C<< Time => $number >>
+
+Sets the MTIME field in the gzip header to $number.
+
+This field defaults to the time the C<IO::Compress::Gzip> object was created
+if this option is not specified.
+
+=item C<< TextFlag => 0|1 >>
+
+This parameter controls the setting of the FLG.FTEXT bit in the gzip
+header. It is used to signal that the data stored in the gzip file/buffer
+is probably text.
+
+The default is 0.
+
+=item C<< HeaderCRC => 0|1 >>
+
+When true this parameter will set the FLG.FHCRC bit to 1 in the gzip header
+and set the CRC16 header field to the CRC of the complete gzip header
+except the CRC16 field itself.
+
+B<Note> that gzip files created with the C<HeaderCRC> flag set to 1 cannot
+be read by most, if not all, of the the standard gunzip utilities, most
+notably gzip version 1.2.4. You should therefore avoid using this option if
+you want to maximize the portability of your gzip files.
+
+This parameter defaults to 0.
+
+=item C<< OS_Code => $value >>
+
+Stores C<$value> in the gzip OS header field. A number between 0 and 255 is
+valid.
+
+If not specified, this parameter defaults to the OS code of the Operating
+System this module was built on. The value 3 is used as a catch-all for all
+Unix variants and unknown Operating Systems.
+
+=item C<< ExtraField => $data >>
+
+This parameter allows additional metadata to be stored in the ExtraField in
+the gzip header. An RFC 1952 compliant ExtraField consists of zero or more
+subfields. Each subfield consists of a two byte header followed by the
+subfield data.
+
+The list of subfields can be supplied in any of the following formats
+
+ -ExtraField => [$id1, $data1,
+ $id2, $data2,
+ ...
+ ]
+ -ExtraField => [ [$id1 => $data1],
+ [$id2 => $data2],
+ ...
+ ]
+ -ExtraField => { $id1 => $data1,
+ $id2 => $data2,
+ ...
+ }
+
+Where C<$id1>, C<$id2> are two byte subfield ID's. The second byte of
+the ID cannot be 0, unless the C<Strict> option has been disabled.
+
+If you use the hash syntax, you have no control over the order in which
+the ExtraSubFields are stored, plus you cannot have SubFields with
+duplicate ID.
+
+Alternatively the list of subfields can by supplied as a scalar, thus
+
+ -ExtraField => $rawdata
+
+If you use the raw format, and the C<Strict> option is enabled,
+C<IO::Compress::Gzip> will check that C<$rawdata> consists of zero or more
+conformant sub-fields. When C<Strict> is disabled, C<$rawdata> can
+consist of any arbitrary byte stream.
+
+The maximum size of the Extra Field 65535 bytes.
+
+=item C<< ExtraFlags => $value >>
+
+Sets the XFL byte in the gzip header to C<$value>.
+
+If this option is not present, the value stored in XFL field will be
+determined by the setting of the C<Level> option.
+
+If C<< Level => Z_BEST_SPEED >> has been specified then XFL is set to 2.
+If C<< Level => Z_BEST_COMPRESSION >> has been specified then XFL is set to 4.
+Otherwise XFL is set to 0.
+
+=item C<< Strict => 0|1 >>
+
+C<Strict> will optionally police the values supplied with other options
+to ensure they are compliant with RFC1952.
+
+This option is enabled by default.
+
+If C<Strict> is enabled the following behaviour will be policed:
+
+=over 5
+
+=item *
+
+The value supplied with the C<Name> option can only contain ISO 8859-1
+characters.
+
+=item *
+
+The value supplied with the C<Comment> option can only contain ISO 8859-1
+characters plus line-feed.
+
+=item *
+
+The values supplied with the C<-Name> and C<-Comment> options cannot
+contain multiple embedded nulls.
+
+=item *
+
+If an C<ExtraField> option is specified and it is a simple scalar,
+it must conform to the sub-field structure as defined in RFC 1952.
+
+=item *
+
+If an C<ExtraField> option is specified the second byte of the ID will be
+checked in each subfield to ensure that it does not contain the reserved
+value 0x00.
+
+=back
+
+When C<Strict> is disabled the following behaviour will be policed:
+
+=over 5
+
+=item *
+
+The value supplied with C<-Name> option can contain
+any character except NULL.
+
+=item *
+
+The value supplied with C<-Comment> option can contain any character
+except NULL.
+
+=item *
+
+The values supplied with the C<-Name> and C<-Comment> options can contain
+multiple embedded nulls. The string written to the gzip header will
+consist of the characters up to, but not including, the first embedded
+NULL.
+
+=item *
+
+If an C<ExtraField> option is specified and it is a simple scalar, the
+structure will not be checked. The only error is if the length is too big.
+
+=item *
+
+The ID header in an C<ExtraField> sub-field can consist of any two bytes.
+
+=back
+
+=back
+
+=head2 Examples
+
+TODO
+
+=head1 Methods
+
+=head2 print
+
+Usage is
+
+ $z->print($data)
+ print $z $data
+
+Compresses and outputs the contents of the C<$data> parameter. This
+has the same behaviour as the C<print> built-in.
+
+Returns true if successful.
+
+=head2 printf
+
+Usage is
+
+ $z->printf($format, $data)
+ printf $z $format, $data
+
+Compresses and outputs the contents of the C<$data> parameter.
+
+Returns true if successful.
+
+=head2 syswrite
+
+Usage is
+
+ $z->syswrite $data
+ $z->syswrite $data, $length
+ $z->syswrite $data, $length, $offset
+
+Compresses and outputs the contents of the C<$data> parameter.
+
+Returns the number of uncompressed bytes written, or C<undef> if
+unsuccessful.
+
+=head2 write
+
+Usage is
+
+ $z->write $data
+ $z->write $data, $length
+ $z->write $data, $length, $offset
+
+Compresses and outputs the contents of the C<$data> parameter.
+
+Returns the number of uncompressed bytes written, or C<undef> if
+unsuccessful.
+
+=head2 flush
+
+Usage is
+
+ $z->flush;
+ $z->flush($flush_type);
+
+Flushes any pending compressed data to the output file/buffer.
+
+This method takes an optional parameter, C<$flush_type>, that controls
+how the flushing will be carried out. By default the C<$flush_type>
+used is C<Z_FINISH>. Other valid values for C<$flush_type> are
+C<Z_NO_FLUSH>, C<Z_SYNC_FLUSH>, C<Z_FULL_FLUSH> and C<Z_BLOCK>. It is
+strongly recommended that you only set the C<flush_type> parameter if
+you fully understand the implications of what it does - overuse of C<flush>
+can seriously degrade the level of compression achieved. See the C<zlib>
+documentation for details.
+
+Returns true on success.
+
+=head2 tell
+
+Usage is
+
+ $z->tell()
+ tell $z
+
+Returns the uncompressed file offset.
+
+=head2 eof
+
+Usage is
+
+ $z->eof();
+ eof($z);
+
+Returns true if the C<close> method has been called.
+
+=head2 seek
+
+ $z->seek($position, $whence);
+ seek($z, $position, $whence);
+
+Provides a sub-set of the C<seek> functionality, with the restriction
+that it is only legal to seek forward in the output file/buffer.
+It is a fatal error to attempt to seek backward.
+
+Empty parts of the file/buffer will have NULL (0x00) bytes written to them.
+
+The C<$whence> parameter takes one the usual values, namely SEEK_SET,
+SEEK_CUR or SEEK_END.
+
+Returns 1 on success, 0 on failure.
+
+=head2 binmode
+
+Usage is
+
+ $z->binmode
+ binmode $z ;
+
+This is a noop provided for completeness.
+
+=head2 opened
+
+ $z->opened()
+
+Returns true if the object currently refers to a opened file/buffer.
+
+=head2 autoflush
+
+ my $prev = $z->autoflush()
+ my $prev = $z->autoflush(EXPR)
+
+If the C<$z> object is associated with a file or a filehandle, this method
+returns the current autoflush setting for the underlying filehandle. If
+C<EXPR> is present, and is non-zero, it will enable flushing after every
+write/print operation.
+
+If C<$z> is associated with a buffer, this method has no effect and always
+returns C<undef>.
+
+B<Note> that the special variable C<$|> B<cannot> be used to set or
+retrieve the autoflush setting.
+
+=head2 input_line_number
+
+ $z->input_line_number()
+ $z->input_line_number(EXPR)
+
+This method always returns C<undef> when compressing.
+
+=head2 fileno
+
+ $z->fileno()
+ fileno($z)
+
+If the C<$z> object is associated with a file or a filehandle, C<fileno>
+will return the underlying file descriptor. Once the C<close> method is
+called C<fileno> will return C<undef>.
+
+If the C<$z> object is is associated with a buffer, this method will return
+C<undef>.
+
+=head2 close
+
+ $z->close() ;
+ close $z ;
+
+Flushes any pending compressed data and then closes the output file/buffer.
+
+For most versions of Perl this method will be automatically invoked if
+the IO::Compress::Gzip object is destroyed (either explicitly or by the
+variable with the reference to the object going out of scope). The
+exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In
+these cases, the C<close> method will be called automatically, but
+not until global destruction of all live objects when the program is
+terminating.
+
+Therefore, if you want your scripts to be able to run on all versions
+of Perl, you should call C<close> explicitly and not rely on automatic
+closing.
+
+Returns true on success, otherwise 0.
+
+If the C<AutoClose> option has been enabled when the IO::Compress::Gzip
+object was created, and the object is associated with a file, the
+underlying file will also be closed.
+
+=head2 newStream([OPTS])
+
+Usage is
+
+ $z->newStream( [OPTS] )
+
+Closes the current compressed data stream and starts a new one.
+
+OPTS consists of any of the the options that are available when creating
+the C<$z> object.
+
+See the L</"Constructor Options"> section for more details.
+
+=head2 deflateParams
+
+Usage is
+
+ $z->deflateParams
+
+TODO
+
+=head1 Importing
+
+A number of symbolic constants are required by some methods in
+C<IO::Compress::Gzip>. None are imported by default.
+
+=over 5
+
+=item :all
+
+Imports C<gzip>, C<$GzipError> and all symbolic
+constants that can be used by C<IO::Compress::Gzip>. Same as doing this
+
+ use IO::Compress::Gzip qw(gzip $GzipError :constants) ;
+
+=item :constants
+
+Import all symbolic constants. Same as doing this
+
+ use IO::Compress::Gzip qw(:flush :level :strategy) ;
+
+=item :flush
+
+These symbolic constants are used by the C<flush> method.
+
+ Z_NO_FLUSH
+ Z_PARTIAL_FLUSH
+ Z_SYNC_FLUSH
+ Z_FULL_FLUSH
+ Z_FINISH
+ Z_BLOCK
+
+=item :level
+
+These symbolic constants are used by the C<Level> option in the constructor.
+
+ Z_NO_COMPRESSION
+ Z_BEST_SPEED
+ Z_BEST_COMPRESSION
+ Z_DEFAULT_COMPRESSION
+
+=item :strategy
+
+These symbolic constants are used by the C<Strategy> option in the constructor.
+
+ Z_FILTERED
+ Z_HUFFMAN_ONLY
+ Z_RLE
+ Z_FIXED
+ Z_DEFAULT_STRATEGY
+
+
+
+
+=back
+
+=head1 EXAMPLES
+
+=head2 Apache::GZip Revisited
+
+See L<IO::Compress::FAQ|IO::Compress::FAQ/"Apache::GZip Revisited">
+
+
+
+=head2 Working with Net::FTP
+
+See L<IO::Compress::FAQ|IO::Compress::FAQ/"Compressed files and Net::FTP">
+
+=head1 SEE ALSO
+
+L<Compress::Zlib>, L<IO::Uncompress::Gunzip>, L<IO::Compress::Deflate>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Compress::Bzip2>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
+
+L<Compress::Zlib::FAQ|Compress::Zlib::FAQ>
+
+L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
+L<Archive::Tar|Archive::Tar>,
+L<IO::Zlib|IO::Zlib>
+
+For RFC 1950, 1951 and 1952 see
+F<http://www.faqs.org/rfcs/rfc1950.html>,
+F<http://www.faqs.org/rfcs/rfc1951.html> and
+F<http://www.faqs.org/rfcs/rfc1952.html>
+
+The I<zlib> compression library was written by Jean-loup Gailly
+F<gzip@prep.ai.mit.edu> and Mark Adler F<madler@alumni.caltech.edu>.
+
+The primary site for the I<zlib> compression library is
+F<http://www.zlib.org>.
+
+The primary site for gzip is F<http://www.gzip.org>.
+
+=head1 AUTHOR
+
+This module was written by Paul Marquess, F<pmqs@cpan.org>.
+
+=head1 MODIFICATION HISTORY
+
+See the Changes file.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2005-2010 Paul Marquess. All rights reserved.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Compress/Gzip/Constants.pm b/Master/tlpkg/tlperl/lib/IO/Compress/Gzip/Constants.pm
new file mode 100644
index 00000000000..8504330d188
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Compress/Gzip/Constants.pm
@@ -0,0 +1,148 @@
+package IO::Compress::Gzip::Constants;
+
+use strict ;
+use warnings;
+use bytes;
+
+require Exporter;
+
+our ($VERSION, @ISA, @EXPORT, %GZIP_OS_Names);
+our ($GZIP_FNAME_INVALID_CHAR_RE, $GZIP_FCOMMENT_INVALID_CHAR_RE);
+
+$VERSION = '2.024';
+
+@ISA = qw(Exporter);
+
+@EXPORT= qw(
+
+ GZIP_ID_SIZE
+ GZIP_ID1
+ GZIP_ID2
+
+ GZIP_FLG_DEFAULT
+ GZIP_FLG_FTEXT
+ GZIP_FLG_FHCRC
+ GZIP_FLG_FEXTRA
+ GZIP_FLG_FNAME
+ GZIP_FLG_FCOMMENT
+ GZIP_FLG_RESERVED
+
+ GZIP_CM_DEFLATED
+
+ GZIP_MIN_HEADER_SIZE
+ GZIP_TRAILER_SIZE
+
+ GZIP_MTIME_DEFAULT
+ GZIP_XFL_DEFAULT
+ GZIP_FEXTRA_HEADER_SIZE
+ GZIP_FEXTRA_MAX_SIZE
+ GZIP_FEXTRA_SUBFIELD_HEADER_SIZE
+ GZIP_FEXTRA_SUBFIELD_ID_SIZE
+ GZIP_FEXTRA_SUBFIELD_LEN_SIZE
+ GZIP_FEXTRA_SUBFIELD_MAX_SIZE
+
+ $GZIP_FNAME_INVALID_CHAR_RE
+ $GZIP_FCOMMENT_INVALID_CHAR_RE
+
+ GZIP_FHCRC_SIZE
+
+ GZIP_ISIZE_MAX
+ GZIP_ISIZE_MOD_VALUE
+
+
+ GZIP_NULL_BYTE
+
+ GZIP_OS_DEFAULT
+
+ %GZIP_OS_Names
+
+ GZIP_MINIMUM_HEADER
+
+ );
+
+# Constant names derived from RFC 1952
+
+use constant GZIP_ID_SIZE => 2 ;
+use constant GZIP_ID1 => 0x1F;
+use constant GZIP_ID2 => 0x8B;
+
+use constant GZIP_MIN_HEADER_SIZE => 10 ;# minimum gzip header size
+use constant GZIP_TRAILER_SIZE => 8 ;
+
+
+use constant GZIP_FLG_DEFAULT => 0x00 ;
+use constant GZIP_FLG_FTEXT => 0x01 ;
+use constant GZIP_FLG_FHCRC => 0x02 ; # called CONTINUATION in gzip
+use constant GZIP_FLG_FEXTRA => 0x04 ;
+use constant GZIP_FLG_FNAME => 0x08 ;
+use constant GZIP_FLG_FCOMMENT => 0x10 ;
+#use constant GZIP_FLG_ENCRYPTED => 0x20 ; # documented in gzip sources
+use constant GZIP_FLG_RESERVED => (0x20 | 0x40 | 0x80) ;
+
+use constant GZIP_XFL_DEFAULT => 0x00 ;
+
+use constant GZIP_MTIME_DEFAULT => 0x00 ;
+
+use constant GZIP_FEXTRA_HEADER_SIZE => 2 ;
+use constant GZIP_FEXTRA_MAX_SIZE => 0xFFFF ;
+use constant GZIP_FEXTRA_SUBFIELD_ID_SIZE => 2 ;
+use constant GZIP_FEXTRA_SUBFIELD_LEN_SIZE => 2 ;
+use constant GZIP_FEXTRA_SUBFIELD_HEADER_SIZE => GZIP_FEXTRA_SUBFIELD_ID_SIZE +
+ GZIP_FEXTRA_SUBFIELD_LEN_SIZE;
+use constant GZIP_FEXTRA_SUBFIELD_MAX_SIZE => GZIP_FEXTRA_MAX_SIZE -
+ GZIP_FEXTRA_SUBFIELD_HEADER_SIZE ;
+
+
+if (ord('A') == 193)
+{
+ # EBCDIC
+ $GZIP_FNAME_INVALID_CHAR_RE = '[\x00-\x3f\xff]';
+ $GZIP_FCOMMENT_INVALID_CHAR_RE = '[\x00-\x0a\x11-\x14\x16-\x3f\xff]';
+
+}
+else
+{
+ $GZIP_FNAME_INVALID_CHAR_RE = '[\x00-\x1F\x7F-\x9F]';
+ $GZIP_FCOMMENT_INVALID_CHAR_RE = '[\x00-\x09\x11-\x1F\x7F-\x9F]';
+}
+
+use constant GZIP_FHCRC_SIZE => 2 ; # aka CONTINUATION in gzip
+
+use constant GZIP_CM_DEFLATED => 8 ;
+
+use constant GZIP_NULL_BYTE => "\x00";
+use constant GZIP_ISIZE_MAX => 0xFFFFFFFF ;
+use constant GZIP_ISIZE_MOD_VALUE => GZIP_ISIZE_MAX + 1 ;
+
+# OS Names sourced from http://www.gzip.org/format.txt
+
+use constant GZIP_OS_DEFAULT=> 0xFF ;
+%GZIP_OS_Names = (
+ 0 => 'MS-DOS',
+ 1 => 'Amiga',
+ 2 => 'VMS',
+ 3 => 'Unix',
+ 4 => 'VM/CMS',
+ 5 => 'Atari TOS',
+ 6 => 'HPFS (OS/2, NT)',
+ 7 => 'Macintosh',
+ 8 => 'Z-System',
+ 9 => 'CP/M',
+ 10 => 'TOPS-20',
+ 11 => 'NTFS (NT)',
+ 12 => 'SMS QDOS',
+ 13 => 'Acorn RISCOS',
+ 14 => 'VFAT file system (Win95, NT)',
+ 15 => 'MVS',
+ 16 => 'BeOS',
+ 17 => 'Tandem/NSK',
+ 18 => 'THEOS',
+ GZIP_OS_DEFAULT() => 'Unknown',
+ ) ;
+
+use constant GZIP_MINIMUM_HEADER => pack("C4 V C C",
+ GZIP_ID1, GZIP_ID2, GZIP_CM_DEFLATED, GZIP_FLG_DEFAULT,
+ GZIP_MTIME_DEFAULT, GZIP_XFL_DEFAULT, GZIP_OS_DEFAULT) ;
+
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/IO/Compress/RawDeflate.pm b/Master/tlpkg/tlperl/lib/IO/Compress/RawDeflate.pm
new file mode 100644
index 00000000000..b97b51c0509
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Compress/RawDeflate.pm
@@ -0,0 +1,1017 @@
+package IO::Compress::RawDeflate ;
+
+# create RFC1951
+#
+use strict ;
+use warnings;
+use bytes;
+
+
+use IO::Compress::Base 2.024 ;
+use IO::Compress::Base::Common 2.024 qw(:Status createSelfTiedObject);
+use IO::Compress::Adapter::Deflate 2.024 ;
+
+require Exporter ;
+
+
+our ($VERSION, @ISA, @EXPORT_OK, %DEFLATE_CONSTANTS, %EXPORT_TAGS, $RawDeflateError);
+
+$VERSION = '2.024';
+$RawDeflateError = '';
+
+@ISA = qw(Exporter IO::Compress::Base);
+@EXPORT_OK = qw( $RawDeflateError rawdeflate ) ;
+
+%EXPORT_TAGS = ( flush => [qw{
+ Z_NO_FLUSH
+ Z_PARTIAL_FLUSH
+ Z_SYNC_FLUSH
+ Z_FULL_FLUSH
+ Z_FINISH
+ Z_BLOCK
+ }],
+ level => [qw{
+ Z_NO_COMPRESSION
+ Z_BEST_SPEED
+ Z_BEST_COMPRESSION
+ Z_DEFAULT_COMPRESSION
+ }],
+ strategy => [qw{
+ Z_FILTERED
+ Z_HUFFMAN_ONLY
+ Z_RLE
+ Z_FIXED
+ Z_DEFAULT_STRATEGY
+ }],
+
+ );
+
+{
+ my %seen;
+ foreach (keys %EXPORT_TAGS )
+ {
+ push @{$EXPORT_TAGS{constants}},
+ grep { !$seen{$_}++ }
+ @{ $EXPORT_TAGS{$_} }
+ }
+ $EXPORT_TAGS{all} = $EXPORT_TAGS{constants} ;
+}
+
+
+%DEFLATE_CONSTANTS = %EXPORT_TAGS;
+
+push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
+
+Exporter::export_ok_tags('all');
+
+
+
+sub new
+{
+ my $class = shift ;
+
+ my $obj = createSelfTiedObject($class, \$RawDeflateError);
+
+ return $obj->_create(undef, @_);
+}
+
+sub rawdeflate
+{
+ my $obj = createSelfTiedObject(undef, \$RawDeflateError);
+ return $obj->_def(@_);
+}
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift;
+
+ return 1 ;
+}
+
+sub mkComp
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ my ($obj, $errstr, $errno) = IO::Compress::Adapter::Deflate::mkCompObject(
+ $got->value('CRC32'),
+ $got->value('Adler32'),
+ $got->value('Level'),
+ $got->value('Strategy')
+ );
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ return $obj;
+}
+
+
+sub mkHeader
+{
+ my $self = shift ;
+ return '';
+}
+
+sub mkTrailer
+{
+ my $self = shift ;
+ return '';
+}
+
+sub mkFinalTrailer
+{
+ return '';
+}
+
+
+#sub newHeader
+#{
+# my $self = shift ;
+# return '';
+#}
+
+sub getExtraParams
+{
+ my $self = shift ;
+ return $self->getZlibParams();
+}
+
+sub getZlibParams
+{
+ my $self = shift ;
+
+ use IO::Compress::Base::Common 2.024 qw(:Parse);
+ use Compress::Raw::Zlib 2.024 qw(Z_DEFLATED Z_DEFAULT_COMPRESSION Z_DEFAULT_STRATEGY);
+
+
+ return (
+
+ # zlib behaviour
+ #'Method' => [0, 1, Parse_unsigned, Z_DEFLATED],
+ 'Level' => [0, 1, Parse_signed, Z_DEFAULT_COMPRESSION],
+ 'Strategy' => [0, 1, Parse_signed, Z_DEFAULT_STRATEGY],
+
+ 'CRC32' => [0, 1, Parse_boolean, 0],
+ 'ADLER32' => [0, 1, Parse_boolean, 0],
+ 'Merge' => [1, 1, Parse_boolean, 0],
+ );
+
+
+}
+
+sub getInverseClass
+{
+ return ('IO::Uncompress::RawInflate',
+ \$IO::Uncompress::RawInflate::RawInflateError);
+}
+
+sub getFileInfo
+{
+ my $self = shift ;
+ my $params = shift;
+ my $file = shift ;
+
+}
+
+use IO::Seekable qw(SEEK_SET);
+
+sub createMerge
+{
+ my $self = shift ;
+ my $outValue = shift ;
+ my $outType = shift ;
+
+ my ($invClass, $error_ref) = $self->getInverseClass();
+ eval "require $invClass"
+ or die "aaaahhhh" ;
+
+ my $inf = $invClass->new( $outValue,
+ Transparent => 0,
+ #Strict => 1,
+ AutoClose => 0,
+ Scan => 1)
+ or return $self->saveErrorString(undef, "Cannot create InflateScan object: $$error_ref" ) ;
+
+ my $end_offset = 0;
+ $inf->scan()
+ or return $self->saveErrorString(undef, "Error Scanning: $$error_ref", $inf->errorNo) ;
+ $inf->zap($end_offset)
+ or return $self->saveErrorString(undef, "Error Zapping: $$error_ref", $inf->errorNo) ;
+
+ my $def = *$self->{Compress} = $inf->createDeflate();
+
+ *$self->{Header} = *$inf->{Info}{Header};
+ *$self->{UnCompSize} = *$inf->{UnCompSize}->clone();
+ *$self->{CompSize} = *$inf->{CompSize}->clone();
+ # TODO -- fix this
+ #*$self->{CompSize} = new U64(0, *$self->{UnCompSize_32bit});
+
+
+ if ( $outType eq 'buffer')
+ { substr( ${ *$self->{Buffer} }, $end_offset) = '' }
+ elsif ($outType eq 'handle' || $outType eq 'filename') {
+ *$self->{FH} = *$inf->{FH} ;
+ delete *$inf->{FH};
+ *$self->{FH}->flush() ;
+ *$self->{Handle} = 1 if $outType eq 'handle';
+
+ #seek(*$self->{FH}, $end_offset, SEEK_SET)
+ *$self->{FH}->seek($end_offset, SEEK_SET)
+ or return $self->saveErrorString(undef, $!, $!) ;
+ }
+
+ return $def ;
+}
+
+#### zlib specific methods
+
+sub deflateParams
+{
+ my $self = shift ;
+
+ my $level = shift ;
+ my $strategy = shift ;
+
+ my $status = *$self->{Compress}->deflateParams(Level => $level, Strategy => $strategy) ;
+ return $self->saveErrorString(0, *$self->{Compress}{Error}, *$self->{Compress}{ErrorNo})
+ if $status == STATUS_ERROR;
+
+ return 1;
+}
+
+
+
+
+1;
+
+__END__
+
+=head1 NAME
+
+IO::Compress::RawDeflate - Write RFC 1951 files/buffers
+
+
+
+=head1 SYNOPSIS
+
+ use IO::Compress::RawDeflate qw(rawdeflate $RawDeflateError) ;
+
+ my $status = rawdeflate $input => $output [,OPTS]
+ or die "rawdeflate failed: $RawDeflateError\n";
+
+ my $z = new IO::Compress::RawDeflate $output [,OPTS]
+ or die "rawdeflate failed: $RawDeflateError\n";
+
+ $z->print($string);
+ $z->printf($format, $string);
+ $z->write($string);
+ $z->syswrite($string [, $length, $offset]);
+ $z->flush();
+ $z->tell();
+ $z->eof();
+ $z->seek($position, $whence);
+ $z->binmode();
+ $z->fileno();
+ $z->opened();
+ $z->autoflush();
+ $z->input_line_number();
+ $z->newStream( [OPTS] );
+
+ $z->deflateParams();
+
+ $z->close() ;
+
+ $RawDeflateError ;
+
+ # IO::File mode
+
+ print $z $string;
+ printf $z $format, $string;
+ tell $z
+ eof $z
+ seek $z, $position, $whence
+ binmode $z
+ fileno $z
+ close $z ;
+
+
+=head1 DESCRIPTION
+
+This module provides a Perl interface that allows writing compressed
+data to files or buffer as defined in RFC 1951.
+
+Note that RFC 1951 data is not a good choice of compression format
+to use in isolation, especially if you want to auto-detect it.
+
+For reading RFC 1951 files/buffers, see the companion module
+L<IO::Uncompress::RawInflate|IO::Uncompress::RawInflate>.
+
+=head1 Functional Interface
+
+A top-level function, C<rawdeflate>, is provided to carry out
+"one-shot" compression between buffers and/or files. For finer
+control over the compression process, see the L</"OO Interface">
+section.
+
+ use IO::Compress::RawDeflate qw(rawdeflate $RawDeflateError) ;
+
+ rawdeflate $input => $output [,OPTS]
+ or die "rawdeflate failed: $RawDeflateError\n";
+
+The functional interface needs Perl5.005 or better.
+
+=head2 rawdeflate $input => $output [, OPTS]
+
+C<rawdeflate> expects at least two parameters, C<$input> and C<$output>.
+
+=head3 The C<$input> parameter
+
+The parameter, C<$input>, is used to define the source of
+the uncompressed data.
+
+It can take one of the following forms:
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for reading and the input data
+will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the input data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the input data will be read
+from C<$$input>.
+
+=item An array reference
+
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
+The complete array will be walked to ensure that it only
+contains valid filenames before any data is compressed.
+
+=item An Input FileGlob string
+
+If C<$input> is a string that is delimited by the characters "<" and ">"
+C<rawdeflate> will assume that it is an I<input fileglob string>. The
+input is the list of files that match the fileglob.
+
+If the fileglob does not match any files ...
+
+See L<File::GlobMapper|File::GlobMapper> for more details.
+
+=back
+
+If the C<$input> parameter is any other type, C<undef> will be returned.
+
+=head3 The C<$output> parameter
+
+The parameter C<$output> is used to control the destination of the
+compressed data. This parameter can take one of these forms.
+
+=over 5
+
+=item A filename
+
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the compressed
+data will be written to it.
+
+=item A filehandle
+
+If the C<$output> parameter is a filehandle, the compressed data
+will be written to it.
+The string '-' can be used as an alias for standard output.
+
+=item A scalar reference
+
+If C<$output> is a scalar reference, the compressed data will be
+stored in C<$$output>.
+
+=item An Array Reference
+
+If C<$output> is an array reference, the compressed data will be
+pushed onto the array.
+
+=item An Output FileGlob
+
+If C<$output> is a string that is delimited by the characters "<" and ">"
+C<rawdeflate> will assume that it is an I<output fileglob string>. The
+output is the list of files that match the fileglob.
+
+When C<$output> is an fileglob string, C<$input> must also be a fileglob
+string. Anything else is an error.
+
+=back
+
+If the C<$output> parameter is any other type, C<undef> will be returned.
+
+=head2 Notes
+
+When C<$input> maps to multiple files/buffers and C<$output> is a single
+file/buffer the input files/buffers will be stored
+in C<$output> as a concatenated series of compressed data streams.
+
+=head2 Optional Parameters
+
+Unless specified below, the optional parameters for C<rawdeflate>,
+C<OPTS>, are the same as those used with the OO interface defined in the
+L</"Constructor Options"> section below.
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option applies to any input or output data streams to
+C<rawdeflate> that are filehandles.
+
+If C<AutoClose> is specified, and the value is true, it will result in all
+input and/or output filehandles being closed once C<rawdeflate> has
+completed.
+
+This parameter defaults to 0.
+
+=item C<< BinModeIn => 0|1 >>
+
+When reading from a file or filehandle, set C<binmode> before reading.
+
+Defaults to 0.
+
+=item C<< Append => 0|1 >>
+
+The behaviour of this option is dependent on the type of output data
+stream.
+
+=over 5
+
+=item * A Buffer
+
+If C<Append> is enabled, all compressed data will be append to the end of
+the output buffer. Otherwise the output buffer will be cleared before any
+compressed data is written to it.
+
+=item * A Filename
+
+If C<Append> is enabled, the file will be opened in append mode. Otherwise
+the contents of the file, if any, will be truncated before any compressed
+data is written to it.
+
+=item * A Filehandle
+
+If C<Append> is enabled, the filehandle will be positioned to the end of
+the file via a call to C<seek> before any compressed data is
+written to it. Otherwise the file pointer will not be moved.
+
+=back
+
+When C<Append> is specified, and set to true, it will I<append> all compressed
+data to the output data stream.
+
+So when the output is a filehandle it will carry out a seek to the eof
+before writing any compressed data. If the output is a filename, it will be opened for
+appending. If the output is a buffer, all compressed data will be appened to
+the existing buffer.
+
+Conversely when C<Append> is not specified, or it is present and is set to
+false, it will operate as follows.
+
+When the output is a filename, it will truncate the contents of the file
+before writing any compressed data. If the output is a filehandle
+its position will not be changed. If the output is a buffer, it will be
+wiped before any compressed data is output.
+
+Defaults to 0.
+
+=back
+
+=head2 Examples
+
+To read the contents of the file C<file1.txt> and write the compressed
+data to the file C<file1.txt.1951>.
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::RawDeflate qw(rawdeflate $RawDeflateError) ;
+
+ my $input = "file1.txt";
+ rawdeflate $input => "$input.1951"
+ or die "rawdeflate failed: $RawDeflateError\n";
+
+To read from an existing Perl filehandle, C<$input>, and write the
+compressed data to a buffer, C<$buffer>.
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::RawDeflate qw(rawdeflate $RawDeflateError) ;
+ use IO::File ;
+
+ my $input = new IO::File "<file1.txt"
+ or die "Cannot open 'file1.txt': $!\n" ;
+ my $buffer ;
+ rawdeflate $input => \$buffer
+ or die "rawdeflate failed: $RawDeflateError\n";
+
+To compress all files in the directory "/my/home" that match "*.txt"
+and store the compressed data in the same directory
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::RawDeflate qw(rawdeflate $RawDeflateError) ;
+
+ rawdeflate '</my/home/*.txt>' => '<*.1951>'
+ or die "rawdeflate failed: $RawDeflateError\n";
+
+and if you want to compress each file one at a time, this will do the trick
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::RawDeflate qw(rawdeflate $RawDeflateError) ;
+
+ for my $input ( glob "/my/home/*.txt" )
+ {
+ my $output = "$input.1951" ;
+ rawdeflate $input => $output
+ or die "Error compressing '$input': $RawDeflateError\n";
+ }
+
+=head1 OO Interface
+
+=head2 Constructor
+
+The format of the constructor for C<IO::Compress::RawDeflate> is shown below
+
+ my $z = new IO::Compress::RawDeflate $output [,OPTS]
+ or die "IO::Compress::RawDeflate failed: $RawDeflateError\n";
+
+It returns an C<IO::Compress::RawDeflate> object on success and undef on failure.
+The variable C<$RawDeflateError> will contain an error message on failure.
+
+If you are running Perl 5.005 or better the object, C<$z>, returned from
+IO::Compress::RawDeflate can be used exactly like an L<IO::File|IO::File> filehandle.
+This means that all normal output file operations can be carried out
+with C<$z>.
+For example, to write to a compressed file/buffer you can use either of
+these forms
+
+ $z->print("hello world\n");
+ print $z "hello world\n";
+
+The mandatory parameter C<$output> is used to control the destination
+of the compressed data. This parameter can take one of these forms.
+
+=over 5
+
+=item A filename
+
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the compressed data
+will be written to it.
+
+=item A filehandle
+
+If the C<$output> parameter is a filehandle, the compressed data will be
+written to it.
+The string '-' can be used as an alias for standard output.
+
+=item A scalar reference
+
+If C<$output> is a scalar reference, the compressed data will be stored
+in C<$$output>.
+
+=back
+
+If the C<$output> parameter is any other type, C<IO::Compress::RawDeflate>::new will
+return undef.
+
+=head2 Constructor Options
+
+C<OPTS> is any combination of the following options:
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option is only valid when the C<$output> parameter is a filehandle. If
+specified, and the value is true, it will result in the C<$output> being
+closed once either the C<close> method is called or the C<IO::Compress::RawDeflate>
+object is destroyed.
+
+This parameter defaults to 0.
+
+=item C<< Append => 0|1 >>
+
+Opens C<$output> in append mode.
+
+The behaviour of this option is dependent on the type of C<$output>.
+
+=over 5
+
+=item * A Buffer
+
+If C<$output> is a buffer and C<Append> is enabled, all compressed data
+will be append to the end of C<$output>. Otherwise C<$output> will be
+cleared before any data is written to it.
+
+=item * A Filename
+
+If C<$output> is a filename and C<Append> is enabled, the file will be
+opened in append mode. Otherwise the contents of the file, if any, will be
+truncated before any compressed data is written to it.
+
+=item * A Filehandle
+
+If C<$output> is a filehandle, the file pointer will be positioned to the
+end of the file via a call to C<seek> before any compressed data is written
+to it. Otherwise the file pointer will not be moved.
+
+=back
+
+This parameter defaults to 0.
+
+=item C<< Merge => 0|1 >>
+
+This option is used to compress input data and append it to an existing
+compressed data stream in C<$output>. The end result is a single compressed
+data stream stored in C<$output>.
+
+It is a fatal error to attempt to use this option when C<$output> is not an
+RFC 1951 data stream.
+
+There are a number of other limitations with the C<Merge> option:
+
+=over 5
+
+=item 1
+
+This module needs to have been built with zlib 1.2.1 or better to work. A
+fatal error will be thrown if C<Merge> is used with an older version of
+zlib.
+
+=item 2
+
+If C<$output> is a file or a filehandle, it must be seekable.
+
+=back
+
+This parameter defaults to 0.
+
+=item -Level
+
+Defines the compression level used by zlib. The value should either be
+a number between 0 and 9 (0 means no compression and 9 is maximum
+compression), or one of the symbolic constants defined below.
+
+ Z_NO_COMPRESSION
+ Z_BEST_SPEED
+ Z_BEST_COMPRESSION
+ Z_DEFAULT_COMPRESSION
+
+The default is Z_DEFAULT_COMPRESSION.
+
+Note, these constants are not imported by C<IO::Compress::RawDeflate> by default.
+
+ use IO::Compress::RawDeflate qw(:strategy);
+ use IO::Compress::RawDeflate qw(:constants);
+ use IO::Compress::RawDeflate qw(:all);
+
+=item -Strategy
+
+Defines the strategy used to tune the compression. Use one of the symbolic
+constants defined below.
+
+ Z_FILTERED
+ Z_HUFFMAN_ONLY
+ Z_RLE
+ Z_FIXED
+ Z_DEFAULT_STRATEGY
+
+The default is Z_DEFAULT_STRATEGY.
+
+=item C<< Strict => 0|1 >>
+
+This is a placeholder option.
+
+=back
+
+=head2 Examples
+
+TODO
+
+=head1 Methods
+
+=head2 print
+
+Usage is
+
+ $z->print($data)
+ print $z $data
+
+Compresses and outputs the contents of the C<$data> parameter. This
+has the same behaviour as the C<print> built-in.
+
+Returns true if successful.
+
+=head2 printf
+
+Usage is
+
+ $z->printf($format, $data)
+ printf $z $format, $data
+
+Compresses and outputs the contents of the C<$data> parameter.
+
+Returns true if successful.
+
+=head2 syswrite
+
+Usage is
+
+ $z->syswrite $data
+ $z->syswrite $data, $length
+ $z->syswrite $data, $length, $offset
+
+Compresses and outputs the contents of the C<$data> parameter.
+
+Returns the number of uncompressed bytes written, or C<undef> if
+unsuccessful.
+
+=head2 write
+
+Usage is
+
+ $z->write $data
+ $z->write $data, $length
+ $z->write $data, $length, $offset
+
+Compresses and outputs the contents of the C<$data> parameter.
+
+Returns the number of uncompressed bytes written, or C<undef> if
+unsuccessful.
+
+=head2 flush
+
+Usage is
+
+ $z->flush;
+ $z->flush($flush_type);
+
+Flushes any pending compressed data to the output file/buffer.
+
+This method takes an optional parameter, C<$flush_type>, that controls
+how the flushing will be carried out. By default the C<$flush_type>
+used is C<Z_FINISH>. Other valid values for C<$flush_type> are
+C<Z_NO_FLUSH>, C<Z_SYNC_FLUSH>, C<Z_FULL_FLUSH> and C<Z_BLOCK>. It is
+strongly recommended that you only set the C<flush_type> parameter if
+you fully understand the implications of what it does - overuse of C<flush>
+can seriously degrade the level of compression achieved. See the C<zlib>
+documentation for details.
+
+Returns true on success.
+
+=head2 tell
+
+Usage is
+
+ $z->tell()
+ tell $z
+
+Returns the uncompressed file offset.
+
+=head2 eof
+
+Usage is
+
+ $z->eof();
+ eof($z);
+
+Returns true if the C<close> method has been called.
+
+=head2 seek
+
+ $z->seek($position, $whence);
+ seek($z, $position, $whence);
+
+Provides a sub-set of the C<seek> functionality, with the restriction
+that it is only legal to seek forward in the output file/buffer.
+It is a fatal error to attempt to seek backward.
+
+Empty parts of the file/buffer will have NULL (0x00) bytes written to them.
+
+The C<$whence> parameter takes one the usual values, namely SEEK_SET,
+SEEK_CUR or SEEK_END.
+
+Returns 1 on success, 0 on failure.
+
+=head2 binmode
+
+Usage is
+
+ $z->binmode
+ binmode $z ;
+
+This is a noop provided for completeness.
+
+=head2 opened
+
+ $z->opened()
+
+Returns true if the object currently refers to a opened file/buffer.
+
+=head2 autoflush
+
+ my $prev = $z->autoflush()
+ my $prev = $z->autoflush(EXPR)
+
+If the C<$z> object is associated with a file or a filehandle, this method
+returns the current autoflush setting for the underlying filehandle. If
+C<EXPR> is present, and is non-zero, it will enable flushing after every
+write/print operation.
+
+If C<$z> is associated with a buffer, this method has no effect and always
+returns C<undef>.
+
+B<Note> that the special variable C<$|> B<cannot> be used to set or
+retrieve the autoflush setting.
+
+=head2 input_line_number
+
+ $z->input_line_number()
+ $z->input_line_number(EXPR)
+
+This method always returns C<undef> when compressing.
+
+=head2 fileno
+
+ $z->fileno()
+ fileno($z)
+
+If the C<$z> object is associated with a file or a filehandle, C<fileno>
+will return the underlying file descriptor. Once the C<close> method is
+called C<fileno> will return C<undef>.
+
+If the C<$z> object is is associated with a buffer, this method will return
+C<undef>.
+
+=head2 close
+
+ $z->close() ;
+ close $z ;
+
+Flushes any pending compressed data and then closes the output file/buffer.
+
+For most versions of Perl this method will be automatically invoked if
+the IO::Compress::RawDeflate object is destroyed (either explicitly or by the
+variable with the reference to the object going out of scope). The
+exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In
+these cases, the C<close> method will be called automatically, but
+not until global destruction of all live objects when the program is
+terminating.
+
+Therefore, if you want your scripts to be able to run on all versions
+of Perl, you should call C<close> explicitly and not rely on automatic
+closing.
+
+Returns true on success, otherwise 0.
+
+If the C<AutoClose> option has been enabled when the IO::Compress::RawDeflate
+object was created, and the object is associated with a file, the
+underlying file will also be closed.
+
+=head2 newStream([OPTS])
+
+Usage is
+
+ $z->newStream( [OPTS] )
+
+Closes the current compressed data stream and starts a new one.
+
+OPTS consists of any of the the options that are available when creating
+the C<$z> object.
+
+See the L</"Constructor Options"> section for more details.
+
+=head2 deflateParams
+
+Usage is
+
+ $z->deflateParams
+
+TODO
+
+=head1 Importing
+
+A number of symbolic constants are required by some methods in
+C<IO::Compress::RawDeflate>. None are imported by default.
+
+=over 5
+
+=item :all
+
+Imports C<rawdeflate>, C<$RawDeflateError> and all symbolic
+constants that can be used by C<IO::Compress::RawDeflate>. Same as doing this
+
+ use IO::Compress::RawDeflate qw(rawdeflate $RawDeflateError :constants) ;
+
+=item :constants
+
+Import all symbolic constants. Same as doing this
+
+ use IO::Compress::RawDeflate qw(:flush :level :strategy) ;
+
+=item :flush
+
+These symbolic constants are used by the C<flush> method.
+
+ Z_NO_FLUSH
+ Z_PARTIAL_FLUSH
+ Z_SYNC_FLUSH
+ Z_FULL_FLUSH
+ Z_FINISH
+ Z_BLOCK
+
+=item :level
+
+These symbolic constants are used by the C<Level> option in the constructor.
+
+ Z_NO_COMPRESSION
+ Z_BEST_SPEED
+ Z_BEST_COMPRESSION
+ Z_DEFAULT_COMPRESSION
+
+=item :strategy
+
+These symbolic constants are used by the C<Strategy> option in the constructor.
+
+ Z_FILTERED
+ Z_HUFFMAN_ONLY
+ Z_RLE
+ Z_FIXED
+ Z_DEFAULT_STRATEGY
+
+
+
+
+=back
+
+=head1 EXAMPLES
+
+=head2 Apache::GZip Revisited
+
+See L<IO::Compress::FAQ|IO::Compress::FAQ/"Apache::GZip Revisited">
+
+
+
+=head2 Working with Net::FTP
+
+See L<IO::Compress::FAQ|IO::Compress::FAQ/"Compressed files and Net::FTP">
+
+=head1 SEE ALSO
+
+L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Compress::Deflate>, L<IO::Uncompress::Inflate>, L<IO::Uncompress::RawInflate>, L<IO::Compress::Bzip2>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
+
+L<Compress::Zlib::FAQ|Compress::Zlib::FAQ>
+
+L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
+L<Archive::Tar|Archive::Tar>,
+L<IO::Zlib|IO::Zlib>
+
+For RFC 1950, 1951 and 1952 see
+F<http://www.faqs.org/rfcs/rfc1950.html>,
+F<http://www.faqs.org/rfcs/rfc1951.html> and
+F<http://www.faqs.org/rfcs/rfc1952.html>
+
+The I<zlib> compression library was written by Jean-loup Gailly
+F<gzip@prep.ai.mit.edu> and Mark Adler F<madler@alumni.caltech.edu>.
+
+The primary site for the I<zlib> compression library is
+F<http://www.zlib.org>.
+
+The primary site for gzip is F<http://www.gzip.org>.
+
+=head1 AUTHOR
+
+This module was written by Paul Marquess, F<pmqs@cpan.org>.
+
+=head1 MODIFICATION HISTORY
+
+See the Changes file.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2005-2010 Paul Marquess. All rights reserved.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Compress/Zip.pm b/Master/tlpkg/tlperl/lib/IO/Compress/Zip.pm
new file mode 100644
index 00000000000..5e37d78f97d
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Compress/Zip.pm
@@ -0,0 +1,1612 @@
+package IO::Compress::Zip ;
+
+use strict ;
+use warnings;
+use bytes;
+
+use IO::Compress::Base::Common 2.024 qw(:Status createSelfTiedObject);
+use IO::Compress::RawDeflate 2.024 ;
+use IO::Compress::Adapter::Deflate 2.024 ;
+use IO::Compress::Adapter::Identity 2.024 ;
+use IO::Compress::Zlib::Extra 2.024 ;
+use IO::Compress::Zip::Constants 2.024 ;
+
+
+use Compress::Raw::Zlib 2.024 qw(crc32) ;
+BEGIN
+{
+ eval { require IO::Compress::Adapter::Bzip2 ;
+ import IO::Compress::Adapter::Bzip2 2.024 ;
+ require IO::Compress::Bzip2 ;
+ import IO::Compress::Bzip2 2.024 ;
+ } ;
+# eval { require IO::Compress::Adapter::Lzma ;
+# import IO::Compress::Adapter::Lzma 2.020 ;
+# require IO::Compress::Lzma ;
+# import IO::Compress::Lzma 2.024 ;
+# } ;
+}
+
+
+require Exporter ;
+
+our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $ZipError);
+
+$VERSION = '2.024';
+$ZipError = '';
+
+@ISA = qw(Exporter IO::Compress::RawDeflate);
+@EXPORT_OK = qw( $ZipError zip ) ;
+%EXPORT_TAGS = %IO::Compress::RawDeflate::DEFLATE_CONSTANTS ;
+push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
+
+$EXPORT_TAGS{zip_method} = [qw( ZIP_CM_STORE ZIP_CM_DEFLATE ZIP_CM_BZIP2 ZIP_CM_LZMA)];
+push @{ $EXPORT_TAGS{all} }, @{ $EXPORT_TAGS{zip_method} };
+
+Exporter::export_ok_tags('all');
+
+sub new
+{
+ my $class = shift ;
+
+ my $obj = createSelfTiedObject($class, \$ZipError);
+ $obj->_create(undef, @_);
+}
+
+sub zip
+{
+ my $obj = createSelfTiedObject(undef, \$ZipError);
+ return $obj->_def(@_);
+}
+
+sub mkComp
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ my ($obj, $errstr, $errno) ;
+
+ if (*$self->{ZipData}{Method} == ZIP_CM_STORE) {
+ ($obj, $errstr, $errno) = IO::Compress::Adapter::Identity::mkCompObject(
+ $got->value('Level'),
+ $got->value('Strategy')
+ );
+ *$self->{ZipData}{CRC32} = crc32(undef);
+ }
+ elsif (*$self->{ZipData}{Method} == ZIP_CM_DEFLATE) {
+ ($obj, $errstr, $errno) = IO::Compress::Adapter::Deflate::mkCompObject(
+ $got->value('CRC32'),
+ $got->value('Adler32'),
+ $got->value('Level'),
+ $got->value('Strategy')
+ );
+ }
+ elsif (*$self->{ZipData}{Method} == ZIP_CM_BZIP2) {
+ ($obj, $errstr, $errno) = IO::Compress::Adapter::Bzip2::mkCompObject(
+ $got->value('BlockSize100K'),
+ $got->value('WorkFactor'),
+ $got->value('Verbosity')
+ );
+ *$self->{ZipData}{CRC32} = crc32(undef);
+ }
+# elsif (*$self->{ZipData}{Method} == ZIP_CM_LZMA) {
+# ($obj, $errstr, $errno) = IO::Compress::Adapter::Lzma::mkCompObject();
+# *$self->{ZipData}{CRC32} = crc32(undef);
+# }
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ if (! defined *$self->{ZipData}{SizesOffset}) {
+ *$self->{ZipData}{SizesOffset} = 0;
+ *$self->{ZipData}{Offset} = new U64 ;
+ }
+
+ *$self->{ZipData}{AnyZip64} = 0
+ if ! defined *$self->{ZipData}{AnyZip64} ;
+
+ return $obj;
+}
+
+sub reset
+{
+ my $self = shift ;
+
+ *$self->{Compress}->reset();
+ *$self->{ZipData}{CRC32} = Compress::Raw::Zlib::crc32('');
+
+ return STATUS_OK;
+}
+
+sub filterUncompressed
+{
+ my $self = shift ;
+
+ if (*$self->{ZipData}{Method} == ZIP_CM_DEFLATE) {
+ *$self->{ZipData}{CRC32} = *$self->{Compress}->crc32();
+ }
+ else {
+ *$self->{ZipData}{CRC32} = crc32(${$_[0]}, *$self->{ZipData}{CRC32});
+
+ }
+}
+
+sub mkHeader
+{
+ my $self = shift;
+ my $param = shift ;
+
+
+ *$self->{ZipData}{LocalHdrOffset} = U64::clone(*$self->{ZipData}{Offset});
+
+ my $filename = '';
+ $filename = $param->value('Name') || '';
+
+ my $comment = '';
+ $comment = $param->value('Comment') || '';
+
+ my $hdr = '';
+
+ my $time = _unixToDosTime($param->value('Time'));
+
+ my $extra = '';
+ my $ctlExtra = '';
+ my $empty = 0;
+ my $osCode = $param->value('OS_Code') ;
+ my $extFileAttr = 0 ;
+
+ # This code assumes Unix.
+ $extFileAttr = 0666 << 16
+ if $osCode == ZIP_OS_CODE_UNIX ;
+
+ if (*$self->{ZipData}{Zip64}) {
+ $empty = 0xFFFFFFFF;
+
+ my $x = '';
+ $x .= pack "V V", 0, 0 ; # uncompressedLength
+ $x .= pack "V V", 0, 0 ; # compressedLength
+ $extra .= IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_ZIP64, $x);
+ }
+
+ if (! $param->value('Minimal')) {
+ if (defined $param->value('exTime'))
+ {
+ $extra .= mkExtendedTime($param->value('MTime'),
+ $param->value('ATime'),
+ $param->value('CTime'));
+
+ $ctlExtra .= mkExtendedTime($param->value('MTime'));
+ }
+
+ if ( $param->value('UID') && $osCode == ZIP_OS_CODE_UNIX)
+ {
+ $extra .= mkUnix2Extra( $param->value('UID'), $param->value('GID'));
+ $ctlExtra .= mkUnix2Extra();
+ }
+
+ $extFileAttr = $param->value('ExtAttr')
+ if defined $param->value('ExtAttr') ;
+
+ $extra .= $param->value('ExtraFieldLocal')
+ if defined $param->value('ExtraFieldLocal');
+
+ $ctlExtra .= $param->value('ExtraFieldCentral')
+ if defined $param->value('ExtraFieldCentral');
+ }
+
+ my $gpFlag = 0 ;
+ $gpFlag |= ZIP_GP_FLAG_STREAMING_MASK
+ if *$self->{ZipData}{Stream} ;
+
+ my $method = *$self->{ZipData}{Method} ;
+
+ my $version = $ZIP_CM_MIN_VERSIONS{$method};
+ $version = ZIP64_MIN_VERSION
+ if ZIP64_MIN_VERSION > $version && *$self->{ZipData}{Zip64};
+ my $madeBy = ($param->value('OS_Code') << 8) + $version;
+ my $extract = $version;
+
+ *$self->{ZipData}{Version} = $version;
+ *$self->{ZipData}{MadeBy} = $madeBy;
+
+ my $ifa = 0;
+ $ifa |= ZIP_IFA_TEXT_MASK
+ if $param->value('TextFlag');
+
+ $hdr .= pack "V", ZIP_LOCAL_HDR_SIG ; # signature
+ $hdr .= pack 'v', $extract ; # extract Version & OS
+ $hdr .= pack 'v', $gpFlag ; # general purpose flag (set streaming mode)
+ $hdr .= pack 'v', $method ; # compression method (deflate)
+ $hdr .= pack 'V', $time ; # last mod date/time
+ $hdr .= pack 'V', 0 ; # crc32 - 0 when streaming
+ $hdr .= pack 'V', $empty ; # compressed length - 0 when streaming
+ $hdr .= pack 'V', $empty ; # uncompressed length - 0 when streaming
+ $hdr .= pack 'v', length $filename ; # filename length
+ $hdr .= pack 'v', length $extra ; # extra length
+
+ $hdr .= $filename ;
+
+ # Remember the offset for the compressed & uncompressed lengths in the
+ # local header.
+ if (*$self->{ZipData}{Zip64}) {
+ *$self->{ZipData}{SizesOffset} = *$self->{ZipData}{Offset}->get64bit()
+ + length($hdr) + 4 ;
+ }
+ else {
+ *$self->{ZipData}{SizesOffset} = *$self->{ZipData}{Offset}->get64bit()
+ + 18;
+ }
+
+ $hdr .= $extra ;
+
+
+ my $ctl = '';
+
+ $ctl .= pack "V", ZIP_CENTRAL_HDR_SIG ; # signature
+ $ctl .= pack 'v', $madeBy ; # version made by
+ $ctl .= pack 'v', $extract ; # extract Version
+ $ctl .= pack 'v', $gpFlag ; # general purpose flag (streaming mode)
+ $ctl .= pack 'v', $method ; # compression method (deflate)
+ $ctl .= pack 'V', $time ; # last mod date/time
+ $ctl .= pack 'V', 0 ; # crc32
+ $ctl .= pack 'V', $empty ; # compressed length
+ $ctl .= pack 'V', $empty ; # uncompressed length
+ $ctl .= pack 'v', length $filename ; # filename length
+
+ *$self->{ZipData}{ExtraOffset} = length $ctl;
+ *$self->{ZipData}{ExtraSize} = length $ctlExtra ;
+
+ $ctl .= pack 'v', length $ctlExtra ; # extra length
+ $ctl .= pack 'v', length $comment ; # file comment length
+ $ctl .= pack 'v', 0 ; # disk number start
+ $ctl .= pack 'v', $ifa ; # internal file attributes
+ $ctl .= pack 'V', $extFileAttr ; # external file attributes
+
+ # offset to local hdr
+ if (*$self->{ZipData}{LocalHdrOffset}->is64bit() ) {
+ $ctl .= pack 'V', 0xFFFFFFFF ;
+ }
+ else {
+ $ctl .= *$self->{ZipData}{LocalHdrOffset}->getPacked_V32() ;
+ }
+
+ $ctl .= $filename ;
+ $ctl .= $ctlExtra ;
+ $ctl .= $comment ;
+
+ *$self->{ZipData}{Offset}->add(length $hdr) ;
+
+ *$self->{ZipData}{CentralHeader} = $ctl;
+
+ return $hdr;
+}
+
+sub mkTrailer
+{
+ my $self = shift ;
+
+ my $crc32 ;
+ if (*$self->{ZipData}{Method} == ZIP_CM_DEFLATE) {
+ $crc32 = pack "V", *$self->{Compress}->crc32();
+ }
+ else {
+ $crc32 = pack "V", *$self->{ZipData}{CRC32};
+ }
+
+ my $ctl = *$self->{ZipData}{CentralHeader} ;
+
+ my $sizes ;
+ if (! *$self->{ZipData}{Zip64}) {
+ $sizes .= *$self->{CompSize}->getPacked_V32() ; # Compressed size
+ $sizes .= *$self->{UnCompSize}->getPacked_V32() ; # Uncompressed size
+ }
+ else {
+ $sizes .= *$self->{CompSize}->getPacked_V64() ; # Compressed size
+ $sizes .= *$self->{UnCompSize}->getPacked_V64() ; # Uncompressed size
+ }
+
+ my $data = $crc32 . $sizes ;
+
+ my $xtrasize = *$self->{UnCompSize}->getPacked_V64() ; # Uncompressed size
+ $xtrasize .= *$self->{CompSize}->getPacked_V64() ; # Compressed size
+
+ my $hdr = '';
+
+ if (*$self->{ZipData}{Stream}) {
+ $hdr = pack "V", ZIP_DATA_HDR_SIG ; # signature
+ $hdr .= $data ;
+ }
+ else {
+ $self->writeAt(*$self->{ZipData}{LocalHdrOffset}->get64bit() + 14, $crc32)
+ or return undef;
+ $self->writeAt(*$self->{ZipData}{SizesOffset},
+ *$self->{ZipData}{Zip64} ? $xtrasize : $sizes)
+ or return undef;
+ }
+
+ # Central Header Record/Zip64 extended field
+
+ substr($ctl, 16, length $crc32) = $crc32 ;
+
+ my $x = '';
+
+ # uncompressed length
+ if (*$self->{UnCompSize}->is64bit() ) {
+ $x .= *$self->{UnCompSize}->getPacked_V64() ;
+ } else {
+ substr($ctl, 24, 4) = *$self->{UnCompSize}->getPacked_V32() ;
+ }
+
+ # compressed length
+ if (*$self->{CompSize}->is64bit() ) {
+ $x .= *$self->{CompSize}->getPacked_V64() ;
+ } else {
+ substr($ctl, 20, 4) = *$self->{CompSize}->getPacked_V32() ;
+ }
+
+ # Local Header offset
+ $x .= *$self->{ZipData}{LocalHdrOffset}->getPacked_V64()
+ if *$self->{ZipData}{LocalHdrOffset}->is64bit() ;
+
+ # disk no - always zero, so don't need it
+ #$x .= pack "V", 0 ;
+
+ if (length $x) {
+ my $xtra = IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_ZIP64, $x);
+ $ctl .= $xtra ;
+ substr($ctl, *$self->{ZipData}{ExtraOffset}, 2) =
+ pack 'v', *$self->{ZipData}{ExtraSize} + length $xtra;
+
+ *$self->{ZipData}{AnyZip64} = 1;
+ }
+
+ *$self->{ZipData}{Offset}->add(length($hdr));
+ *$self->{ZipData}{Offset}->add( *$self->{CompSize} );
+ push @{ *$self->{ZipData}{CentralDir} }, $ctl ;
+
+ return $hdr;
+}
+
+sub mkFinalTrailer
+{
+ my $self = shift ;
+
+ my $comment = '';
+ $comment = *$self->{ZipData}{ZipComment} ;
+
+ my $cd_offset = *$self->{ZipData}{Offset}->get32bit() ; # offset to start central dir
+
+ my $entries = @{ *$self->{ZipData}{CentralDir} };
+ my $cd = join '', @{ *$self->{ZipData}{CentralDir} };
+ my $cd_len = length $cd ;
+
+ my $z64e = '';
+
+ if ( *$self->{ZipData}{AnyZip64} ) {
+
+ my $v = *$self->{ZipData}{Version} ;
+ my $mb = *$self->{ZipData}{MadeBy} ;
+ $z64e .= pack 'v', $mb ; # Version made by
+ $z64e .= pack 'v', $v ; # Version to extract
+ $z64e .= pack 'V', 0 ; # number of disk
+ $z64e .= pack 'V', 0 ; # number of disk with central dir
+ $z64e .= U64::pack_V64 $entries ; # entries in central dir on this disk
+ $z64e .= U64::pack_V64 $entries ; # entries in central dir
+ $z64e .= U64::pack_V64 $cd_len ; # size of central dir
+ $z64e .= *$self->{ZipData}{Offset}->getPacked_V64() ; # offset to start central dir
+
+ $z64e = pack("V", ZIP64_END_CENTRAL_REC_HDR_SIG) # signature
+ . U64::pack_V64(length $z64e)
+ . $z64e ;
+
+ *$self->{ZipData}{Offset}->add(length $cd) ;
+
+ $z64e .= pack "V", ZIP64_END_CENTRAL_LOC_HDR_SIG; # signature
+ $z64e .= pack 'V', 0 ; # number of disk with central dir
+ $z64e .= *$self->{ZipData}{Offset}->getPacked_V64() ; # offset to end zip64 central dir
+ $z64e .= pack 'V', 1 ; # Total number of disks
+
+ $cd_offset = 0xFFFFFFFF ;
+ $cd_len = 0xFFFFFFFF if $cd_len >= 0xFFFFFFFF ;
+ $entries = 0xFFFF if $entries >= 0xFFFF ;
+ }
+
+ my $ecd = '';
+ $ecd .= pack "V", ZIP_END_CENTRAL_HDR_SIG ; # signature
+ $ecd .= pack 'v', 0 ; # number of disk
+ $ecd .= pack 'v', 0 ; # number of disk with central dir
+ $ecd .= pack 'v', $entries ; # entries in central dir on this disk
+ $ecd .= pack 'v', $entries ; # entries in central dir
+ $ecd .= pack 'V', $cd_len ; # size of central dir
+ $ecd .= pack 'V', $cd_offset ; # offset to start central dir
+ $ecd .= pack 'v', length $comment ; # zipfile comment length
+ $ecd .= $comment;
+
+ return $cd . $z64e . $ecd ;
+}
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift;
+
+ $got->value('CRC32' => 1);
+
+ if (! $got->parsed('Time') ) {
+ # Modification time defaults to now.
+ $got->value('Time' => time) ;
+ }
+
+ if ($got->parsed('exTime') ) {
+ my $timeRef = $got->value('exTime');
+ if ( defined $timeRef) {
+ return $self->saveErrorString(undef, "exTime not a 3-element array ref")
+ if ref $timeRef ne 'ARRAY' || @$timeRef != 3;
+ }
+
+ $got->value("MTime", $timeRef->[1]);
+ $got->value("ATime", $timeRef->[0]);
+ $got->value("CTime", $timeRef->[2]);
+ }
+
+ # Unix2 Extended Attribute
+ if ($got->parsed('exUnix2') ) {
+ my $timeRef = $got->value('exUnix2');
+ if ( defined $timeRef) {
+ return $self->saveErrorString(undef, "exUnix2 not a 2-element array ref")
+ if ref $timeRef ne 'ARRAY' || @$timeRef != 2;
+ }
+
+ $got->value("UID", $timeRef->[0]);
+ $got->value("GID", $timeRef->[1]);
+ }
+
+ *$self->{ZipData}{AnyZip64} = 1
+ if $got->value('Zip64');
+ *$self->{ZipData}{Zip64} = $got->value('Zip64');
+ *$self->{ZipData}{Stream} = $got->value('Stream');
+
+ my $method = $got->value('Method');
+ return $self->saveErrorString(undef, "Unknown Method '$method'")
+ if ! defined $ZIP_CM_MIN_VERSIONS{$method};
+
+ return $self->saveErrorString(undef, "Bzip2 not available")
+ if $method == ZIP_CM_BZIP2 and
+ ! defined $IO::Compress::Adapter::Bzip2::VERSION;
+
+ return $self->saveErrorString(undef, "Lzma not available")
+ if $method == ZIP_CM_LZMA ;
+ #and
+ #! defined $IO::Compress::Adapter::Lzma::VERSION;
+
+ *$self->{ZipData}{Method} = $method;
+
+ *$self->{ZipData}{ZipComment} = $got->value('ZipComment') ;
+
+ for my $name (qw( ExtraFieldLocal ExtraFieldCentral ))
+ {
+ my $data = $got->value($name) ;
+ if (defined $data) {
+ my $bad = IO::Compress::Zlib::Extra::parseExtraField($data, 1, 0) ;
+ return $self->saveErrorString(undef, "Error with $name Parameter: $bad")
+ if $bad ;
+
+ $got->value($name, $data) ;
+ }
+ }
+
+ return undef
+ if defined $IO::Compress::Bzip2::VERSION
+ and ! IO::Compress::Bzip2::ckParams($self, $got);
+
+ return 1 ;
+}
+
+#sub newHeader
+#{
+# my $self = shift ;
+#
+# return $self->mkHeader(*$self->{Got});
+#}
+
+sub getExtraParams
+{
+ my $self = shift ;
+
+ use IO::Compress::Base::Common 2.024 qw(:Parse);
+ use Compress::Raw::Zlib 2.024 qw(Z_DEFLATED Z_DEFAULT_COMPRESSION Z_DEFAULT_STRATEGY);
+
+ my @Bzip2 = ();
+
+ @Bzip2 = IO::Compress::Bzip2::getExtraParams($self)
+ if defined $IO::Compress::Bzip2::VERSION;
+
+ return (
+ # zlib behaviour
+ $self->getZlibParams(),
+
+ 'Stream' => [1, 1, Parse_boolean, 1],
+ #'Store' => [0, 1, Parse_boolean, 0],
+ 'Method' => [0, 1, Parse_unsigned, ZIP_CM_DEFLATE],
+
+# # Zip header fields
+ 'Minimal' => [0, 1, Parse_boolean, 0],
+ 'Zip64' => [0, 1, Parse_boolean, 0],
+ 'Comment' => [0, 1, Parse_any, ''],
+ 'ZipComment'=> [0, 1, Parse_any, ''],
+ 'Name' => [0, 1, Parse_any, ''],
+ 'Time' => [0, 1, Parse_any, undef],
+ 'exTime' => [0, 1, Parse_any, undef],
+ 'exUnix2' => [0, 1, Parse_any, undef],
+ 'ExtAttr' => [0, 1, Parse_any, 0],
+ 'OS_Code' => [0, 1, Parse_unsigned, $Compress::Raw::Zlib::gzip_os_code],
+
+ 'TextFlag' => [0, 1, Parse_boolean, 0],
+ 'ExtraFieldLocal' => [0, 1, Parse_any, undef],
+ 'ExtraFieldCentral'=> [0, 1, Parse_any, undef],
+
+ @Bzip2,
+ );
+}
+
+sub getInverseClass
+{
+ return ('IO::Uncompress::Unzip',
+ \$IO::Uncompress::Unzip::UnzipError);
+}
+
+sub getFileInfo
+{
+ my $self = shift ;
+ my $params = shift;
+ my $filename = shift ;
+
+ my ($mode, $uid, $gid, $atime, $mtime, $ctime)
+ = (stat($filename))[2, 4,5, 8,9,10] ;
+
+ $params->value('Name' => $filename)
+ if ! $params->parsed('Name') ;
+
+ $params->value('Time' => $mtime)
+ if ! $params->parsed('Time') ;
+
+ if ( ! $params->parsed('exTime'))
+ {
+ $params->value('MTime' => $mtime) ;
+ $params->value('ATime' => $atime) ;
+ $params->value('CTime' => undef) ; # No Creation time
+ $params->value("exTime", [$mtime, $atime, undef]);
+ }
+
+ # NOTE - Unix specific code alert
+ $params->value('ExtAttr' => $mode << 16)
+ if ! $params->parsed('ExtAttr');
+
+ $params->value('UID' => $uid) ;
+ $params->value('GID' => $gid) ;
+
+}
+
+sub mkExtendedTime
+{
+ # order expected is m, a, c
+
+ my $times = '';
+ my $bit = 1 ;
+ my $flags = 0;
+
+ for my $time (@_)
+ {
+ if (defined $time)
+ {
+ $flags |= $bit;
+ $times .= pack("V", $time);
+ }
+
+ $bit <<= 1 ;
+ }
+
+ return IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_EXT_TIMESTAMP,
+ pack("C", $flags) . $times);
+}
+
+sub mkUnix2Extra
+{
+ my $ids = '';
+ for my $id (@_)
+ {
+ $ids .= pack("v", $id);
+ }
+
+ return IO::Compress::Zlib::Extra::mkSubField(ZIP_EXTRA_ID_INFO_ZIP_UNIX2,
+ $ids);
+}
+
+
+# from Archive::Zip
+sub _unixToDosTime # Archive::Zip::Member
+{
+ my $time_t = shift;
+ # TODO - add something to cope with unix time < 1980
+ my ( $sec, $min, $hour, $mday, $mon, $year ) = localtime($time_t);
+ my $dt = 0;
+ $dt += ( $sec >> 1 );
+ $dt += ( $min << 5 );
+ $dt += ( $hour << 11 );
+ $dt += ( $mday << 16 );
+ $dt += ( ( $mon + 1 ) << 21 );
+ $dt += ( ( $year - 80 ) << 25 );
+ return $dt;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+IO::Compress::Zip - Write zip files/buffers
+
+
+
+=head1 SYNOPSIS
+
+ use IO::Compress::Zip qw(zip $ZipError) ;
+
+ my $status = zip $input => $output [,OPTS]
+ or die "zip failed: $ZipError\n";
+
+ my $z = new IO::Compress::Zip $output [,OPTS]
+ or die "zip failed: $ZipError\n";
+
+ $z->print($string);
+ $z->printf($format, $string);
+ $z->write($string);
+ $z->syswrite($string [, $length, $offset]);
+ $z->flush();
+ $z->tell();
+ $z->eof();
+ $z->seek($position, $whence);
+ $z->binmode();
+ $z->fileno();
+ $z->opened();
+ $z->autoflush();
+ $z->input_line_number();
+ $z->newStream( [OPTS] );
+
+ $z->deflateParams();
+
+ $z->close() ;
+
+ $ZipError ;
+
+ # IO::File mode
+
+ print $z $string;
+ printf $z $format, $string;
+ tell $z
+ eof $z
+ seek $z, $position, $whence
+ binmode $z
+ fileno $z
+ close $z ;
+
+
+=head1 DESCRIPTION
+
+This module provides a Perl interface that allows writing zip
+compressed data to files or buffer.
+
+The primary purpose of this module is to provide streaming write access to
+zip files and buffers. It is not a general-purpose file archiver. If that
+is what you want, check out C<Archive::Zip>.
+
+At present three compression methods are supported by IO::Compress::Zip,
+namely Store (no compression at all), Deflate and Bzip2.
+
+Note that to create Bzip2 content, the module C<IO::Compress::Bzip2> must
+be installed.
+
+For reading zip files/buffers, see the companion module
+L<IO::Uncompress::Unzip|IO::Uncompress::Unzip>.
+
+=head1 Functional Interface
+
+A top-level function, C<zip>, is provided to carry out
+"one-shot" compression between buffers and/or files. For finer
+control over the compression process, see the L</"OO Interface">
+section.
+
+ use IO::Compress::Zip qw(zip $ZipError) ;
+
+ zip $input => $output [,OPTS]
+ or die "zip failed: $ZipError\n";
+
+The functional interface needs Perl5.005 or better.
+
+=head2 zip $input => $output [, OPTS]
+
+C<zip> expects at least two parameters, C<$input> and C<$output>.
+
+=head3 The C<$input> parameter
+
+The parameter, C<$input>, is used to define the source of
+the uncompressed data.
+
+It can take one of the following forms:
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for reading and the input data
+will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the input data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the input data will be read
+from C<$$input>.
+
+=item An array reference
+
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
+The complete array will be walked to ensure that it only
+contains valid filenames before any data is compressed.
+
+=item An Input FileGlob string
+
+If C<$input> is a string that is delimited by the characters "<" and ">"
+C<zip> will assume that it is an I<input fileglob string>. The
+input is the list of files that match the fileglob.
+
+If the fileglob does not match any files ...
+
+See L<File::GlobMapper|File::GlobMapper> for more details.
+
+=back
+
+If the C<$input> parameter is any other type, C<undef> will be returned.
+
+In addition, if C<$input> is a simple filename, the default values for
+the C<Name>, C<Time>, C<ExtAttr> and C<exTime> options will be sourced from that file.
+
+If you do not want to use these defaults they can be overridden by
+explicitly setting the C<Name>, C<Time>, C<ExtAttr> and C<exTime> options or by setting the
+C<Minimal> parameter.
+
+=head3 The C<$output> parameter
+
+The parameter C<$output> is used to control the destination of the
+compressed data. This parameter can take one of these forms.
+
+=over 5
+
+=item A filename
+
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the compressed
+data will be written to it.
+
+=item A filehandle
+
+If the C<$output> parameter is a filehandle, the compressed data
+will be written to it.
+The string '-' can be used as an alias for standard output.
+
+=item A scalar reference
+
+If C<$output> is a scalar reference, the compressed data will be
+stored in C<$$output>.
+
+=item An Array Reference
+
+If C<$output> is an array reference, the compressed data will be
+pushed onto the array.
+
+=item An Output FileGlob
+
+If C<$output> is a string that is delimited by the characters "<" and ">"
+C<zip> will assume that it is an I<output fileglob string>. The
+output is the list of files that match the fileglob.
+
+When C<$output> is an fileglob string, C<$input> must also be a fileglob
+string. Anything else is an error.
+
+=back
+
+If the C<$output> parameter is any other type, C<undef> will be returned.
+
+=head2 Notes
+
+When C<$input> maps to multiple files/buffers and C<$output> is a single
+file/buffer the input files/buffers will each be stored
+in C<$output> as a distinct entry.
+
+=head2 Optional Parameters
+
+Unless specified below, the optional parameters for C<zip>,
+C<OPTS>, are the same as those used with the OO interface defined in the
+L</"Constructor Options"> section below.
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option applies to any input or output data streams to
+C<zip> that are filehandles.
+
+If C<AutoClose> is specified, and the value is true, it will result in all
+input and/or output filehandles being closed once C<zip> has
+completed.
+
+This parameter defaults to 0.
+
+=item C<< BinModeIn => 0|1 >>
+
+When reading from a file or filehandle, set C<binmode> before reading.
+
+Defaults to 0.
+
+=item C<< Append => 0|1 >>
+
+The behaviour of this option is dependent on the type of output data
+stream.
+
+=over 5
+
+=item * A Buffer
+
+If C<Append> is enabled, all compressed data will be append to the end of
+the output buffer. Otherwise the output buffer will be cleared before any
+compressed data is written to it.
+
+=item * A Filename
+
+If C<Append> is enabled, the file will be opened in append mode. Otherwise
+the contents of the file, if any, will be truncated before any compressed
+data is written to it.
+
+=item * A Filehandle
+
+If C<Append> is enabled, the filehandle will be positioned to the end of
+the file via a call to C<seek> before any compressed data is
+written to it. Otherwise the file pointer will not be moved.
+
+=back
+
+When C<Append> is specified, and set to true, it will I<append> all compressed
+data to the output data stream.
+
+So when the output is a filehandle it will carry out a seek to the eof
+before writing any compressed data. If the output is a filename, it will be opened for
+appending. If the output is a buffer, all compressed data will be appened to
+the existing buffer.
+
+Conversely when C<Append> is not specified, or it is present and is set to
+false, it will operate as follows.
+
+When the output is a filename, it will truncate the contents of the file
+before writing any compressed data. If the output is a filehandle
+its position will not be changed. If the output is a buffer, it will be
+wiped before any compressed data is output.
+
+Defaults to 0.
+
+=back
+
+=head2 Examples
+
+To read the contents of the file C<file1.txt> and write the compressed
+data to the file C<file1.txt.zip>.
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::Zip qw(zip $ZipError) ;
+
+ my $input = "file1.txt";
+ zip $input => "$input.zip"
+ or die "zip failed: $ZipError\n";
+
+To read from an existing Perl filehandle, C<$input>, and write the
+compressed data to a buffer, C<$buffer>.
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::Zip qw(zip $ZipError) ;
+ use IO::File ;
+
+ my $input = new IO::File "<file1.txt"
+ or die "Cannot open 'file1.txt': $!\n" ;
+ my $buffer ;
+ zip $input => \$buffer
+ or die "zip failed: $ZipError\n";
+
+To compress all files in the directory "/my/home" that match "*.txt"
+and store the compressed data in the same directory
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::Zip qw(zip $ZipError) ;
+
+ zip '</my/home/*.txt>' => '<*.zip>'
+ or die "zip failed: $ZipError\n";
+
+and if you want to compress each file one at a time, this will do the trick
+
+ use strict ;
+ use warnings ;
+ use IO::Compress::Zip qw(zip $ZipError) ;
+
+ for my $input ( glob "/my/home/*.txt" )
+ {
+ my $output = "$input.zip" ;
+ zip $input => $output
+ or die "Error compressing '$input': $ZipError\n";
+ }
+
+=head1 OO Interface
+
+=head2 Constructor
+
+The format of the constructor for C<IO::Compress::Zip> is shown below
+
+ my $z = new IO::Compress::Zip $output [,OPTS]
+ or die "IO::Compress::Zip failed: $ZipError\n";
+
+It returns an C<IO::Compress::Zip> object on success and undef on failure.
+The variable C<$ZipError> will contain an error message on failure.
+
+If you are running Perl 5.005 or better the object, C<$z>, returned from
+IO::Compress::Zip can be used exactly like an L<IO::File|IO::File> filehandle.
+This means that all normal output file operations can be carried out
+with C<$z>.
+For example, to write to a compressed file/buffer you can use either of
+these forms
+
+ $z->print("hello world\n");
+ print $z "hello world\n";
+
+The mandatory parameter C<$output> is used to control the destination
+of the compressed data. This parameter can take one of these forms.
+
+=over 5
+
+=item A filename
+
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the compressed data
+will be written to it.
+
+=item A filehandle
+
+If the C<$output> parameter is a filehandle, the compressed data will be
+written to it.
+The string '-' can be used as an alias for standard output.
+
+=item A scalar reference
+
+If C<$output> is a scalar reference, the compressed data will be stored
+in C<$$output>.
+
+=back
+
+If the C<$output> parameter is any other type, C<IO::Compress::Zip>::new will
+return undef.
+
+=head2 Constructor Options
+
+C<OPTS> is any combination of the following options:
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option is only valid when the C<$output> parameter is a filehandle. If
+specified, and the value is true, it will result in the C<$output> being
+closed once either the C<close> method is called or the C<IO::Compress::Zip>
+object is destroyed.
+
+This parameter defaults to 0.
+
+=item C<< Append => 0|1 >>
+
+Opens C<$output> in append mode.
+
+The behaviour of this option is dependent on the type of C<$output>.
+
+=over 5
+
+=item * A Buffer
+
+If C<$output> is a buffer and C<Append> is enabled, all compressed data
+will be append to the end of C<$output>. Otherwise C<$output> will be
+cleared before any data is written to it.
+
+=item * A Filename
+
+If C<$output> is a filename and C<Append> is enabled, the file will be
+opened in append mode. Otherwise the contents of the file, if any, will be
+truncated before any compressed data is written to it.
+
+=item * A Filehandle
+
+If C<$output> is a filehandle, the file pointer will be positioned to the
+end of the file via a call to C<seek> before any compressed data is written
+to it. Otherwise the file pointer will not be moved.
+
+=back
+
+This parameter defaults to 0.
+
+=item C<< Name => $string >>
+
+Stores the contents of C<$string> in the zip filename header field. If
+C<Name> is not specified, no zip filename field will be created.
+
+=item C<< Time => $number >>
+
+Sets the last modified time field in the zip header to $number.
+
+This field defaults to the time the C<IO::Compress::Zip> object was created
+if this option is not specified.
+
+=item C<< ExtAttr => $attr >>
+
+This option controls the "external file attributes" field in the central
+header of the zip file. This is a 4 byte field.
+
+If you are running a Unix derivative this value defaults to
+
+ 0666 << 16
+
+This should allow read/write access to any files that are extracted from
+the zip file/buffer.
+
+For all other systems it defaults to 0.
+
+=item C<< exTime => [$atime, $mtime, $ctime] >>
+
+This option expects an array reference with exactly three elements:
+C<$atime>, C<mtime> and C<$ctime>. These correspond to the last access
+time, last modification time and creation time respectively.
+
+It uses these values to set the extended timestamp field (ID is "UT") in
+the local zip header using the three values, $atime, $mtime, $ctime. In
+addition it sets the extended timestamp field in the central zip header
+using C<$mtime>.
+
+If any of the three values is C<undef> that time value will not be used.
+So, for example, to set only the C<$mtime> you would use this
+
+ exTime => [undef, $mtime, undef]
+
+If the C<Minimal> option is set to true, this option will be ignored.
+
+By default no extended time field is created.
+
+=item C<< exUnix2 => [$uid, $gid] >>
+
+This option expects an array reference with exactly two elements: C<$uid>
+and C<$gid>. These values correspond to the numeric user ID and group ID
+of the owner of the files respectively.
+
+When the C<exUnix2> option is present it will trigger the creation of a
+Unix2 extra field (ID is "Ux") in the local zip. This will be populated
+with C<$uid> and C<$gid>. In addition an empty Unix2 extra field will also
+be created in the central zip header
+
+If the C<Minimal> option is set to true, this option will be ignored.
+
+By default no Unix2 extra field is created.
+
+=item C<< Comment => $comment >>
+
+Stores the contents of C<$comment> in the Central File Header of
+the zip file.
+
+By default, no comment field is written to the zip file.
+
+=item C<< ZipComment => $comment >>
+
+Stores the contents of C<$comment> in the End of Central Directory record
+of the zip file.
+
+By default, no comment field is written to the zip file.
+
+=item C<< Method => $method >>
+
+Controls which compression method is used. At present three compression
+methods are supported, namely Store (no compression at all), Deflate and
+Bzip2.
+
+The symbols, ZIP_CM_STORE, ZIP_CM_DEFLATE and ZIP_CM_BZIP2 are used to
+select the compression method.
+
+These constants are not imported by C<IO::Compress::Zip> by default.
+
+ use IO::Compress::Zip qw(:zip_method);
+ use IO::Compress::Zip qw(:constants);
+ use IO::Compress::Zip qw(:all);
+
+Note that to create Bzip2 content, the module C<IO::Compress::Bzip2> must
+be installed. A fatal error will be thrown if you attempt to create Bzip2
+content when C<IO::Compress::Bzip2> is not available.
+
+The default method is ZIP_CM_DEFLATE.
+
+=item C<< Stream => 0|1 >>
+
+This option controls whether the zip file/buffer output is created in
+streaming mode.
+
+Note that when outputting to a file with streaming mode disabled (C<Stream>
+is 0), the output file must be seekable.
+
+The default is 1.
+
+=item C<< Zip64 => 0|1 >>
+
+Create a Zip64 zip file/buffer. This option should only be used if you want
+to store files larger than 4 Gig.
+
+If you intend to manipulate the Zip64 zip files created with this module
+using an external zip/unzip make sure that it supports Zip64.
+
+In particular, if you are using Info-Zip you need to have zip version 3.x
+or better to update a Zip64 archive and unzip version 6.x to read a zip64
+archive.
+
+The default is 0.
+
+=item C<< TextFlag => 0|1 >>
+
+This parameter controls the setting of a bit in the zip central header. It
+is used to signal that the data stored in the zip file/buffer is probably
+text.
+
+The default is 0.
+
+=item C<< ExtraFieldLocal => $data >>
+=item C<< ExtraFieldCentral => $data >>
+
+The C<ExtraFieldLocal> option is used to store additional metadata in the
+local header for the zip file/buffer. The C<ExtraFieldCentral> does the
+same for the matching central header.
+
+An extra field consists of zero or more subfields. Each subfield consists
+of a two byte header followed by the subfield data.
+
+The list of subfields can be supplied in any of the following formats
+
+ ExtraFieldLocal => [$id1, $data1,
+ $id2, $data2,
+ ...
+ ]
+
+ ExtraFieldLocal => [ [$id1 => $data1],
+ [$id2 => $data2],
+ ...
+ ]
+
+ ExtraFieldLocal => { $id1 => $data1,
+ $id2 => $data2,
+ ...
+ }
+
+Where C<$id1>, C<$id2> are two byte subfield ID's.
+
+If you use the hash syntax, you have no control over the order in which
+the ExtraSubFields are stored, plus you cannot have SubFields with
+duplicate ID.
+
+Alternatively the list of subfields can by supplied as a scalar, thus
+
+ ExtraField => $rawdata
+
+The Extended Time field (ID "UT"), set using the C<exTime> option, and the
+Unix2 extra field (ID "Ux), set using the C<exUnix2> option, are examples
+of extra fields.
+
+If the C<Minimal> option is set to true, this option will be ignored.
+
+The maximum size of an extra field 65535 bytes.
+
+=item C<< Minimal => 1|0 >>
+
+If specified, this option will disable the creation of all extra fields
+in the zip local and central headers. So the C<exTime>, C<exUnix2>,
+C<ExtraFieldLocal> and C<ExtraFieldCentral> options will be ignored.
+
+This parameter defaults to 0.
+
+=item C<< BlockSize100K => number >>
+
+Specify the number of 100K blocks bzip2 uses during compression.
+
+Valid values are from 1 to 9, where 9 is best compression.
+
+This option is only valid if the C<Method> is ZIP_CM_BZIP2. It is ignored
+otherwise.
+
+The default is 1.
+
+=item C<< WorkFactor => number >>
+
+Specifies how much effort bzip2 should take before resorting to a slower
+fallback compression algorithm.
+
+Valid values range from 0 to 250, where 0 means use the default value 30.
+
+This option is only valid if the C<Method> is ZIP_CM_BZIP2. It is ignored
+otherwise.
+
+The default is 0.
+
+=item -Level
+
+Defines the compression level used by zlib. The value should either be
+a number between 0 and 9 (0 means no compression and 9 is maximum
+compression), or one of the symbolic constants defined below.
+
+ Z_NO_COMPRESSION
+ Z_BEST_SPEED
+ Z_BEST_COMPRESSION
+ Z_DEFAULT_COMPRESSION
+
+The default is Z_DEFAULT_COMPRESSION.
+
+Note, these constants are not imported by C<IO::Compress::Zip> by default.
+
+ use IO::Compress::Zip qw(:strategy);
+ use IO::Compress::Zip qw(:constants);
+ use IO::Compress::Zip qw(:all);
+
+=item -Strategy
+
+Defines the strategy used to tune the compression. Use one of the symbolic
+constants defined below.
+
+ Z_FILTERED
+ Z_HUFFMAN_ONLY
+ Z_RLE
+ Z_FIXED
+ Z_DEFAULT_STRATEGY
+
+The default is Z_DEFAULT_STRATEGY.
+
+=item C<< Strict => 0|1 >>
+
+This is a placeholder option.
+
+=back
+
+=head2 Examples
+
+TODO
+
+=head1 Methods
+
+=head2 print
+
+Usage is
+
+ $z->print($data)
+ print $z $data
+
+Compresses and outputs the contents of the C<$data> parameter. This
+has the same behaviour as the C<print> built-in.
+
+Returns true if successful.
+
+=head2 printf
+
+Usage is
+
+ $z->printf($format, $data)
+ printf $z $format, $data
+
+Compresses and outputs the contents of the C<$data> parameter.
+
+Returns true if successful.
+
+=head2 syswrite
+
+Usage is
+
+ $z->syswrite $data
+ $z->syswrite $data, $length
+ $z->syswrite $data, $length, $offset
+
+Compresses and outputs the contents of the C<$data> parameter.
+
+Returns the number of uncompressed bytes written, or C<undef> if
+unsuccessful.
+
+=head2 write
+
+Usage is
+
+ $z->write $data
+ $z->write $data, $length
+ $z->write $data, $length, $offset
+
+Compresses and outputs the contents of the C<$data> parameter.
+
+Returns the number of uncompressed bytes written, or C<undef> if
+unsuccessful.
+
+=head2 flush
+
+Usage is
+
+ $z->flush;
+ $z->flush($flush_type);
+
+Flushes any pending compressed data to the output file/buffer.
+
+This method takes an optional parameter, C<$flush_type>, that controls
+how the flushing will be carried out. By default the C<$flush_type>
+used is C<Z_FINISH>. Other valid values for C<$flush_type> are
+C<Z_NO_FLUSH>, C<Z_SYNC_FLUSH>, C<Z_FULL_FLUSH> and C<Z_BLOCK>. It is
+strongly recommended that you only set the C<flush_type> parameter if
+you fully understand the implications of what it does - overuse of C<flush>
+can seriously degrade the level of compression achieved. See the C<zlib>
+documentation for details.
+
+Returns true on success.
+
+=head2 tell
+
+Usage is
+
+ $z->tell()
+ tell $z
+
+Returns the uncompressed file offset.
+
+=head2 eof
+
+Usage is
+
+ $z->eof();
+ eof($z);
+
+Returns true if the C<close> method has been called.
+
+=head2 seek
+
+ $z->seek($position, $whence);
+ seek($z, $position, $whence);
+
+Provides a sub-set of the C<seek> functionality, with the restriction
+that it is only legal to seek forward in the output file/buffer.
+It is a fatal error to attempt to seek backward.
+
+Empty parts of the file/buffer will have NULL (0x00) bytes written to them.
+
+The C<$whence> parameter takes one the usual values, namely SEEK_SET,
+SEEK_CUR or SEEK_END.
+
+Returns 1 on success, 0 on failure.
+
+=head2 binmode
+
+Usage is
+
+ $z->binmode
+ binmode $z ;
+
+This is a noop provided for completeness.
+
+=head2 opened
+
+ $z->opened()
+
+Returns true if the object currently refers to a opened file/buffer.
+
+=head2 autoflush
+
+ my $prev = $z->autoflush()
+ my $prev = $z->autoflush(EXPR)
+
+If the C<$z> object is associated with a file or a filehandle, this method
+returns the current autoflush setting for the underlying filehandle. If
+C<EXPR> is present, and is non-zero, it will enable flushing after every
+write/print operation.
+
+If C<$z> is associated with a buffer, this method has no effect and always
+returns C<undef>.
+
+B<Note> that the special variable C<$|> B<cannot> be used to set or
+retrieve the autoflush setting.
+
+=head2 input_line_number
+
+ $z->input_line_number()
+ $z->input_line_number(EXPR)
+
+This method always returns C<undef> when compressing.
+
+=head2 fileno
+
+ $z->fileno()
+ fileno($z)
+
+If the C<$z> object is associated with a file or a filehandle, C<fileno>
+will return the underlying file descriptor. Once the C<close> method is
+called C<fileno> will return C<undef>.
+
+If the C<$z> object is is associated with a buffer, this method will return
+C<undef>.
+
+=head2 close
+
+ $z->close() ;
+ close $z ;
+
+Flushes any pending compressed data and then closes the output file/buffer.
+
+For most versions of Perl this method will be automatically invoked if
+the IO::Compress::Zip object is destroyed (either explicitly or by the
+variable with the reference to the object going out of scope). The
+exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In
+these cases, the C<close> method will be called automatically, but
+not until global destruction of all live objects when the program is
+terminating.
+
+Therefore, if you want your scripts to be able to run on all versions
+of Perl, you should call C<close> explicitly and not rely on automatic
+closing.
+
+Returns true on success, otherwise 0.
+
+If the C<AutoClose> option has been enabled when the IO::Compress::Zip
+object was created, and the object is associated with a file, the
+underlying file will also be closed.
+
+=head2 newStream([OPTS])
+
+Usage is
+
+ $z->newStream( [OPTS] )
+
+Closes the current compressed data stream and starts a new one.
+
+OPTS consists of any of the the options that are available when creating
+the C<$z> object.
+
+See the L</"Constructor Options"> section for more details.
+
+=head2 deflateParams
+
+Usage is
+
+ $z->deflateParams
+
+TODO
+
+=head1 Importing
+
+A number of symbolic constants are required by some methods in
+C<IO::Compress::Zip>. None are imported by default.
+
+=over 5
+
+=item :all
+
+Imports C<zip>, C<$ZipError> and all symbolic
+constants that can be used by C<IO::Compress::Zip>. Same as doing this
+
+ use IO::Compress::Zip qw(zip $ZipError :constants) ;
+
+=item :constants
+
+Import all symbolic constants. Same as doing this
+
+ use IO::Compress::Zip qw(:flush :level :strategy :zip_method) ;
+
+=item :flush
+
+These symbolic constants are used by the C<flush> method.
+
+ Z_NO_FLUSH
+ Z_PARTIAL_FLUSH
+ Z_SYNC_FLUSH
+ Z_FULL_FLUSH
+ Z_FINISH
+ Z_BLOCK
+
+=item :level
+
+These symbolic constants are used by the C<Level> option in the constructor.
+
+ Z_NO_COMPRESSION
+ Z_BEST_SPEED
+ Z_BEST_COMPRESSION
+ Z_DEFAULT_COMPRESSION
+
+=item :strategy
+
+These symbolic constants are used by the C<Strategy> option in the constructor.
+
+ Z_FILTERED
+ Z_HUFFMAN_ONLY
+ Z_RLE
+ Z_FIXED
+ Z_DEFAULT_STRATEGY
+
+=item :zip_method
+
+These symbolic constants are used by the C<Method> option in the
+constructor.
+
+ ZIP_CM_STORE
+ ZIP_CM_DEFLATE
+ ZIP_CM_BZIP2
+
+
+
+
+=back
+
+=head1 EXAMPLES
+
+=head2 Apache::GZip Revisited
+
+See L<IO::Compress::FAQ|IO::Compress::FAQ/"Apache::GZip Revisited">
+
+
+
+=head2 Working with Net::FTP
+
+See L<IO::Compress::FAQ|IO::Compress::FAQ/"Compressed files and Net::FTP">
+
+=head1 SEE ALSO
+
+L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Compress::Deflate>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Compress::Bzip2>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
+
+L<Compress::Zlib::FAQ|Compress::Zlib::FAQ>
+
+L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
+L<Archive::Tar|Archive::Tar>,
+L<IO::Zlib|IO::Zlib>
+
+For RFC 1950, 1951 and 1952 see
+F<http://www.faqs.org/rfcs/rfc1950.html>,
+F<http://www.faqs.org/rfcs/rfc1951.html> and
+F<http://www.faqs.org/rfcs/rfc1952.html>
+
+The I<zlib> compression library was written by Jean-loup Gailly
+F<gzip@prep.ai.mit.edu> and Mark Adler F<madler@alumni.caltech.edu>.
+
+The primary site for the I<zlib> compression library is
+F<http://www.zlib.org>.
+
+The primary site for gzip is F<http://www.gzip.org>.
+
+=head1 AUTHOR
+
+This module was written by Paul Marquess, F<pmqs@cpan.org>.
+
+=head1 MODIFICATION HISTORY
+
+See the Changes file.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2005-2010 Paul Marquess. All rights reserved.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Compress/Zip/Constants.pm b/Master/tlpkg/tlperl/lib/IO/Compress/Zip/Constants.pm
new file mode 100644
index 00000000000..c8cb95342a2
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Compress/Zip/Constants.pm
@@ -0,0 +1,105 @@
+package IO::Compress::Zip::Constants;
+
+use strict ;
+use warnings;
+
+require Exporter;
+
+our ($VERSION, @ISA, @EXPORT, %ZIP_CM_MIN_VERSIONS);
+
+$VERSION = '2.024';
+
+@ISA = qw(Exporter);
+
+@EXPORT= qw(
+
+ ZIP_CM_STORE
+ ZIP_CM_DEFLATE
+ ZIP_CM_BZIP2
+ ZIP_CM_LZMA
+ ZIP_CM_PPMD
+
+ ZIP_LOCAL_HDR_SIG
+ ZIP_DATA_HDR_SIG
+ ZIP_CENTRAL_HDR_SIG
+ ZIP_END_CENTRAL_HDR_SIG
+ ZIP64_END_CENTRAL_REC_HDR_SIG
+ ZIP64_END_CENTRAL_LOC_HDR_SIG
+ ZIP64_ARCHIVE_EXTRA_SIG
+ ZIP64_DIGITAL_SIGNATURE_SIG
+
+ ZIP_GP_FLAG_ENCRYPTED_MASK
+ ZIP_GP_FLAG_STREAMING_MASK
+ ZIP_GP_FLAG_PATCHED_MASK
+ ZIP_GP_FLAG_STRONG_ENCRYPTED_MASK
+ ZIP_GP_FLAG_LZMA_EOS_PRESENT
+ ZIP_GP_FLAG_LANGUAGE_ENCODING
+
+ ZIP_EXTRA_ID_ZIP64
+ ZIP_EXTRA_ID_EXT_TIMESTAMP
+ ZIP_EXTRA_ID_INFO_ZIP_UNIX2
+ ZIP_EXTRA_ID_INFO_ZIP_UNIXn
+ ZIP_EXTRA_ID_JAVA_EXE
+
+ ZIP_OS_CODE_UNIX
+ ZIP_OS_CODE_DEFAULT
+
+ ZIP_IFA_TEXT_MASK
+
+ %ZIP_CM_MIN_VERSIONS
+ ZIP64_MIN_VERSION
+
+ );
+
+# Compression types supported
+use constant ZIP_CM_STORE => 0 ;
+use constant ZIP_CM_DEFLATE => 8 ;
+use constant ZIP_CM_BZIP2 => 12 ;
+use constant ZIP_CM_LZMA => 14 ; # Not Supported yet
+use constant ZIP_CM_PPMD => 98 ; # Not Supported yet
+
+# General Purpose Flag
+use constant ZIP_GP_FLAG_ENCRYPTED_MASK => (1 << 0) ;
+use constant ZIP_GP_FLAG_STREAMING_MASK => (1 << 3) ;
+use constant ZIP_GP_FLAG_PATCHED_MASK => (1 << 5) ;
+use constant ZIP_GP_FLAG_STRONG_ENCRYPTED_MASK => (1 << 6) ;
+use constant ZIP_GP_FLAG_LZMA_EOS_PRESENT => (1 << 1) ;
+use constant ZIP_GP_FLAG_LANGUAGE_ENCODING => (1 << 11) ;
+
+# Internal File Attributes
+use constant ZIP_IFA_TEXT_MASK => 1;
+
+# Signatures for each of the headers
+use constant ZIP_LOCAL_HDR_SIG => 0x04034b50;
+use constant ZIP_DATA_HDR_SIG => 0x08074b50;
+use constant ZIP_CENTRAL_HDR_SIG => 0x02014b50;
+use constant ZIP_END_CENTRAL_HDR_SIG => 0x06054b50;
+use constant ZIP64_END_CENTRAL_REC_HDR_SIG => 0x06064b50;
+use constant ZIP64_END_CENTRAL_LOC_HDR_SIG => 0x07064b50;
+use constant ZIP64_ARCHIVE_EXTRA_SIG => 0x08064b50;
+use constant ZIP64_DIGITAL_SIGNATURE_SIG => 0x05054b50;
+
+use constant ZIP_OS_CODE_UNIX => 3;
+use constant ZIP_OS_CODE_DEFAULT => 3;
+
+# Extra Field ID's
+use constant ZIP_EXTRA_ID_ZIP64 => pack "v", 1;
+use constant ZIP_EXTRA_ID_EXT_TIMESTAMP => "UT";
+use constant ZIP_EXTRA_ID_INFO_ZIP_UNIX2 => "Ux";
+use constant ZIP_EXTRA_ID_INFO_ZIP_UNIXn => "ux";
+use constant ZIP_EXTRA_ID_JAVA_EXE => pack "v", 0xCAFE;
+
+use constant ZIP64_MIN_VERSION => 45;
+
+%ZIP_CM_MIN_VERSIONS = (
+ ZIP_CM_STORE() => 20,
+ ZIP_CM_DEFLATE() => 20,
+ ZIP_CM_BZIP2() => 46,
+ ZIP_CM_LZMA() => 63,
+ );
+
+
+1;
+
+__END__
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Compress/Zlib/Constants.pm b/Master/tlpkg/tlperl/lib/IO/Compress/Zlib/Constants.pm
new file mode 100644
index 00000000000..10fcf345f63
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Compress/Zlib/Constants.pm
@@ -0,0 +1,77 @@
+
+package IO::Compress::Zlib::Constants ;
+
+use strict ;
+use warnings;
+use bytes;
+
+require Exporter;
+
+our ($VERSION, @ISA, @EXPORT);
+
+$VERSION = '2.024';
+
+@ISA = qw(Exporter);
+
+@EXPORT= qw(
+
+ ZLIB_HEADER_SIZE
+ ZLIB_TRAILER_SIZE
+
+ ZLIB_CMF_CM_OFFSET
+ ZLIB_CMF_CM_BITS
+ ZLIB_CMF_CM_DEFLATED
+
+ ZLIB_CMF_CINFO_OFFSET
+ ZLIB_CMF_CINFO_BITS
+ ZLIB_CMF_CINFO_MAX
+
+ ZLIB_FLG_FCHECK_OFFSET
+ ZLIB_FLG_FCHECK_BITS
+
+ ZLIB_FLG_FDICT_OFFSET
+ ZLIB_FLG_FDICT_BITS
+
+ ZLIB_FLG_LEVEL_OFFSET
+ ZLIB_FLG_LEVEL_BITS
+
+ ZLIB_FLG_LEVEL_FASTEST
+ ZLIB_FLG_LEVEL_FAST
+ ZLIB_FLG_LEVEL_DEFAULT
+ ZLIB_FLG_LEVEL_SLOWEST
+
+ ZLIB_FDICT_SIZE
+
+ );
+
+# Constant names derived from RFC1950
+
+use constant ZLIB_HEADER_SIZE => 2;
+use constant ZLIB_TRAILER_SIZE => 4;
+
+use constant ZLIB_CMF_CM_OFFSET => 0;
+use constant ZLIB_CMF_CM_BITS => 0xF ; # 0b1111
+use constant ZLIB_CMF_CM_DEFLATED => 8;
+
+use constant ZLIB_CMF_CINFO_OFFSET => 4;
+use constant ZLIB_CMF_CINFO_BITS => 0xF ; # 0b1111;
+use constant ZLIB_CMF_CINFO_MAX => 7;
+
+use constant ZLIB_FLG_FCHECK_OFFSET => 0;
+use constant ZLIB_FLG_FCHECK_BITS => 0x1F ; # 0b11111;
+
+use constant ZLIB_FLG_FDICT_OFFSET => 5;
+use constant ZLIB_FLG_FDICT_BITS => 0x1 ; # 0b1;
+
+use constant ZLIB_FLG_LEVEL_OFFSET => 6;
+use constant ZLIB_FLG_LEVEL_BITS => 0x3 ; # 0b11;
+
+use constant ZLIB_FLG_LEVEL_FASTEST => 0;
+use constant ZLIB_FLG_LEVEL_FAST => 1;
+use constant ZLIB_FLG_LEVEL_DEFAULT => 2;
+use constant ZLIB_FLG_LEVEL_SLOWEST => 3;
+
+use constant ZLIB_FDICT_SIZE => 4;
+
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/IO/Compress/Zlib/Extra.pm b/Master/tlpkg/tlperl/lib/IO/Compress/Zlib/Extra.pm
new file mode 100644
index 00000000000..6812bb409dc
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Compress/Zlib/Extra.pm
@@ -0,0 +1,198 @@
+package IO::Compress::Zlib::Extra;
+
+require 5.004 ;
+
+use strict ;
+use warnings;
+use bytes;
+
+our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS);
+
+$VERSION = '2.024';
+
+use IO::Compress::Gzip::Constants 2.024 ;
+
+sub ExtraFieldError
+{
+ return $_[0];
+ return "Error with ExtraField Parameter: $_[0]" ;
+}
+
+sub validateExtraFieldPair
+{
+ my $pair = shift ;
+ my $strict = shift;
+ my $gzipMode = shift ;
+
+ return ExtraFieldError("Not an array ref")
+ unless ref $pair && ref $pair eq 'ARRAY';
+
+ return ExtraFieldError("SubField must have two parts")
+ unless @$pair == 2 ;
+
+ return ExtraFieldError("SubField ID is a reference")
+ if ref $pair->[0] ;
+
+ return ExtraFieldError("SubField Data is a reference")
+ if ref $pair->[1] ;
+
+ # ID is exactly two chars
+ return ExtraFieldError("SubField ID not two chars long")
+ unless length $pair->[0] == GZIP_FEXTRA_SUBFIELD_ID_SIZE ;
+
+ # Check that the 2nd byte of the ID isn't 0
+ return ExtraFieldError("SubField ID 2nd byte is 0x00")
+ if $strict && $gzipMode && substr($pair->[0], 1, 1) eq "\x00" ;
+
+ return ExtraFieldError("SubField Data too long")
+ if length $pair->[1] > GZIP_FEXTRA_SUBFIELD_MAX_SIZE ;
+
+
+ return undef ;
+}
+
+sub parseRawExtra
+{
+ my $data = shift ;
+ my $extraRef = shift;
+ my $strict = shift;
+ my $gzipMode = shift ;
+
+ #my $lax = shift ;
+
+ #return undef
+ # if $lax ;
+
+ my $XLEN = length $data ;
+
+ return ExtraFieldError("Too Large")
+ if $XLEN > GZIP_FEXTRA_MAX_SIZE;
+
+ my $offset = 0 ;
+ while ($offset < $XLEN) {
+
+ return ExtraFieldError("Truncated in FEXTRA Body Section")
+ if $offset + GZIP_FEXTRA_SUBFIELD_HEADER_SIZE > $XLEN ;
+
+ my $id = substr($data, $offset, GZIP_FEXTRA_SUBFIELD_ID_SIZE);
+ $offset += GZIP_FEXTRA_SUBFIELD_ID_SIZE;
+
+ my $subLen = unpack("v", substr($data, $offset,
+ GZIP_FEXTRA_SUBFIELD_LEN_SIZE));
+ $offset += GZIP_FEXTRA_SUBFIELD_LEN_SIZE ;
+
+ return ExtraFieldError("Truncated in FEXTRA Body Section")
+ if $offset + $subLen > $XLEN ;
+
+ my $bad = validateExtraFieldPair( [$id,
+ substr($data, $offset, $subLen)],
+ $strict, $gzipMode );
+ return $bad if $bad ;
+ push @$extraRef, [$id => substr($data, $offset, $subLen)]
+ if defined $extraRef;;
+
+ $offset += $subLen ;
+ }
+
+
+ return undef ;
+}
+
+
+sub mkSubField
+{
+ my $id = shift ;
+ my $data = shift ;
+
+ return $id . pack("v", length $data) . $data ;
+}
+
+sub parseExtraField
+{
+ my $dataRef = $_[0];
+ my $strict = $_[1];
+ my $gzipMode = $_[2];
+ #my $lax = @_ == 2 ? $_[1] : 1;
+
+
+ # ExtraField can be any of
+ #
+ # -ExtraField => $data
+ #
+ # -ExtraField => [$id1, $data1,
+ # $id2, $data2]
+ # ...
+ # ]
+ #
+ # -ExtraField => [ [$id1 => $data1],
+ # [$id2 => $data2],
+ # ...
+ # ]
+ #
+ # -ExtraField => { $id1 => $data1,
+ # $id2 => $data2,
+ # ...
+ # }
+
+ if ( ! ref $dataRef ) {
+
+ return undef
+ if ! $strict;
+
+ return parseRawExtra($dataRef, undef, 1, $gzipMode);
+ }
+
+ #my $data = $$dataRef;
+ my $data = $dataRef;
+ my $out = '' ;
+
+ if (ref $data eq 'ARRAY') {
+ if (ref $data->[0]) {
+
+ foreach my $pair (@$data) {
+ return ExtraFieldError("Not list of lists")
+ unless ref $pair eq 'ARRAY' ;
+
+ my $bad = validateExtraFieldPair($pair, $strict, $gzipMode) ;
+ return $bad if $bad ;
+
+ $out .= mkSubField(@$pair);
+ }
+ }
+ else {
+ return ExtraFieldError("Not even number of elements")
+ unless @$data % 2 == 0;
+
+ for (my $ix = 0; $ix <= length(@$data) -1 ; $ix += 2) {
+ my $bad = validateExtraFieldPair([$data->[$ix],
+ $data->[$ix+1]],
+ $strict, $gzipMode) ;
+ return $bad if $bad ;
+
+ $out .= mkSubField($data->[$ix], $data->[$ix+1]);
+ }
+ }
+ }
+ elsif (ref $data eq 'HASH') {
+ while (my ($id, $info) = each %$data) {
+ my $bad = validateExtraFieldPair([$id, $info], $strict, $gzipMode);
+ return $bad if $bad ;
+
+ $out .= mkSubField($id, $info);
+ }
+ }
+ else {
+ return ExtraFieldError("Not a scalar, array ref or hash ref") ;
+ }
+
+ return ExtraFieldError("Too Large")
+ if length $out > GZIP_FEXTRA_MAX_SIZE;
+
+ $_[0] = $out ;
+
+ return undef;
+}
+
+1;
+
+__END__
diff --git a/Master/tlpkg/tlperl/lib/IO/Dir.pm b/Master/tlpkg/tlperl/lib/IO/Dir.pm
new file mode 100644
index 00000000000..cce392c2ce3
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Dir.pm
@@ -0,0 +1,248 @@
+# IO::Dir.pm
+#
+# Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
+# This program is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+
+package IO::Dir;
+
+use 5.006;
+
+use strict;
+use Carp;
+use Symbol;
+use Exporter;
+use IO::File;
+our(@ISA, $VERSION, @EXPORT_OK);
+use Tie::Hash;
+use File::stat;
+use File::Spec;
+
+@ISA = qw(Tie::Hash Exporter);
+$VERSION = "1.07";
+$VERSION = eval $VERSION;
+@EXPORT_OK = qw(DIR_UNLINK);
+
+sub DIR_UNLINK () { 1 }
+
+sub new {
+ @_ >= 1 && @_ <= 2 or croak 'usage: new IO::Dir [DIRNAME]';
+ my $class = shift;
+ my $dh = gensym;
+ if (@_) {
+ IO::Dir::open($dh, $_[0])
+ or return undef;
+ }
+ bless $dh, $class;
+}
+
+sub DESTROY {
+ my ($dh) = @_;
+ local($., $@, $!, $^E, $?);
+ no warnings 'io';
+ closedir($dh);
+}
+
+sub open {
+ @_ == 2 or croak 'usage: $dh->open(DIRNAME)';
+ my ($dh, $dirname) = @_;
+ return undef
+ unless opendir($dh, $dirname);
+ # a dir name should always have a ":" in it; assume dirname is
+ # in current directory
+ $dirname = ':' . $dirname if ( ($^O eq 'MacOS') && ($dirname !~ /:/) );
+ ${*$dh}{io_dir_path} = $dirname;
+ 1;
+}
+
+sub close {
+ @_ == 1 or croak 'usage: $dh->close()';
+ my ($dh) = @_;
+ closedir($dh);
+}
+
+sub read {
+ @_ == 1 or croak 'usage: $dh->read()';
+ my ($dh) = @_;
+ readdir($dh);
+}
+
+sub seek {
+ @_ == 2 or croak 'usage: $dh->seek(POS)';
+ my ($dh,$pos) = @_;
+ seekdir($dh,$pos);
+}
+
+sub tell {
+ @_ == 1 or croak 'usage: $dh->tell()';
+ my ($dh) = @_;
+ telldir($dh);
+}
+
+sub rewind {
+ @_ == 1 or croak 'usage: $dh->rewind()';
+ my ($dh) = @_;
+ rewinddir($dh);
+}
+
+sub TIEHASH {
+ my($class,$dir,$options) = @_;
+
+ my $dh = $class->new($dir)
+ or return undef;
+
+ $options ||= 0;
+
+ ${*$dh}{io_dir_unlink} = $options & DIR_UNLINK;
+ $dh;
+}
+
+sub FIRSTKEY {
+ my($dh) = @_;
+ $dh->rewind;
+ scalar $dh->read;
+}
+
+sub NEXTKEY {
+ my($dh) = @_;
+ scalar $dh->read;
+}
+
+sub EXISTS {
+ my($dh,$key) = @_;
+ -e File::Spec->catfile(${*$dh}{io_dir_path}, $key);
+}
+
+sub FETCH {
+ my($dh,$key) = @_;
+ &lstat(File::Spec->catfile(${*$dh}{io_dir_path}, $key));
+}
+
+sub STORE {
+ my($dh,$key,$data) = @_;
+ my($atime,$mtime) = ref($data) ? @$data : ($data,$data);
+ my $file = File::Spec->catfile(${*$dh}{io_dir_path}, $key);
+ unless(-e $file) {
+ my $io = IO::File->new($file,O_CREAT | O_RDWR);
+ $io->close if $io;
+ }
+ utime($atime,$mtime, $file);
+}
+
+sub DELETE {
+ my($dh,$key) = @_;
+
+ # Only unlink if unlink-ing is enabled
+ return 0
+ unless ${*$dh}{io_dir_unlink};
+
+ my $file = File::Spec->catfile(${*$dh}{io_dir_path}, $key);
+
+ -d $file
+ ? rmdir($file)
+ : unlink($file);
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+IO::Dir - supply object methods for directory handles
+
+=head1 SYNOPSIS
+
+ use IO::Dir;
+ $d = IO::Dir->new(".");
+ if (defined $d) {
+ while (defined($_ = $d->read)) { something($_); }
+ $d->rewind;
+ while (defined($_ = $d->read)) { something_else($_); }
+ undef $d;
+ }
+
+ tie %dir, 'IO::Dir', ".";
+ foreach (keys %dir) {
+ print $_, " " , $dir{$_}->size,"\n";
+ }
+
+=head1 DESCRIPTION
+
+The C<IO::Dir> package provides two interfaces to perl's directory reading
+routines.
+
+The first interface is an object approach. C<IO::Dir> provides an object
+constructor and methods, which are just wrappers around perl's built in
+directory reading routines.
+
+=over 4
+
+=item new ( [ DIRNAME ] )
+
+C<new> is the constructor for C<IO::Dir> objects. It accepts one optional
+argument which, if given, C<new> will pass to C<open>
+
+=back
+
+The following methods are wrappers for the directory related functions built
+into perl (the trailing `dir' has been removed from the names). See L<perlfunc>
+for details of these functions.
+
+=over 4
+
+=item open ( DIRNAME )
+
+=item read ()
+
+=item seek ( POS )
+
+=item tell ()
+
+=item rewind ()
+
+=item close ()
+
+=back
+
+C<IO::Dir> also provides an interface to reading directories via a tied
+hash. The tied hash extends the interface beyond just the directory
+reading routines by the use of C<lstat>, from the C<File::stat> package,
+C<unlink>, C<rmdir> and C<utime>.
+
+=over 4
+
+=item tie %hash, 'IO::Dir', DIRNAME [, OPTIONS ]
+
+=back
+
+The keys of the hash will be the names of the entries in the directory.
+Reading a value from the hash will be the result of calling
+C<File::stat::lstat>. Deleting an element from the hash will
+delete the corresponding file or subdirectory,
+provided that C<DIR_UNLINK> is included in the C<OPTIONS>.
+
+Assigning to an entry in the hash will cause the time stamps of the file
+to be modified. If the file does not exist then it will be created. Assigning
+a single integer to a hash element will cause both the access and
+modification times to be changed to that value. Alternatively a reference to
+an array of two values can be passed. The first array element will be used to
+set the access time and the second element will be used to set the modification
+time.
+
+=head1 SEE ALSO
+
+L<File::stat>
+
+=head1 AUTHOR
+
+Graham Barr. Currently maintained by the Perl Porters. Please report all
+bugs to <perl5-porters@perl.org>.
+
+=head1 COPYRIGHT
+
+Copyright (c) 1997-2003 Graham Barr <gbarr@pobox.com>. All rights reserved.
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/IO/File.pm b/Master/tlpkg/tlperl/lib/IO/File.pm
new file mode 100644
index 00000000000..d33d090d0b2
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/File.pm
@@ -0,0 +1,204 @@
+#
+
+package IO::File;
+
+=head1 NAME
+
+IO::File - supply object methods for filehandles
+
+=head1 SYNOPSIS
+
+ use IO::File;
+
+ $fh = new IO::File;
+ if ($fh->open("< file")) {
+ print <$fh>;
+ $fh->close;
+ }
+
+ $fh = new IO::File "> file";
+ if (defined $fh) {
+ print $fh "bar\n";
+ $fh->close;
+ }
+
+ $fh = new IO::File "file", "r";
+ if (defined $fh) {
+ print <$fh>;
+ undef $fh; # automatically closes the file
+ }
+
+ $fh = new IO::File "file", O_WRONLY|O_APPEND;
+ if (defined $fh) {
+ print $fh "corge\n";
+
+ $pos = $fh->getpos;
+ $fh->setpos($pos);
+
+ undef $fh; # automatically closes the file
+ }
+
+ autoflush STDOUT 1;
+
+=head1 DESCRIPTION
+
+C<IO::File> inherits from C<IO::Handle> and C<IO::Seekable>. It extends
+these classes with methods that are specific to file handles.
+
+=head1 CONSTRUCTOR
+
+=over 4
+
+=item new ( FILENAME [,MODE [,PERMS]] )
+
+Creates an C<IO::File>. If it receives any parameters, they are passed to
+the method C<open>; if the open fails, the object is destroyed. Otherwise,
+it is returned to the caller.
+
+=item new_tmpfile
+
+Creates an C<IO::File> opened for read/write on a newly created temporary
+file. On systems where this is possible, the temporary file is anonymous
+(i.e. it is unlinked after creation, but held open). If the temporary
+file cannot be created or opened, the C<IO::File> object is destroyed.
+Otherwise, it is returned to the caller.
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item open( FILENAME [,MODE [,PERMS]] )
+
+=item open( FILENAME, IOLAYERS )
+
+C<open> accepts one, two or three parameters. With one parameter,
+it is just a front end for the built-in C<open> function. With two or three
+parameters, the first parameter is a filename that may include
+whitespace or other special characters, and the second parameter is
+the open mode, optionally followed by a file permission value.
+
+If C<IO::File::open> receives a Perl mode string ("E<gt>", "+E<lt>", etc.)
+or an ANSI C fopen() mode string ("w", "r+", etc.), it uses the basic
+Perl C<open> operator (but protects any special characters).
+
+If C<IO::File::open> is given a numeric mode, it passes that mode
+and the optional permissions value to the Perl C<sysopen> operator.
+The permissions default to 0666.
+
+If C<IO::File::open> is given a mode that includes the C<:> character,
+it passes all the three arguments to the three-argument C<open> operator.
+
+For convenience, C<IO::File> exports the O_XXX constants from the
+Fcntl module, if this module is available.
+
+=item binmode( [LAYER] )
+
+C<binmode> sets C<binmode> on the underlying C<IO> object, as documented
+in C<perldoc -f binmode>.
+
+C<binmode> accepts one optional parameter, which is the layer to be
+passed on to the C<binmode> call.
+
+=back
+
+=head1 NOTE
+
+Some operating systems may perform C<IO::File::new()> or C<IO::File::open()>
+on a directory without errors. This behavior is not portable and not
+suggested for use. Using C<opendir()> and C<readdir()> or C<IO::Dir> are
+suggested instead.
+
+=head1 SEE ALSO
+
+L<perlfunc>,
+L<perlop/"I/O Operators">,
+L<IO::Handle>,
+L<IO::Seekable>,
+L<IO::Dir>
+
+=head1 HISTORY
+
+Derived from FileHandle.pm by Graham Barr E<lt>F<gbarr@pobox.com>E<gt>.
+
+=cut
+
+use 5.006_001;
+use strict;
+our($VERSION, @EXPORT, @EXPORT_OK, @ISA);
+use Carp;
+use Symbol;
+use SelectSaver;
+use IO::Seekable;
+use File::Spec;
+
+require Exporter;
+
+@ISA = qw(IO::Handle IO::Seekable Exporter);
+
+$VERSION = "1.14";
+
+@EXPORT = @IO::Seekable::EXPORT;
+
+eval {
+ # Make all Fcntl O_XXX constants available for importing
+ require Fcntl;
+ my @O = grep /^O_/, @Fcntl::EXPORT;
+ Fcntl->import(@O); # first we import what we want to export
+ push(@EXPORT, @O);
+};
+
+################################################
+## Constructor
+##
+
+sub new {
+ my $type = shift;
+ my $class = ref($type) || $type || "IO::File";
+ @_ >= 0 && @_ <= 3
+ or croak "usage: new $class [FILENAME [,MODE [,PERMS]]]";
+ my $fh = $class->SUPER::new();
+ if (@_) {
+ $fh->open(@_)
+ or return undef;
+ }
+ $fh;
+}
+
+################################################
+## Open
+##
+
+sub open {
+ @_ >= 2 && @_ <= 4 or croak 'usage: $fh->open(FILENAME [,MODE [,PERMS]])';
+ my ($fh, $file) = @_;
+ if (@_ > 2) {
+ my ($mode, $perms) = @_[2, 3];
+ if ($mode =~ /^\d+$/) {
+ defined $perms or $perms = 0666;
+ return sysopen($fh, $file, $mode, $perms);
+ } elsif ($mode =~ /:/) {
+ return open($fh, $mode, $file) if @_ == 3;
+ croak 'usage: $fh->open(FILENAME, IOLAYERS)';
+ } else {
+ return open($fh, IO::Handle::_open_mode_string($mode), $file);
+ }
+ }
+ open($fh, $file);
+}
+
+################################################
+## Binmode
+##
+
+sub binmode {
+ ( @_ == 1 or @_ == 2 ) or croak 'usage $fh->binmode([LAYER])';
+
+ my($fh, $layer) = @_;
+
+ return binmode $$fh unless $layer;
+ return binmode $$fh, $layer;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/IO/Handle.pm b/Master/tlpkg/tlperl/lib/IO/Handle.pm
new file mode 100644
index 00000000000..2f1f1b423bc
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Handle.pm
@@ -0,0 +1,635 @@
+package IO::Handle;
+
+=head1 NAME
+
+IO::Handle - supply object methods for I/O handles
+
+=head1 SYNOPSIS
+
+ use IO::Handle;
+
+ $io = new IO::Handle;
+ if ($io->fdopen(fileno(STDIN),"r")) {
+ print $io->getline;
+ $io->close;
+ }
+
+ $io = new IO::Handle;
+ if ($io->fdopen(fileno(STDOUT),"w")) {
+ $io->print("Some text\n");
+ }
+
+ # setvbuf is not available by default on Perls 5.8.0 and later.
+ use IO::Handle '_IOLBF';
+ $io->setvbuf($buffer_var, _IOLBF, 1024);
+
+ undef $io; # automatically closes the file if it's open
+
+ autoflush STDOUT 1;
+
+=head1 DESCRIPTION
+
+C<IO::Handle> is the base class for all other IO handle classes. It is
+not intended that objects of C<IO::Handle> would be created directly,
+but instead C<IO::Handle> is inherited from by several other classes
+in the IO hierarchy.
+
+If you are reading this documentation, looking for a replacement for
+the C<FileHandle> package, then I suggest you read the documentation
+for C<IO::File> too.
+
+=head1 CONSTRUCTOR
+
+=over 4
+
+=item new ()
+
+Creates a new C<IO::Handle> object.
+
+=item new_from_fd ( FD, MODE )
+
+Creates an C<IO::Handle> like C<new> does.
+It requires two parameters, which are passed to the method C<fdopen>;
+if the fdopen fails, the object is destroyed. Otherwise, it is returned
+to the caller.
+
+=back
+
+=head1 METHODS
+
+See L<perlfunc> for complete descriptions of each of the following
+supported C<IO::Handle> methods, which are just front ends for the
+corresponding built-in functions:
+
+ $io->close
+ $io->eof
+ $io->fcntl( FUNCTION, SCALAR )
+ $io->fileno
+ $io->format_write( [FORMAT_NAME] )
+ $io->getc
+ $io->ioctl( FUNCTION, SCALAR )
+ $io->read ( BUF, LEN, [OFFSET] )
+ $io->print ( ARGS )
+ $io->printf ( FMT, [ARGS] )
+ $io->say ( ARGS )
+ $io->stat
+ $io->sysread ( BUF, LEN, [OFFSET] )
+ $io->syswrite ( BUF, [LEN, [OFFSET]] )
+ $io->truncate ( LEN )
+
+See L<perlvar> for complete descriptions of each of the following
+supported C<IO::Handle> methods. All of them return the previous
+value of the attribute and takes an optional single argument that when
+given will set the value. If no argument is given the previous value
+is unchanged (except for $io->autoflush will actually turn ON
+autoflush by default).
+
+ $io->autoflush ( [BOOL] ) $|
+ $io->format_page_number( [NUM] ) $%
+ $io->format_lines_per_page( [NUM] ) $=
+ $io->format_lines_left( [NUM] ) $-
+ $io->format_name( [STR] ) $~
+ $io->format_top_name( [STR] ) $^
+ $io->input_line_number( [NUM]) $.
+
+The following methods are not supported on a per-filehandle basis.
+
+ IO::Handle->format_line_break_characters( [STR] ) $:
+ IO::Handle->format_formfeed( [STR]) $^L
+ IO::Handle->output_field_separator( [STR] ) $,
+ IO::Handle->output_record_separator( [STR] ) $\
+
+ IO::Handle->input_record_separator( [STR] ) $/
+
+Furthermore, for doing normal I/O you might need these:
+
+=over 4
+
+=item $io->fdopen ( FD, MODE )
+
+C<fdopen> is like an ordinary C<open> except that its first parameter
+is not a filename but rather a file handle name, an IO::Handle object,
+or a file descriptor number. (For the documentation of the C<open>
+method, see L<IO::File>.)
+
+=item $io->opened
+
+Returns true if the object is currently a valid file descriptor, false
+otherwise.
+
+=item $io->getline
+
+This works like <$io> described in L<perlop/"I/O Operators">
+except that it's more readable and can be safely called in a
+list context but still returns just one line. If used as the conditional
++within a C<while> or C-style C<for> loop, however, you will need to
++emulate the functionality of <$io> with C<< defined($_ = $io->getline) >>.
+
+=item $io->getlines
+
+This works like <$io> when called in a list context to read all
+the remaining lines in a file, except that it's more readable.
+It will also croak() if accidentally called in a scalar context.
+
+=item $io->ungetc ( ORD )
+
+Pushes a character with the given ordinal value back onto the given
+handle's input stream. Only one character of pushback per handle is
+guaranteed.
+
+=item $io->write ( BUF, LEN [, OFFSET ] )
+
+This C<write> is like C<write> found in C, that is it is the
+opposite of read. The wrapper for the perl C<write> function is
+called C<format_write>.
+
+=item $io->error
+
+Returns a true value if the given handle has experienced any errors
+since it was opened or since the last call to C<clearerr>, or if the
+handle is invalid. It only returns false for a valid handle with no
+outstanding errors.
+
+=item $io->clearerr
+
+Clear the given handle's error indicator. Returns -1 if the handle is
+invalid, 0 otherwise.
+
+=item $io->sync
+
+C<sync> synchronizes a file's in-memory state with that on the
+physical medium. C<sync> does not operate at the perlio api level, but
+operates on the file descriptor (similar to sysread, sysseek and
+systell). This means that any data held at the perlio api level will not
+be synchronized. To synchronize data that is buffered at the perlio api
+level you must use the flush method. C<sync> is not implemented on all
+platforms. Returns "0 but true" on success, C<undef> on error, C<undef>
+for an invalid handle. See L<fsync(3c)>.
+
+=item $io->flush
+
+C<flush> causes perl to flush any buffered data at the perlio api level.
+Any unread data in the buffer will be discarded, and any unwritten data
+will be written to the underlying file descriptor. Returns "0 but true"
+on success, C<undef> on error.
+
+=item $io->printflush ( ARGS )
+
+Turns on autoflush, print ARGS and then restores the autoflush status of the
+C<IO::Handle> object. Returns the return value from print.
+
+=item $io->blocking ( [ BOOL ] )
+
+If called with an argument C<blocking> will turn on non-blocking IO if
+C<BOOL> is false, and turn it off if C<BOOL> is true.
+
+C<blocking> will return the value of the previous setting, or the
+current setting if C<BOOL> is not given.
+
+If an error occurs C<blocking> will return undef and C<$!> will be set.
+
+=back
+
+
+If the C functions setbuf() and/or setvbuf() are available, then
+C<IO::Handle::setbuf> and C<IO::Handle::setvbuf> set the buffering
+policy for an IO::Handle. The calling sequences for the Perl functions
+are the same as their C counterparts--including the constants C<_IOFBF>,
+C<_IOLBF>, and C<_IONBF> for setvbuf()--except that the buffer parameter
+specifies a scalar variable to use as a buffer. You should only
+change the buffer before any I/O, or immediately after calling flush.
+
+WARNING: The IO::Handle::setvbuf() is not available by default on
+Perls 5.8.0 and later because setvbuf() is rather specific to using
+the stdio library, while Perl prefers the new perlio subsystem instead.
+
+WARNING: A variable used as a buffer by C<setbuf> or C<setvbuf> B<must not
+be modified> in any way until the IO::Handle is closed or C<setbuf> or
+C<setvbuf> is called again, or memory corruption may result! Remember that
+the order of global destruction is undefined, so even if your buffer
+variable remains in scope until program termination, it may be undefined
+before the file IO::Handle is closed. Note that you need to import the
+constants C<_IOFBF>, C<_IOLBF>, and C<_IONBF> explicitly. Like C, setbuf
+returns nothing. setvbuf returns "0 but true", on success, C<undef> on
+failure.
+
+Lastly, there is a special method for working under B<-T> and setuid/gid
+scripts:
+
+=over 4
+
+=item $io->untaint
+
+Marks the object as taint-clean, and as such data read from it will also
+be considered taint-clean. Note that this is a very trusting action to
+take, and appropriate consideration for the data source and potential
+vulnerability should be kept in mind. Returns 0 on success, -1 if setting
+the taint-clean flag failed. (eg invalid handle)
+
+=back
+
+=head1 NOTE
+
+An C<IO::Handle> object is a reference to a symbol/GLOB reference (see
+the C<Symbol> package). Some modules that
+inherit from C<IO::Handle> may want to keep object related variables
+in the hash table part of the GLOB. In an attempt to prevent modules
+trampling on each other I propose the that any such module should prefix
+its variables with its own name separated by _'s. For example the IO::Socket
+module keeps a C<timeout> variable in 'io_socket_timeout'.
+
+=head1 SEE ALSO
+
+L<perlfunc>,
+L<perlop/"I/O Operators">,
+L<IO::File>
+
+=head1 BUGS
+
+Due to backwards compatibility, all filehandles resemble objects
+of class C<IO::Handle>, or actually classes derived from that class.
+They actually aren't. Which means you can't derive your own
+class from C<IO::Handle> and inherit those methods.
+
+=head1 HISTORY
+
+Derived from FileHandle.pm by Graham Barr E<lt>F<gbarr@pobox.com>E<gt>
+
+=cut
+
+use 5.006_001;
+use strict;
+our($VERSION, @EXPORT_OK, @ISA);
+use Carp;
+use Symbol;
+use SelectSaver;
+use IO (); # Load the XS module
+
+require Exporter;
+@ISA = qw(Exporter);
+
+$VERSION = "1.28";
+$VERSION = eval $VERSION;
+
+@EXPORT_OK = qw(
+ autoflush
+ output_field_separator
+ output_record_separator
+ input_record_separator
+ input_line_number
+ format_page_number
+ format_lines_per_page
+ format_lines_left
+ format_name
+ format_top_name
+ format_line_break_characters
+ format_formfeed
+ format_write
+
+ print
+ printf
+ say
+ getline
+ getlines
+
+ printflush
+ flush
+
+ SEEK_SET
+ SEEK_CUR
+ SEEK_END
+ _IOFBF
+ _IOLBF
+ _IONBF
+);
+
+################################################
+## Constructors, destructors.
+##
+
+sub new {
+ my $class = ref($_[0]) || $_[0] || "IO::Handle";
+ @_ == 1 or croak "usage: new $class";
+ my $io = gensym;
+ bless $io, $class;
+}
+
+sub new_from_fd {
+ my $class = ref($_[0]) || $_[0] || "IO::Handle";
+ @_ == 3 or croak "usage: new_from_fd $class FD, MODE";
+ my $io = gensym;
+ shift;
+ IO::Handle::fdopen($io, @_)
+ or return undef;
+ bless $io, $class;
+}
+
+#
+# There is no need for DESTROY to do anything, because when the
+# last reference to an IO object is gone, Perl automatically
+# closes its associated files (if any). However, to avoid any
+# attempts to autoload DESTROY, we here define it to do nothing.
+#
+sub DESTROY {}
+
+
+################################################
+## Open and close.
+##
+
+sub _open_mode_string {
+ my ($mode) = @_;
+ $mode =~ /^\+?(<|>>?)$/
+ or $mode =~ s/^r(\+?)$/$1</
+ or $mode =~ s/^w(\+?)$/$1>/
+ or $mode =~ s/^a(\+?)$/$1>>/
+ or croak "IO::Handle: bad open mode: $mode";
+ $mode;
+}
+
+sub fdopen {
+ @_ == 3 or croak 'usage: $io->fdopen(FD, MODE)';
+ my ($io, $fd, $mode) = @_;
+ local(*GLOB);
+
+ if (ref($fd) && "".$fd =~ /GLOB\(/o) {
+ # It's a glob reference; Alias it as we cannot get name of anon GLOBs
+ my $n = qualify(*GLOB);
+ *GLOB = *{*$fd};
+ $fd = $n;
+ } elsif ($fd =~ m#^\d+$#) {
+ # It's an FD number; prefix with "=".
+ $fd = "=$fd";
+ }
+
+ open($io, _open_mode_string($mode) . '&' . $fd)
+ ? $io : undef;
+}
+
+sub close {
+ @_ == 1 or croak 'usage: $io->close()';
+ my($io) = @_;
+
+ close($io);
+}
+
+################################################
+## Normal I/O functions.
+##
+
+# flock
+# select
+
+sub opened {
+ @_ == 1 or croak 'usage: $io->opened()';
+ defined fileno($_[0]);
+}
+
+sub fileno {
+ @_ == 1 or croak 'usage: $io->fileno()';
+ fileno($_[0]);
+}
+
+sub getc {
+ @_ == 1 or croak 'usage: $io->getc()';
+ getc($_[0]);
+}
+
+sub eof {
+ @_ == 1 or croak 'usage: $io->eof()';
+ eof($_[0]);
+}
+
+sub print {
+ @_ or croak 'usage: $io->print(ARGS)';
+ my $this = shift;
+ print $this @_;
+}
+
+sub printf {
+ @_ >= 2 or croak 'usage: $io->printf(FMT,[ARGS])';
+ my $this = shift;
+ printf $this @_;
+}
+
+sub say {
+ @_ or croak 'usage: $io->say(ARGS)';
+ my $this = shift;
+ local $\ = "\n";
+ print $this @_;
+}
+
+sub getline {
+ @_ == 1 or croak 'usage: $io->getline()';
+ my $this = shift;
+ return scalar <$this>;
+}
+
+*gets = \&getline; # deprecated
+
+sub getlines {
+ @_ == 1 or croak 'usage: $io->getlines()';
+ wantarray or
+ croak 'Can\'t call $io->getlines in a scalar context, use $io->getline';
+ my $this = shift;
+ return <$this>;
+}
+
+sub truncate {
+ @_ == 2 or croak 'usage: $io->truncate(LEN)';
+ truncate($_[0], $_[1]);
+}
+
+sub read {
+ @_ == 3 || @_ == 4 or croak 'usage: $io->read(BUF, LEN [, OFFSET])';
+ read($_[0], $_[1], $_[2], $_[3] || 0);
+}
+
+sub sysread {
+ @_ == 3 || @_ == 4 or croak 'usage: $io->sysread(BUF, LEN [, OFFSET])';
+ sysread($_[0], $_[1], $_[2], $_[3] || 0);
+}
+
+sub write {
+ @_ >= 2 && @_ <= 4 or croak 'usage: $io->write(BUF [, LEN [, OFFSET]])';
+ local($\) = "";
+ $_[2] = length($_[1]) unless defined $_[2];
+ print { $_[0] } substr($_[1], $_[3] || 0, $_[2]);
+}
+
+sub syswrite {
+ @_ >= 2 && @_ <= 4 or croak 'usage: $io->syswrite(BUF [, LEN [, OFFSET]])';
+ if (defined($_[2])) {
+ syswrite($_[0], $_[1], $_[2], $_[3] || 0);
+ } else {
+ syswrite($_[0], $_[1]);
+ }
+}
+
+sub stat {
+ @_ == 1 or croak 'usage: $io->stat()';
+ stat($_[0]);
+}
+
+################################################
+## State modification functions.
+##
+
+sub autoflush {
+ my $old = new SelectSaver qualify($_[0], caller);
+ my $prev = $|;
+ $| = @_ > 1 ? $_[1] : 1;
+ $prev;
+}
+
+sub output_field_separator {
+ carp "output_field_separator is not supported on a per-handle basis"
+ if ref($_[0]);
+ my $prev = $,;
+ $, = $_[1] if @_ > 1;
+ $prev;
+}
+
+sub output_record_separator {
+ carp "output_record_separator is not supported on a per-handle basis"
+ if ref($_[0]);
+ my $prev = $\;
+ $\ = $_[1] if @_ > 1;
+ $prev;
+}
+
+sub input_record_separator {
+ carp "input_record_separator is not supported on a per-handle basis"
+ if ref($_[0]);
+ my $prev = $/;
+ $/ = $_[1] if @_ > 1;
+ $prev;
+}
+
+sub input_line_number {
+ local $.;
+ () = tell qualify($_[0], caller) if ref($_[0]);
+ my $prev = $.;
+ $. = $_[1] if @_ > 1;
+ $prev;
+}
+
+sub format_page_number {
+ my $old;
+ $old = new SelectSaver qualify($_[0], caller) if ref($_[0]);
+ my $prev = $%;
+ $% = $_[1] if @_ > 1;
+ $prev;
+}
+
+sub format_lines_per_page {
+ my $old;
+ $old = new SelectSaver qualify($_[0], caller) if ref($_[0]);
+ my $prev = $=;
+ $= = $_[1] if @_ > 1;
+ $prev;
+}
+
+sub format_lines_left {
+ my $old;
+ $old = new SelectSaver qualify($_[0], caller) if ref($_[0]);
+ my $prev = $-;
+ $- = $_[1] if @_ > 1;
+ $prev;
+}
+
+sub format_name {
+ my $old;
+ $old = new SelectSaver qualify($_[0], caller) if ref($_[0]);
+ my $prev = $~;
+ $~ = qualify($_[1], caller) if @_ > 1;
+ $prev;
+}
+
+sub format_top_name {
+ my $old;
+ $old = new SelectSaver qualify($_[0], caller) if ref($_[0]);
+ my $prev = $^;
+ $^ = qualify($_[1], caller) if @_ > 1;
+ $prev;
+}
+
+sub format_line_break_characters {
+ carp "format_line_break_characters is not supported on a per-handle basis"
+ if ref($_[0]);
+ my $prev = $:;
+ $: = $_[1] if @_ > 1;
+ $prev;
+}
+
+sub format_formfeed {
+ carp "format_formfeed is not supported on a per-handle basis"
+ if ref($_[0]);
+ my $prev = $^L;
+ $^L = $_[1] if @_ > 1;
+ $prev;
+}
+
+sub formline {
+ my $io = shift;
+ my $picture = shift;
+ local($^A) = $^A;
+ local($\) = "";
+ formline($picture, @_);
+ print $io $^A;
+}
+
+sub format_write {
+ @_ < 3 || croak 'usage: $io->write( [FORMAT_NAME] )';
+ if (@_ == 2) {
+ my ($io, $fmt) = @_;
+ my $oldfmt = $io->format_name(qualify($fmt,caller));
+ CORE::write($io);
+ $io->format_name($oldfmt);
+ } else {
+ CORE::write($_[0]);
+ }
+}
+
+sub fcntl {
+ @_ == 3 || croak 'usage: $io->fcntl( OP, VALUE );';
+ my ($io, $op) = @_;
+ return fcntl($io, $op, $_[2]);
+}
+
+sub ioctl {
+ @_ == 3 || croak 'usage: $io->ioctl( OP, VALUE );';
+ my ($io, $op) = @_;
+ return ioctl($io, $op, $_[2]);
+}
+
+# this sub is for compatability with older releases of IO that used
+# a sub called constant to detemine if a constant existed -- GMB
+#
+# The SEEK_* and _IO?BF constants were the only constants at that time
+# any new code should just chech defined(&CONSTANT_NAME)
+
+sub constant {
+ no strict 'refs';
+ my $name = shift;
+ (($name =~ /^(SEEK_(SET|CUR|END)|_IO[FLN]BF)$/) && defined &{$name})
+ ? &{$name}() : undef;
+}
+
+
+# so that flush.pl can be deprecated
+
+sub printflush {
+ my $io = shift;
+ my $old;
+ $old = new SelectSaver qualify($io, caller) if ref($io);
+ local $| = 1;
+ if(ref($io)) {
+ print $io @_;
+ }
+ else {
+ print @_;
+ }
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/IO/Pipe.pm b/Master/tlpkg/tlperl/lib/IO/Pipe.pm
new file mode 100644
index 00000000000..827cc48bfcd
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Pipe.pm
@@ -0,0 +1,257 @@
+# IO::Pipe.pm
+#
+# Copyright (c) 1996-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
+# This program is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+
+package IO::Pipe;
+
+use 5.006_001;
+
+use IO::Handle;
+use strict;
+our($VERSION);
+use Carp;
+use Symbol;
+
+$VERSION = "1.13";
+
+sub new {
+ my $type = shift;
+ my $class = ref($type) || $type || "IO::Pipe";
+ @_ == 0 || @_ == 2 or croak "usage: new $class [READFH, WRITEFH]";
+
+ my $me = bless gensym(), $class;
+
+ my($readfh,$writefh) = @_ ? @_ : $me->handles;
+
+ pipe($readfh, $writefh)
+ or return undef;
+
+ @{*$me} = ($readfh, $writefh);
+
+ $me;
+}
+
+sub handles {
+ @_ == 1 or croak 'usage: $pipe->handles()';
+ (IO::Pipe::End->new(), IO::Pipe::End->new());
+}
+
+my $do_spawn = $^O eq 'os2' || $^O eq 'MSWin32';
+
+sub _doit {
+ my $me = shift;
+ my $rw = shift;
+
+ my $pid = $do_spawn ? 0 : fork();
+
+ if($pid) { # Parent
+ return $pid;
+ }
+ elsif(defined $pid) { # Child or spawn
+ my $fh;
+ my $io = $rw ? \*STDIN : \*STDOUT;
+ my ($mode, $save) = $rw ? "r" : "w";
+ if ($do_spawn) {
+ require Fcntl;
+ $save = IO::Handle->new_from_fd($io, $mode);
+ my $handle = shift;
+ # Close in child:
+ unless ($^O eq 'MSWin32') {
+ fcntl($handle, Fcntl::F_SETFD(), 1) or croak "fcntl: $!";
+ }
+ $fh = $rw ? ${*$me}[0] : ${*$me}[1];
+ } else {
+ shift;
+ $fh = $rw ? $me->reader() : $me->writer(); # close the other end
+ }
+ bless $io, "IO::Handle";
+ $io->fdopen($fh, $mode);
+ $fh->close;
+
+ if ($do_spawn) {
+ $pid = eval { system 1, @_ }; # 1 == P_NOWAIT
+ my $err = $!;
+
+ $io->fdopen($save, $mode);
+ $save->close or croak "Cannot close $!";
+ croak "IO::Pipe: Cannot spawn-NOWAIT: $err" if not $pid or $pid < 0;
+ return $pid;
+ } else {
+ exec @_ or
+ croak "IO::Pipe: Cannot exec: $!";
+ }
+ }
+ else {
+ croak "IO::Pipe: Cannot fork: $!";
+ }
+
+ # NOT Reached
+}
+
+sub reader {
+ @_ >= 1 or croak 'usage: $pipe->reader( [SUB_COMMAND_ARGS] )';
+ my $me = shift;
+
+ return undef
+ unless(ref($me) || ref($me = $me->new));
+
+ my $fh = ${*$me}[0];
+ my $pid;
+ $pid = $me->_doit(0, $fh, @_)
+ if(@_);
+
+ close ${*$me}[1];
+ bless $me, ref($fh);
+ *$me = *$fh; # Alias self to handle
+ $me->fdopen($fh->fileno,"r")
+ unless defined($me->fileno);
+ bless $fh; # Really wan't un-bless here
+ ${*$me}{'io_pipe_pid'} = $pid
+ if defined $pid;
+
+ $me;
+}
+
+sub writer {
+ @_ >= 1 or croak 'usage: $pipe->writer( [SUB_COMMAND_ARGS] )';
+ my $me = shift;
+
+ return undef
+ unless(ref($me) || ref($me = $me->new));
+
+ my $fh = ${*$me}[1];
+ my $pid;
+ $pid = $me->_doit(1, $fh, @_)
+ if(@_);
+
+ close ${*$me}[0];
+ bless $me, ref($fh);
+ *$me = *$fh; # Alias self to handle
+ $me->fdopen($fh->fileno,"w")
+ unless defined($me->fileno);
+ bless $fh; # Really wan't un-bless here
+ ${*$me}{'io_pipe_pid'} = $pid
+ if defined $pid;
+
+ $me;
+}
+
+package IO::Pipe::End;
+
+our(@ISA);
+
+@ISA = qw(IO::Handle);
+
+sub close {
+ my $fh = shift;
+ my $r = $fh->SUPER::close(@_);
+
+ waitpid(${*$fh}{'io_pipe_pid'},0)
+ if(defined ${*$fh}{'io_pipe_pid'});
+
+ $r;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+IO::Pipe - supply object methods for pipes
+
+=head1 SYNOPSIS
+
+ use IO::Pipe;
+
+ $pipe = new IO::Pipe;
+
+ if($pid = fork()) { # Parent
+ $pipe->reader();
+
+ while(<$pipe>) {
+ ...
+ }
+
+ }
+ elsif(defined $pid) { # Child
+ $pipe->writer();
+
+ print $pipe ...
+ }
+
+ or
+
+ $pipe = new IO::Pipe;
+
+ $pipe->reader(qw(ls -l));
+
+ while(<$pipe>) {
+ ...
+ }
+
+=head1 DESCRIPTION
+
+C<IO::Pipe> provides an interface to creating pipes between
+processes.
+
+=head1 CONSTRUCTOR
+
+=over 4
+
+=item new ( [READER, WRITER] )
+
+Creates an C<IO::Pipe>, which is a reference to a newly created symbol
+(see the C<Symbol> package). C<IO::Pipe::new> optionally takes two
+arguments, which should be objects blessed into C<IO::Handle>, or a
+subclass thereof. These two objects will be used for the system call
+to C<pipe>. If no arguments are given then method C<handles> is called
+on the new C<IO::Pipe> object.
+
+These two handles are held in the array part of the GLOB until either
+C<reader> or C<writer> is called.
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item reader ([ARGS])
+
+The object is re-blessed into a sub-class of C<IO::Handle>, and becomes a
+handle at the reading end of the pipe. If C<ARGS> are given then C<fork>
+is called and C<ARGS> are passed to exec.
+
+=item writer ([ARGS])
+
+The object is re-blessed into a sub-class of C<IO::Handle>, and becomes a
+handle at the writing end of the pipe. If C<ARGS> are given then C<fork>
+is called and C<ARGS> are passed to exec.
+
+=item handles ()
+
+This method is called during construction by C<IO::Pipe::new>
+on the newly created C<IO::Pipe> object. It returns an array of two objects
+blessed into C<IO::Pipe::End>, or a subclass thereof.
+
+=back
+
+=head1 SEE ALSO
+
+L<IO::Handle>
+
+=head1 AUTHOR
+
+Graham Barr. Currently maintained by the Perl Porters. Please report all
+bugs to <perl5-porters@perl.org>.
+
+=head1 COPYRIGHT
+
+Copyright (c) 1996-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/IO/Poll.pm b/Master/tlpkg/tlperl/lib/IO/Poll.pm
new file mode 100644
index 00000000000..e7fb0135069
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Poll.pm
@@ -0,0 +1,209 @@
+
+# IO::Poll.pm
+#
+# Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
+# This program is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+
+package IO::Poll;
+
+use strict;
+use IO::Handle;
+use Exporter ();
+our(@ISA, @EXPORT_OK, @EXPORT, $VERSION);
+
+@ISA = qw(Exporter);
+$VERSION = "0.07";
+
+@EXPORT = qw( POLLIN
+ POLLOUT
+ POLLERR
+ POLLHUP
+ POLLNVAL
+ );
+
+@EXPORT_OK = qw(
+ POLLPRI
+ POLLRDNORM
+ POLLWRNORM
+ POLLRDBAND
+ POLLWRBAND
+ POLLNORM
+ );
+
+# [0] maps fd's to requested masks
+# [1] maps fd's to returned masks
+# [2] maps fd's to handles
+sub new {
+ my $class = shift;
+
+ my $self = bless [{},{},{}], $class;
+
+ $self;
+}
+
+sub mask {
+ my $self = shift;
+ my $io = shift;
+ my $fd = fileno($io);
+ return unless defined $fd;
+ if (@_) {
+ my $mask = shift;
+ if($mask) {
+ $self->[0]{$fd}{$io} = $mask; # the error events are always returned
+ $self->[1]{$fd} = 0; # output mask
+ $self->[2]{$io} = $io; # remember handle
+ } else {
+ delete $self->[0]{$fd}{$io};
+ unless(%{$self->[0]{$fd}}) {
+ # We no longer have any handles for this FD
+ delete $self->[1]{$fd};
+ delete $self->[0]{$fd};
+ }
+ delete $self->[2]{$io};
+ }
+ }
+
+ return unless exists $self->[0]{$fd} and exists $self->[0]{$fd}{$io};
+ return $self->[0]{$fd}{$io};
+}
+
+
+sub poll {
+ my($self,$timeout) = @_;
+
+ $self->[1] = {};
+
+ my($fd,$mask,$iom);
+ my @poll = ();
+
+ while(($fd,$iom) = each %{$self->[0]}) {
+ $mask = 0;
+ $mask |= $_ for values(%$iom);
+ push(@poll,$fd => $mask);
+ }
+
+ my $ret = @poll ? _poll(defined($timeout) ? $timeout * 1000 : -1,@poll) : 0;
+
+ return $ret
+ unless $ret > 0;
+
+ while(@poll) {
+ my($fd,$got) = splice(@poll,0,2);
+ $self->[1]{$fd} = $got if $got;
+ }
+
+ return $ret;
+}
+
+sub events {
+ my $self = shift;
+ my $io = shift;
+ my $fd = fileno($io);
+ exists $self->[1]{$fd} and exists $self->[0]{$fd}{$io}
+ ? $self->[1]{$fd} & ($self->[0]{$fd}{$io}|POLLHUP|POLLERR|POLLNVAL)
+ : 0;
+}
+
+sub remove {
+ my $self = shift;
+ my $io = shift;
+ $self->mask($io,0);
+}
+
+sub handles {
+ my $self = shift;
+ return values %{$self->[2]} unless @_;
+
+ my $events = shift || 0;
+ my($fd,$ev,$io,$mask);
+ my @handles = ();
+
+ while(($fd,$ev) = each %{$self->[1]}) {
+ while (($io,$mask) = each %{$self->[0]{$fd}}) {
+ $mask |= POLLHUP|POLLERR|POLLNVAL; # must allow these
+ push @handles,$self->[2]{$io} if ($ev & $mask) & $events;
+ }
+ }
+ return @handles;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+IO::Poll - Object interface to system poll call
+
+=head1 SYNOPSIS
+
+ use IO::Poll qw(POLLRDNORM POLLWRNORM POLLIN POLLHUP);
+
+ $poll = new IO::Poll;
+
+ $poll->mask($input_handle => POLLIN);
+ $poll->mask($output_handle => POLLOUT);
+
+ $poll->poll($timeout);
+
+ $ev = $poll->events($input);
+
+=head1 DESCRIPTION
+
+C<IO::Poll> is a simple interface to the system level poll routine.
+
+=head1 METHODS
+
+=over 4
+
+=item mask ( IO [, EVENT_MASK ] )
+
+If EVENT_MASK is given, then, if EVENT_MASK is non-zero, IO is added to the
+list of file descriptors and the next call to poll will check for
+any event specified in EVENT_MASK. If EVENT_MASK is zero then IO will be
+removed from the list of file descriptors.
+
+If EVENT_MASK is not given then the return value will be the current
+event mask value for IO.
+
+=item poll ( [ TIMEOUT ] )
+
+Call the system level poll routine. If TIMEOUT is not specified then the
+call will block. Returns the number of handles which had events
+happen, or -1 on error.
+
+=item events ( IO )
+
+Returns the event mask which represents the events that happened on IO
+during the last call to C<poll>.
+
+=item remove ( IO )
+
+Remove IO from the list of file descriptors for the next poll.
+
+=item handles( [ EVENT_MASK ] )
+
+Returns a list of handles. If EVENT_MASK is not given then a list of all
+handles known will be returned. If EVENT_MASK is given then a list
+of handles will be returned which had one of the events specified by
+EVENT_MASK happen during the last call ti C<poll>
+
+=back
+
+=head1 SEE ALSO
+
+L<poll(2)>, L<IO::Handle>, L<IO::Select>
+
+=head1 AUTHOR
+
+Graham Barr. Currently maintained by the Perl Porters. Please report all
+bugs to <perl5-porters@perl.org>.
+
+=head1 COPYRIGHT
+
+Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/IO/Seekable.pm b/Master/tlpkg/tlperl/lib/IO/Seekable.pm
new file mode 100644
index 00000000000..db1effda287
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Seekable.pm
@@ -0,0 +1,128 @@
+#
+
+package IO::Seekable;
+
+=head1 NAME
+
+IO::Seekable - supply seek based methods for I/O objects
+
+=head1 SYNOPSIS
+
+ use IO::Seekable;
+ package IO::Something;
+ @ISA = qw(IO::Seekable);
+
+=head1 DESCRIPTION
+
+C<IO::Seekable> does not have a constructor of its own as it is intended to
+be inherited by other C<IO::Handle> based objects. It provides methods
+which allow seeking of the file descriptors.
+
+=over 4
+
+=item $io->getpos
+
+Returns an opaque value that represents the current position of the
+IO::File, or C<undef> if this is not possible (eg an unseekable stream such
+as a terminal, pipe or socket). If the fgetpos() function is available in
+your C library it is used to implements getpos, else perl emulates getpos
+using C's ftell() function.
+
+=item $io->setpos
+
+Uses the value of a previous getpos call to return to a previously visited
+position. Returns "0 but true" on success, C<undef> on failure.
+
+=back
+
+See L<perlfunc> for complete descriptions of each of the following
+supported C<IO::Seekable> methods, which are just front ends for the
+corresponding built-in functions:
+
+=over 4
+
+=item $io->seek ( POS, WHENCE )
+
+Seek the IO::File to position POS, relative to WHENCE:
+
+=over 8
+
+=item WHENCE=0 (SEEK_SET)
+
+POS is absolute position. (Seek relative to the start of the file)
+
+=item WHENCE=1 (SEEK_CUR)
+
+POS is an offset from the current position. (Seek relative to current)
+
+=item WHENCE=2 (SEEK_END)
+
+POS is an offset from the end of the file. (Seek relative to end)
+
+=back
+
+The SEEK_* constants can be imported from the C<Fcntl> module if you
+don't wish to use the numbers C<0> C<1> or C<2> in your code.
+
+Returns C<1> upon success, C<0> otherwise.
+
+=item $io->sysseek( POS, WHENCE )
+
+Similar to $io->seek, but sets the IO::File's position using the system
+call lseek(2) directly, so will confuse most perl IO operators except
+sysread and syswrite (see L<perlfunc> for full details)
+
+Returns the new position, or C<undef> on failure. A position
+of zero is returned as the string C<"0 but true">
+
+=item $io->tell
+
+Returns the IO::File's current position, or -1 on error.
+
+=back
+
+=head1 SEE ALSO
+
+L<perlfunc>,
+L<perlop/"I/O Operators">,
+L<IO::Handle>
+L<IO::File>
+
+=head1 HISTORY
+
+Derived from FileHandle.pm by Graham Barr E<lt>gbarr@pobox.comE<gt>
+
+=cut
+
+use 5.006_001;
+use Carp;
+use strict;
+our($VERSION, @EXPORT, @ISA);
+use IO::Handle ();
+# XXX we can't get these from IO::Handle or we'll get prototype
+# mismatch warnings on C<use POSIX; use IO::File;> :-(
+use Fcntl qw(SEEK_SET SEEK_CUR SEEK_END);
+require Exporter;
+
+@EXPORT = qw(SEEK_SET SEEK_CUR SEEK_END);
+@ISA = qw(Exporter);
+
+$VERSION = "1.10";
+$VERSION = eval $VERSION;
+
+sub seek {
+ @_ == 3 or croak 'usage: $io->seek(POS, WHENCE)';
+ seek($_[0], $_[1], $_[2]);
+}
+
+sub sysseek {
+ @_ == 3 or croak 'usage: $io->sysseek(POS, WHENCE)';
+ sysseek($_[0], $_[1], $_[2]);
+}
+
+sub tell {
+ @_ == 1 or croak 'usage: $io->tell()';
+ tell($_[0]);
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/IO/Select.pm b/Master/tlpkg/tlperl/lib/IO/Select.pm
new file mode 100644
index 00000000000..fc05fe70e9c
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Select.pm
@@ -0,0 +1,381 @@
+# IO::Select.pm
+#
+# Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
+# This program is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+
+package IO::Select;
+
+use strict;
+use warnings::register;
+use vars qw($VERSION @ISA);
+require Exporter;
+
+$VERSION = "1.17";
+
+@ISA = qw(Exporter); # This is only so we can do version checking
+
+sub VEC_BITS () {0}
+sub FD_COUNT () {1}
+sub FIRST_FD () {2}
+
+sub new
+{
+ my $self = shift;
+ my $type = ref($self) || $self;
+
+ my $vec = bless [undef,0], $type;
+
+ $vec->add(@_)
+ if @_;
+
+ $vec;
+}
+
+sub add
+{
+ shift->_update('add', @_);
+}
+
+
+sub remove
+{
+ shift->_update('remove', @_);
+}
+
+
+sub exists
+{
+ my $vec = shift;
+ my $fno = $vec->_fileno(shift);
+ return undef unless defined $fno;
+ $vec->[$fno + FIRST_FD];
+}
+
+
+sub _fileno
+{
+ my($self, $f) = @_;
+ return unless defined $f;
+ $f = $f->[0] if ref($f) eq 'ARRAY';
+ ($f =~ /^\d+$/) ? $f : fileno($f);
+}
+
+sub _update
+{
+ my $vec = shift;
+ my $add = shift eq 'add';
+
+ my $bits = $vec->[VEC_BITS];
+ $bits = '' unless defined $bits;
+
+ my $count = 0;
+ my $f;
+ foreach $f (@_)
+ {
+ my $fn = $vec->_fileno($f);
+ next unless defined $fn;
+ my $i = $fn + FIRST_FD;
+ if ($add) {
+ if (defined $vec->[$i]) {
+ $vec->[$i] = $f; # if array rest might be different, so we update
+ next;
+ }
+ $vec->[FD_COUNT]++;
+ vec($bits, $fn, 1) = 1;
+ $vec->[$i] = $f;
+ } else { # remove
+ next unless defined $vec->[$i];
+ $vec->[FD_COUNT]--;
+ vec($bits, $fn, 1) = 0;
+ $vec->[$i] = undef;
+ }
+ $count++;
+ }
+ $vec->[VEC_BITS] = $vec->[FD_COUNT] ? $bits : undef;
+ $count;
+}
+
+sub can_read
+{
+ my $vec = shift;
+ my $timeout = shift;
+ my $r = $vec->[VEC_BITS];
+
+ defined($r) && (select($r,undef,undef,$timeout) > 0)
+ ? handles($vec, $r)
+ : ();
+}
+
+sub can_write
+{
+ my $vec = shift;
+ my $timeout = shift;
+ my $w = $vec->[VEC_BITS];
+
+ defined($w) && (select(undef,$w,undef,$timeout) > 0)
+ ? handles($vec, $w)
+ : ();
+}
+
+sub has_exception
+{
+ my $vec = shift;
+ my $timeout = shift;
+ my $e = $vec->[VEC_BITS];
+
+ defined($e) && (select(undef,undef,$e,$timeout) > 0)
+ ? handles($vec, $e)
+ : ();
+}
+
+sub has_error
+{
+ warnings::warn("Call to deprecated method 'has_error', use 'has_exception'")
+ if warnings::enabled();
+ goto &has_exception;
+}
+
+sub count
+{
+ my $vec = shift;
+ $vec->[FD_COUNT];
+}
+
+sub bits
+{
+ my $vec = shift;
+ $vec->[VEC_BITS];
+}
+
+sub as_string # for debugging
+{
+ my $vec = shift;
+ my $str = ref($vec) . ": ";
+ my $bits = $vec->bits;
+ my $count = $vec->count;
+ $str .= defined($bits) ? unpack("b*", $bits) : "undef";
+ $str .= " $count";
+ my @handles = @$vec;
+ splice(@handles, 0, FIRST_FD);
+ for (@handles) {
+ $str .= " " . (defined($_) ? "$_" : "-");
+ }
+ $str;
+}
+
+sub _max
+{
+ my($a,$b,$c) = @_;
+ $a > $b
+ ? $a > $c
+ ? $a
+ : $c
+ : $b > $c
+ ? $b
+ : $c;
+}
+
+sub select
+{
+ shift
+ if defined $_[0] && !ref($_[0]);
+
+ my($r,$w,$e,$t) = @_;
+ my @result = ();
+
+ my $rb = defined $r ? $r->[VEC_BITS] : undef;
+ my $wb = defined $w ? $w->[VEC_BITS] : undef;
+ my $eb = defined $e ? $e->[VEC_BITS] : undef;
+
+ if(select($rb,$wb,$eb,$t) > 0)
+ {
+ my @r = ();
+ my @w = ();
+ my @e = ();
+ my $i = _max(defined $r ? scalar(@$r)-1 : 0,
+ defined $w ? scalar(@$w)-1 : 0,
+ defined $e ? scalar(@$e)-1 : 0);
+
+ for( ; $i >= FIRST_FD ; $i--)
+ {
+ my $j = $i - FIRST_FD;
+ push(@r, $r->[$i])
+ if defined $rb && defined $r->[$i] && vec($rb, $j, 1);
+ push(@w, $w->[$i])
+ if defined $wb && defined $w->[$i] && vec($wb, $j, 1);
+ push(@e, $e->[$i])
+ if defined $eb && defined $e->[$i] && vec($eb, $j, 1);
+ }
+
+ @result = (\@r, \@w, \@e);
+ }
+ @result;
+}
+
+
+sub handles
+{
+ my $vec = shift;
+ my $bits = shift;
+ my @h = ();
+ my $i;
+ my $max = scalar(@$vec) - 1;
+
+ for ($i = FIRST_FD; $i <= $max; $i++)
+ {
+ next unless defined $vec->[$i];
+ push(@h, $vec->[$i])
+ if !defined($bits) || vec($bits, $i - FIRST_FD, 1);
+ }
+
+ @h;
+}
+
+1;
+__END__
+
+=head1 NAME
+
+IO::Select - OO interface to the select system call
+
+=head1 SYNOPSIS
+
+ use IO::Select;
+
+ $s = IO::Select->new();
+
+ $s->add(\*STDIN);
+ $s->add($some_handle);
+
+ @ready = $s->can_read($timeout);
+
+ @ready = IO::Select->new(@handles)->can_read(0);
+
+=head1 DESCRIPTION
+
+The C<IO::Select> package implements an object approach to the system C<select>
+function call. It allows the user to see what IO handles, see L<IO::Handle>,
+are ready for reading, writing or have an exception pending.
+
+=head1 CONSTRUCTOR
+
+=over 4
+
+=item new ( [ HANDLES ] )
+
+The constructor creates a new object and optionally initialises it with a set
+of handles.
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item add ( HANDLES )
+
+Add the list of handles to the C<IO::Select> object. It is these values that
+will be returned when an event occurs. C<IO::Select> keeps these values in a
+cache which is indexed by the C<fileno> of the handle, so if more than one
+handle with the same C<fileno> is specified then only the last one is cached.
+
+Each handle can be an C<IO::Handle> object, an integer or an array
+reference where the first element is an C<IO::Handle> or an integer.
+
+=item remove ( HANDLES )
+
+Remove all the given handles from the object. This method also works
+by the C<fileno> of the handles. So the exact handles that were added
+need not be passed, just handles that have an equivalent C<fileno>
+
+=item exists ( HANDLE )
+
+Returns a true value (actually the handle itself) if it is present.
+Returns undef otherwise.
+
+=item handles
+
+Return an array of all registered handles.
+
+=item can_read ( [ TIMEOUT ] )
+
+Return an array of handles that are ready for reading. C<TIMEOUT> is
+the maximum amount of time to wait before returning an empty list, in
+seconds, possibly fractional. If C<TIMEOUT> is not given and any
+handles are registered then the call will block.
+
+=item can_write ( [ TIMEOUT ] )
+
+Same as C<can_read> except check for handles that can be written to.
+
+=item has_exception ( [ TIMEOUT ] )
+
+Same as C<can_read> except check for handles that have an exception
+condition, for example pending out-of-band data.
+
+=item count ()
+
+Returns the number of handles that the object will check for when
+one of the C<can_> methods is called or the object is passed to
+the C<select> static method.
+
+=item bits()
+
+Return the bit string suitable as argument to the core select() call.
+
+=item select ( READ, WRITE, EXCEPTION [, TIMEOUT ] )
+
+C<select> is a static method, that is you call it with the package name
+like C<new>. C<READ>, C<WRITE> and C<EXCEPTION> are either C<undef> or
+C<IO::Select> objects. C<TIMEOUT> is optional and has the same effect as
+for the core select call.
+
+The result will be an array of 3 elements, each a reference to an array
+which will hold the handles that are ready for reading, writing and have
+exceptions respectively. Upon error an empty list is returned.
+
+=back
+
+=head1 EXAMPLE
+
+Here is a short example which shows how C<IO::Select> could be used
+to write a server which communicates with several sockets while also
+listening for more connections on a listen socket
+
+ use IO::Select;
+ use IO::Socket;
+
+ $lsn = new IO::Socket::INET(Listen => 1, LocalPort => 8080);
+ $sel = new IO::Select( $lsn );
+
+ while(@ready = $sel->can_read) {
+ foreach $fh (@ready) {
+ if($fh == $lsn) {
+ # Create a new socket
+ $new = $lsn->accept;
+ $sel->add($new);
+ }
+ else {
+ # Process socket
+
+ # Maybe we have finished with the socket
+ $sel->remove($fh);
+ $fh->close;
+ }
+ }
+ }
+
+=head1 AUTHOR
+
+Graham Barr. Currently maintained by the Perl Porters. Please report all
+bugs to <perl5-porters@perl.org>.
+
+=head1 COPYRIGHT
+
+Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=cut
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Socket.pm b/Master/tlpkg/tlperl/lib/IO/Socket.pm
new file mode 100644
index 00000000000..6d4f6ab6123
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Socket.pm
@@ -0,0 +1,540 @@
+# IO::Socket.pm
+#
+# Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
+# This program is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+
+package IO::Socket;
+
+require 5.006;
+
+use IO::Handle;
+use Socket 1.3;
+use Carp;
+use strict;
+our(@ISA, $VERSION, @EXPORT_OK);
+use Exporter;
+use Errno;
+
+# legacy
+
+require IO::Socket::INET;
+require IO::Socket::UNIX if ($^O ne 'epoc' && $^O ne 'symbian');
+
+@ISA = qw(IO::Handle);
+
+$VERSION = "1.31";
+
+@EXPORT_OK = qw(sockatmark);
+
+sub import {
+ my $pkg = shift;
+ if (@_ && $_[0] eq 'sockatmark') { # not very extensible but for now, fast
+ Exporter::export_to_level('IO::Socket', 1, $pkg, 'sockatmark');
+ } else {
+ my $callpkg = caller;
+ Exporter::export 'Socket', $callpkg, @_;
+ }
+}
+
+sub new {
+ my($class,%arg) = @_;
+ my $sock = $class->SUPER::new();
+
+ $sock->autoflush(1);
+
+ ${*$sock}{'io_socket_timeout'} = delete $arg{Timeout};
+
+ return scalar(%arg) ? $sock->configure(\%arg)
+ : $sock;
+}
+
+my @domain2pkg;
+
+sub register_domain {
+ my($p,$d) = @_;
+ $domain2pkg[$d] = $p;
+}
+
+sub configure {
+ my($sock,$arg) = @_;
+ my $domain = delete $arg->{Domain};
+
+ croak 'IO::Socket: Cannot configure a generic socket'
+ unless defined $domain;
+
+ croak "IO::Socket: Unsupported socket domain"
+ unless defined $domain2pkg[$domain];
+
+ croak "IO::Socket: Cannot configure socket in domain '$domain'"
+ unless ref($sock) eq "IO::Socket";
+
+ bless($sock, $domain2pkg[$domain]);
+ $sock->configure($arg);
+}
+
+sub socket {
+ @_ == 4 or croak 'usage: $sock->socket(DOMAIN, TYPE, PROTOCOL)';
+ my($sock,$domain,$type,$protocol) = @_;
+
+ socket($sock,$domain,$type,$protocol) or
+ return undef;
+
+ ${*$sock}{'io_socket_domain'} = $domain;
+ ${*$sock}{'io_socket_type'} = $type;
+ ${*$sock}{'io_socket_proto'} = $protocol;
+
+ $sock;
+}
+
+sub socketpair {
+ @_ == 4 || croak 'usage: IO::Socket->socketpair(DOMAIN, TYPE, PROTOCOL)';
+ my($class,$domain,$type,$protocol) = @_;
+ my $sock1 = $class->new();
+ my $sock2 = $class->new();
+
+ socketpair($sock1,$sock2,$domain,$type,$protocol) or
+ return ();
+
+ ${*$sock1}{'io_socket_type'} = ${*$sock2}{'io_socket_type'} = $type;
+ ${*$sock1}{'io_socket_proto'} = ${*$sock2}{'io_socket_proto'} = $protocol;
+
+ ($sock1,$sock2);
+}
+
+sub connect {
+ @_ == 2 or croak 'usage: $sock->connect(NAME)';
+ my $sock = shift;
+ my $addr = shift;
+ my $timeout = ${*$sock}{'io_socket_timeout'};
+ my $err;
+ my $blocking;
+
+ $blocking = $sock->blocking(0) if $timeout;
+ if (!connect($sock, $addr)) {
+ if (defined $timeout && ($!{EINPROGRESS} || $!{EWOULDBLOCK})) {
+ require IO::Select;
+
+ my $sel = new IO::Select $sock;
+
+ undef $!;
+ if (!$sel->can_write($timeout)) {
+ $err = $! || (exists &Errno::ETIMEDOUT ? &Errno::ETIMEDOUT : 1);
+ $@ = "connect: timeout";
+ }
+ elsif (!connect($sock,$addr) &&
+ not ($!{EISCONN} || ($! == 10022 && $^O eq 'MSWin32'))
+ ) {
+ # Some systems refuse to re-connect() to
+ # an already open socket and set errno to EISCONN.
+ # Windows sets errno to WSAEINVAL (10022)
+ $err = $!;
+ $@ = "connect: $!";
+ }
+ }
+ elsif ($blocking || !($!{EINPROGRESS} || $!{EWOULDBLOCK})) {
+ $err = $!;
+ $@ = "connect: $!";
+ }
+ }
+
+ $sock->blocking(1) if $blocking;
+
+ $! = $err if $err;
+
+ $err ? undef : $sock;
+}
+
+# Enable/disable blocking IO on sockets.
+# Without args return the current status of blocking,
+# with args change the mode as appropriate, returning the
+# old setting, or in case of error during the mode change
+# undef.
+
+sub blocking {
+ my $sock = shift;
+
+ return $sock->SUPER::blocking(@_)
+ if $^O ne 'MSWin32';
+
+ # Windows handles blocking differently
+ #
+ # http://groups.google.co.uk/group/perl.perl5.porters/browse_thread/thread/b4e2b1d88280ddff/630b667a66e3509f?#630b667a66e3509f
+ # http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/ioctlsocket_2.asp
+ #
+ # 0x8004667e is FIONBIO
+ #
+ # which is used to set blocking behaviour.
+
+ # NOTE:
+ # This is a little confusing, the perl keyword for this is
+ # 'blocking' but the OS level behaviour is 'non-blocking', probably
+ # because sockets are blocking by default.
+ # Therefore internally we have to reverse the semantics.
+
+ my $orig= !${*$sock}{io_sock_nonblocking};
+
+ return $orig unless @_;
+
+ my $block = shift;
+
+ if ( !$block != !$orig ) {
+ ${*$sock}{io_sock_nonblocking} = $block ? 0 : 1;
+ ioctl($sock, 0x8004667e, pack("L!",${*$sock}{io_sock_nonblocking}))
+ or return undef;
+ }
+
+ return $orig;
+}
+
+
+sub close {
+ @_ == 1 or croak 'usage: $sock->close()';
+ my $sock = shift;
+ ${*$sock}{'io_socket_peername'} = undef;
+ $sock->SUPER::close();
+}
+
+sub bind {
+ @_ == 2 or croak 'usage: $sock->bind(NAME)';
+ my $sock = shift;
+ my $addr = shift;
+
+ return bind($sock, $addr) ? $sock
+ : undef;
+}
+
+sub listen {
+ @_ >= 1 && @_ <= 2 or croak 'usage: $sock->listen([QUEUE])';
+ my($sock,$queue) = @_;
+ $queue = 5
+ unless $queue && $queue > 0;
+
+ return listen($sock, $queue) ? $sock
+ : undef;
+}
+
+sub accept {
+ @_ == 1 || @_ == 2 or croak 'usage $sock->accept([PKG])';
+ my $sock = shift;
+ my $pkg = shift || $sock;
+ my $timeout = ${*$sock}{'io_socket_timeout'};
+ my $new = $pkg->new(Timeout => $timeout);
+ my $peer = undef;
+
+ if(defined $timeout) {
+ require IO::Select;
+
+ my $sel = new IO::Select $sock;
+
+ unless ($sel->can_read($timeout)) {
+ $@ = 'accept: timeout';
+ $! = (exists &Errno::ETIMEDOUT ? &Errno::ETIMEDOUT : 1);
+ return;
+ }
+ }
+
+ $peer = accept($new,$sock)
+ or return;
+
+ return wantarray ? ($new, $peer)
+ : $new;
+}
+
+sub sockname {
+ @_ == 1 or croak 'usage: $sock->sockname()';
+ getsockname($_[0]);
+}
+
+sub peername {
+ @_ == 1 or croak 'usage: $sock->peername()';
+ my($sock) = @_;
+ ${*$sock}{'io_socket_peername'} ||= getpeername($sock);
+}
+
+sub connected {
+ @_ == 1 or croak 'usage: $sock->connected()';
+ my($sock) = @_;
+ getpeername($sock);
+}
+
+sub send {
+ @_ >= 2 && @_ <= 4 or croak 'usage: $sock->send(BUF, [FLAGS, [TO]])';
+ my $sock = $_[0];
+ my $flags = $_[2] || 0;
+ my $peer = $_[3] || $sock->peername;
+
+ croak 'send: Cannot determine peer address'
+ unless(defined $peer);
+
+ my $r = defined(getpeername($sock))
+ ? send($sock, $_[1], $flags)
+ : send($sock, $_[1], $flags, $peer);
+
+ # remember who we send to, if it was successful
+ ${*$sock}{'io_socket_peername'} = $peer
+ if(@_ == 4 && defined $r);
+
+ $r;
+}
+
+sub recv {
+ @_ == 3 || @_ == 4 or croak 'usage: $sock->recv(BUF, LEN [, FLAGS])';
+ my $sock = $_[0];
+ my $len = $_[2];
+ my $flags = $_[3] || 0;
+
+ # remember who we recv'd from
+ ${*$sock}{'io_socket_peername'} = recv($sock, $_[1]='', $len, $flags);
+}
+
+sub shutdown {
+ @_ == 2 or croak 'usage: $sock->shutdown(HOW)';
+ my($sock, $how) = @_;
+ ${*$sock}{'io_socket_peername'} = undef;
+ shutdown($sock, $how);
+}
+
+sub setsockopt {
+ @_ == 4 or croak '$sock->setsockopt(LEVEL, OPTNAME, OPTVAL)';
+ setsockopt($_[0],$_[1],$_[2],$_[3]);
+}
+
+my $intsize = length(pack("i",0));
+
+sub getsockopt {
+ @_ == 3 or croak '$sock->getsockopt(LEVEL, OPTNAME)';
+ my $r = getsockopt($_[0],$_[1],$_[2]);
+ # Just a guess
+ $r = unpack("i", $r)
+ if(defined $r && length($r) == $intsize);
+ $r;
+}
+
+sub sockopt {
+ my $sock = shift;
+ @_ == 1 ? $sock->getsockopt(SOL_SOCKET,@_)
+ : $sock->setsockopt(SOL_SOCKET,@_);
+}
+
+sub atmark {
+ @_ == 1 or croak 'usage: $sock->atmark()';
+ my($sock) = @_;
+ sockatmark($sock);
+}
+
+sub timeout {
+ @_ == 1 || @_ == 2 or croak 'usage: $sock->timeout([VALUE])';
+ my($sock,$val) = @_;
+ my $r = ${*$sock}{'io_socket_timeout'};
+
+ ${*$sock}{'io_socket_timeout'} = defined $val ? 0 + $val : $val
+ if(@_ == 2);
+
+ $r;
+}
+
+sub sockdomain {
+ @_ == 1 or croak 'usage: $sock->sockdomain()';
+ my $sock = shift;
+ ${*$sock}{'io_socket_domain'};
+}
+
+sub socktype {
+ @_ == 1 or croak 'usage: $sock->socktype()';
+ my $sock = shift;
+ ${*$sock}{'io_socket_type'}
+}
+
+sub protocol {
+ @_ == 1 or croak 'usage: $sock->protocol()';
+ my($sock) = @_;
+ ${*$sock}{'io_socket_proto'};
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+IO::Socket - Object interface to socket communications
+
+=head1 SYNOPSIS
+
+ use IO::Socket;
+
+=head1 DESCRIPTION
+
+C<IO::Socket> provides an object interface to creating and using sockets. It
+is built upon the L<IO::Handle> interface and inherits all the methods defined
+by L<IO::Handle>.
+
+C<IO::Socket> only defines methods for those operations which are common to all
+types of socket. Operations which are specified to a socket in a particular
+domain have methods defined in sub classes of C<IO::Socket>
+
+C<IO::Socket> will export all functions (and constants) defined by L<Socket>.
+
+=head1 CONSTRUCTOR
+
+=over 4
+
+=item new ( [ARGS] )
+
+Creates an C<IO::Socket>, which is a reference to a
+newly created symbol (see the C<Symbol> package). C<new>
+optionally takes arguments, these arguments are in key-value pairs.
+C<new> only looks for one key C<Domain> which tells new which domain
+the socket will be in. All other arguments will be passed to the
+configuration method of the package for that domain, See below.
+
+ NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
+
+As of VERSION 1.18 all IO::Socket objects have autoflush turned on
+by default. This was not the case with earlier releases.
+
+ NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
+
+=back
+
+=head1 METHODS
+
+See L<perlfunc> for complete descriptions of each of the following
+supported C<IO::Socket> methods, which are just front ends for the
+corresponding built-in functions:
+
+ socket
+ socketpair
+ bind
+ listen
+ accept
+ send
+ recv
+ peername (getpeername)
+ sockname (getsockname)
+ shutdown
+
+Some methods take slightly different arguments to those defined in L<perlfunc>
+in attempt to make the interface more flexible. These are
+
+=over 4
+
+=item accept([PKG])
+
+perform the system call C<accept> on the socket and return a new
+object. The new object will be created in the same class as the listen
+socket, unless C<PKG> is specified. This object can be used to
+communicate with the client that was trying to connect.
+
+In a scalar context the new socket is returned, or undef upon
+failure. In a list context a two-element array is returned containing
+the new socket and the peer address; the list will be empty upon
+failure.
+
+The timeout in the [PKG] can be specified as zero to effect a "poll",
+but you shouldn't do that because a new IO::Select object will be
+created behind the scenes just to do the single poll. This is
+horrendously inefficient. Use rather true select() with a zero
+timeout on the handle, or non-blocking IO.
+
+=item socketpair(DOMAIN, TYPE, PROTOCOL)
+
+Call C<socketpair> and return a list of two sockets created, or an
+empty list on failure.
+
+=back
+
+Additional methods that are provided are:
+
+=over 4
+
+=item atmark
+
+True if the socket is currently positioned at the urgent data mark,
+false otherwise.
+
+ use IO::Socket;
+
+ my $sock = IO::Socket::INET->new('some_server');
+ $sock->read($data, 1024) until $sock->atmark;
+
+Note: this is a reasonably new addition to the family of socket
+functions, so all systems may not support this yet. If it is
+unsupported by the system, an attempt to use this method will
+abort the program.
+
+The atmark() functionality is also exportable as sockatmark() function:
+
+ use IO::Socket 'sockatmark';
+
+This allows for a more traditional use of sockatmark() as a procedural
+socket function. If your system does not support sockatmark(), the
+C<use> declaration will fail at compile time.
+
+=item connected
+
+If the socket is in a connected state the peer address is returned.
+If the socket is not in a connected state then undef will be returned.
+
+=item protocol
+
+Returns the numerical number for the protocol being used on the socket, if
+known. If the protocol is unknown, as with an AF_UNIX socket, zero
+is returned.
+
+=item sockdomain
+
+Returns the numerical number for the socket domain type. For example, for
+an AF_INET socket the value of &AF_INET will be returned.
+
+=item sockopt(OPT [, VAL])
+
+Unified method to both set and get options in the SOL_SOCKET level. If called
+with one argument then getsockopt is called, otherwise setsockopt is called.
+
+=item getsockopt(LEVEL, OPT)
+
+Get option associated with the socket. Other levels than SOL_SOCKET
+may be specified here.
+
+=item setsockopt(LEVEL, OPT, VAL)
+
+Set option associated with the socket. Other levels than SOL_SOCKET
+may be specified here.
+
+=item socktype
+
+Returns the numerical number for the socket type. For example, for
+a SOCK_STREAM socket the value of &SOCK_STREAM will be returned.
+
+=item timeout([VAL])
+
+Set or get the timeout value (in seconds) associated with this socket.
+If called without any arguments then the current setting is returned. If
+called with an argument the current setting is changed and the previous
+value returned.
+
+=back
+
+=head1 SEE ALSO
+
+L<Socket>, L<IO::Handle>, L<IO::Socket::INET>, L<IO::Socket::UNIX>
+
+=head1 AUTHOR
+
+Graham Barr. atmark() by Lincoln Stein. Currently maintained by the
+Perl Porters. Please report all bugs to <perl5-porters@perl.org>.
+
+=head1 COPYRIGHT
+
+Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+The atmark() implementation: Copyright 2001, Lincoln Stein <lstein@cshl.org>.
+This module is distributed under the same terms as Perl itself.
+Feel free to use, modify and redistribute it as long as you retain
+the correct attribution.
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/IO/Socket/INET.pm b/Master/tlpkg/tlperl/lib/IO/Socket/INET.pm
new file mode 100644
index 00000000000..2f0e5d1d7a6
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Socket/INET.pm
@@ -0,0 +1,464 @@
+# IO::Socket::INET.pm
+#
+# Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
+# This program is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+
+package IO::Socket::INET;
+
+use strict;
+our(@ISA, $VERSION);
+use IO::Socket;
+use Socket;
+use Carp;
+use Exporter;
+use Errno;
+
+@ISA = qw(IO::Socket);
+$VERSION = "1.31";
+
+my $EINVAL = exists(&Errno::EINVAL) ? Errno::EINVAL() : 1;
+
+IO::Socket::INET->register_domain( AF_INET );
+
+my %socket_type = ( tcp => SOCK_STREAM,
+ udp => SOCK_DGRAM,
+ icmp => SOCK_RAW
+ );
+my %proto_number;
+$proto_number{tcp} = Socket::IPPROTO_TCP() if defined &Socket::IPPROTO_TCP;
+$proto_number{udp} = Socket::IPPROTO_UDP() if defined &Socket::IPPROTO_UDP;
+$proto_number{icmp} = Socket::IPPROTO_ICMP() if defined &Socket::IPPROTO_ICMP;
+my %proto_name = reverse %proto_number;
+
+sub new {
+ my $class = shift;
+ unshift(@_, "PeerAddr") if @_ == 1;
+ return $class->SUPER::new(@_);
+}
+
+sub _cache_proto {
+ my @proto = @_;
+ for (map lc($_), $proto[0], split(' ', $proto[1])) {
+ $proto_number{$_} = $proto[2];
+ }
+ $proto_name{$proto[2]} = $proto[0];
+}
+
+sub _get_proto_number {
+ my $name = lc(shift);
+ return undef unless defined $name;
+ return $proto_number{$name} if exists $proto_number{$name};
+
+ my @proto = getprotobyname($name);
+ return undef unless @proto;
+ _cache_proto(@proto);
+
+ return $proto[2];
+}
+
+sub _get_proto_name {
+ my $num = shift;
+ return undef unless defined $num;
+ return $proto_name{$num} if exists $proto_name{$num};
+
+ my @proto = getprotobynumber($num);
+ return undef unless @proto;
+ _cache_proto(@proto);
+
+ return $proto[0];
+}
+
+sub _sock_info {
+ my($addr,$port,$proto) = @_;
+ my $origport = $port;
+ my @serv = ();
+
+ $port = $1
+ if(defined $addr && $addr =~ s,:([\w\(\)/]+)$,,);
+
+ if(defined $proto && $proto =~ /\D/) {
+ my $num = _get_proto_number($proto);
+ unless (defined $num) {
+ $@ = "Bad protocol '$proto'";
+ return;
+ }
+ $proto = $num;
+ }
+
+ if(defined $port) {
+ my $defport = ($port =~ s,\((\d+)\)$,,) ? $1 : undef;
+ my $pnum = ($port =~ m,^(\d+)$,)[0];
+
+ @serv = getservbyname($port, _get_proto_name($proto) || "")
+ if ($port =~ m,\D,);
+
+ $port = $serv[2] || $defport || $pnum;
+ unless (defined $port) {
+ $@ = "Bad service '$origport'";
+ return;
+ }
+
+ $proto = _get_proto_number($serv[3]) if @serv && !$proto;
+ }
+
+ return ($addr || undef,
+ $port || undef,
+ $proto || undef
+ );
+}
+
+sub _error {
+ my $sock = shift;
+ my $err = shift;
+ {
+ local($!);
+ my $title = ref($sock).": ";
+ $@ = join("", $_[0] =~ /^$title/ ? "" : $title, @_);
+ $sock->close()
+ if(defined fileno($sock));
+ }
+ $! = $err;
+ return undef;
+}
+
+sub _get_addr {
+ my($sock,$addr_str, $multi) = @_;
+ my @addr;
+ if ($multi && $addr_str !~ /^\d+(?:\.\d+){3}$/) {
+ (undef, undef, undef, undef, @addr) = gethostbyname($addr_str);
+ } else {
+ my $h = inet_aton($addr_str);
+ push(@addr, $h) if defined $h;
+ }
+ @addr;
+}
+
+sub configure {
+ my($sock,$arg) = @_;
+ my($lport,$rport,$laddr,$raddr,$proto,$type);
+
+
+ $arg->{LocalAddr} = $arg->{LocalHost}
+ if exists $arg->{LocalHost} && !exists $arg->{LocalAddr};
+
+ ($laddr,$lport,$proto) = _sock_info($arg->{LocalAddr},
+ $arg->{LocalPort},
+ $arg->{Proto})
+ or return _error($sock, $!, $@);
+
+ $laddr = defined $laddr ? inet_aton($laddr)
+ : INADDR_ANY;
+
+ return _error($sock, $EINVAL, "Bad hostname '",$arg->{LocalAddr},"'")
+ unless(defined $laddr);
+
+ $arg->{PeerAddr} = $arg->{PeerHost}
+ if exists $arg->{PeerHost} && !exists $arg->{PeerAddr};
+
+ unless(exists $arg->{Listen}) {
+ ($raddr,$rport,$proto) = _sock_info($arg->{PeerAddr},
+ $arg->{PeerPort},
+ $proto)
+ or return _error($sock, $!, $@);
+ }
+
+ $proto ||= _get_proto_number('tcp');
+
+ $type = $arg->{Type} || $socket_type{lc _get_proto_name($proto)};
+
+ my @raddr = ();
+
+ if(defined $raddr) {
+ @raddr = $sock->_get_addr($raddr, $arg->{MultiHomed});
+ return _error($sock, $EINVAL, "Bad hostname '",$arg->{PeerAddr},"'")
+ unless @raddr;
+ }
+
+ while(1) {
+
+ $sock->socket(AF_INET, $type, $proto) or
+ return _error($sock, $!, "$!");
+
+ if (defined $arg->{Blocking}) {
+ defined $sock->blocking($arg->{Blocking})
+ or return _error($sock, $!, "$!");
+ }
+
+ if ($arg->{Reuse} || $arg->{ReuseAddr}) {
+ $sock->sockopt(SO_REUSEADDR,1) or
+ return _error($sock, $!, "$!");
+ }
+
+ if ($arg->{ReusePort}) {
+ $sock->sockopt(SO_REUSEPORT,1) or
+ return _error($sock, $!, "$!");
+ }
+
+ if ($arg->{Broadcast}) {
+ $sock->sockopt(SO_BROADCAST,1) or
+ return _error($sock, $!, "$!");
+ }
+
+ if($lport || ($laddr ne INADDR_ANY) || exists $arg->{Listen}) {
+ $sock->bind($lport || 0, $laddr) or
+ return _error($sock, $!, "$!");
+ }
+
+ if(exists $arg->{Listen}) {
+ $sock->listen($arg->{Listen} || 5) or
+ return _error($sock, $!, "$!");
+ last;
+ }
+
+ # don't try to connect unless we're given a PeerAddr
+ last unless exists($arg->{PeerAddr});
+
+ $raddr = shift @raddr;
+
+ return _error($sock, $EINVAL, 'Cannot determine remote port')
+ unless($rport || $type == SOCK_DGRAM || $type == SOCK_RAW);
+
+ last
+ unless($type == SOCK_STREAM || defined $raddr);
+
+ return _error($sock, $EINVAL, "Bad hostname '",$arg->{PeerAddr},"'")
+ unless defined $raddr;
+
+# my $timeout = ${*$sock}{'io_socket_timeout'};
+# my $before = time() if $timeout;
+
+ undef $@;
+ if ($sock->connect(pack_sockaddr_in($rport, $raddr))) {
+# ${*$sock}{'io_socket_timeout'} = $timeout;
+ return $sock;
+ }
+
+ return _error($sock, $!, $@ || "Timeout")
+ unless @raddr;
+
+# if ($timeout) {
+# my $new_timeout = $timeout - (time() - $before);
+# return _error($sock,
+# (exists(&Errno::ETIMEDOUT) ? Errno::ETIMEDOUT() : $EINVAL),
+# "Timeout") if $new_timeout <= 0;
+# ${*$sock}{'io_socket_timeout'} = $new_timeout;
+# }
+
+ }
+
+ $sock;
+}
+
+sub connect {
+ @_ == 2 || @_ == 3 or
+ croak 'usage: $sock->connect(NAME) or $sock->connect(PORT, ADDR)';
+ my $sock = shift;
+ return $sock->SUPER::connect(@_ == 1 ? shift : pack_sockaddr_in(@_));
+}
+
+sub bind {
+ @_ == 2 || @_ == 3 or
+ croak 'usage: $sock->bind(NAME) or $sock->bind(PORT, ADDR)';
+ my $sock = shift;
+ return $sock->SUPER::bind(@_ == 1 ? shift : pack_sockaddr_in(@_))
+}
+
+sub sockaddr {
+ @_ == 1 or croak 'usage: $sock->sockaddr()';
+ my($sock) = @_;
+ my $name = $sock->sockname;
+ $name ? (sockaddr_in($name))[1] : undef;
+}
+
+sub sockport {
+ @_ == 1 or croak 'usage: $sock->sockport()';
+ my($sock) = @_;
+ my $name = $sock->sockname;
+ $name ? (sockaddr_in($name))[0] : undef;
+}
+
+sub sockhost {
+ @_ == 1 or croak 'usage: $sock->sockhost()';
+ my($sock) = @_;
+ my $addr = $sock->sockaddr;
+ $addr ? inet_ntoa($addr) : undef;
+}
+
+sub peeraddr {
+ @_ == 1 or croak 'usage: $sock->peeraddr()';
+ my($sock) = @_;
+ my $name = $sock->peername;
+ $name ? (sockaddr_in($name))[1] : undef;
+}
+
+sub peerport {
+ @_ == 1 or croak 'usage: $sock->peerport()';
+ my($sock) = @_;
+ my $name = $sock->peername;
+ $name ? (sockaddr_in($name))[0] : undef;
+}
+
+sub peerhost {
+ @_ == 1 or croak 'usage: $sock->peerhost()';
+ my($sock) = @_;
+ my $addr = $sock->peeraddr;
+ $addr ? inet_ntoa($addr) : undef;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+IO::Socket::INET - Object interface for AF_INET domain sockets
+
+=head1 SYNOPSIS
+
+ use IO::Socket::INET;
+
+=head1 DESCRIPTION
+
+C<IO::Socket::INET> provides an object interface to creating and using sockets
+in the AF_INET domain. It is built upon the L<IO::Socket> interface and
+inherits all the methods defined by L<IO::Socket>.
+
+=head1 CONSTRUCTOR
+
+=over 4
+
+=item new ( [ARGS] )
+
+Creates an C<IO::Socket::INET> object, which is a reference to a
+newly created symbol (see the C<Symbol> package). C<new>
+optionally takes arguments, these arguments are in key-value pairs.
+
+In addition to the key-value pairs accepted by L<IO::Socket>,
+C<IO::Socket::INET> provides.
+
+
+ PeerAddr Remote host address <hostname>[:<port>]
+ PeerHost Synonym for PeerAddr
+ PeerPort Remote port or service <service>[(<no>)] | <no>
+ LocalAddr Local host bind address hostname[:port]
+ LocalHost Synonym for LocalAddr
+ LocalPort Local host bind port <service>[(<no>)] | <no>
+ Proto Protocol name (or number) "tcp" | "udp" | ...
+ Type Socket type SOCK_STREAM | SOCK_DGRAM | ...
+ Listen Queue size for listen
+ ReuseAddr Set SO_REUSEADDR before binding
+ Reuse Set SO_REUSEADDR before binding (deprecated, prefer ReuseAddr)
+ ReusePort Set SO_REUSEPORT before binding
+ Broadcast Set SO_BROADCAST before binding
+ Timeout Timeout value for various operations
+ MultiHomed Try all addresses for multi-homed hosts
+ Blocking Determine if connection will be blocking mode
+
+If C<Listen> is defined then a listen socket is created, else if the
+socket type, which is derived from the protocol, is SOCK_STREAM then
+connect() is called.
+
+Although it is not illegal, the use of C<MultiHomed> on a socket
+which is in non-blocking mode is of little use. This is because the
+first connect will never fail with a timeout as the connect call
+will not block.
+
+The C<PeerAddr> can be a hostname or the IP-address on the
+"xx.xx.xx.xx" form. The C<PeerPort> can be a number or a symbolic
+service name. The service name might be followed by a number in
+parenthesis which is used if the service is not known by the system.
+The C<PeerPort> specification can also be embedded in the C<PeerAddr>
+by preceding it with a ":".
+
+If C<Proto> is not given and you specify a symbolic C<PeerPort> port,
+then the constructor will try to derive C<Proto> from the service
+name. As a last resort C<Proto> "tcp" is assumed. The C<Type>
+parameter will be deduced from C<Proto> if not specified.
+
+If the constructor is only passed a single argument, it is assumed to
+be a C<PeerAddr> specification.
+
+If C<Blocking> is set to 0, the connection will be in nonblocking mode.
+If not specified it defaults to 1 (blocking mode).
+
+Examples:
+
+ $sock = IO::Socket::INET->new(PeerAddr => 'www.perl.org',
+ PeerPort => 'http(80)',
+ Proto => 'tcp');
+
+ $sock = IO::Socket::INET->new(PeerAddr => 'localhost:smtp(25)');
+
+ $sock = IO::Socket::INET->new(Listen => 5,
+ LocalAddr => 'localhost',
+ LocalPort => 9000,
+ Proto => 'tcp');
+
+ $sock = IO::Socket::INET->new('127.0.0.1:25');
+
+ $sock = IO::Socket::INET->new(PeerPort => 9999,
+ PeerAddr => inet_ntoa(INADDR_BROADCAST),
+ Proto => udp,
+ LocalAddr => 'localhost',
+ Broadcast => 1 )
+ or die "Can't bind : $@\n";
+
+ NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
+
+As of VERSION 1.18 all IO::Socket objects have autoflush turned on
+by default. This was not the case with earlier releases.
+
+ NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
+
+=back
+
+=head2 METHODS
+
+=over 4
+
+=item sockaddr ()
+
+Return the address part of the sockaddr structure for the socket
+
+=item sockport ()
+
+Return the port number that the socket is using on the local host
+
+=item sockhost ()
+
+Return the address part of the sockaddr structure for the socket in a
+text form xx.xx.xx.xx
+
+=item peeraddr ()
+
+Return the address part of the sockaddr structure for the socket on
+the peer host
+
+=item peerport ()
+
+Return the port number for the socket on the peer host.
+
+=item peerhost ()
+
+Return the address part of the sockaddr structure for the socket on the
+peer host in a text form xx.xx.xx.xx
+
+=back
+
+=head1 SEE ALSO
+
+L<Socket>, L<IO::Socket>
+
+=head1 AUTHOR
+
+Graham Barr. Currently maintained by the Perl Porters. Please report all
+bugs to <perl5-porters@perl.org>.
+
+=head1 COPYRIGHT
+
+Copyright (c) 1996-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/IO/Socket/UNIX.pm b/Master/tlpkg/tlperl/lib/IO/Socket/UNIX.pm
new file mode 100644
index 00000000000..baa092ba1fb
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Socket/UNIX.pm
@@ -0,0 +1,143 @@
+# IO::Socket::UNIX.pm
+#
+# Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
+# This program is free software; you can redistribute it and/or
+# modify it under the same terms as Perl itself.
+
+package IO::Socket::UNIX;
+
+use strict;
+our(@ISA, $VERSION);
+use IO::Socket;
+use Carp;
+
+@ISA = qw(IO::Socket);
+$VERSION = "1.23";
+$VERSION = eval $VERSION;
+
+IO::Socket::UNIX->register_domain( AF_UNIX );
+
+sub new {
+ my $class = shift;
+ unshift(@_, "Peer") if @_ == 1;
+ return $class->SUPER::new(@_);
+}
+
+sub configure {
+ my($sock,$arg) = @_;
+ my($bport,$cport);
+
+ my $type = $arg->{Type} || SOCK_STREAM;
+
+ $sock->socket(AF_UNIX, $type, 0) or
+ return undef;
+
+ if(exists $arg->{Local}) {
+ my $addr = sockaddr_un($arg->{Local});
+ $sock->bind($addr) or
+ return undef;
+ }
+ if(exists $arg->{Listen} && $type != SOCK_DGRAM) {
+ $sock->listen($arg->{Listen} || 5) or
+ return undef;
+ }
+ elsif(exists $arg->{Peer}) {
+ my $addr = sockaddr_un($arg->{Peer});
+ $sock->connect($addr) or
+ return undef;
+ }
+
+ $sock;
+}
+
+sub hostpath {
+ @_ == 1 or croak 'usage: $sock->hostpath()';
+ my $n = $_[0]->sockname || return undef;
+ (sockaddr_un($n))[0];
+}
+
+sub peerpath {
+ @_ == 1 or croak 'usage: $sock->peerpath()';
+ my $n = $_[0]->peername || return undef;
+ (sockaddr_un($n))[0];
+}
+
+1; # Keep require happy
+
+__END__
+
+=head1 NAME
+
+IO::Socket::UNIX - Object interface for AF_UNIX domain sockets
+
+=head1 SYNOPSIS
+
+ use IO::Socket::UNIX;
+
+=head1 DESCRIPTION
+
+C<IO::Socket::UNIX> provides an object interface to creating and using sockets
+in the AF_UNIX domain. It is built upon the L<IO::Socket> interface and
+inherits all the methods defined by L<IO::Socket>.
+
+=head1 CONSTRUCTOR
+
+=over 4
+
+=item new ( [ARGS] )
+
+Creates an C<IO::Socket::UNIX> object, which is a reference to a
+newly created symbol (see the C<Symbol> package). C<new>
+optionally takes arguments, these arguments are in key-value pairs.
+
+In addition to the key-value pairs accepted by L<IO::Socket>,
+C<IO::Socket::UNIX> provides.
+
+ Type Type of socket (eg SOCK_STREAM or SOCK_DGRAM)
+ Local Path to local fifo
+ Peer Path to peer fifo
+ Listen Create a listen socket
+
+If the constructor is only passed a single argument, it is assumed to
+be a C<Peer> specification.
+
+
+ NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
+
+As of VERSION 1.18 all IO::Socket objects have autoflush turned on
+by default. This was not the case with earlier releases.
+
+ NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item hostpath()
+
+Returns the pathname to the fifo at the local end
+
+=item peerpath()
+
+Returns the pathanme to the fifo at the peer end
+
+=back
+
+=head1 SEE ALSO
+
+L<Socket>, L<IO::Socket>
+
+=head1 AUTHOR
+
+Graham Barr. Currently maintained by the Perl Porters. Please report all
+bugs to <perl5-porters@perl.org>.
+
+=head1 COPYRIGHT
+
+Copyright (c) 1996-8 Graham Barr <gbarr@pobox.com>. All rights reserved.
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/IO/Uncompress/Adapter/Bunzip2.pm b/Master/tlpkg/tlperl/lib/IO/Uncompress/Adapter/Bunzip2.pm
new file mode 100644
index 00000000000..98677e3c09f
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Uncompress/Adapter/Bunzip2.pm
@@ -0,0 +1,112 @@
+package IO::Uncompress::Adapter::Bunzip2;
+
+use strict;
+use warnings;
+use bytes;
+
+use IO::Compress::Base::Common 2.024 qw(:Status);
+
+use Compress::Raw::Bzip2 2.024 ;
+
+our ($VERSION, @ISA);
+$VERSION = '2.024';
+
+sub mkUncompObject
+{
+ my $small = shift || 0;
+ my $verbosity = shift || 0;
+
+ my ($inflate, $status) = new Compress::Raw::Bunzip2(1, 1, $small, $verbosity, 1);
+
+ return (undef, "Could not create Inflation object: $status", $status)
+ if $status != BZ_OK ;
+
+ return bless {'Inf' => $inflate,
+ 'CompSize' => 0,
+ 'UnCompSize' => 0,
+ 'Error' => '',
+ 'ConsumesInput' => 1,
+ } ;
+
+}
+
+sub uncompr
+{
+ my $self = shift ;
+ my $from = shift ;
+ my $to = shift ;
+ my $eof = shift ;
+
+ my $inf = $self->{Inf};
+
+ my $status = $inf->bzinflate($from, $to);
+ $self->{ErrorNo} = $status;
+
+ if ($status != BZ_OK && $status != BZ_STREAM_END )
+ {
+ $self->{Error} = "Inflation Error: $status";
+ return STATUS_ERROR;
+ }
+
+
+ return STATUS_OK if $status == BZ_OK ;
+ return STATUS_ENDSTREAM if $status == BZ_STREAM_END ;
+ return STATUS_ERROR ;
+}
+
+
+sub reset
+{
+ my $self = shift ;
+
+ my ($inf, $status) = new Compress::Raw::Bunzip2();
+ $self->{ErrorNo} = ($status == BZ_OK) ? 0 : $status ;
+
+ if ($status != BZ_OK)
+ {
+ $self->{Error} = "Cannot create Inflate object: $status";
+ return STATUS_ERROR;
+ }
+
+ $self->{Inf} = $inf;
+
+ return STATUS_OK ;
+}
+
+sub compressedBytes
+{
+ my $self = shift ;
+ $self->{Inf}->compressedBytes();
+}
+
+sub uncompressedBytes
+{
+ my $self = shift ;
+ $self->{Inf}->uncompressedBytes();
+}
+
+sub crc32
+{
+ my $self = shift ;
+ #$self->{Inf}->crc32();
+}
+
+sub adler32
+{
+ my $self = shift ;
+ #$self->{Inf}->adler32();
+}
+
+sub sync
+{
+ my $self = shift ;
+ #( $self->{Inf}->inflateSync(@_) == BZ_OK)
+ # ? STATUS_OK
+ # : STATUS_ERROR ;
+}
+
+
+1;
+
+__END__
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Uncompress/Adapter/Identity.pm b/Master/tlpkg/tlperl/lib/IO/Uncompress/Adapter/Identity.pm
new file mode 100644
index 00000000000..27de6e0f36b
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Uncompress/Adapter/Identity.pm
@@ -0,0 +1,105 @@
+package IO::Uncompress::Adapter::Identity;
+
+use warnings;
+use strict;
+use bytes;
+
+use IO::Compress::Base::Common 2.024 qw(:Status);
+
+our ($VERSION);
+
+$VERSION = '2.024';
+
+use Compress::Raw::Zlib 2.024 ();
+
+sub mkUncompObject
+{
+ my $crc32 = 1; #shift ;
+ my $adler32 = shift;
+
+ bless { 'CompSize' => 0,
+ 'UnCompSize' => 0,
+ 'wantCRC32' => $crc32,
+ 'CRC32' => Compress::Raw::Zlib::crc32(''),
+ 'wantADLER32'=> $adler32,
+ 'ADLER32' => Compress::Raw::Zlib::adler32(''),
+ 'ConsumesInput' => 1,
+
+ } ;
+}
+
+sub uncompr
+{
+ my $self = shift;
+ my $eof = $_[2];
+
+ if (defined ${ $_[0] } && length ${ $_[0] }) {
+ $self->{CompSize} += length ${ $_[0] } ;
+ $self->{UnCompSize} = $self->{CompSize} ;
+
+ $self->{CRC32} = Compress::Raw::Zlib::crc32($_[0], $self->{CRC32})
+ if $self->{wantCRC32};
+
+ $self->{ADLER32} = Compress::Zlib::adler32($_[0], $self->{ADLER32})
+ if $self->{wantADLER32};
+
+ ${ $_[1] } .= ${ $_[0] };
+ ${ $_[0] } = "";
+ }
+
+ return STATUS_ENDSTREAM if $eof;
+ return STATUS_OK ;
+}
+
+sub reset
+{
+ my $self = shift;
+
+ $self->{CompSize} = 0;
+ $self->{UnCompSize} = 0;
+ $self->{CRC32} = Compress::Raw::Zlib::crc32('');
+ $self->{ADLER32} = Compress::Raw::Zlib::adler32('');
+
+ return STATUS_OK ;
+}
+
+
+#sub count
+#{
+# my $self = shift ;
+# return $self->{UnCompSize} ;
+#}
+
+sub compressedBytes
+{
+ my $self = shift ;
+ return $self->{UnCompSize} ;
+}
+
+sub uncompressedBytes
+{
+ my $self = shift ;
+ return $self->{UnCompSize} ;
+}
+
+sub sync
+{
+ return STATUS_OK ;
+}
+
+sub crc32
+{
+ my $self = shift ;
+ return $self->{CRC32};
+}
+
+sub adler32
+{
+ my $self = shift ;
+ return $self->{ADLER32};
+}
+
+
+1;
+
+__END__
diff --git a/Master/tlpkg/tlperl/lib/IO/Uncompress/Adapter/Inflate.pm b/Master/tlpkg/tlperl/lib/IO/Uncompress/Adapter/Inflate.pm
new file mode 100644
index 00000000000..aac1e413ffe
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Uncompress/Adapter/Inflate.pm
@@ -0,0 +1,158 @@
+package IO::Uncompress::Adapter::Inflate;
+
+use strict;
+use warnings;
+use bytes;
+
+use IO::Compress::Base::Common 2.024 qw(:Status);
+use Compress::Raw::Zlib 2.024 qw(Z_OK Z_BUF_ERROR Z_STREAM_END Z_FINISH MAX_WBITS);
+
+our ($VERSION);
+$VERSION = '2.024';
+
+
+
+sub mkUncompObject
+{
+ my $crc32 = shift || 1;
+ my $adler32 = shift || 1;
+ my $scan = shift || 0;
+
+ my $inflate ;
+ my $status ;
+
+ if ($scan)
+ {
+ ($inflate, $status) = new Compress::Raw::Zlib::InflateScan
+ #LimitOutput => 1,
+ CRC32 => $crc32,
+ ADLER32 => $adler32,
+ WindowBits => - MAX_WBITS ;
+ }
+ else
+ {
+ ($inflate, $status) = new Compress::Raw::Zlib::Inflate
+ AppendOutput => 1,
+ LimitOutput => 1,
+ CRC32 => $crc32,
+ ADLER32 => $adler32,
+ WindowBits => - MAX_WBITS ;
+ }
+
+ return (undef, "Could not create Inflation object: $status", $status)
+ if $status != Z_OK ;
+
+ return bless {'Inf' => $inflate,
+ 'CompSize' => 0,
+ 'UnCompSize' => 0,
+ 'Error' => '',
+ 'ConsumesInput' => 1,
+ } ;
+
+}
+
+sub uncompr
+{
+ my $self = shift ;
+ my $from = shift ;
+ my $to = shift ;
+ my $eof = shift ;
+
+ my $inf = $self->{Inf};
+
+ my $status = $inf->inflate($from, $to, $eof);
+ $self->{ErrorNo} = $status;
+
+ if ($status != Z_OK && $status != Z_STREAM_END && $status != Z_BUF_ERROR)
+ {
+ $self->{Error} = "Inflation Error: $status";
+ return STATUS_ERROR;
+ }
+
+ return STATUS_OK if $status == Z_BUF_ERROR ; # ???
+ return STATUS_OK if $status == Z_OK ;
+ return STATUS_ENDSTREAM if $status == Z_STREAM_END ;
+ return STATUS_ERROR ;
+}
+
+sub reset
+{
+ my $self = shift ;
+ $self->{Inf}->inflateReset();
+
+ return STATUS_OK ;
+}
+
+#sub count
+#{
+# my $self = shift ;
+# $self->{Inf}->inflateCount();
+#}
+
+sub crc32
+{
+ my $self = shift ;
+ $self->{Inf}->crc32();
+}
+
+sub compressedBytes
+{
+ my $self = shift ;
+ $self->{Inf}->compressedBytes();
+}
+
+sub uncompressedBytes
+{
+ my $self = shift ;
+ $self->{Inf}->uncompressedBytes();
+}
+
+sub adler32
+{
+ my $self = shift ;
+ $self->{Inf}->adler32();
+}
+
+sub sync
+{
+ my $self = shift ;
+ ( $self->{Inf}->inflateSync(@_) == Z_OK)
+ ? STATUS_OK
+ : STATUS_ERROR ;
+}
+
+
+sub getLastBlockOffset
+{
+ my $self = shift ;
+ $self->{Inf}->getLastBlockOffset();
+}
+
+sub getEndOffset
+{
+ my $self = shift ;
+ $self->{Inf}->getEndOffset();
+}
+
+sub resetLastBlockByte
+{
+ my $self = shift ;
+ $self->{Inf}->resetLastBlockByte(@_);
+}
+
+sub createDeflateStream
+{
+ my $self = shift ;
+ my $deflate = $self->{Inf}->createDeflateStream(@_);
+ return bless {'Def' => $deflate,
+ 'CompSize' => 0,
+ 'UnCompSize' => 0,
+ 'Error' => '',
+ }, 'IO::Compress::Adapter::Deflate';
+}
+
+1;
+
+
+__END__
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Uncompress/AnyInflate.pm b/Master/tlpkg/tlperl/lib/IO/Uncompress/AnyInflate.pm
new file mode 100644
index 00000000000..68038f5d374
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Uncompress/AnyInflate.pm
@@ -0,0 +1,987 @@
+package IO::Uncompress::AnyInflate ;
+
+# for RFC1950, RFC1951 or RFC1952
+
+use strict;
+use warnings;
+use bytes;
+
+use IO::Compress::Base::Common 2.024 qw(createSelfTiedObject);
+
+use IO::Uncompress::Adapter::Inflate 2.024 ();
+
+
+use IO::Uncompress::Base 2.024 ;
+use IO::Uncompress::Gunzip 2.024 ;
+use IO::Uncompress::Inflate 2.024 ;
+use IO::Uncompress::RawInflate 2.024 ;
+use IO::Uncompress::Unzip 2.024 ;
+
+require Exporter ;
+
+our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $AnyInflateError);
+
+$VERSION = '2.024';
+$AnyInflateError = '';
+
+@ISA = qw( Exporter IO::Uncompress::Base );
+@EXPORT_OK = qw( $AnyInflateError anyinflate ) ;
+%EXPORT_TAGS = %IO::Uncompress::Base::DEFLATE_CONSTANTS ;
+push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
+Exporter::export_ok_tags('all');
+
+# TODO - allow the user to pick a set of the three formats to allow
+# or just assume want to auto-detect any of the three formats.
+
+sub new
+{
+ my $class = shift ;
+ my $obj = createSelfTiedObject($class, \$AnyInflateError);
+ $obj->_create(undef, 0, @_);
+}
+
+sub anyinflate
+{
+ my $obj = createSelfTiedObject(undef, \$AnyInflateError);
+ return $obj->_inf(@_) ;
+}
+
+sub getExtraParams
+{
+ use IO::Compress::Base::Common 2.024 qw(:Parse);
+ return ( 'RawInflate' => [1, 1, Parse_boolean, 0] ) ;
+}
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ # any always needs both crc32 and adler32
+ $got->value('CRC32' => 1);
+ $got->value('ADLER32' => 1);
+
+ return 1;
+}
+
+sub mkUncomp
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ my ($obj, $errstr, $errno) = IO::Uncompress::Adapter::Inflate::mkUncompObject();
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ *$self->{Uncomp} = $obj;
+
+ my @possible = qw( Inflate Gunzip Unzip );
+ unshift @possible, 'RawInflate'
+ if 1 || $got->value('RawInflate');
+
+ my $magic = $self->ckMagic( @possible );
+
+ if ($magic) {
+ *$self->{Info} = $self->readHeader($magic)
+ or return undef ;
+
+ return 1;
+ }
+
+ return 0 ;
+}
+
+
+
+sub ckMagic
+{
+ my $self = shift;
+ my @names = @_ ;
+
+ my $keep = ref $self ;
+ for my $class ( map { "IO::Uncompress::$_" } @names)
+ {
+ bless $self => $class;
+ my $magic = $self->ckMagic();
+
+ if ($magic)
+ {
+ #bless $self => $class;
+ return $magic ;
+ }
+
+ $self->pushBack(*$self->{HeaderPending}) ;
+ *$self->{HeaderPending} = '' ;
+ }
+
+ bless $self => $keep;
+ return undef;
+}
+
+1 ;
+
+__END__
+
+
+=head1 NAME
+
+IO::Uncompress::AnyInflate - Uncompress zlib-based (zip, gzip) file/buffer
+
+=head1 SYNOPSIS
+
+ use IO::Uncompress::AnyInflate qw(anyinflate $AnyInflateError) ;
+
+ my $status = anyinflate $input => $output [,OPTS]
+ or die "anyinflate failed: $AnyInflateError\n";
+
+ my $z = new IO::Uncompress::AnyInflate $input [OPTS]
+ or die "anyinflate failed: $AnyInflateError\n";
+
+ $status = $z->read($buffer)
+ $status = $z->read($buffer, $length)
+ $status = $z->read($buffer, $length, $offset)
+ $line = $z->getline()
+ $char = $z->getc()
+ $char = $z->ungetc()
+ $char = $z->opened()
+
+ $status = $z->inflateSync()
+
+ $data = $z->trailingData()
+ $status = $z->nextStream()
+ $data = $z->getHeaderInfo()
+ $z->tell()
+ $z->seek($position, $whence)
+ $z->binmode()
+ $z->fileno()
+ $z->eof()
+ $z->close()
+
+ $AnyInflateError ;
+
+ # IO::File mode
+
+ <$z>
+ read($z, $buffer);
+ read($z, $buffer, $length);
+ read($z, $buffer, $length, $offset);
+ tell($z)
+ seek($z, $position, $whence)
+ binmode($z)
+ fileno($z)
+ eof($z)
+ close($z)
+
+=head1 DESCRIPTION
+
+This module provides a Perl interface that allows the reading of
+files/buffers that have been compressed in a number of formats that use the
+zlib compression library.
+
+The formats supported are
+
+=over 5
+
+=item RFC 1950
+
+=item RFC 1951 (optionally)
+
+=item gzip (RFC 1952)
+
+=item zip
+
+=back
+
+The module will auto-detect which, if any, of the supported
+compression formats is being used.
+
+=head1 Functional Interface
+
+A top-level function, C<anyinflate>, is provided to carry out
+"one-shot" uncompression between buffers and/or files. For finer
+control over the uncompression process, see the L</"OO Interface">
+section.
+
+ use IO::Uncompress::AnyInflate qw(anyinflate $AnyInflateError) ;
+
+ anyinflate $input => $output [,OPTS]
+ or die "anyinflate failed: $AnyInflateError\n";
+
+The functional interface needs Perl5.005 or better.
+
+=head2 anyinflate $input => $output [, OPTS]
+
+C<anyinflate> expects at least two parameters, C<$input> and C<$output>.
+
+=head3 The C<$input> parameter
+
+The parameter, C<$input>, is used to define the source of
+the compressed data.
+
+It can take one of the following forms:
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for reading and the input data
+will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the input data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the input data will be read
+from C<$$input>.
+
+=item An array reference
+
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
+The complete array will be walked to ensure that it only
+contains valid filenames before any data is uncompressed.
+
+=item An Input FileGlob string
+
+If C<$input> is a string that is delimited by the characters "<" and ">"
+C<anyinflate> will assume that it is an I<input fileglob string>. The
+input is the list of files that match the fileglob.
+
+If the fileglob does not match any files ...
+
+See L<File::GlobMapper|File::GlobMapper> for more details.
+
+=back
+
+If the C<$input> parameter is any other type, C<undef> will be returned.
+
+=head3 The C<$output> parameter
+
+The parameter C<$output> is used to control the destination of the
+uncompressed data. This parameter can take one of these forms.
+
+=over 5
+
+=item A filename
+
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the uncompressed
+data will be written to it.
+
+=item A filehandle
+
+If the C<$output> parameter is a filehandle, the uncompressed data
+will be written to it.
+The string '-' can be used as an alias for standard output.
+
+=item A scalar reference
+
+If C<$output> is a scalar reference, the uncompressed data will be
+stored in C<$$output>.
+
+=item An Array Reference
+
+If C<$output> is an array reference, the uncompressed data will be
+pushed onto the array.
+
+=item An Output FileGlob
+
+If C<$output> is a string that is delimited by the characters "<" and ">"
+C<anyinflate> will assume that it is an I<output fileglob string>. The
+output is the list of files that match the fileglob.
+
+When C<$output> is an fileglob string, C<$input> must also be a fileglob
+string. Anything else is an error.
+
+=back
+
+If the C<$output> parameter is any other type, C<undef> will be returned.
+
+=head2 Notes
+
+When C<$input> maps to multiple compressed files/buffers and C<$output> is
+a single file/buffer, after uncompression C<$output> will contain a
+concatenation of all the uncompressed data from each of the input
+files/buffers.
+
+=head2 Optional Parameters
+
+Unless specified below, the optional parameters for C<anyinflate>,
+C<OPTS>, are the same as those used with the OO interface defined in the
+L</"Constructor Options"> section below.
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option applies to any input or output data streams to
+C<anyinflate> that are filehandles.
+
+If C<AutoClose> is specified, and the value is true, it will result in all
+input and/or output filehandles being closed once C<anyinflate> has
+completed.
+
+This parameter defaults to 0.
+
+=item C<< BinModeOut => 0|1 >>
+
+When writing to a file or filehandle, set C<binmode> before writing to the
+file.
+
+Defaults to 0.
+
+=item C<< Append => 0|1 >>
+
+The behaviour of this option is dependent on the type of output data
+stream.
+
+=over 5
+
+=item * A Buffer
+
+If C<Append> is enabled, all uncompressed data will be append to the end of
+the output buffer. Otherwise the output buffer will be cleared before any
+uncompressed data is written to it.
+
+=item * A Filename
+
+If C<Append> is enabled, the file will be opened in append mode. Otherwise
+the contents of the file, if any, will be truncated before any uncompressed
+data is written to it.
+
+=item * A Filehandle
+
+If C<Append> is enabled, the filehandle will be positioned to the end of
+the file via a call to C<seek> before any uncompressed data is
+written to it. Otherwise the file pointer will not be moved.
+
+=back
+
+When C<Append> is specified, and set to true, it will I<append> all uncompressed
+data to the output data stream.
+
+So when the output is a filehandle it will carry out a seek to the eof
+before writing any uncompressed data. If the output is a filename, it will be opened for
+appending. If the output is a buffer, all uncompressed data will be appened to
+the existing buffer.
+
+Conversely when C<Append> is not specified, or it is present and is set to
+false, it will operate as follows.
+
+When the output is a filename, it will truncate the contents of the file
+before writing any uncompressed data. If the output is a filehandle
+its position will not be changed. If the output is a buffer, it will be
+wiped before any uncompressed data is output.
+
+Defaults to 0.
+
+=item C<< MultiStream => 0|1 >>
+
+If the input file/buffer contains multiple compressed data streams, this
+option will uncompress the whole lot as a single data stream.
+
+Defaults to 0.
+
+=item C<< TrailingData => $scalar >>
+
+Returns the data, if any, that is present immediately after the compressed
+data stream once uncompression is complete.
+
+This option can be used when there is useful information immediately
+following the compressed data stream, and you don't know the length of the
+compressed data stream.
+
+If the input is a buffer, C<trailingData> will return everything from the
+end of the compressed data stream to the end of the buffer.
+
+If the input is a filehandle, C<trailingData> will return the data that is
+left in the filehandle input buffer once the end of the compressed data
+stream has been reached. You can then use the filehandle to read the rest
+of the input file.
+
+Don't bother using C<trailingData> if the input is a filename.
+
+If you know the length of the compressed data stream before you start
+uncompressing, you can avoid having to use C<trailingData> by setting the
+C<InputLength> option.
+
+=back
+
+=head2 Examples
+
+To read the contents of the file C<file1.txt.Compressed> and write the
+uncompressed data to the file C<file1.txt>.
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::AnyInflate qw(anyinflate $AnyInflateError) ;
+
+ my $input = "file1.txt.Compressed";
+ my $output = "file1.txt";
+ anyinflate $input => $output
+ or die "anyinflate failed: $AnyInflateError\n";
+
+To read from an existing Perl filehandle, C<$input>, and write the
+uncompressed data to a buffer, C<$buffer>.
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::AnyInflate qw(anyinflate $AnyInflateError) ;
+ use IO::File ;
+
+ my $input = new IO::File "<file1.txt.Compressed"
+ or die "Cannot open 'file1.txt.Compressed': $!\n" ;
+ my $buffer ;
+ anyinflate $input => \$buffer
+ or die "anyinflate failed: $AnyInflateError\n";
+
+To uncompress all files in the directory "/my/home" that match "*.txt.Compressed" and store the compressed data in the same directory
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::AnyInflate qw(anyinflate $AnyInflateError) ;
+
+ anyinflate '</my/home/*.txt.Compressed>' => '</my/home/#1.txt>'
+ or die "anyinflate failed: $AnyInflateError\n";
+
+and if you want to compress each file one at a time, this will do the trick
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::AnyInflate qw(anyinflate $AnyInflateError) ;
+
+ for my $input ( glob "/my/home/*.txt.Compressed" )
+ {
+ my $output = $input;
+ $output =~ s/.Compressed// ;
+ anyinflate $input => $output
+ or die "Error compressing '$input': $AnyInflateError\n";
+ }
+
+=head1 OO Interface
+
+=head2 Constructor
+
+The format of the constructor for IO::Uncompress::AnyInflate is shown below
+
+ my $z = new IO::Uncompress::AnyInflate $input [OPTS]
+ or die "IO::Uncompress::AnyInflate failed: $AnyInflateError\n";
+
+Returns an C<IO::Uncompress::AnyInflate> object on success and undef on failure.
+The variable C<$AnyInflateError> will contain an error message on failure.
+
+If you are running Perl 5.005 or better the object, C<$z>, returned from
+IO::Uncompress::AnyInflate can be used exactly like an L<IO::File|IO::File> filehandle.
+This means that all normal input file operations can be carried out with
+C<$z>. For example, to read a line from a compressed file/buffer you can
+use either of these forms
+
+ $line = $z->getline();
+ $line = <$z>;
+
+The mandatory parameter C<$input> is used to determine the source of the
+compressed data. This parameter can take one of three forms.
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a scalar, it is assumed to be a filename. This
+file will be opened for reading and the compressed data will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the compressed data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the compressed data will be read from
+C<$$output>.
+
+=back
+
+=head2 Constructor Options
+
+The option names defined below are case insensitive and can be optionally
+prefixed by a '-'. So all of the following are valid
+
+ -AutoClose
+ -autoclose
+ AUTOCLOSE
+ autoclose
+
+OPTS is a combination of the following options:
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option is only valid when the C<$input> parameter is a filehandle. If
+specified, and the value is true, it will result in the file being closed once
+either the C<close> method is called or the IO::Uncompress::AnyInflate object is
+destroyed.
+
+This parameter defaults to 0.
+
+=item C<< MultiStream => 0|1 >>
+
+Allows multiple concatenated compressed streams to be treated as a single
+compressed stream. Decompression will stop once either the end of the
+file/buffer is reached, an error is encountered (premature eof, corrupt
+compressed data) or the end of a stream is not immediately followed by the
+start of another stream.
+
+This parameter defaults to 0.
+
+=item C<< Prime => $string >>
+
+This option will uncompress the contents of C<$string> before processing the
+input file/buffer.
+
+This option can be useful when the compressed data is embedded in another
+file/data structure and it is not possible to work out where the compressed
+data begins without having to read the first few bytes. If this is the
+case, the uncompression can be I<primed> with these bytes using this
+option.
+
+=item C<< Transparent => 0|1 >>
+
+If this option is set and the input file/buffer is not compressed data,
+the module will allow reading of it anyway.
+
+In addition, if the input file/buffer does contain compressed data and
+there is non-compressed data immediately following it, setting this option
+will make this module treat the whole file/bufffer as a single data stream.
+
+This option defaults to 1.
+
+=item C<< BlockSize => $num >>
+
+When reading the compressed input data, IO::Uncompress::AnyInflate will read it in
+blocks of C<$num> bytes.
+
+This option defaults to 4096.
+
+=item C<< InputLength => $size >>
+
+When present this option will limit the number of compressed bytes read
+from the input file/buffer to C<$size>. This option can be used in the
+situation where there is useful data directly after the compressed data
+stream and you know beforehand the exact length of the compressed data
+stream.
+
+This option is mostly used when reading from a filehandle, in which case
+the file pointer will be left pointing to the first byte directly after the
+compressed data stream.
+
+This option defaults to off.
+
+=item C<< Append => 0|1 >>
+
+This option controls what the C<read> method does with uncompressed data.
+
+If set to 1, all uncompressed data will be appended to the output parameter
+of the C<read> method.
+
+If set to 0, the contents of the output parameter of the C<read> method
+will be overwritten by the uncompressed data.
+
+Defaults to 0.
+
+=item C<< Strict => 0|1 >>
+
+This option controls whether the extra checks defined below are used when
+carrying out the decompression. When Strict is on, the extra tests are
+carried out, when Strict is off they are not.
+
+The default for this option is off.
+
+If the input is an RFC 1950 data stream, the following will be checked:
+
+=over 5
+
+=item 1
+
+The ADLER32 checksum field must be present.
+
+=item 2
+
+The value of the ADLER32 field read must match the adler32 value of the
+uncompressed data actually contained in the file.
+
+=back
+
+If the input is a gzip (RFC 1952) data stream, the following will be checked:
+
+=over 5
+
+=item 1
+
+If the FHCRC bit is set in the gzip FLG header byte, the CRC16 bytes in the
+header must match the crc16 value of the gzip header actually read.
+
+=item 2
+
+If the gzip header contains a name field (FNAME) it consists solely of ISO
+8859-1 characters.
+
+=item 3
+
+If the gzip header contains a comment field (FCOMMENT) it consists solely
+of ISO 8859-1 characters plus line-feed.
+
+=item 4
+
+If the gzip FEXTRA header field is present it must conform to the sub-field
+structure as defined in RFC 1952.
+
+=item 5
+
+The CRC32 and ISIZE trailer fields must be present.
+
+=item 6
+
+The value of the CRC32 field read must match the crc32 value of the
+uncompressed data actually contained in the gzip file.
+
+=item 7
+
+The value of the ISIZE fields read must match the length of the
+uncompressed data actually read from the file.
+
+=back
+
+=item C<< RawInflate => 0|1 >>
+
+When auto-detecting the compressed format, try to test for raw-deflate (RFC
+1951) content using the C<IO::Uncompress::RawInflate> module.
+
+The reason this is not default behaviour is because RFC 1951 content can
+only be detected by attempting to uncompress it. This process is error
+prone and can result is false positives.
+
+Defaults to 0.
+
+=item C<< ParseExtra => 0|1 >>
+If the gzip FEXTRA header field is present and this option is set, it will
+force the module to check that it conforms to the sub-field structure as
+defined in RFC 1952.
+
+If the C<Strict> is on it will automatically enable this option.
+
+Defaults to 0.
+
+=back
+
+=head2 Examples
+
+TODO
+
+=head1 Methods
+
+=head2 read
+
+Usage is
+
+ $status = $z->read($buffer)
+
+Reads a block of compressed data (the size the the compressed block is
+determined by the C<Buffer> option in the constructor), uncompresses it and
+writes any uncompressed data into C<$buffer>. If the C<Append> parameter is
+set in the constructor, the uncompressed data will be appended to the
+C<$buffer> parameter. Otherwise C<$buffer> will be overwritten.
+
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
+
+=head2 read
+
+Usage is
+
+ $status = $z->read($buffer, $length)
+ $status = $z->read($buffer, $length, $offset)
+
+ $status = read($z, $buffer, $length)
+ $status = read($z, $buffer, $length, $offset)
+
+Attempt to read C<$length> bytes of uncompressed data into C<$buffer>.
+
+The main difference between this form of the C<read> method and the
+previous one, is that this one will attempt to return I<exactly> C<$length>
+bytes. The only circumstances that this function will not is if end-of-file
+or an IO error is encountered.
+
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
+
+=head2 getline
+
+Usage is
+
+ $line = $z->getline()
+ $line = <$z>
+
+Reads a single line.
+
+This method fully supports the use of of the variable C<$/> (or
+C<$INPUT_RECORD_SEPARATOR> or C<$RS> when C<English> is in use) to
+determine what constitutes an end of line. Paragraph mode, record mode and
+file slurp mode are all supported.
+
+=head2 getc
+
+Usage is
+
+ $char = $z->getc()
+
+Read a single character.
+
+=head2 ungetc
+
+Usage is
+
+ $char = $z->ungetc($string)
+
+=head2 inflateSync
+
+Usage is
+
+ $status = $z->inflateSync()
+
+TODO
+
+=head2 getHeaderInfo
+
+Usage is
+
+ $hdr = $z->getHeaderInfo();
+ @hdrs = $z->getHeaderInfo();
+
+This method returns either a hash reference (in scalar context) or a list
+or hash references (in array context) that contains information about each
+of the header fields in the compressed data stream(s).
+
+=head2 tell
+
+Usage is
+
+ $z->tell()
+ tell $z
+
+Returns the uncompressed file offset.
+
+=head2 eof
+
+Usage is
+
+ $z->eof();
+ eof($z);
+
+Returns true if the end of the compressed input stream has been reached.
+
+=head2 seek
+
+ $z->seek($position, $whence);
+ seek($z, $position, $whence);
+
+Provides a sub-set of the C<seek> functionality, with the restriction
+that it is only legal to seek forward in the input file/buffer.
+It is a fatal error to attempt to seek backward.
+
+The C<$whence> parameter takes one the usual values, namely SEEK_SET,
+SEEK_CUR or SEEK_END.
+
+Returns 1 on success, 0 on failure.
+
+=head2 binmode
+
+Usage is
+
+ $z->binmode
+ binmode $z ;
+
+This is a noop provided for completeness.
+
+=head2 opened
+
+ $z->opened()
+
+Returns true if the object currently refers to a opened file/buffer.
+
+=head2 autoflush
+
+ my $prev = $z->autoflush()
+ my $prev = $z->autoflush(EXPR)
+
+If the C<$z> object is associated with a file or a filehandle, this method
+returns the current autoflush setting for the underlying filehandle. If
+C<EXPR> is present, and is non-zero, it will enable flushing after every
+write/print operation.
+
+If C<$z> is associated with a buffer, this method has no effect and always
+returns C<undef>.
+
+B<Note> that the special variable C<$|> B<cannot> be used to set or
+retrieve the autoflush setting.
+
+=head2 input_line_number
+
+ $z->input_line_number()
+ $z->input_line_number(EXPR)
+
+Returns the current uncompressed line number. If C<EXPR> is present it has
+the effect of setting the line number. Note that setting the line number
+does not change the current position within the file/buffer being read.
+
+The contents of C<$/> are used to to determine what constitutes a line
+terminator.
+
+=head2 fileno
+
+ $z->fileno()
+ fileno($z)
+
+If the C<$z> object is associated with a file or a filehandle, C<fileno>
+will return the underlying file descriptor. Once the C<close> method is
+called C<fileno> will return C<undef>.
+
+If the C<$z> object is is associated with a buffer, this method will return
+C<undef>.
+
+=head2 close
+
+ $z->close() ;
+ close $z ;
+
+Closes the output file/buffer.
+
+For most versions of Perl this method will be automatically invoked if
+the IO::Uncompress::AnyInflate object is destroyed (either explicitly or by the
+variable with the reference to the object going out of scope). The
+exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In
+these cases, the C<close> method will be called automatically, but
+not until global destruction of all live objects when the program is
+terminating.
+
+Therefore, if you want your scripts to be able to run on all versions
+of Perl, you should call C<close> explicitly and not rely on automatic
+closing.
+
+Returns true on success, otherwise 0.
+
+If the C<AutoClose> option has been enabled when the IO::Uncompress::AnyInflate
+object was created, and the object is associated with a file, the
+underlying file will also be closed.
+
+=head2 nextStream
+
+Usage is
+
+ my $status = $z->nextStream();
+
+Skips to the next compressed data stream in the input file/buffer. If a new
+compressed data stream is found, the eof marker will be cleared and C<$.>
+will be reset to 0.
+
+Returns 1 if a new stream was found, 0 if none was found, and -1 if an
+error was encountered.
+
+=head2 trailingData
+
+Usage is
+
+ my $data = $z->trailingData();
+
+Returns the data, if any, that is present immediately after the compressed
+data stream once uncompression is complete. It only makes sense to call
+this method once the end of the compressed data stream has been
+encountered.
+
+This option can be used when there is useful information immediately
+following the compressed data stream, and you don't know the length of the
+compressed data stream.
+
+If the input is a buffer, C<trailingData> will return everything from the
+end of the compressed data stream to the end of the buffer.
+
+If the input is a filehandle, C<trailingData> will return the data that is
+left in the filehandle input buffer once the end of the compressed data
+stream has been reached. You can then use the filehandle to read the rest
+of the input file.
+
+Don't bother using C<trailingData> if the input is a filename.
+
+If you know the length of the compressed data stream before you start
+uncompressing, you can avoid having to use C<trailingData> by setting the
+C<InputLength> option in the constructor.
+
+=head1 Importing
+
+No symbolic constants are required by this IO::Uncompress::AnyInflate at present.
+
+=over 5
+
+=item :all
+
+Imports C<anyinflate> and C<$AnyInflateError>.
+Same as doing this
+
+ use IO::Uncompress::AnyInflate qw(anyinflate $AnyInflateError) ;
+
+=back
+
+=head1 EXAMPLES
+
+=head2 Working with Net::FTP
+
+See L<IO::Uncompress::AnyInflate::FAQ|IO::Uncompress::AnyInflate::FAQ/"Compressed files and Net::FTP">
+
+=head1 SEE ALSO
+
+L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Compress::Deflate>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Compress::Bzip2>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Uncompress::AnyUncompress>
+
+L<Compress::Zlib::FAQ|Compress::Zlib::FAQ>
+
+L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
+L<Archive::Tar|Archive::Tar>,
+L<IO::Zlib|IO::Zlib>
+
+For RFC 1950, 1951 and 1952 see
+F<http://www.faqs.org/rfcs/rfc1950.html>,
+F<http://www.faqs.org/rfcs/rfc1951.html> and
+F<http://www.faqs.org/rfcs/rfc1952.html>
+
+The I<zlib> compression library was written by Jean-loup Gailly
+F<gzip@prep.ai.mit.edu> and Mark Adler F<madler@alumni.caltech.edu>.
+
+The primary site for the I<zlib> compression library is
+F<http://www.zlib.org>.
+
+The primary site for gzip is F<http://www.gzip.org>.
+
+=head1 AUTHOR
+
+This module was written by Paul Marquess, F<pmqs@cpan.org>.
+
+=head1 MODIFICATION HISTORY
+
+See the Changes file.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2005-2010 Paul Marquess. All rights reserved.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Uncompress/AnyUncompress.pm b/Master/tlpkg/tlperl/lib/IO/Uncompress/AnyUncompress.pm
new file mode 100644
index 00000000000..5984921e25b
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Uncompress/AnyUncompress.pm
@@ -0,0 +1,1018 @@
+package IO::Uncompress::AnyUncompress ;
+
+use strict;
+use warnings;
+use bytes;
+
+use IO::Compress::Base::Common 2.024 qw(createSelfTiedObject);
+
+use IO::Uncompress::Base 2.024 ;
+
+
+require Exporter ;
+
+our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $AnyUncompressError);
+
+$VERSION = '2.024';
+$AnyUncompressError = '';
+
+@ISA = qw( Exporter IO::Uncompress::Base );
+@EXPORT_OK = qw( $AnyUncompressError anyuncompress ) ;
+%EXPORT_TAGS = %IO::Uncompress::Base::DEFLATE_CONSTANTS ;
+push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
+Exporter::export_ok_tags('all');
+
+# TODO - allow the user to pick a set of the three formats to allow
+# or just assume want to auto-detect any of the three formats.
+
+BEGIN
+{
+ eval ' use IO::Uncompress::Adapter::Inflate 2.024 ;';
+ eval ' use IO::Uncompress::Adapter::Bunzip2 2.024 ;';
+ eval ' use IO::Uncompress::Adapter::LZO 2.024 ;';
+ eval ' use IO::Uncompress::Adapter::Lzf 2.024 ;';
+ eval ' use IO::Uncompress::Adapter::UnLzma 2.020 ;';
+ eval ' use IO::Uncompress::Adapter::UnXz 2.020 ;';
+
+ eval ' use IO::Uncompress::Bunzip2 2.024 ;';
+ eval ' use IO::Uncompress::UnLzop 2.024 ;';
+ eval ' use IO::Uncompress::Gunzip 2.024 ;';
+ eval ' use IO::Uncompress::Inflate 2.024 ;';
+ eval ' use IO::Uncompress::RawInflate 2.024 ;';
+ eval ' use IO::Uncompress::Unzip 2.024 ;';
+ eval ' use IO::Uncompress::UnLzf 2.024 ;';
+ eval ' use IO::Uncompress::UnLzma 2.024 ;';
+ eval ' use IO::Uncompress::UnXz 2.024 ;';
+}
+
+sub new
+{
+ my $class = shift ;
+ my $obj = createSelfTiedObject($class, \$AnyUncompressError);
+ $obj->_create(undef, 0, @_);
+}
+
+sub anyuncompress
+{
+ my $obj = createSelfTiedObject(undef, \$AnyUncompressError);
+ return $obj->_inf(@_) ;
+}
+
+sub getExtraParams
+{
+ use IO::Compress::Base::Common 2.024 qw(:Parse);
+ return ( 'RawInflate' => [1, 1, Parse_boolean, 0] ,
+ 'UnLzma' => [1, 1, Parse_boolean, 0] ) ;
+}
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ # any always needs both crc32 and adler32
+ $got->value('CRC32' => 1);
+ $got->value('ADLER32' => 1);
+
+ return 1;
+}
+
+sub mkUncomp
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ my $magic ;
+
+ # try zlib first
+ if (defined $IO::Uncompress::RawInflate::VERSION )
+ {
+ my ($obj, $errstr, $errno) = IO::Uncompress::Adapter::Inflate::mkUncompObject();
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ *$self->{Uncomp} = $obj;
+
+ my @possible = qw( Inflate Gunzip Unzip );
+ unshift @possible, 'RawInflate'
+ if $got->value('RawInflate');
+
+ $magic = $self->ckMagic( @possible );
+
+ if ($magic) {
+ *$self->{Info} = $self->readHeader($magic)
+ or return undef ;
+
+ return 1;
+ }
+ }
+
+ if (defined $IO::Uncompress::UnLzma::VERSION && $got->value('UnLzma'))
+ {
+ my ($obj, $errstr, $errno) = IO::Uncompress::Adapter::UnLzma::mkUncompObject();
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ *$self->{Uncomp} = $obj;
+
+ my @possible = qw( UnLzma );
+ #unshift @possible, 'RawInflate'
+ # if $got->value('RawInflate');
+
+ if ( *$self->{Info} = $self->ckMagic( @possible ))
+ {
+ return 1;
+ }
+ }
+
+ if (defined $IO::Uncompress::UnXz::VERSION and
+ $magic = $self->ckMagic('UnXz')) {
+ *$self->{Info} = $self->readHeader($magic)
+ or return undef ;
+
+ my ($obj, $errstr, $errno) =
+ IO::Uncompress::Adapter::UnXz::mkUncompObject();
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ *$self->{Uncomp} = $obj;
+
+ return 1;
+ }
+
+ if (defined $IO::Uncompress::Bunzip2::VERSION and
+ $magic = $self->ckMagic('Bunzip2')) {
+ *$self->{Info} = $self->readHeader($magic)
+ or return undef ;
+
+ my ($obj, $errstr, $errno) = IO::Uncompress::Adapter::Bunzip2::mkUncompObject();
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ *$self->{Uncomp} = $obj;
+
+ return 1;
+ }
+
+ if (defined $IO::Uncompress::UnLzop::VERSION and
+ $magic = $self->ckMagic('UnLzop')) {
+
+ *$self->{Info} = $self->readHeader($magic)
+ or return undef ;
+
+ my ($obj, $errstr, $errno) = IO::Uncompress::Adapter::LZO::mkUncompObject();
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ *$self->{Uncomp} = $obj;
+
+ return 1;
+ }
+
+ if (defined $IO::Uncompress::UnLzf::VERSION and
+ $magic = $self->ckMagic('UnLzf')) {
+
+ *$self->{Info} = $self->readHeader($magic)
+ or return undef ;
+
+ my ($obj, $errstr, $errno) = IO::Uncompress::Adapter::Lzf::mkUncompObject();
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ *$self->{Uncomp} = $obj;
+
+ return 1;
+ }
+
+ return 0 ;
+}
+
+
+
+sub ckMagic
+{
+ my $self = shift;
+ my @names = @_ ;
+
+ my $keep = ref $self ;
+ for my $class ( map { "IO::Uncompress::$_" } @names)
+ {
+ bless $self => $class;
+ my $magic = $self->ckMagic();
+
+ if ($magic)
+ {
+ #bless $self => $class;
+ return $magic ;
+ }
+
+ $self->pushBack(*$self->{HeaderPending}) ;
+ *$self->{HeaderPending} = '' ;
+ }
+
+ bless $self => $keep;
+ return undef;
+}
+
+1 ;
+
+__END__
+
+
+=head1 NAME
+
+IO::Uncompress::AnyUncompress - Uncompress gzip, zip, bzip2 or lzop file/buffer
+
+=head1 SYNOPSIS
+
+ use IO::Uncompress::AnyUncompress qw(anyuncompress $AnyUncompressError) ;
+
+ my $status = anyuncompress $input => $output [,OPTS]
+ or die "anyuncompress failed: $AnyUncompressError\n";
+
+ my $z = new IO::Uncompress::AnyUncompress $input [OPTS]
+ or die "anyuncompress failed: $AnyUncompressError\n";
+
+ $status = $z->read($buffer)
+ $status = $z->read($buffer, $length)
+ $status = $z->read($buffer, $length, $offset)
+ $line = $z->getline()
+ $char = $z->getc()
+ $char = $z->ungetc()
+ $char = $z->opened()
+
+ $data = $z->trailingData()
+ $status = $z->nextStream()
+ $data = $z->getHeaderInfo()
+ $z->tell()
+ $z->seek($position, $whence)
+ $z->binmode()
+ $z->fileno()
+ $z->eof()
+ $z->close()
+
+ $AnyUncompressError ;
+
+ # IO::File mode
+
+ <$z>
+ read($z, $buffer);
+ read($z, $buffer, $length);
+ read($z, $buffer, $length, $offset);
+ tell($z)
+ seek($z, $position, $whence)
+ binmode($z)
+ fileno($z)
+ eof($z)
+ close($z)
+
+=head1 DESCRIPTION
+
+This module provides a Perl interface that allows the reading of
+files/buffers that have been compressed with a variety of compression
+libraries.
+
+The formats supported are:
+
+=over 5
+
+=item RFC 1950
+
+=item RFC 1951 (optionally)
+
+=item gzip (RFC 1952)
+
+=item zip
+
+=item bzip2
+
+=item lzop
+
+=item lzf
+
+=item lzma
+
+=item xz
+
+=back
+
+The module will auto-detect which, if any, of the supported
+compression formats is being used.
+
+=head1 Functional Interface
+
+A top-level function, C<anyuncompress>, is provided to carry out
+"one-shot" uncompression between buffers and/or files. For finer
+control over the uncompression process, see the L</"OO Interface">
+section.
+
+ use IO::Uncompress::AnyUncompress qw(anyuncompress $AnyUncompressError) ;
+
+ anyuncompress $input => $output [,OPTS]
+ or die "anyuncompress failed: $AnyUncompressError\n";
+
+The functional interface needs Perl5.005 or better.
+
+=head2 anyuncompress $input => $output [, OPTS]
+
+C<anyuncompress> expects at least two parameters, C<$input> and C<$output>.
+
+=head3 The C<$input> parameter
+
+The parameter, C<$input>, is used to define the source of
+the compressed data.
+
+It can take one of the following forms:
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for reading and the input data
+will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the input data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the input data will be read
+from C<$$input>.
+
+=item An array reference
+
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
+The complete array will be walked to ensure that it only
+contains valid filenames before any data is uncompressed.
+
+=item An Input FileGlob string
+
+If C<$input> is a string that is delimited by the characters "<" and ">"
+C<anyuncompress> will assume that it is an I<input fileglob string>. The
+input is the list of files that match the fileglob.
+
+If the fileglob does not match any files ...
+
+See L<File::GlobMapper|File::GlobMapper> for more details.
+
+=back
+
+If the C<$input> parameter is any other type, C<undef> will be returned.
+
+=head3 The C<$output> parameter
+
+The parameter C<$output> is used to control the destination of the
+uncompressed data. This parameter can take one of these forms.
+
+=over 5
+
+=item A filename
+
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the uncompressed
+data will be written to it.
+
+=item A filehandle
+
+If the C<$output> parameter is a filehandle, the uncompressed data
+will be written to it.
+The string '-' can be used as an alias for standard output.
+
+=item A scalar reference
+
+If C<$output> is a scalar reference, the uncompressed data will be
+stored in C<$$output>.
+
+=item An Array Reference
+
+If C<$output> is an array reference, the uncompressed data will be
+pushed onto the array.
+
+=item An Output FileGlob
+
+If C<$output> is a string that is delimited by the characters "<" and ">"
+C<anyuncompress> will assume that it is an I<output fileglob string>. The
+output is the list of files that match the fileglob.
+
+When C<$output> is an fileglob string, C<$input> must also be a fileglob
+string. Anything else is an error.
+
+=back
+
+If the C<$output> parameter is any other type, C<undef> will be returned.
+
+=head2 Notes
+
+When C<$input> maps to multiple compressed files/buffers and C<$output> is
+a single file/buffer, after uncompression C<$output> will contain a
+concatenation of all the uncompressed data from each of the input
+files/buffers.
+
+=head2 Optional Parameters
+
+Unless specified below, the optional parameters for C<anyuncompress>,
+C<OPTS>, are the same as those used with the OO interface defined in the
+L</"Constructor Options"> section below.
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option applies to any input or output data streams to
+C<anyuncompress> that are filehandles.
+
+If C<AutoClose> is specified, and the value is true, it will result in all
+input and/or output filehandles being closed once C<anyuncompress> has
+completed.
+
+This parameter defaults to 0.
+
+=item C<< BinModeOut => 0|1 >>
+
+When writing to a file or filehandle, set C<binmode> before writing to the
+file.
+
+Defaults to 0.
+
+=item C<< Append => 0|1 >>
+
+The behaviour of this option is dependent on the type of output data
+stream.
+
+=over 5
+
+=item * A Buffer
+
+If C<Append> is enabled, all uncompressed data will be append to the end of
+the output buffer. Otherwise the output buffer will be cleared before any
+uncompressed data is written to it.
+
+=item * A Filename
+
+If C<Append> is enabled, the file will be opened in append mode. Otherwise
+the contents of the file, if any, will be truncated before any uncompressed
+data is written to it.
+
+=item * A Filehandle
+
+If C<Append> is enabled, the filehandle will be positioned to the end of
+the file via a call to C<seek> before any uncompressed data is
+written to it. Otherwise the file pointer will not be moved.
+
+=back
+
+When C<Append> is specified, and set to true, it will I<append> all uncompressed
+data to the output data stream.
+
+So when the output is a filehandle it will carry out a seek to the eof
+before writing any uncompressed data. If the output is a filename, it will be opened for
+appending. If the output is a buffer, all uncompressed data will be appened to
+the existing buffer.
+
+Conversely when C<Append> is not specified, or it is present and is set to
+false, it will operate as follows.
+
+When the output is a filename, it will truncate the contents of the file
+before writing any uncompressed data. If the output is a filehandle
+its position will not be changed. If the output is a buffer, it will be
+wiped before any uncompressed data is output.
+
+Defaults to 0.
+
+=item C<< MultiStream => 0|1 >>
+
+If the input file/buffer contains multiple compressed data streams, this
+option will uncompress the whole lot as a single data stream.
+
+Defaults to 0.
+
+=item C<< TrailingData => $scalar >>
+
+Returns the data, if any, that is present immediately after the compressed
+data stream once uncompression is complete.
+
+This option can be used when there is useful information immediately
+following the compressed data stream, and you don't know the length of the
+compressed data stream.
+
+If the input is a buffer, C<trailingData> will return everything from the
+end of the compressed data stream to the end of the buffer.
+
+If the input is a filehandle, C<trailingData> will return the data that is
+left in the filehandle input buffer once the end of the compressed data
+stream has been reached. You can then use the filehandle to read the rest
+of the input file.
+
+Don't bother using C<trailingData> if the input is a filename.
+
+If you know the length of the compressed data stream before you start
+uncompressing, you can avoid having to use C<trailingData> by setting the
+C<InputLength> option.
+
+=back
+
+=head2 Examples
+
+To read the contents of the file C<file1.txt.Compressed> and write the
+uncompressed data to the file C<file1.txt>.
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::AnyUncompress qw(anyuncompress $AnyUncompressError) ;
+
+ my $input = "file1.txt.Compressed";
+ my $output = "file1.txt";
+ anyuncompress $input => $output
+ or die "anyuncompress failed: $AnyUncompressError\n";
+
+To read from an existing Perl filehandle, C<$input>, and write the
+uncompressed data to a buffer, C<$buffer>.
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::AnyUncompress qw(anyuncompress $AnyUncompressError) ;
+ use IO::File ;
+
+ my $input = new IO::File "<file1.txt.Compressed"
+ or die "Cannot open 'file1.txt.Compressed': $!\n" ;
+ my $buffer ;
+ anyuncompress $input => \$buffer
+ or die "anyuncompress failed: $AnyUncompressError\n";
+
+To uncompress all files in the directory "/my/home" that match "*.txt.Compressed" and store the compressed data in the same directory
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::AnyUncompress qw(anyuncompress $AnyUncompressError) ;
+
+ anyuncompress '</my/home/*.txt.Compressed>' => '</my/home/#1.txt>'
+ or die "anyuncompress failed: $AnyUncompressError\n";
+
+and if you want to compress each file one at a time, this will do the trick
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::AnyUncompress qw(anyuncompress $AnyUncompressError) ;
+
+ for my $input ( glob "/my/home/*.txt.Compressed" )
+ {
+ my $output = $input;
+ $output =~ s/.Compressed// ;
+ anyuncompress $input => $output
+ or die "Error compressing '$input': $AnyUncompressError\n";
+ }
+
+=head1 OO Interface
+
+=head2 Constructor
+
+The format of the constructor for IO::Uncompress::AnyUncompress is shown below
+
+ my $z = new IO::Uncompress::AnyUncompress $input [OPTS]
+ or die "IO::Uncompress::AnyUncompress failed: $AnyUncompressError\n";
+
+Returns an C<IO::Uncompress::AnyUncompress> object on success and undef on failure.
+The variable C<$AnyUncompressError> will contain an error message on failure.
+
+If you are running Perl 5.005 or better the object, C<$z>, returned from
+IO::Uncompress::AnyUncompress can be used exactly like an L<IO::File|IO::File> filehandle.
+This means that all normal input file operations can be carried out with
+C<$z>. For example, to read a line from a compressed file/buffer you can
+use either of these forms
+
+ $line = $z->getline();
+ $line = <$z>;
+
+The mandatory parameter C<$input> is used to determine the source of the
+compressed data. This parameter can take one of three forms.
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a scalar, it is assumed to be a filename. This
+file will be opened for reading and the compressed data will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the compressed data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the compressed data will be read from
+C<$$output>.
+
+=back
+
+=head2 Constructor Options
+
+The option names defined below are case insensitive and can be optionally
+prefixed by a '-'. So all of the following are valid
+
+ -AutoClose
+ -autoclose
+ AUTOCLOSE
+ autoclose
+
+OPTS is a combination of the following options:
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option is only valid when the C<$input> parameter is a filehandle. If
+specified, and the value is true, it will result in the file being closed once
+either the C<close> method is called or the IO::Uncompress::AnyUncompress object is
+destroyed.
+
+This parameter defaults to 0.
+
+=item C<< MultiStream => 0|1 >>
+
+Allows multiple concatenated compressed streams to be treated as a single
+compressed stream. Decompression will stop once either the end of the
+file/buffer is reached, an error is encountered (premature eof, corrupt
+compressed data) or the end of a stream is not immediately followed by the
+start of another stream.
+
+This parameter defaults to 0.
+
+=item C<< Prime => $string >>
+
+This option will uncompress the contents of C<$string> before processing the
+input file/buffer.
+
+This option can be useful when the compressed data is embedded in another
+file/data structure and it is not possible to work out where the compressed
+data begins without having to read the first few bytes. If this is the
+case, the uncompression can be I<primed> with these bytes using this
+option.
+
+=item C<< Transparent => 0|1 >>
+
+If this option is set and the input file/buffer is not compressed data,
+the module will allow reading of it anyway.
+
+In addition, if the input file/buffer does contain compressed data and
+there is non-compressed data immediately following it, setting this option
+will make this module treat the whole file/bufffer as a single data stream.
+
+This option defaults to 1.
+
+=item C<< BlockSize => $num >>
+
+When reading the compressed input data, IO::Uncompress::AnyUncompress will read it in
+blocks of C<$num> bytes.
+
+This option defaults to 4096.
+
+=item C<< InputLength => $size >>
+
+When present this option will limit the number of compressed bytes read
+from the input file/buffer to C<$size>. This option can be used in the
+situation where there is useful data directly after the compressed data
+stream and you know beforehand the exact length of the compressed data
+stream.
+
+This option is mostly used when reading from a filehandle, in which case
+the file pointer will be left pointing to the first byte directly after the
+compressed data stream.
+
+This option defaults to off.
+
+=item C<< Append => 0|1 >>
+
+This option controls what the C<read> method does with uncompressed data.
+
+If set to 1, all uncompressed data will be appended to the output parameter
+of the C<read> method.
+
+If set to 0, the contents of the output parameter of the C<read> method
+will be overwritten by the uncompressed data.
+
+Defaults to 0.
+
+=item C<< Strict => 0|1 >>
+
+This option controls whether the extra checks defined below are used when
+carrying out the decompression. When Strict is on, the extra tests are
+carried out, when Strict is off they are not.
+
+The default for this option is off.
+
+=item C<< RawInflate => 0|1 >>
+
+When auto-detecting the compressed format, try to test for raw-deflate (RFC
+1951) content using the C<IO::Uncompress::RawInflate> module.
+
+The reason this is not default behaviour is because RFC 1951 content can
+only be detected by attempting to uncompress it. This process is error
+prone and can result is false positives.
+
+Defaults to 0.
+
+=item C<< UnLzma => 0|1 >>
+
+When auto-detecting the compressed format, try to test for lzma_alone
+content using the C<IO::Uncompress::UnLzma> module.
+
+The reason this is not default behaviour is because lzma_alone content can
+only be detected by attempting to uncompress it. This process is error
+prone and can result is false positives.
+
+Defaults to 0.
+
+=back
+
+=head2 Examples
+
+TODO
+
+=head1 Methods
+
+=head2 read
+
+Usage is
+
+ $status = $z->read($buffer)
+
+Reads a block of compressed data (the size the the compressed block is
+determined by the C<Buffer> option in the constructor), uncompresses it and
+writes any uncompressed data into C<$buffer>. If the C<Append> parameter is
+set in the constructor, the uncompressed data will be appended to the
+C<$buffer> parameter. Otherwise C<$buffer> will be overwritten.
+
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
+
+=head2 read
+
+Usage is
+
+ $status = $z->read($buffer, $length)
+ $status = $z->read($buffer, $length, $offset)
+
+ $status = read($z, $buffer, $length)
+ $status = read($z, $buffer, $length, $offset)
+
+Attempt to read C<$length> bytes of uncompressed data into C<$buffer>.
+
+The main difference between this form of the C<read> method and the
+previous one, is that this one will attempt to return I<exactly> C<$length>
+bytes. The only circumstances that this function will not is if end-of-file
+or an IO error is encountered.
+
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
+
+=head2 getline
+
+Usage is
+
+ $line = $z->getline()
+ $line = <$z>
+
+Reads a single line.
+
+This method fully supports the use of of the variable C<$/> (or
+C<$INPUT_RECORD_SEPARATOR> or C<$RS> when C<English> is in use) to
+determine what constitutes an end of line. Paragraph mode, record mode and
+file slurp mode are all supported.
+
+=head2 getc
+
+Usage is
+
+ $char = $z->getc()
+
+Read a single character.
+
+=head2 ungetc
+
+Usage is
+
+ $char = $z->ungetc($string)
+
+=head2 getHeaderInfo
+
+Usage is
+
+ $hdr = $z->getHeaderInfo();
+ @hdrs = $z->getHeaderInfo();
+
+This method returns either a hash reference (in scalar context) or a list
+or hash references (in array context) that contains information about each
+of the header fields in the compressed data stream(s).
+
+=head2 tell
+
+Usage is
+
+ $z->tell()
+ tell $z
+
+Returns the uncompressed file offset.
+
+=head2 eof
+
+Usage is
+
+ $z->eof();
+ eof($z);
+
+Returns true if the end of the compressed input stream has been reached.
+
+=head2 seek
+
+ $z->seek($position, $whence);
+ seek($z, $position, $whence);
+
+Provides a sub-set of the C<seek> functionality, with the restriction
+that it is only legal to seek forward in the input file/buffer.
+It is a fatal error to attempt to seek backward.
+
+The C<$whence> parameter takes one the usual values, namely SEEK_SET,
+SEEK_CUR or SEEK_END.
+
+Returns 1 on success, 0 on failure.
+
+=head2 binmode
+
+Usage is
+
+ $z->binmode
+ binmode $z ;
+
+This is a noop provided for completeness.
+
+=head2 opened
+
+ $z->opened()
+
+Returns true if the object currently refers to a opened file/buffer.
+
+=head2 autoflush
+
+ my $prev = $z->autoflush()
+ my $prev = $z->autoflush(EXPR)
+
+If the C<$z> object is associated with a file or a filehandle, this method
+returns the current autoflush setting for the underlying filehandle. If
+C<EXPR> is present, and is non-zero, it will enable flushing after every
+write/print operation.
+
+If C<$z> is associated with a buffer, this method has no effect and always
+returns C<undef>.
+
+B<Note> that the special variable C<$|> B<cannot> be used to set or
+retrieve the autoflush setting.
+
+=head2 input_line_number
+
+ $z->input_line_number()
+ $z->input_line_number(EXPR)
+
+Returns the current uncompressed line number. If C<EXPR> is present it has
+the effect of setting the line number. Note that setting the line number
+does not change the current position within the file/buffer being read.
+
+The contents of C<$/> are used to to determine what constitutes a line
+terminator.
+
+=head2 fileno
+
+ $z->fileno()
+ fileno($z)
+
+If the C<$z> object is associated with a file or a filehandle, C<fileno>
+will return the underlying file descriptor. Once the C<close> method is
+called C<fileno> will return C<undef>.
+
+If the C<$z> object is is associated with a buffer, this method will return
+C<undef>.
+
+=head2 close
+
+ $z->close() ;
+ close $z ;
+
+Closes the output file/buffer.
+
+For most versions of Perl this method will be automatically invoked if
+the IO::Uncompress::AnyUncompress object is destroyed (either explicitly or by the
+variable with the reference to the object going out of scope). The
+exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In
+these cases, the C<close> method will be called automatically, but
+not until global destruction of all live objects when the program is
+terminating.
+
+Therefore, if you want your scripts to be able to run on all versions
+of Perl, you should call C<close> explicitly and not rely on automatic
+closing.
+
+Returns true on success, otherwise 0.
+
+If the C<AutoClose> option has been enabled when the IO::Uncompress::AnyUncompress
+object was created, and the object is associated with a file, the
+underlying file will also be closed.
+
+=head2 nextStream
+
+Usage is
+
+ my $status = $z->nextStream();
+
+Skips to the next compressed data stream in the input file/buffer. If a new
+compressed data stream is found, the eof marker will be cleared and C<$.>
+will be reset to 0.
+
+Returns 1 if a new stream was found, 0 if none was found, and -1 if an
+error was encountered.
+
+=head2 trailingData
+
+Usage is
+
+ my $data = $z->trailingData();
+
+Returns the data, if any, that is present immediately after the compressed
+data stream once uncompression is complete. It only makes sense to call
+this method once the end of the compressed data stream has been
+encountered.
+
+This option can be used when there is useful information immediately
+following the compressed data stream, and you don't know the length of the
+compressed data stream.
+
+If the input is a buffer, C<trailingData> will return everything from the
+end of the compressed data stream to the end of the buffer.
+
+If the input is a filehandle, C<trailingData> will return the data that is
+left in the filehandle input buffer once the end of the compressed data
+stream has been reached. You can then use the filehandle to read the rest
+of the input file.
+
+Don't bother using C<trailingData> if the input is a filename.
+
+If you know the length of the compressed data stream before you start
+uncompressing, you can avoid having to use C<trailingData> by setting the
+C<InputLength> option in the constructor.
+
+=head1 Importing
+
+No symbolic constants are required by this IO::Uncompress::AnyUncompress at present.
+
+=over 5
+
+=item :all
+
+Imports C<anyuncompress> and C<$AnyUncompressError>.
+Same as doing this
+
+ use IO::Uncompress::AnyUncompress qw(anyuncompress $AnyUncompressError) ;
+
+=back
+
+=head1 EXAMPLES
+
+=head1 SEE ALSO
+
+L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Compress::Deflate>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Compress::Bzip2>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Uncompress::AnyInflate>
+
+L<Compress::Zlib::FAQ|Compress::Zlib::FAQ>
+
+L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
+L<Archive::Tar|Archive::Tar>,
+L<IO::Zlib|IO::Zlib>
+
+=head1 AUTHOR
+
+This module was written by Paul Marquess, F<pmqs@cpan.org>.
+
+=head1 MODIFICATION HISTORY
+
+See the Changes file.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2005-2010 Paul Marquess. All rights reserved.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Uncompress/Base.pm b/Master/tlpkg/tlperl/lib/IO/Uncompress/Base.pm
new file mode 100644
index 00000000000..33f2ac23758
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Uncompress/Base.pm
@@ -0,0 +1,1474 @@
+
+package IO::Uncompress::Base ;
+
+use strict ;
+use warnings;
+use bytes;
+
+our (@ISA, $VERSION, @EXPORT_OK, %EXPORT_TAGS);
+@ISA = qw(Exporter IO::File);
+
+
+$VERSION = '2.024';
+
+use constant G_EOF => 0 ;
+use constant G_ERR => -1 ;
+
+use IO::Compress::Base::Common 2.024 ;
+#use Parse::Parameters ;
+
+use IO::File ;
+use Symbol;
+use Scalar::Util qw(readonly);
+use List::Util qw(min);
+use Carp ;
+
+%EXPORT_TAGS = ( );
+push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
+#Exporter::export_ok_tags('all') ;
+
+
+
+sub smartRead
+{
+ my $self = $_[0];
+ my $out = $_[1];
+ my $size = $_[2];
+ $$out = "" ;
+
+ my $offset = 0 ;
+
+
+ if (defined *$self->{InputLength}) {
+ return 0
+ if *$self->{InputLengthRemaining} <= 0 ;
+ $size = min($size, *$self->{InputLengthRemaining});
+ }
+
+ if ( length *$self->{Prime} ) {
+ #$$out = substr(*$self->{Prime}, 0, $size, '') ;
+ $$out = substr(*$self->{Prime}, 0, $size) ;
+ substr(*$self->{Prime}, 0, $size) = '' ;
+ if (length $$out == $size) {
+ *$self->{InputLengthRemaining} -= length $$out
+ if defined *$self->{InputLength};
+
+ return length $$out ;
+ }
+ $offset = length $$out ;
+ }
+
+ my $get_size = $size - $offset ;
+
+ if (defined *$self->{FH}) {
+ if ($offset) {
+ # Not using this
+ #
+ # *$self->{FH}->read($$out, $get_size, $offset);
+ #
+ # because the filehandle may not support the offset parameter
+ # An example is Net::FTP
+ my $tmp = '';
+ *$self->{FH}->read($tmp, $get_size) &&
+ (substr($$out, $offset) = $tmp);
+ }
+ else
+ { *$self->{FH}->read($$out, $get_size) }
+ }
+ elsif (defined *$self->{InputEvent}) {
+ my $got = 1 ;
+ while (length $$out < $size) {
+ last
+ if ($got = *$self->{InputEvent}->($$out, $get_size)) <= 0;
+ }
+
+ if (length $$out > $size ) {
+ #*$self->{Prime} = substr($$out, $size, length($$out), '');
+ *$self->{Prime} = substr($$out, $size, length($$out));
+ substr($$out, $size, length($$out)) = '';
+ }
+
+ *$self->{EventEof} = 1 if $got <= 0 ;
+ }
+ else {
+ no warnings 'uninitialized';
+ my $buf = *$self->{Buffer} ;
+ $$buf = '' unless defined $$buf ;
+ #$$out = '' unless defined $$out ;
+ substr($$out, $offset) = substr($$buf, *$self->{BufferOffset}, $get_size);
+ if (*$self->{ConsumeInput})
+ { substr($$buf, 0, $get_size) = '' }
+ else
+ { *$self->{BufferOffset} += length($$out) - $offset }
+ }
+
+ *$self->{InputLengthRemaining} -= length($$out) #- $offset
+ if defined *$self->{InputLength};
+
+ $self->saveStatus(length $$out < 0 ? STATUS_ERROR : STATUS_OK) ;
+
+ return length $$out;
+}
+
+sub pushBack
+{
+ my $self = shift ;
+
+ return if ! defined $_[0] || length $_[0] == 0 ;
+
+ if (defined *$self->{FH} || defined *$self->{InputEvent} ) {
+ *$self->{Prime} = $_[0] . *$self->{Prime} ;
+ *$self->{InputLengthRemaining} += length($_[0]);
+ }
+ else {
+ my $len = length $_[0];
+
+ if($len > *$self->{BufferOffset}) {
+ *$self->{Prime} = substr($_[0], 0, $len - *$self->{BufferOffset}) . *$self->{Prime} ;
+ *$self->{InputLengthRemaining} = *$self->{InputLength};
+ *$self->{BufferOffset} = 0
+ }
+ else {
+ *$self->{InputLengthRemaining} += length($_[0]);
+ *$self->{BufferOffset} -= length($_[0]) ;
+ }
+ }
+}
+
+sub smartSeek
+{
+ my $self = shift ;
+ my $offset = shift ;
+ my $truncate = shift;
+ #print "smartSeek to $offset\n";
+
+ # TODO -- need to take prime into account
+ if (defined *$self->{FH})
+ { *$self->{FH}->seek($offset, SEEK_SET) }
+ else {
+ *$self->{BufferOffset} = $offset ;
+ substr(${ *$self->{Buffer} }, *$self->{BufferOffset}) = ''
+ if $truncate;
+ return 1;
+ }
+}
+
+sub smartWrite
+{
+ my $self = shift ;
+ my $out_data = shift ;
+
+ if (defined *$self->{FH}) {
+ # flush needed for 5.8.0
+ defined *$self->{FH}->write($out_data, length $out_data) &&
+ defined *$self->{FH}->flush() ;
+ }
+ else {
+ my $buf = *$self->{Buffer} ;
+ substr($$buf, *$self->{BufferOffset}, length $out_data) = $out_data ;
+ *$self->{BufferOffset} += length($out_data) ;
+ return 1;
+ }
+}
+
+sub smartReadExact
+{
+ return $_[0]->smartRead($_[1], $_[2]) == $_[2];
+}
+
+sub smartEof
+{
+ my ($self) = $_[0];
+ local $.;
+
+ return 0 if length *$self->{Prime} || *$self->{PushMode};
+
+ if (defined *$self->{FH})
+ {
+ # Could use
+ #
+ # *$self->{FH}->eof()
+ #
+ # here, but this can cause trouble if
+ # the filehandle is itself a tied handle, but it uses sysread.
+ # Then we get into mixing buffered & non-buffered IO, which will cause trouble
+
+ my $info = $self->getErrInfo();
+
+ my $buffer = '';
+ my $status = $self->smartRead(\$buffer, 1);
+ $self->pushBack($buffer) if length $buffer;
+ $self->setErrInfo($info);
+
+ return $status == 0 ;
+ }
+ elsif (defined *$self->{InputEvent})
+ { *$self->{EventEof} }
+ else
+ { *$self->{BufferOffset} >= length(${ *$self->{Buffer} }) }
+}
+
+sub clearError
+{
+ my $self = shift ;
+
+ *$self->{ErrorNo} = 0 ;
+ ${ *$self->{Error} } = '' ;
+}
+
+sub getErrInfo
+{
+ my $self = shift ;
+
+ return [ *$self->{ErrorNo}, ${ *$self->{Error} } ] ;
+}
+
+sub setErrInfo
+{
+ my $self = shift ;
+ my $ref = shift;
+
+ *$self->{ErrorNo} = $ref->[0] ;
+ ${ *$self->{Error} } = $ref->[1] ;
+}
+
+sub saveStatus
+{
+ my $self = shift ;
+ my $errno = shift() + 0 ;
+ #return $errno unless $errno || ! defined *$self->{ErrorNo};
+ #return $errno unless $errno ;
+
+ *$self->{ErrorNo} = $errno;
+ ${ *$self->{Error} } = '' ;
+
+ return *$self->{ErrorNo} ;
+}
+
+
+sub saveErrorString
+{
+ my $self = shift ;
+ my $retval = shift ;
+
+ #return $retval if ${ *$self->{Error} };
+
+ ${ *$self->{Error} } = shift ;
+ *$self->{ErrorNo} = shift() + 0 if @_ ;
+
+ #warn "saveErrorString: " . ${ *$self->{Error} } . " " . *$self->{Error} . "\n" ;
+ return $retval;
+}
+
+sub croakError
+{
+ my $self = shift ;
+ $self->saveErrorString(0, $_[0]);
+ croak $_[0];
+}
+
+
+sub closeError
+{
+ my $self = shift ;
+ my $retval = shift ;
+
+ my $errno = *$self->{ErrorNo};
+ my $error = ${ *$self->{Error} };
+
+ $self->close();
+
+ *$self->{ErrorNo} = $errno ;
+ ${ *$self->{Error} } = $error ;
+
+ return $retval;
+}
+
+sub error
+{
+ my $self = shift ;
+ return ${ *$self->{Error} } ;
+}
+
+sub errorNo
+{
+ my $self = shift ;
+ return *$self->{ErrorNo};
+}
+
+sub HeaderError
+{
+ my ($self) = shift;
+ return $self->saveErrorString(undef, "Header Error: $_[0]", STATUS_ERROR);
+}
+
+sub TrailerError
+{
+ my ($self) = shift;
+ return $self->saveErrorString(G_ERR, "Trailer Error: $_[0]", STATUS_ERROR);
+}
+
+sub TruncatedHeader
+{
+ my ($self) = shift;
+ return $self->HeaderError("Truncated in $_[0] Section");
+}
+
+sub TruncatedTrailer
+{
+ my ($self) = shift;
+ return $self->TrailerError("Truncated in $_[0] Section");
+}
+
+sub postCheckParams
+{
+ return 1;
+}
+
+sub checkParams
+{
+ my $self = shift ;
+ my $class = shift ;
+
+ my $got = shift || IO::Compress::Base::Parameters::new();
+
+ my $Valid = {
+ 'BlockSize' => [1, 1, Parse_unsigned, 16 * 1024],
+ 'AutoClose' => [1, 1, Parse_boolean, 0],
+ 'Strict' => [1, 1, Parse_boolean, 0],
+ 'Append' => [1, 1, Parse_boolean, 0],
+ 'Prime' => [1, 1, Parse_any, undef],
+ 'MultiStream' => [1, 1, Parse_boolean, 0],
+ 'Transparent' => [1, 1, Parse_any, 1],
+ 'Scan' => [1, 1, Parse_boolean, 0],
+ 'InputLength' => [1, 1, Parse_unsigned, undef],
+ 'BinModeOut' => [1, 1, Parse_boolean, 0],
+ #'Encode' => [1, 1, Parse_any, undef],
+
+ #'ConsumeInput' => [1, 1, Parse_boolean, 0],
+
+ $self->getExtraParams(),
+
+ #'Todo - Revert to ordinary file on end Z_STREAM_END'=> 0,
+ # ContinueAfterEof
+ } ;
+
+ $Valid->{TrailingData} = [1, 1, Parse_writable_scalar, undef]
+ if *$self->{OneShot} ;
+
+ $got->parse($Valid, @_ )
+ or $self->croakError("${class}: $got->{Error}") ;
+
+ $self->postCheckParams($got)
+ or $self->croakError("${class}: " . $self->error()) ;
+
+ return $got;
+}
+
+sub _create
+{
+ my $obj = shift;
+ my $got = shift;
+ my $append_mode = shift ;
+
+ my $class = ref $obj;
+ $obj->croakError("$class: Missing Input parameter")
+ if ! @_ && ! $got ;
+
+ my $inValue = shift ;
+
+ *$obj->{OneShot} = 0 ;
+
+ if (! $got)
+ {
+ $got = $obj->checkParams($class, undef, @_)
+ or return undef ;
+ }
+
+ my $inType = whatIsInput($inValue, 1);
+
+ $obj->ckInputParam($class, $inValue, 1)
+ or return undef ;
+
+ *$obj->{InNew} = 1;
+
+ $obj->ckParams($got)
+ or $obj->croakError("${class}: " . *$obj->{Error});
+
+ if ($inType eq 'buffer' || $inType eq 'code') {
+ *$obj->{Buffer} = $inValue ;
+ *$obj->{InputEvent} = $inValue
+ if $inType eq 'code' ;
+ }
+ else {
+ if ($inType eq 'handle') {
+ *$obj->{FH} = $inValue ;
+ *$obj->{Handle} = 1 ;
+
+ # Need to rewind for Scan
+ *$obj->{FH}->seek(0, SEEK_SET)
+ if $got->value('Scan');
+ }
+ else {
+ no warnings ;
+ my $mode = '<';
+ $mode = '+<' if $got->value('Scan');
+ *$obj->{StdIO} = ($inValue eq '-');
+ *$obj->{FH} = new IO::File "$mode $inValue"
+ or return $obj->saveErrorString(undef, "cannot open file '$inValue': $!", $!) ;
+ }
+
+ *$obj->{LineNo} = $. = 0;
+ setBinModeInput(*$obj->{FH}) ;
+
+ my $buff = "" ;
+ *$obj->{Buffer} = \$buff ;
+ }
+
+ if ($got->parsed('Encode')) {
+ my $want_encoding = $got->value('Encode');
+ *$obj->{Encoding} = getEncoding($obj, $class, $want_encoding);
+ }
+
+
+ *$obj->{InputLength} = $got->parsed('InputLength')
+ ? $got->value('InputLength')
+ : undef ;
+ *$obj->{InputLengthRemaining} = $got->value('InputLength');
+ *$obj->{BufferOffset} = 0 ;
+ *$obj->{AutoClose} = $got->value('AutoClose');
+ *$obj->{Strict} = $got->value('Strict');
+ *$obj->{BlockSize} = $got->value('BlockSize');
+ *$obj->{Append} = $got->value('Append');
+ *$obj->{AppendOutput} = $append_mode || $got->value('Append');
+ *$obj->{ConsumeInput} = $got->value('ConsumeInput');
+ *$obj->{Transparent} = $got->value('Transparent');
+ *$obj->{MultiStream} = $got->value('MultiStream');
+
+ # TODO - move these two into RawDeflate
+ *$obj->{Scan} = $got->value('Scan');
+ *$obj->{ParseExtra} = $got->value('ParseExtra')
+ || $got->value('Strict') ;
+ *$obj->{Type} = '';
+ *$obj->{Prime} = $got->value('Prime') || '' ;
+ *$obj->{Pending} = '';
+ *$obj->{Plain} = 0;
+ *$obj->{PlainBytesRead} = 0;
+ *$obj->{InflatedBytesRead} = 0;
+ *$obj->{UnCompSize} = new U64;
+ *$obj->{CompSize} = new U64;
+ *$obj->{TotalInflatedBytesRead} = 0;
+ *$obj->{NewStream} = 0 ;
+ *$obj->{EventEof} = 0 ;
+ *$obj->{ClassName} = $class ;
+ *$obj->{Params} = $got ;
+
+ if (*$obj->{ConsumeInput}) {
+ *$obj->{InNew} = 0;
+ *$obj->{Closed} = 0;
+ return $obj
+ }
+
+ my $status = $obj->mkUncomp($got);
+
+ return undef
+ unless defined $status;
+
+ if ( ! $status) {
+ return undef
+ unless *$obj->{Transparent};
+
+ $obj->clearError();
+ *$obj->{Type} = 'plain';
+ *$obj->{Plain} = 1;
+ #$status = $obj->mkIdentityUncomp($class, $got);
+ $obj->pushBack(*$obj->{HeaderPending}) ;
+ }
+
+ push @{ *$obj->{InfoList} }, *$obj->{Info} ;
+
+ $obj->saveStatus(STATUS_OK) ;
+ *$obj->{InNew} = 0;
+ *$obj->{Closed} = 0;
+
+ return $obj;
+}
+
+sub ckInputParam
+{
+ my $self = shift ;
+ my $from = shift ;
+ my $inType = whatIsInput($_[0], $_[1]);
+
+ $self->croakError("$from: input parameter not a filename, filehandle, array ref or scalar ref")
+ if ! $inType ;
+
+# if ($inType eq 'filename' )
+# {
+# return $self->saveErrorString(1, "$from: input filename is undef or null string", STATUS_ERROR)
+# if ! defined $_[0] || $_[0] eq '' ;
+#
+# if ($_[0] ne '-' && ! -e $_[0] )
+# {
+# return $self->saveErrorString(1,
+# "input file '$_[0]' does not exist", STATUS_ERROR);
+# }
+# }
+
+ return 1;
+}
+
+
+sub _inf
+{
+ my $obj = shift ;
+
+ my $class = (caller)[0] ;
+ my $name = (caller(1))[3] ;
+
+ $obj->croakError("$name: expected at least 1 parameters\n")
+ unless @_ >= 1 ;
+
+ my $input = shift ;
+ my $haveOut = @_ ;
+ my $output = shift ;
+
+
+ my $x = new IO::Compress::Base::Validator($class, *$obj->{Error}, $name, $input, $output)
+ or return undef ;
+
+ push @_, $output if $haveOut && $x->{Hash};
+
+ *$obj->{OneShot} = 1 ;
+
+ my $got = $obj->checkParams($name, undef, @_)
+ or return undef ;
+
+ if ($got->parsed('TrailingData'))
+ {
+ *$obj->{TrailingData} = $got->value('TrailingData');
+ }
+
+ *$obj->{MultiStream} = $got->value('MultiStream');
+ $got->value('MultiStream', 0);
+
+ $x->{Got} = $got ;
+
+# if ($x->{Hash})
+# {
+# while (my($k, $v) = each %$input)
+# {
+# $v = \$input->{$k}
+# unless defined $v ;
+#
+# $obj->_singleTarget($x, $k, $v, @_)
+# or return undef ;
+# }
+#
+# return keys %$input ;
+# }
+
+ if ($x->{GlobMap})
+ {
+ $x->{oneInput} = 1 ;
+ foreach my $pair (@{ $x->{Pairs} })
+ {
+ my ($from, $to) = @$pair ;
+ $obj->_singleTarget($x, $from, $to, @_)
+ or return undef ;
+ }
+
+ return scalar @{ $x->{Pairs} } ;
+ }
+
+ if (! $x->{oneOutput} )
+ {
+ my $inFile = ($x->{inType} eq 'filenames'
+ || $x->{inType} eq 'filename');
+
+ $x->{inType} = $inFile ? 'filename' : 'buffer';
+
+ foreach my $in ($x->{oneInput} ? $input : @$input)
+ {
+ my $out ;
+ $x->{oneInput} = 1 ;
+
+ $obj->_singleTarget($x, $in, $output, @_)
+ or return undef ;
+ }
+
+ return 1 ;
+ }
+
+ # finally the 1 to 1 and n to 1
+ return $obj->_singleTarget($x, $input, $output, @_);
+
+ croak "should not be here" ;
+}
+
+sub retErr
+{
+ my $x = shift ;
+ my $string = shift ;
+
+ ${ $x->{Error} } = $string ;
+
+ return undef ;
+}
+
+sub _singleTarget
+{
+ my $self = shift ;
+ my $x = shift ;
+ my $input = shift;
+ my $output = shift;
+
+ my $buff = '';
+ $x->{buff} = \$buff ;
+
+ my $fh ;
+ if ($x->{outType} eq 'filename') {
+ my $mode = '>' ;
+ $mode = '>>'
+ if $x->{Got}->value('Append') ;
+ $x->{fh} = new IO::File "$mode $output"
+ or return retErr($x, "cannot open file '$output': $!") ;
+ binmode $x->{fh} if $x->{Got}->valueOrDefault('BinModeOut');
+
+ }
+
+ elsif ($x->{outType} eq 'handle') {
+ $x->{fh} = $output;
+ binmode $x->{fh} if $x->{Got}->valueOrDefault('BinModeOut');
+ if ($x->{Got}->value('Append')) {
+ seek($x->{fh}, 0, SEEK_END)
+ or return retErr($x, "Cannot seek to end of output filehandle: $!") ;
+ }
+ }
+
+
+ elsif ($x->{outType} eq 'buffer' )
+ {
+ $$output = ''
+ unless $x->{Got}->value('Append');
+ $x->{buff} = $output ;
+ }
+
+ if ($x->{oneInput})
+ {
+ defined $self->_rd2($x, $input, $output)
+ or return undef;
+ }
+ else
+ {
+ for my $element ( ($x->{inType} eq 'hash') ? keys %$input : @$input)
+ {
+ defined $self->_rd2($x, $element, $output)
+ or return undef ;
+ }
+ }
+
+
+ if ( ($x->{outType} eq 'filename' && $output ne '-') ||
+ ($x->{outType} eq 'handle' && $x->{Got}->value('AutoClose'))) {
+ $x->{fh}->close()
+ or return retErr($x, $!);
+ delete $x->{fh};
+ }
+
+ return 1 ;
+}
+
+sub _rd2
+{
+ my $self = shift ;
+ my $x = shift ;
+ my $input = shift;
+ my $output = shift;
+
+ my $z = createSelfTiedObject($x->{Class}, *$self->{Error});
+
+ $z->_create($x->{Got}, 1, $input, @_)
+ or return undef ;
+
+ my $status ;
+ my $fh = $x->{fh};
+
+ while (1) {
+
+ while (($status = $z->read($x->{buff})) > 0) {
+ if ($fh) {
+ print $fh ${ $x->{buff} }
+ or return $z->saveErrorString(undef, "Error writing to output file: $!", $!);
+ ${ $x->{buff} } = '' ;
+ }
+ }
+
+ if (! $x->{oneOutput} ) {
+ my $ot = $x->{outType} ;
+
+ if ($ot eq 'array')
+ { push @$output, $x->{buff} }
+ elsif ($ot eq 'hash')
+ { $output->{$input} = $x->{buff} }
+
+ my $buff = '';
+ $x->{buff} = \$buff;
+ }
+
+ last if $status < 0 || $z->smartEof();
+ #last if $status < 0 ;
+
+ last
+ unless *$self->{MultiStream};
+
+ $status = $z->nextStream();
+
+ last
+ unless $status == 1 ;
+ }
+
+ return $z->closeError(undef)
+ if $status < 0 ;
+
+ ${ *$self->{TrailingData} } = $z->trailingData()
+ if defined *$self->{TrailingData} ;
+
+ $z->close()
+ or return undef ;
+
+ return 1 ;
+}
+
+sub TIEHANDLE
+{
+ return $_[0] if ref($_[0]);
+ die "OOPS\n" ;
+
+}
+
+sub UNTIE
+{
+ my $self = shift ;
+}
+
+
+sub getHeaderInfo
+{
+ my $self = shift ;
+ wantarray ? @{ *$self->{InfoList} } : *$self->{Info};
+}
+
+sub readBlock
+{
+ my $self = shift ;
+ my $buff = shift ;
+ my $size = shift ;
+
+ if (defined *$self->{CompressedInputLength}) {
+ if (*$self->{CompressedInputLengthRemaining} == 0) {
+ delete *$self->{CompressedInputLength};
+ *$self->{CompressedInputLengthDone} = 1;
+ return STATUS_OK ;
+ }
+ $size = min($size, *$self->{CompressedInputLengthRemaining} );
+ *$self->{CompressedInputLengthRemaining} -= $size ;
+ }
+
+ my $status = $self->smartRead($buff, $size) ;
+ return $self->saveErrorString(STATUS_ERROR, "Error Reading Data")
+ if $status < 0 ;
+
+ if ($status == 0 ) {
+ *$self->{Closed} = 1 ;
+ *$self->{EndStream} = 1 ;
+ return $self->saveErrorString(STATUS_ERROR, "unexpected end of file", STATUS_ERROR);
+ }
+
+ return STATUS_OK;
+}
+
+sub postBlockChk
+{
+ return STATUS_OK;
+}
+
+sub _raw_read
+{
+ # return codes
+ # >0 - ok, number of bytes read
+ # =0 - ok, eof
+ # <0 - not ok
+
+ my $self = shift ;
+
+ return G_EOF if *$self->{Closed} ;
+ #return G_EOF if !length *$self->{Pending} && *$self->{EndStream} ;
+ return G_EOF if *$self->{EndStream} ;
+
+ my $buffer = shift ;
+ my $scan_mode = shift ;
+
+ if (*$self->{Plain}) {
+ my $tmp_buff ;
+ my $len = $self->smartRead(\$tmp_buff, *$self->{BlockSize}) ;
+
+ return $self->saveErrorString(G_ERR, "Error reading data: $!", $!)
+ if $len < 0 ;
+
+ if ($len == 0 ) {
+ *$self->{EndStream} = 1 ;
+ }
+ else {
+ *$self->{PlainBytesRead} += $len ;
+ $$buffer .= $tmp_buff;
+ }
+
+ return $len ;
+ }
+
+ if (*$self->{NewStream}) {
+
+ $self->gotoNextStream() > 0
+ or return G_ERR;
+
+ # For the headers that actually uncompressed data, put the
+ # uncompressed data into the output buffer.
+ $$buffer .= *$self->{Pending} ;
+ my $len = length *$self->{Pending} ;
+ *$self->{Pending} = '';
+ return $len;
+ }
+
+ my $temp_buf = '';
+ my $outSize = 0;
+ my $status = $self->readBlock(\$temp_buf, *$self->{BlockSize}, $outSize) ;
+ return G_ERR
+ if $status == STATUS_ERROR ;
+
+ my $buf_len = 0;
+ if ($status == STATUS_OK) {
+ my $beforeC_len = length $temp_buf;
+ my $before_len = defined $$buffer ? length $$buffer : 0 ;
+ $status = *$self->{Uncomp}->uncompr(\$temp_buf, $buffer,
+ defined *$self->{CompressedInputLengthDone} ||
+ $self->smartEof(), $outSize);
+
+ # Remember the input buffer if it wasn't consumed completely
+ $self->pushBack($temp_buf) if *$self->{Uncomp}{ConsumesInput};
+
+ return $self->saveErrorString(G_ERR, *$self->{Uncomp}{Error}, *$self->{Uncomp}{ErrorNo})
+ if $self->saveStatus($status) == STATUS_ERROR;
+
+ $self->postBlockChk($buffer, $before_len) == STATUS_OK
+ or return G_ERR;
+
+ $buf_len = defined $$buffer ? length($$buffer) - $before_len : 0;
+
+ *$self->{CompSize}->add($beforeC_len - length $temp_buf) ;
+
+ *$self->{InflatedBytesRead} += $buf_len ;
+ *$self->{TotalInflatedBytesRead} += $buf_len ;
+ *$self->{UnCompSize}->add($buf_len) ;
+
+ $self->filterUncompressed($buffer);
+
+ if (*$self->{Encoding}) {
+ $$buffer = *$self->{Encoding}->decode($$buffer);
+ }
+ }
+
+ if ($status == STATUS_ENDSTREAM) {
+
+ *$self->{EndStream} = 1 ;
+#$self->pushBack($temp_buf) ;
+#$temp_buf = '';
+
+ my $trailer;
+ my $trailer_size = *$self->{Info}{TrailerLength} ;
+ my $got = 0;
+ if (*$self->{Info}{TrailerLength})
+ {
+ $got = $self->smartRead(\$trailer, $trailer_size) ;
+ }
+
+ if ($got == $trailer_size) {
+ $self->chkTrailer($trailer) == STATUS_OK
+ or return G_ERR;
+ }
+ else {
+ return $self->TrailerError("trailer truncated. Expected " .
+ "$trailer_size bytes, got $got")
+ if *$self->{Strict};
+ $self->pushBack($trailer) ;
+ }
+
+ # TODO - if want to file file pointer, do it here
+
+ if (! $self->smartEof()) {
+ *$self->{NewStream} = 1 ;
+
+ if (*$self->{MultiStream}) {
+ *$self->{EndStream} = 0 ;
+ return $buf_len ;
+ }
+ }
+
+ }
+
+
+ # return the number of uncompressed bytes read
+ return $buf_len ;
+}
+
+sub reset
+{
+ my $self = shift ;
+
+ return *$self->{Uncomp}->reset();
+}
+
+sub filterUncompressed
+{
+}
+
+#sub isEndStream
+#{
+# my $self = shift ;
+# return *$self->{NewStream} ||
+# *$self->{EndStream} ;
+#}
+
+sub nextStream
+{
+ my $self = shift ;
+
+ my $status = $self->gotoNextStream();
+ $status == 1
+ or return $status ;
+
+ *$self->{TotalInflatedBytesRead} = 0 ;
+ *$self->{LineNo} = $. = 0;
+
+ return 1;
+}
+
+sub gotoNextStream
+{
+ my $self = shift ;
+
+ if (! *$self->{NewStream}) {
+ my $status = 1;
+ my $buffer ;
+
+ # TODO - make this more efficient if know the offset for the end of
+ # the stream and seekable
+ $status = $self->read($buffer)
+ while $status > 0 ;
+
+ return $status
+ if $status < 0;
+ }
+
+ *$self->{NewStream} = 0 ;
+ *$self->{EndStream} = 0 ;
+ $self->reset();
+ *$self->{UnCompSize}->reset();
+ *$self->{CompSize}->reset();
+
+ my $magic = $self->ckMagic();
+ #*$self->{EndStream} = 0 ;
+
+ if ( ! defined $magic) {
+ if (! *$self->{Transparent} )
+ {
+ *$self->{EndStream} = 1 ;
+ return 0;
+ }
+
+ $self->clearError();
+ *$self->{Type} = 'plain';
+ *$self->{Plain} = 1;
+ $self->pushBack(*$self->{HeaderPending}) ;
+ }
+ else
+ {
+ *$self->{Info} = $self->readHeader($magic);
+
+ if ( ! defined *$self->{Info} ) {
+ *$self->{EndStream} = 1 ;
+ return -1;
+ }
+ }
+
+ push @{ *$self->{InfoList} }, *$self->{Info} ;
+
+ return 1;
+}
+
+sub streamCount
+{
+ my $self = shift ;
+ return 1 if ! defined *$self->{InfoList};
+ return scalar @{ *$self->{InfoList} } ;
+}
+
+sub read
+{
+ # return codes
+ # >0 - ok, number of bytes read
+ # =0 - ok, eof
+ # <0 - not ok
+
+ my $self = shift ;
+
+ return G_EOF if *$self->{Closed} ;
+
+ my $buffer ;
+
+ if (ref $_[0] ) {
+ $self->croakError(*$self->{ClassName} . "::read: buffer parameter is read-only")
+ if readonly(${ $_[0] });
+
+ $self->croakError(*$self->{ClassName} . "::read: not a scalar reference $_[0]" )
+ unless ref $_[0] eq 'SCALAR' ;
+ $buffer = $_[0] ;
+ }
+ else {
+ $self->croakError(*$self->{ClassName} . "::read: buffer parameter is read-only")
+ if readonly($_[0]);
+
+ $buffer = \$_[0] ;
+ }
+
+ my $length = $_[1] ;
+ my $offset = $_[2] || 0;
+
+ if (! *$self->{AppendOutput}) {
+ if (! $offset) {
+ $$buffer = '' ;
+ }
+ else {
+ if ($offset > length($$buffer)) {
+ $$buffer .= "\x00" x ($offset - length($$buffer));
+ }
+ else {
+ substr($$buffer, $offset) = '';
+ }
+ }
+ }
+
+ return G_EOF if !length *$self->{Pending} && *$self->{EndStream} ;
+
+ # the core read will return 0 if asked for 0 bytes
+ return 0 if defined $length && $length == 0 ;
+
+ $length = $length || 0;
+
+ $self->croakError(*$self->{ClassName} . "::read: length parameter is negative")
+ if $length < 0 ;
+
+ # Short-circuit if this is a simple read, with no length
+ # or offset specified.
+ unless ( $length || $offset) {
+ if (length *$self->{Pending}) {
+ $$buffer .= *$self->{Pending} ;
+ my $len = length *$self->{Pending};
+ *$self->{Pending} = '' ;
+ return $len ;
+ }
+ else {
+ my $len = 0;
+ $len = $self->_raw_read($buffer)
+ while ! *$self->{EndStream} && $len == 0 ;
+ return $len ;
+ }
+ }
+
+ # Need to jump through more hoops - either length or offset
+ # or both are specified.
+ my $out_buffer = *$self->{Pending} ;
+ *$self->{Pending} = '';
+
+
+ while (! *$self->{EndStream} && length($out_buffer) < $length)
+ {
+ my $buf_len = $self->_raw_read(\$out_buffer);
+ return $buf_len
+ if $buf_len < 0 ;
+ }
+
+ $length = length $out_buffer
+ if length($out_buffer) < $length ;
+
+ return 0
+ if $length == 0 ;
+
+ $$buffer = ''
+ if ! defined $$buffer;
+
+ $offset = length $$buffer
+ if *$self->{AppendOutput} ;
+
+ *$self->{Pending} = $out_buffer;
+ $out_buffer = \*$self->{Pending} ;
+
+ #substr($$buffer, $offset) = substr($$out_buffer, 0, $length, '') ;
+ substr($$buffer, $offset) = substr($$out_buffer, 0, $length) ;
+ substr($$out_buffer, 0, $length) = '' ;
+
+ return $length ;
+}
+
+sub _getline
+{
+ my $self = shift ;
+
+ # Slurp Mode
+ if ( ! defined $/ ) {
+ my $data ;
+ 1 while $self->read($data) > 0 ;
+ return \$data ;
+ }
+
+ # Record Mode
+ if ( ref $/ eq 'SCALAR' && ${$/} =~ /^\d+$/ && ${$/} > 0) {
+ my $reclen = ${$/} ;
+ my $data ;
+ $self->read($data, $reclen) ;
+ return \$data ;
+ }
+
+ # Paragraph Mode
+ if ( ! length $/ ) {
+ my $paragraph ;
+ while ($self->read($paragraph) > 0 ) {
+ if ($paragraph =~ s/^(.*?\n\n+)//s) {
+ *$self->{Pending} = $paragraph ;
+ my $par = $1 ;
+ return \$par ;
+ }
+ }
+ return \$paragraph;
+ }
+
+ # $/ isn't empty, or a reference, so it's Line Mode.
+ {
+ my $line ;
+ my $offset;
+ my $p = \*$self->{Pending} ;
+
+ if (length(*$self->{Pending}) &&
+ ($offset = index(*$self->{Pending}, $/)) >=0) {
+ my $l = substr(*$self->{Pending}, 0, $offset + length $/ );
+ substr(*$self->{Pending}, 0, $offset + length $/) = '';
+ return \$l;
+ }
+
+ while ($self->read($line) > 0 ) {
+ my $offset = index($line, $/);
+ if ($offset >= 0) {
+ my $l = substr($line, 0, $offset + length $/ );
+ substr($line, 0, $offset + length $/) = '';
+ $$p = $line;
+ return \$l;
+ }
+ }
+
+ return \$line;
+ }
+}
+
+sub getline
+{
+ my $self = shift;
+ my $current_append = *$self->{AppendOutput} ;
+ *$self->{AppendOutput} = 1;
+ my $lineref = $self->_getline();
+ $. = ++ *$self->{LineNo} if defined $$lineref ;
+ *$self->{AppendOutput} = $current_append;
+ return $$lineref ;
+}
+
+sub getlines
+{
+ my $self = shift;
+ $self->croakError(*$self->{ClassName} .
+ "::getlines: called in scalar context\n") unless wantarray;
+ my($line, @lines);
+ push(@lines, $line)
+ while defined($line = $self->getline);
+ return @lines;
+}
+
+sub READLINE
+{
+ goto &getlines if wantarray;
+ goto &getline;
+}
+
+sub getc
+{
+ my $self = shift;
+ my $buf;
+ return $buf if $self->read($buf, 1);
+ return undef;
+}
+
+sub ungetc
+{
+ my $self = shift;
+ *$self->{Pending} = "" unless defined *$self->{Pending} ;
+ *$self->{Pending} = $_[0] . *$self->{Pending} ;
+}
+
+
+sub trailingData
+{
+ my $self = shift ;
+
+ if (defined *$self->{FH} || defined *$self->{InputEvent} ) {
+ return *$self->{Prime} ;
+ }
+ else {
+ my $buf = *$self->{Buffer} ;
+ my $offset = *$self->{BufferOffset} ;
+ return substr($$buf, $offset) ;
+ }
+}
+
+
+sub eof
+{
+ my $self = shift ;
+
+ return (*$self->{Closed} ||
+ (!length *$self->{Pending}
+ && ( $self->smartEof() || *$self->{EndStream}))) ;
+}
+
+sub tell
+{
+ my $self = shift ;
+
+ my $in ;
+ if (*$self->{Plain}) {
+ $in = *$self->{PlainBytesRead} ;
+ }
+ else {
+ $in = *$self->{TotalInflatedBytesRead} ;
+ }
+
+ my $pending = length *$self->{Pending} ;
+
+ return 0 if $pending > $in ;
+ return $in - $pending ;
+}
+
+sub close
+{
+ # todo - what to do if close is called before the end of the gzip file
+ # do we remember any trailing data?
+ my $self = shift ;
+
+ return 1 if *$self->{Closed} ;
+
+ untie *$self
+ if $] >= 5.008 ;
+
+ my $status = 1 ;
+
+ if (defined *$self->{FH}) {
+ if ((! *$self->{Handle} || *$self->{AutoClose}) && ! *$self->{StdIO}) {
+ #if ( *$self->{AutoClose}) {
+ local $.;
+ $! = 0 ;
+ $status = *$self->{FH}->close();
+ return $self->saveErrorString(0, $!, $!)
+ if !*$self->{InNew} && $self->saveStatus($!) != 0 ;
+ }
+ delete *$self->{FH} ;
+ $! = 0 ;
+ }
+ *$self->{Closed} = 1 ;
+
+ return 1;
+}
+
+sub DESTROY
+{
+ my $self = shift ;
+ local ($., $@, $!, $^E, $?);
+
+ $self->close() ;
+}
+
+sub seek
+{
+ my $self = shift ;
+ my $position = shift;
+ my $whence = shift ;
+
+ my $here = $self->tell() ;
+ my $target = 0 ;
+
+
+ if ($whence == SEEK_SET) {
+ $target = $position ;
+ }
+ elsif ($whence == SEEK_CUR) {
+ $target = $here + $position ;
+ }
+ elsif ($whence == SEEK_END) {
+ $target = $position ;
+ $self->croakError(*$self->{ClassName} . "::seek: SEEK_END not allowed") ;
+ }
+ else {
+ $self->croakError(*$self->{ClassName} ."::seek: unknown value, $whence, for whence parameter");
+ }
+
+ # short circuit if seeking to current offset
+ if ($target == $here) {
+ # On ordinary filehandles, seeking to the current
+ # position also clears the EOF condition, so we
+ # emulate this behavior locally while simultaneously
+ # cascading it to the underlying filehandle
+ if (*$self->{Plain}) {
+ *$self->{EndStream} = 0;
+ seek(*$self->{FH},0,1) if *$self->{FH};
+ }
+ return 1;
+ }
+
+ # Outlaw any attempt to seek backwards
+ $self->croakError( *$self->{ClassName} ."::seek: cannot seek backwards")
+ if $target < $here ;
+
+ # Walk the file to the new offset
+ my $offset = $target - $here ;
+
+ my $got;
+ while (($got = $self->read(my $buffer, min($offset, *$self->{BlockSize})) ) > 0)
+ {
+ $offset -= $got;
+ last if $offset == 0 ;
+ }
+
+ $here = $self->tell() ;
+ return $offset == 0 ? 1 : 0 ;
+}
+
+sub fileno
+{
+ my $self = shift ;
+ return defined *$self->{FH}
+ ? fileno *$self->{FH}
+ : undef ;
+}
+
+sub binmode
+{
+ 1;
+# my $self = shift ;
+# return defined *$self->{FH}
+# ? binmode *$self->{FH}
+# : 1 ;
+}
+
+sub opened
+{
+ my $self = shift ;
+ return ! *$self->{Closed} ;
+}
+
+sub autoflush
+{
+ my $self = shift ;
+ return defined *$self->{FH}
+ ? *$self->{FH}->autoflush(@_)
+ : undef ;
+}
+
+sub input_line_number
+{
+ my $self = shift ;
+ my $last = *$self->{LineNo};
+ $. = *$self->{LineNo} = $_[1] if @_ ;
+ return $last;
+}
+
+
+*BINMODE = \&binmode;
+*SEEK = \&seek;
+*READ = \&read;
+*sysread = \&read;
+*TELL = \&tell;
+*EOF = \&eof;
+
+*FILENO = \&fileno;
+*CLOSE = \&close;
+
+sub _notAvailable
+{
+ my $name = shift ;
+ #return sub { croak "$name Not Available" ; } ;
+ return sub { croak "$name Not Available: File opened only for intput" ; } ;
+}
+
+
+*print = _notAvailable('print');
+*PRINT = _notAvailable('print');
+*printf = _notAvailable('printf');
+*PRINTF = _notAvailable('printf');
+*write = _notAvailable('write');
+*WRITE = _notAvailable('write');
+
+#*sysread = \&read;
+#*syswrite = \&_notAvailable;
+
+
+
+package IO::Uncompress::Base ;
+
+
+1 ;
+__END__
+
+=head1 NAME
+
+IO::Uncompress::Base - Base Class for IO::Uncompress modules
+
+=head1 SYNOPSIS
+
+ use IO::Uncompress::Base ;
+
+=head1 DESCRIPTION
+
+This module is not intended for direct use in application code. Its sole
+purpose if to to be sub-classed by IO::Unompress modules.
+
+=head1 SEE ALSO
+
+L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Compress::Deflate>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Compress::Bzip2>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
+
+L<Compress::Zlib::FAQ|Compress::Zlib::FAQ>
+
+L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
+L<Archive::Tar|Archive::Tar>,
+L<IO::Zlib|IO::Zlib>
+
+=head1 AUTHOR
+
+This module was written by Paul Marquess, F<pmqs@cpan.org>.
+
+=head1 MODIFICATION HISTORY
+
+See the Changes file.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2005-2010 Paul Marquess. All rights reserved.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Uncompress/Bunzip2.pm b/Master/tlpkg/tlperl/lib/IO/Uncompress/Bunzip2.pm
new file mode 100644
index 00000000000..b3988c41851
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Uncompress/Bunzip2.pm
@@ -0,0 +1,858 @@
+package IO::Uncompress::Bunzip2 ;
+
+use strict ;
+use warnings;
+use bytes;
+
+use IO::Compress::Base::Common 2.024 qw(:Status createSelfTiedObject);
+
+use IO::Uncompress::Base 2.024 ;
+use IO::Uncompress::Adapter::Bunzip2 2.024 ;
+
+require Exporter ;
+our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $Bunzip2Error);
+
+$VERSION = '2.024';
+$Bunzip2Error = '';
+
+@ISA = qw( Exporter IO::Uncompress::Base );
+@EXPORT_OK = qw( $Bunzip2Error bunzip2 ) ;
+#%EXPORT_TAGS = %IO::Uncompress::Base::EXPORT_TAGS ;
+push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
+#Exporter::export_ok_tags('all');
+
+
+sub new
+{
+ my $class = shift ;
+ my $obj = createSelfTiedObject($class, \$Bunzip2Error);
+
+ $obj->_create(undef, 0, @_);
+}
+
+sub bunzip2
+{
+ my $obj = createSelfTiedObject(undef, \$Bunzip2Error);
+ return $obj->_inf(@_);
+}
+
+sub getExtraParams
+{
+ my $self = shift ;
+
+ use IO::Compress::Base::Common 2.024 qw(:Parse);
+
+ return (
+ 'Verbosity' => [1, 1, Parse_boolean, 0],
+ 'Small' => [1, 1, Parse_boolean, 0],
+ );
+}
+
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ return 1;
+}
+
+sub mkUncomp
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ my $magic = $self->ckMagic()
+ or return 0;
+
+ *$self->{Info} = $self->readHeader($magic)
+ or return undef ;
+
+ my $Small = $got->value('Small');
+ my $Verbosity = $got->value('Verbosity');
+
+ my ($obj, $errstr, $errno) = IO::Uncompress::Adapter::Bunzip2::mkUncompObject(
+ $Small, $Verbosity);
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ *$self->{Uncomp} = $obj;
+
+ return 1;
+
+}
+
+
+sub ckMagic
+{
+ my $self = shift;
+
+ my $magic ;
+ $self->smartReadExact(\$magic, 4);
+
+ *$self->{HeaderPending} = $magic ;
+
+ return $self->HeaderError("Header size is " .
+ 4 . " bytes")
+ if length $magic != 4;
+
+ return $self->HeaderError("Bad Magic.")
+ if ! isBzip2Magic($magic) ;
+
+
+ *$self->{Type} = 'bzip2';
+ return $magic;
+}
+
+sub readHeader
+{
+ my $self = shift;
+ my $magic = shift ;
+
+ $self->pushBack($magic);
+ *$self->{HeaderPending} = '';
+
+
+ return {
+ 'Type' => 'bzip2',
+ 'FingerprintLength' => 4,
+ 'HeaderLength' => 4,
+ 'TrailerLength' => 0,
+ 'Header' => '$magic'
+ };
+
+}
+
+sub chkTrailer
+{
+ return STATUS_OK;
+}
+
+
+
+sub isBzip2Magic
+{
+ my $buffer = shift ;
+ return $buffer =~ /^BZh\d$/;
+}
+
+1 ;
+
+__END__
+
+
+=head1 NAME
+
+IO::Uncompress::Bunzip2 - Read bzip2 files/buffers
+
+=head1 SYNOPSIS
+
+ use IO::Uncompress::Bunzip2 qw(bunzip2 $Bunzip2Error) ;
+
+ my $status = bunzip2 $input => $output [,OPTS]
+ or die "bunzip2 failed: $Bunzip2Error\n";
+
+ my $z = new IO::Uncompress::Bunzip2 $input [OPTS]
+ or die "bunzip2 failed: $Bunzip2Error\n";
+
+ $status = $z->read($buffer)
+ $status = $z->read($buffer, $length)
+ $status = $z->read($buffer, $length, $offset)
+ $line = $z->getline()
+ $char = $z->getc()
+ $char = $z->ungetc()
+ $char = $z->opened()
+
+ $data = $z->trailingData()
+ $status = $z->nextStream()
+ $data = $z->getHeaderInfo()
+ $z->tell()
+ $z->seek($position, $whence)
+ $z->binmode()
+ $z->fileno()
+ $z->eof()
+ $z->close()
+
+ $Bunzip2Error ;
+
+ # IO::File mode
+
+ <$z>
+ read($z, $buffer);
+ read($z, $buffer, $length);
+ read($z, $buffer, $length, $offset);
+ tell($z)
+ seek($z, $position, $whence)
+ binmode($z)
+ fileno($z)
+ eof($z)
+ close($z)
+
+=head1 DESCRIPTION
+
+This module provides a Perl interface that allows the reading of
+bzip2 files/buffers.
+
+For writing bzip2 files/buffers, see the companion module IO::Compress::Bzip2.
+
+=head1 Functional Interface
+
+A top-level function, C<bunzip2>, is provided to carry out
+"one-shot" uncompression between buffers and/or files. For finer
+control over the uncompression process, see the L</"OO Interface">
+section.
+
+ use IO::Uncompress::Bunzip2 qw(bunzip2 $Bunzip2Error) ;
+
+ bunzip2 $input => $output [,OPTS]
+ or die "bunzip2 failed: $Bunzip2Error\n";
+
+The functional interface needs Perl5.005 or better.
+
+=head2 bunzip2 $input => $output [, OPTS]
+
+C<bunzip2> expects at least two parameters, C<$input> and C<$output>.
+
+=head3 The C<$input> parameter
+
+The parameter, C<$input>, is used to define the source of
+the compressed data.
+
+It can take one of the following forms:
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for reading and the input data
+will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the input data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the input data will be read
+from C<$$input>.
+
+=item An array reference
+
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
+The complete array will be walked to ensure that it only
+contains valid filenames before any data is uncompressed.
+
+=item An Input FileGlob string
+
+If C<$input> is a string that is delimited by the characters "<" and ">"
+C<bunzip2> will assume that it is an I<input fileglob string>. The
+input is the list of files that match the fileglob.
+
+If the fileglob does not match any files ...
+
+See L<File::GlobMapper|File::GlobMapper> for more details.
+
+=back
+
+If the C<$input> parameter is any other type, C<undef> will be returned.
+
+=head3 The C<$output> parameter
+
+The parameter C<$output> is used to control the destination of the
+uncompressed data. This parameter can take one of these forms.
+
+=over 5
+
+=item A filename
+
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the uncompressed
+data will be written to it.
+
+=item A filehandle
+
+If the C<$output> parameter is a filehandle, the uncompressed data
+will be written to it.
+The string '-' can be used as an alias for standard output.
+
+=item A scalar reference
+
+If C<$output> is a scalar reference, the uncompressed data will be
+stored in C<$$output>.
+
+=item An Array Reference
+
+If C<$output> is an array reference, the uncompressed data will be
+pushed onto the array.
+
+=item An Output FileGlob
+
+If C<$output> is a string that is delimited by the characters "<" and ">"
+C<bunzip2> will assume that it is an I<output fileglob string>. The
+output is the list of files that match the fileglob.
+
+When C<$output> is an fileglob string, C<$input> must also be a fileglob
+string. Anything else is an error.
+
+=back
+
+If the C<$output> parameter is any other type, C<undef> will be returned.
+
+=head2 Notes
+
+When C<$input> maps to multiple compressed files/buffers and C<$output> is
+a single file/buffer, after uncompression C<$output> will contain a
+concatenation of all the uncompressed data from each of the input
+files/buffers.
+
+=head2 Optional Parameters
+
+Unless specified below, the optional parameters for C<bunzip2>,
+C<OPTS>, are the same as those used with the OO interface defined in the
+L</"Constructor Options"> section below.
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option applies to any input or output data streams to
+C<bunzip2> that are filehandles.
+
+If C<AutoClose> is specified, and the value is true, it will result in all
+input and/or output filehandles being closed once C<bunzip2> has
+completed.
+
+This parameter defaults to 0.
+
+=item C<< BinModeOut => 0|1 >>
+
+When writing to a file or filehandle, set C<binmode> before writing to the
+file.
+
+Defaults to 0.
+
+=item C<< Append => 0|1 >>
+
+TODO
+
+=item C<< MultiStream => 0|1 >>
+
+If the input file/buffer contains multiple compressed data streams, this
+option will uncompress the whole lot as a single data stream.
+
+Defaults to 0.
+
+=item C<< TrailingData => $scalar >>
+
+Returns the data, if any, that is present immediately after the compressed
+data stream once uncompression is complete.
+
+This option can be used when there is useful information immediately
+following the compressed data stream, and you don't know the length of the
+compressed data stream.
+
+If the input is a buffer, C<trailingData> will return everything from the
+end of the compressed data stream to the end of the buffer.
+
+If the input is a filehandle, C<trailingData> will return the data that is
+left in the filehandle input buffer once the end of the compressed data
+stream has been reached. You can then use the filehandle to read the rest
+of the input file.
+
+Don't bother using C<trailingData> if the input is a filename.
+
+If you know the length of the compressed data stream before you start
+uncompressing, you can avoid having to use C<trailingData> by setting the
+C<InputLength> option.
+
+=back
+
+=head2 Examples
+
+To read the contents of the file C<file1.txt.bz2> and write the
+compressed data to the file C<file1.txt>.
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::Bunzip2 qw(bunzip2 $Bunzip2Error) ;
+
+ my $input = "file1.txt.bz2";
+ my $output = "file1.txt";
+ bunzip2 $input => $output
+ or die "bunzip2 failed: $Bunzip2Error\n";
+
+To read from an existing Perl filehandle, C<$input>, and write the
+uncompressed data to a buffer, C<$buffer>.
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::Bunzip2 qw(bunzip2 $Bunzip2Error) ;
+ use IO::File ;
+
+ my $input = new IO::File "<file1.txt.bz2"
+ or die "Cannot open 'file1.txt.bz2': $!\n" ;
+ my $buffer ;
+ bunzip2 $input => \$buffer
+ or die "bunzip2 failed: $Bunzip2Error\n";
+
+To uncompress all files in the directory "/my/home" that match "*.txt.bz2" and store the compressed data in the same directory
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::Bunzip2 qw(bunzip2 $Bunzip2Error) ;
+
+ bunzip2 '</my/home/*.txt.bz2>' => '</my/home/#1.txt>'
+ or die "bunzip2 failed: $Bunzip2Error\n";
+
+and if you want to compress each file one at a time, this will do the trick
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::Bunzip2 qw(bunzip2 $Bunzip2Error) ;
+
+ for my $input ( glob "/my/home/*.txt.bz2" )
+ {
+ my $output = $input;
+ $output =~ s/.bz2// ;
+ bunzip2 $input => $output
+ or die "Error compressing '$input': $Bunzip2Error\n";
+ }
+
+=head1 OO Interface
+
+=head2 Constructor
+
+The format of the constructor for IO::Uncompress::Bunzip2 is shown below
+
+ my $z = new IO::Uncompress::Bunzip2 $input [OPTS]
+ or die "IO::Uncompress::Bunzip2 failed: $Bunzip2Error\n";
+
+Returns an C<IO::Uncompress::Bunzip2> object on success and undef on failure.
+The variable C<$Bunzip2Error> will contain an error message on failure.
+
+If you are running Perl 5.005 or better the object, C<$z>, returned from
+IO::Uncompress::Bunzip2 can be used exactly like an L<IO::File|IO::File> filehandle.
+This means that all normal input file operations can be carried out with
+C<$z>. For example, to read a line from a compressed file/buffer you can
+use either of these forms
+
+ $line = $z->getline();
+ $line = <$z>;
+
+The mandatory parameter C<$input> is used to determine the source of the
+compressed data. This parameter can take one of three forms.
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a scalar, it is assumed to be a filename. This
+file will be opened for reading and the compressed data will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the compressed data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the compressed data will be read from
+C<$$output>.
+
+=back
+
+=head2 Constructor Options
+
+The option names defined below are case insensitive and can be optionally
+prefixed by a '-'. So all of the following are valid
+
+ -AutoClose
+ -autoclose
+ AUTOCLOSE
+ autoclose
+
+OPTS is a combination of the following options:
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option is only valid when the C<$input> parameter is a filehandle. If
+specified, and the value is true, it will result in the file being closed once
+either the C<close> method is called or the IO::Uncompress::Bunzip2 object is
+destroyed.
+
+This parameter defaults to 0.
+
+=item C<< MultiStream => 0|1 >>
+
+Allows multiple concatenated compressed streams to be treated as a single
+compressed stream. Decompression will stop once either the end of the
+file/buffer is reached, an error is encountered (premature eof, corrupt
+compressed data) or the end of a stream is not immediately followed by the
+start of another stream.
+
+This parameter defaults to 0.
+
+=item C<< Prime => $string >>
+
+This option will uncompress the contents of C<$string> before processing the
+input file/buffer.
+
+This option can be useful when the compressed data is embedded in another
+file/data structure and it is not possible to work out where the compressed
+data begins without having to read the first few bytes. If this is the
+case, the uncompression can be I<primed> with these bytes using this
+option.
+
+=item C<< Transparent => 0|1 >>
+
+If this option is set and the input file/buffer is not compressed data,
+the module will allow reading of it anyway.
+
+In addition, if the input file/buffer does contain compressed data and
+there is non-compressed data immediately following it, setting this option
+will make this module treat the whole file/bufffer as a single data stream.
+
+This option defaults to 1.
+
+=item C<< BlockSize => $num >>
+
+When reading the compressed input data, IO::Uncompress::Bunzip2 will read it in
+blocks of C<$num> bytes.
+
+This option defaults to 4096.
+
+=item C<< InputLength => $size >>
+
+When present this option will limit the number of compressed bytes read
+from the input file/buffer to C<$size>. This option can be used in the
+situation where there is useful data directly after the compressed data
+stream and you know beforehand the exact length of the compressed data
+stream.
+
+This option is mostly used when reading from a filehandle, in which case
+the file pointer will be left pointing to the first byte directly after the
+compressed data stream.
+
+This option defaults to off.
+
+=item C<< Append => 0|1 >>
+
+This option controls what the C<read> method does with uncompressed data.
+
+If set to 1, all uncompressed data will be appended to the output parameter
+of the C<read> method.
+
+If set to 0, the contents of the output parameter of the C<read> method
+will be overwritten by the uncompressed data.
+
+Defaults to 0.
+
+=item C<< Strict => 0|1 >>
+
+This option is a no-op.
+
+=item C<< Small => 0|1 >>
+
+When non-zero this options will make bzip2 use a decompression algorithm
+that uses less memory at the expense of increasing the amount of time
+taken for decompression.
+
+Default is 0.
+
+=back
+
+=head2 Examples
+
+TODO
+
+=head1 Methods
+
+=head2 read
+
+Usage is
+
+ $status = $z->read($buffer)
+
+Reads a block of compressed data (the size the the compressed block is
+determined by the C<Buffer> option in the constructor), uncompresses it and
+writes any uncompressed data into C<$buffer>. If the C<Append> parameter is
+set in the constructor, the uncompressed data will be appended to the
+C<$buffer> parameter. Otherwise C<$buffer> will be overwritten.
+
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
+
+=head2 read
+
+Usage is
+
+ $status = $z->read($buffer, $length)
+ $status = $z->read($buffer, $length, $offset)
+
+ $status = read($z, $buffer, $length)
+ $status = read($z, $buffer, $length, $offset)
+
+Attempt to read C<$length> bytes of uncompressed data into C<$buffer>.
+
+The main difference between this form of the C<read> method and the
+previous one, is that this one will attempt to return I<exactly> C<$length>
+bytes. The only circumstances that this function will not is if end-of-file
+or an IO error is encountered.
+
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
+
+=head2 getline
+
+Usage is
+
+ $line = $z->getline()
+ $line = <$z>
+
+Reads a single line.
+
+This method fully supports the use of of the variable C<$/> (or
+C<$INPUT_RECORD_SEPARATOR> or C<$RS> when C<English> is in use) to
+determine what constitutes an end of line. Paragraph mode, record mode and
+file slurp mode are all supported.
+
+=head2 getc
+
+Usage is
+
+ $char = $z->getc()
+
+Read a single character.
+
+=head2 ungetc
+
+Usage is
+
+ $char = $z->ungetc($string)
+
+=head2 getHeaderInfo
+
+Usage is
+
+ $hdr = $z->getHeaderInfo();
+ @hdrs = $z->getHeaderInfo();
+
+This method returns either a hash reference (in scalar context) or a list
+or hash references (in array context) that contains information about each
+of the header fields in the compressed data stream(s).
+
+=head2 tell
+
+Usage is
+
+ $z->tell()
+ tell $z
+
+Returns the uncompressed file offset.
+
+=head2 eof
+
+Usage is
+
+ $z->eof();
+ eof($z);
+
+Returns true if the end of the compressed input stream has been reached.
+
+=head2 seek
+
+ $z->seek($position, $whence);
+ seek($z, $position, $whence);
+
+Provides a sub-set of the C<seek> functionality, with the restriction
+that it is only legal to seek forward in the input file/buffer.
+It is a fatal error to attempt to seek backward.
+
+The C<$whence> parameter takes one the usual values, namely SEEK_SET,
+SEEK_CUR or SEEK_END.
+
+Returns 1 on success, 0 on failure.
+
+=head2 binmode
+
+Usage is
+
+ $z->binmode
+ binmode $z ;
+
+This is a noop provided for completeness.
+
+=head2 opened
+
+ $z->opened()
+
+Returns true if the object currently refers to a opened file/buffer.
+
+=head2 autoflush
+
+ my $prev = $z->autoflush()
+ my $prev = $z->autoflush(EXPR)
+
+If the C<$z> object is associated with a file or a filehandle, this method
+returns the current autoflush setting for the underlying filehandle. If
+C<EXPR> is present, and is non-zero, it will enable flushing after every
+write/print operation.
+
+If C<$z> is associated with a buffer, this method has no effect and always
+returns C<undef>.
+
+B<Note> that the special variable C<$|> B<cannot> be used to set or
+retrieve the autoflush setting.
+
+=head2 input_line_number
+
+ $z->input_line_number()
+ $z->input_line_number(EXPR)
+
+Returns the current uncompressed line number. If C<EXPR> is present it has
+the effect of setting the line number. Note that setting the line number
+does not change the current position within the file/buffer being read.
+
+The contents of C<$/> are used to to determine what constitutes a line
+terminator.
+
+=head2 fileno
+
+ $z->fileno()
+ fileno($z)
+
+If the C<$z> object is associated with a file or a filehandle, C<fileno>
+will return the underlying file descriptor. Once the C<close> method is
+called C<fileno> will return C<undef>.
+
+If the C<$z> object is is associated with a buffer, this method will return
+C<undef>.
+
+=head2 close
+
+ $z->close() ;
+ close $z ;
+
+Closes the output file/buffer.
+
+For most versions of Perl this method will be automatically invoked if
+the IO::Uncompress::Bunzip2 object is destroyed (either explicitly or by the
+variable with the reference to the object going out of scope). The
+exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In
+these cases, the C<close> method will be called automatically, but
+not until global destruction of all live objects when the program is
+terminating.
+
+Therefore, if you want your scripts to be able to run on all versions
+of Perl, you should call C<close> explicitly and not rely on automatic
+closing.
+
+Returns true on success, otherwise 0.
+
+If the C<AutoClose> option has been enabled when the IO::Uncompress::Bunzip2
+object was created, and the object is associated with a file, the
+underlying file will also be closed.
+
+=head2 nextStream
+
+Usage is
+
+ my $status = $z->nextStream();
+
+Skips to the next compressed data stream in the input file/buffer. If a new
+compressed data stream is found, the eof marker will be cleared and C<$.>
+will be reset to 0.
+
+Returns 1 if a new stream was found, 0 if none was found, and -1 if an
+error was encountered.
+
+=head2 trailingData
+
+Usage is
+
+ my $data = $z->trailingData();
+
+Returns the data, if any, that is present immediately after the compressed
+data stream once uncompression is complete. It only makes sense to call
+this method once the end of the compressed data stream has been
+encountered.
+
+This option can be used when there is useful information immediately
+following the compressed data stream, and you don't know the length of the
+compressed data stream.
+
+If the input is a buffer, C<trailingData> will return everything from the
+end of the compressed data stream to the end of the buffer.
+
+If the input is a filehandle, C<trailingData> will return the data that is
+left in the filehandle input buffer once the end of the compressed data
+stream has been reached. You can then use the filehandle to read the rest
+of the input file.
+
+Don't bother using C<trailingData> if the input is a filename.
+
+If you know the length of the compressed data stream before you start
+uncompressing, you can avoid having to use C<trailingData> by setting the
+C<InputLength> option in the constructor.
+
+=head1 Importing
+
+No symbolic constants are required by this IO::Uncompress::Bunzip2 at present.
+
+=over 5
+
+=item :all
+
+Imports C<bunzip2> and C<$Bunzip2Error>.
+Same as doing this
+
+ use IO::Uncompress::Bunzip2 qw(bunzip2 $Bunzip2Error) ;
+
+=back
+
+=head1 EXAMPLES
+
+=head2 Working with Net::FTP
+
+See L<IO::Uncompress::Bunzip2::FAQ|IO::Uncompress::Bunzip2::FAQ/"Compressed files and Net::FTP">
+
+=head1 SEE ALSO
+
+L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Compress::Deflate>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Compress::Bzip2>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
+
+L<Compress::Zlib::FAQ|Compress::Zlib::FAQ>
+
+L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
+L<Archive::Tar|Archive::Tar>,
+L<IO::Zlib|IO::Zlib>
+
+The primary site for the bzip2 program is F<http://www.bzip.org>.
+
+See the module L<Compress::Bzip2|Compress::Bzip2>
+
+=head1 AUTHOR
+
+This module was written by Paul Marquess, F<pmqs@cpan.org>.
+
+=head1 MODIFICATION HISTORY
+
+See the Changes file.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2005-2008 Paul Marquess. All rights reserved.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Uncompress/Gunzip.pm b/Master/tlpkg/tlperl/lib/IO/Uncompress/Gunzip.pm
new file mode 100644
index 00000000000..f3e4e6561f0
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Uncompress/Gunzip.pm
@@ -0,0 +1,1111 @@
+
+package IO::Uncompress::Gunzip ;
+
+require 5.004 ;
+
+# for RFC1952
+
+use strict ;
+use warnings;
+use bytes;
+
+use IO::Uncompress::RawInflate 2.024 ;
+
+use Compress::Raw::Zlib 2.024 qw( crc32 ) ;
+use IO::Compress::Base::Common 2.024 qw(:Status createSelfTiedObject);
+use IO::Compress::Gzip::Constants 2.024 ;
+use IO::Compress::Zlib::Extra 2.024 ;
+
+require Exporter ;
+
+our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $GunzipError);
+
+@ISA = qw( Exporter IO::Uncompress::RawInflate );
+@EXPORT_OK = qw( $GunzipError gunzip );
+%EXPORT_TAGS = %IO::Uncompress::RawInflate::DEFLATE_CONSTANTS ;
+push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
+Exporter::export_ok_tags('all');
+
+$GunzipError = '';
+
+$VERSION = '2.024';
+
+sub new
+{
+ my $class = shift ;
+ $GunzipError = '';
+ my $obj = createSelfTiedObject($class, \$GunzipError);
+
+ $obj->_create(undef, 0, @_);
+}
+
+sub gunzip
+{
+ my $obj = createSelfTiedObject(undef, \$GunzipError);
+ return $obj->_inf(@_) ;
+}
+
+sub getExtraParams
+{
+ use IO::Compress::Base::Common 2.024 qw(:Parse);
+ return ( 'ParseExtra' => [1, 1, Parse_boolean, 0] ) ;
+}
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ # gunzip always needs crc32
+ $got->value('CRC32' => 1);
+
+ return 1;
+}
+
+sub ckMagic
+{
+ my $self = shift;
+
+ my $magic ;
+ $self->smartReadExact(\$magic, GZIP_ID_SIZE);
+
+ *$self->{HeaderPending} = $magic ;
+
+ return $self->HeaderError("Minimum header size is " .
+ GZIP_MIN_HEADER_SIZE . " bytes")
+ if length $magic != GZIP_ID_SIZE ;
+
+ return $self->HeaderError("Bad Magic")
+ if ! isGzipMagic($magic) ;
+
+ *$self->{Type} = 'rfc1952';
+
+ return $magic ;
+}
+
+sub readHeader
+{
+ my $self = shift;
+ my $magic = shift;
+
+ return $self->_readGzipHeader($magic);
+}
+
+sub chkTrailer
+{
+ my $self = shift;
+ my $trailer = shift;
+
+ # Check CRC & ISIZE
+ my ($CRC32, $ISIZE) = unpack("V V", $trailer) ;
+ *$self->{Info}{CRC32} = $CRC32;
+ *$self->{Info}{ISIZE} = $ISIZE;
+
+ if (*$self->{Strict}) {
+ return $self->TrailerError("CRC mismatch")
+ if $CRC32 != *$self->{Uncomp}->crc32() ;
+
+ my $exp_isize = *$self->{UnCompSize}->get32bit();
+ return $self->TrailerError("ISIZE mismatch. Got $ISIZE"
+ . ", expected $exp_isize")
+ if $ISIZE != $exp_isize ;
+ }
+
+ return STATUS_OK;
+}
+
+sub isGzipMagic
+{
+ my $buffer = shift ;
+ return 0 if length $buffer < GZIP_ID_SIZE ;
+ my ($id1, $id2) = unpack("C C", $buffer) ;
+ return $id1 == GZIP_ID1 && $id2 == GZIP_ID2 ;
+}
+
+sub _readFullGzipHeader($)
+{
+ my ($self) = @_ ;
+ my $magic = '' ;
+
+ $self->smartReadExact(\$magic, GZIP_ID_SIZE);
+
+ *$self->{HeaderPending} = $magic ;
+
+ return $self->HeaderError("Minimum header size is " .
+ GZIP_MIN_HEADER_SIZE . " bytes")
+ if length $magic != GZIP_ID_SIZE ;
+
+
+ return $self->HeaderError("Bad Magic")
+ if ! isGzipMagic($magic) ;
+
+ my $status = $self->_readGzipHeader($magic);
+ delete *$self->{Transparent} if ! defined $status ;
+ return $status ;
+}
+
+sub _readGzipHeader($)
+{
+ my ($self, $magic) = @_ ;
+ my ($HeaderCRC) ;
+ my ($buffer) = '' ;
+
+ $self->smartReadExact(\$buffer, GZIP_MIN_HEADER_SIZE - GZIP_ID_SIZE)
+ or return $self->HeaderError("Minimum header size is " .
+ GZIP_MIN_HEADER_SIZE . " bytes") ;
+
+ my $keep = $magic . $buffer ;
+ *$self->{HeaderPending} = $keep ;
+
+ # now split out the various parts
+ my ($cm, $flag, $mtime, $xfl, $os) = unpack("C C V C C", $buffer) ;
+
+ $cm == GZIP_CM_DEFLATED
+ or return $self->HeaderError("Not Deflate (CM is $cm)") ;
+
+ # check for use of reserved bits
+ return $self->HeaderError("Use of Reserved Bits in FLG field.")
+ if $flag & GZIP_FLG_RESERVED ;
+
+ my $EXTRA ;
+ my @EXTRA = () ;
+ if ($flag & GZIP_FLG_FEXTRA) {
+ $EXTRA = "" ;
+ $self->smartReadExact(\$buffer, GZIP_FEXTRA_HEADER_SIZE)
+ or return $self->TruncatedHeader("FEXTRA Length") ;
+
+ my ($XLEN) = unpack("v", $buffer) ;
+ $self->smartReadExact(\$EXTRA, $XLEN)
+ or return $self->TruncatedHeader("FEXTRA Body");
+ $keep .= $buffer . $EXTRA ;
+
+ if ($XLEN && *$self->{'ParseExtra'}) {
+ my $bad = IO::Compress::Zlib::Extra::parseRawExtra($EXTRA,
+ \@EXTRA, 1, 1);
+ return $self->HeaderError($bad)
+ if defined $bad;
+ }
+ }
+
+ my $origname ;
+ if ($flag & GZIP_FLG_FNAME) {
+ $origname = "" ;
+ while (1) {
+ $self->smartReadExact(\$buffer, 1)
+ or return $self->TruncatedHeader("FNAME");
+ last if $buffer eq GZIP_NULL_BYTE ;
+ $origname .= $buffer
+ }
+ $keep .= $origname . GZIP_NULL_BYTE ;
+
+ return $self->HeaderError("Non ISO 8859-1 Character found in Name")
+ if *$self->{Strict} && $origname =~ /$GZIP_FNAME_INVALID_CHAR_RE/o ;
+ }
+
+ my $comment ;
+ if ($flag & GZIP_FLG_FCOMMENT) {
+ $comment = "";
+ while (1) {
+ $self->smartReadExact(\$buffer, 1)
+ or return $self->TruncatedHeader("FCOMMENT");
+ last if $buffer eq GZIP_NULL_BYTE ;
+ $comment .= $buffer
+ }
+ $keep .= $comment . GZIP_NULL_BYTE ;
+
+ return $self->HeaderError("Non ISO 8859-1 Character found in Comment")
+ if *$self->{Strict} && $comment =~ /$GZIP_FCOMMENT_INVALID_CHAR_RE/o ;
+ }
+
+ if ($flag & GZIP_FLG_FHCRC) {
+ $self->smartReadExact(\$buffer, GZIP_FHCRC_SIZE)
+ or return $self->TruncatedHeader("FHCRC");
+
+ $HeaderCRC = unpack("v", $buffer) ;
+ my $crc16 = crc32($keep) & 0xFF ;
+
+ return $self->HeaderError("CRC16 mismatch.")
+ if *$self->{Strict} && $crc16 != $HeaderCRC;
+
+ $keep .= $buffer ;
+ }
+
+ # Assume compression method is deflated for xfl tests
+ #if ($xfl) {
+ #}
+
+ *$self->{Type} = 'rfc1952';
+
+ return {
+ 'Type' => 'rfc1952',
+ 'FingerprintLength' => 2,
+ 'HeaderLength' => length $keep,
+ 'TrailerLength' => GZIP_TRAILER_SIZE,
+ 'Header' => $keep,
+ 'isMinimalHeader' => $keep eq GZIP_MINIMUM_HEADER ? 1 : 0,
+
+ 'MethodID' => $cm,
+ 'MethodName' => $cm == GZIP_CM_DEFLATED ? "Deflated" : "Unknown" ,
+ 'TextFlag' => $flag & GZIP_FLG_FTEXT ? 1 : 0,
+ 'HeaderCRCFlag' => $flag & GZIP_FLG_FHCRC ? 1 : 0,
+ 'NameFlag' => $flag & GZIP_FLG_FNAME ? 1 : 0,
+ 'CommentFlag' => $flag & GZIP_FLG_FCOMMENT ? 1 : 0,
+ 'ExtraFlag' => $flag & GZIP_FLG_FEXTRA ? 1 : 0,
+ 'Name' => $origname,
+ 'Comment' => $comment,
+ 'Time' => $mtime,
+ 'OsID' => $os,
+ 'OsName' => defined $GZIP_OS_Names{$os}
+ ? $GZIP_OS_Names{$os} : "Unknown",
+ 'HeaderCRC' => $HeaderCRC,
+ 'Flags' => $flag,
+ 'ExtraFlags' => $xfl,
+ 'ExtraFieldRaw' => $EXTRA,
+ 'ExtraField' => [ @EXTRA ],
+
+
+ #'CompSize'=> $compsize,
+ #'CRC32'=> $CRC32,
+ #'OrigSize'=> $ISIZE,
+ }
+}
+
+
+1;
+
+__END__
+
+
+=head1 NAME
+
+IO::Uncompress::Gunzip - Read RFC 1952 files/buffers
+
+=head1 SYNOPSIS
+
+ use IO::Uncompress::Gunzip qw(gunzip $GunzipError) ;
+
+ my $status = gunzip $input => $output [,OPTS]
+ or die "gunzip failed: $GunzipError\n";
+
+ my $z = new IO::Uncompress::Gunzip $input [OPTS]
+ or die "gunzip failed: $GunzipError\n";
+
+ $status = $z->read($buffer)
+ $status = $z->read($buffer, $length)
+ $status = $z->read($buffer, $length, $offset)
+ $line = $z->getline()
+ $char = $z->getc()
+ $char = $z->ungetc()
+ $char = $z->opened()
+
+ $status = $z->inflateSync()
+
+ $data = $z->trailingData()
+ $status = $z->nextStream()
+ $data = $z->getHeaderInfo()
+ $z->tell()
+ $z->seek($position, $whence)
+ $z->binmode()
+ $z->fileno()
+ $z->eof()
+ $z->close()
+
+ $GunzipError ;
+
+ # IO::File mode
+
+ <$z>
+ read($z, $buffer);
+ read($z, $buffer, $length);
+ read($z, $buffer, $length, $offset);
+ tell($z)
+ seek($z, $position, $whence)
+ binmode($z)
+ fileno($z)
+ eof($z)
+ close($z)
+
+=head1 DESCRIPTION
+
+This module provides a Perl interface that allows the reading of
+files/buffers that conform to RFC 1952.
+
+For writing RFC 1952 files/buffers, see the companion module IO::Compress::Gzip.
+
+=head1 Functional Interface
+
+A top-level function, C<gunzip>, is provided to carry out
+"one-shot" uncompression between buffers and/or files. For finer
+control over the uncompression process, see the L</"OO Interface">
+section.
+
+ use IO::Uncompress::Gunzip qw(gunzip $GunzipError) ;
+
+ gunzip $input => $output [,OPTS]
+ or die "gunzip failed: $GunzipError\n";
+
+The functional interface needs Perl5.005 or better.
+
+=head2 gunzip $input => $output [, OPTS]
+
+C<gunzip> expects at least two parameters, C<$input> and C<$output>.
+
+=head3 The C<$input> parameter
+
+The parameter, C<$input>, is used to define the source of
+the compressed data.
+
+It can take one of the following forms:
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for reading and the input data
+will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the input data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the input data will be read
+from C<$$input>.
+
+=item An array reference
+
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
+The complete array will be walked to ensure that it only
+contains valid filenames before any data is uncompressed.
+
+=item An Input FileGlob string
+
+If C<$input> is a string that is delimited by the characters "<" and ">"
+C<gunzip> will assume that it is an I<input fileglob string>. The
+input is the list of files that match the fileglob.
+
+If the fileglob does not match any files ...
+
+See L<File::GlobMapper|File::GlobMapper> for more details.
+
+=back
+
+If the C<$input> parameter is any other type, C<undef> will be returned.
+
+=head3 The C<$output> parameter
+
+The parameter C<$output> is used to control the destination of the
+uncompressed data. This parameter can take one of these forms.
+
+=over 5
+
+=item A filename
+
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the uncompressed
+data will be written to it.
+
+=item A filehandle
+
+If the C<$output> parameter is a filehandle, the uncompressed data
+will be written to it.
+The string '-' can be used as an alias for standard output.
+
+=item A scalar reference
+
+If C<$output> is a scalar reference, the uncompressed data will be
+stored in C<$$output>.
+
+=item An Array Reference
+
+If C<$output> is an array reference, the uncompressed data will be
+pushed onto the array.
+
+=item An Output FileGlob
+
+If C<$output> is a string that is delimited by the characters "<" and ">"
+C<gunzip> will assume that it is an I<output fileglob string>. The
+output is the list of files that match the fileglob.
+
+When C<$output> is an fileglob string, C<$input> must also be a fileglob
+string. Anything else is an error.
+
+=back
+
+If the C<$output> parameter is any other type, C<undef> will be returned.
+
+=head2 Notes
+
+When C<$input> maps to multiple compressed files/buffers and C<$output> is
+a single file/buffer, after uncompression C<$output> will contain a
+concatenation of all the uncompressed data from each of the input
+files/buffers.
+
+=head2 Optional Parameters
+
+Unless specified below, the optional parameters for C<gunzip>,
+C<OPTS>, are the same as those used with the OO interface defined in the
+L</"Constructor Options"> section below.
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option applies to any input or output data streams to
+C<gunzip> that are filehandles.
+
+If C<AutoClose> is specified, and the value is true, it will result in all
+input and/or output filehandles being closed once C<gunzip> has
+completed.
+
+This parameter defaults to 0.
+
+=item C<< BinModeOut => 0|1 >>
+
+When writing to a file or filehandle, set C<binmode> before writing to the
+file.
+
+Defaults to 0.
+
+=item C<< Append => 0|1 >>
+
+The behaviour of this option is dependent on the type of output data
+stream.
+
+=over 5
+
+=item * A Buffer
+
+If C<Append> is enabled, all uncompressed data will be append to the end of
+the output buffer. Otherwise the output buffer will be cleared before any
+uncompressed data is written to it.
+
+=item * A Filename
+
+If C<Append> is enabled, the file will be opened in append mode. Otherwise
+the contents of the file, if any, will be truncated before any uncompressed
+data is written to it.
+
+=item * A Filehandle
+
+If C<Append> is enabled, the filehandle will be positioned to the end of
+the file via a call to C<seek> before any uncompressed data is
+written to it. Otherwise the file pointer will not be moved.
+
+=back
+
+When C<Append> is specified, and set to true, it will I<append> all uncompressed
+data to the output data stream.
+
+So when the output is a filehandle it will carry out a seek to the eof
+before writing any uncompressed data. If the output is a filename, it will be opened for
+appending. If the output is a buffer, all uncompressed data will be appened to
+the existing buffer.
+
+Conversely when C<Append> is not specified, or it is present and is set to
+false, it will operate as follows.
+
+When the output is a filename, it will truncate the contents of the file
+before writing any uncompressed data. If the output is a filehandle
+its position will not be changed. If the output is a buffer, it will be
+wiped before any uncompressed data is output.
+
+Defaults to 0.
+
+=item C<< MultiStream => 0|1 >>
+
+If the input file/buffer contains multiple compressed data streams, this
+option will uncompress the whole lot as a single data stream.
+
+Defaults to 0.
+
+=item C<< TrailingData => $scalar >>
+
+Returns the data, if any, that is present immediately after the compressed
+data stream once uncompression is complete.
+
+This option can be used when there is useful information immediately
+following the compressed data stream, and you don't know the length of the
+compressed data stream.
+
+If the input is a buffer, C<trailingData> will return everything from the
+end of the compressed data stream to the end of the buffer.
+
+If the input is a filehandle, C<trailingData> will return the data that is
+left in the filehandle input buffer once the end of the compressed data
+stream has been reached. You can then use the filehandle to read the rest
+of the input file.
+
+Don't bother using C<trailingData> if the input is a filename.
+
+If you know the length of the compressed data stream before you start
+uncompressing, you can avoid having to use C<trailingData> by setting the
+C<InputLength> option.
+
+=back
+
+=head2 Examples
+
+To read the contents of the file C<file1.txt.gz> and write the
+uncompressed data to the file C<file1.txt>.
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::Gunzip qw(gunzip $GunzipError) ;
+
+ my $input = "file1.txt.gz";
+ my $output = "file1.txt";
+ gunzip $input => $output
+ or die "gunzip failed: $GunzipError\n";
+
+To read from an existing Perl filehandle, C<$input>, and write the
+uncompressed data to a buffer, C<$buffer>.
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::Gunzip qw(gunzip $GunzipError) ;
+ use IO::File ;
+
+ my $input = new IO::File "<file1.txt.gz"
+ or die "Cannot open 'file1.txt.gz': $!\n" ;
+ my $buffer ;
+ gunzip $input => \$buffer
+ or die "gunzip failed: $GunzipError\n";
+
+To uncompress all files in the directory "/my/home" that match "*.txt.gz" and store the compressed data in the same directory
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::Gunzip qw(gunzip $GunzipError) ;
+
+ gunzip '</my/home/*.txt.gz>' => '</my/home/#1.txt>'
+ or die "gunzip failed: $GunzipError\n";
+
+and if you want to compress each file one at a time, this will do the trick
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::Gunzip qw(gunzip $GunzipError) ;
+
+ for my $input ( glob "/my/home/*.txt.gz" )
+ {
+ my $output = $input;
+ $output =~ s/.gz// ;
+ gunzip $input => $output
+ or die "Error compressing '$input': $GunzipError\n";
+ }
+
+=head1 OO Interface
+
+=head2 Constructor
+
+The format of the constructor for IO::Uncompress::Gunzip is shown below
+
+ my $z = new IO::Uncompress::Gunzip $input [OPTS]
+ or die "IO::Uncompress::Gunzip failed: $GunzipError\n";
+
+Returns an C<IO::Uncompress::Gunzip> object on success and undef on failure.
+The variable C<$GunzipError> will contain an error message on failure.
+
+If you are running Perl 5.005 or better the object, C<$z>, returned from
+IO::Uncompress::Gunzip can be used exactly like an L<IO::File|IO::File> filehandle.
+This means that all normal input file operations can be carried out with
+C<$z>. For example, to read a line from a compressed file/buffer you can
+use either of these forms
+
+ $line = $z->getline();
+ $line = <$z>;
+
+The mandatory parameter C<$input> is used to determine the source of the
+compressed data. This parameter can take one of three forms.
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a scalar, it is assumed to be a filename. This
+file will be opened for reading and the compressed data will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the compressed data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the compressed data will be read from
+C<$$output>.
+
+=back
+
+=head2 Constructor Options
+
+The option names defined below are case insensitive and can be optionally
+prefixed by a '-'. So all of the following are valid
+
+ -AutoClose
+ -autoclose
+ AUTOCLOSE
+ autoclose
+
+OPTS is a combination of the following options:
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option is only valid when the C<$input> parameter is a filehandle. If
+specified, and the value is true, it will result in the file being closed once
+either the C<close> method is called or the IO::Uncompress::Gunzip object is
+destroyed.
+
+This parameter defaults to 0.
+
+=item C<< MultiStream => 0|1 >>
+
+Allows multiple concatenated compressed streams to be treated as a single
+compressed stream. Decompression will stop once either the end of the
+file/buffer is reached, an error is encountered (premature eof, corrupt
+compressed data) or the end of a stream is not immediately followed by the
+start of another stream.
+
+This parameter defaults to 0.
+
+=item C<< Prime => $string >>
+
+This option will uncompress the contents of C<$string> before processing the
+input file/buffer.
+
+This option can be useful when the compressed data is embedded in another
+file/data structure and it is not possible to work out where the compressed
+data begins without having to read the first few bytes. If this is the
+case, the uncompression can be I<primed> with these bytes using this
+option.
+
+=item C<< Transparent => 0|1 >>
+
+If this option is set and the input file/buffer is not compressed data,
+the module will allow reading of it anyway.
+
+In addition, if the input file/buffer does contain compressed data and
+there is non-compressed data immediately following it, setting this option
+will make this module treat the whole file/bufffer as a single data stream.
+
+This option defaults to 1.
+
+=item C<< BlockSize => $num >>
+
+When reading the compressed input data, IO::Uncompress::Gunzip will read it in
+blocks of C<$num> bytes.
+
+This option defaults to 4096.
+
+=item C<< InputLength => $size >>
+
+When present this option will limit the number of compressed bytes read
+from the input file/buffer to C<$size>. This option can be used in the
+situation where there is useful data directly after the compressed data
+stream and you know beforehand the exact length of the compressed data
+stream.
+
+This option is mostly used when reading from a filehandle, in which case
+the file pointer will be left pointing to the first byte directly after the
+compressed data stream.
+
+This option defaults to off.
+
+=item C<< Append => 0|1 >>
+
+This option controls what the C<read> method does with uncompressed data.
+
+If set to 1, all uncompressed data will be appended to the output parameter
+of the C<read> method.
+
+If set to 0, the contents of the output parameter of the C<read> method
+will be overwritten by the uncompressed data.
+
+Defaults to 0.
+
+=item C<< Strict => 0|1 >>
+
+This option controls whether the extra checks defined below are used when
+carrying out the decompression. When Strict is on, the extra tests are
+carried out, when Strict is off they are not.
+
+The default for this option is off.
+
+=over 5
+
+=item 1
+
+If the FHCRC bit is set in the gzip FLG header byte, the CRC16 bytes in the
+header must match the crc16 value of the gzip header actually read.
+
+=item 2
+
+If the gzip header contains a name field (FNAME) it consists solely of ISO
+8859-1 characters.
+
+=item 3
+
+If the gzip header contains a comment field (FCOMMENT) it consists solely
+of ISO 8859-1 characters plus line-feed.
+
+=item 4
+
+If the gzip FEXTRA header field is present it must conform to the sub-field
+structure as defined in RFC 1952.
+
+=item 5
+
+The CRC32 and ISIZE trailer fields must be present.
+
+=item 6
+
+The value of the CRC32 field read must match the crc32 value of the
+uncompressed data actually contained in the gzip file.
+
+=item 7
+
+The value of the ISIZE fields read must match the length of the
+uncompressed data actually read from the file.
+
+=back
+
+=item C<< ParseExtra => 0|1 >>
+If the gzip FEXTRA header field is present and this option is set, it will
+force the module to check that it conforms to the sub-field structure as
+defined in RFC 1952.
+
+If the C<Strict> is on it will automatically enable this option.
+
+Defaults to 0.
+
+=back
+
+=head2 Examples
+
+TODO
+
+=head1 Methods
+
+=head2 read
+
+Usage is
+
+ $status = $z->read($buffer)
+
+Reads a block of compressed data (the size the the compressed block is
+determined by the C<Buffer> option in the constructor), uncompresses it and
+writes any uncompressed data into C<$buffer>. If the C<Append> parameter is
+set in the constructor, the uncompressed data will be appended to the
+C<$buffer> parameter. Otherwise C<$buffer> will be overwritten.
+
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
+
+=head2 read
+
+Usage is
+
+ $status = $z->read($buffer, $length)
+ $status = $z->read($buffer, $length, $offset)
+
+ $status = read($z, $buffer, $length)
+ $status = read($z, $buffer, $length, $offset)
+
+Attempt to read C<$length> bytes of uncompressed data into C<$buffer>.
+
+The main difference between this form of the C<read> method and the
+previous one, is that this one will attempt to return I<exactly> C<$length>
+bytes. The only circumstances that this function will not is if end-of-file
+or an IO error is encountered.
+
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
+
+=head2 getline
+
+Usage is
+
+ $line = $z->getline()
+ $line = <$z>
+
+Reads a single line.
+
+This method fully supports the use of of the variable C<$/> (or
+C<$INPUT_RECORD_SEPARATOR> or C<$RS> when C<English> is in use) to
+determine what constitutes an end of line. Paragraph mode, record mode and
+file slurp mode are all supported.
+
+=head2 getc
+
+Usage is
+
+ $char = $z->getc()
+
+Read a single character.
+
+=head2 ungetc
+
+Usage is
+
+ $char = $z->ungetc($string)
+
+=head2 inflateSync
+
+Usage is
+
+ $status = $z->inflateSync()
+
+TODO
+
+=head2 getHeaderInfo
+
+Usage is
+
+ $hdr = $z->getHeaderInfo();
+ @hdrs = $z->getHeaderInfo();
+
+This method returns either a hash reference (in scalar context) or a list
+or hash references (in array context) that contains information about each
+of the header fields in the compressed data stream(s).
+
+=over 5
+
+=item Name
+
+The contents of the Name header field, if present. If no name is
+present, the value will be undef. Note this is different from a zero length
+name, which will return an empty string.
+
+=item Comment
+
+The contents of the Comment header field, if present. If no comment is
+present, the value will be undef. Note this is different from a zero length
+comment, which will return an empty string.
+
+=back
+
+=head2 tell
+
+Usage is
+
+ $z->tell()
+ tell $z
+
+Returns the uncompressed file offset.
+
+=head2 eof
+
+Usage is
+
+ $z->eof();
+ eof($z);
+
+Returns true if the end of the compressed input stream has been reached.
+
+=head2 seek
+
+ $z->seek($position, $whence);
+ seek($z, $position, $whence);
+
+Provides a sub-set of the C<seek> functionality, with the restriction
+that it is only legal to seek forward in the input file/buffer.
+It is a fatal error to attempt to seek backward.
+
+The C<$whence> parameter takes one the usual values, namely SEEK_SET,
+SEEK_CUR or SEEK_END.
+
+Returns 1 on success, 0 on failure.
+
+=head2 binmode
+
+Usage is
+
+ $z->binmode
+ binmode $z ;
+
+This is a noop provided for completeness.
+
+=head2 opened
+
+ $z->opened()
+
+Returns true if the object currently refers to a opened file/buffer.
+
+=head2 autoflush
+
+ my $prev = $z->autoflush()
+ my $prev = $z->autoflush(EXPR)
+
+If the C<$z> object is associated with a file or a filehandle, this method
+returns the current autoflush setting for the underlying filehandle. If
+C<EXPR> is present, and is non-zero, it will enable flushing after every
+write/print operation.
+
+If C<$z> is associated with a buffer, this method has no effect and always
+returns C<undef>.
+
+B<Note> that the special variable C<$|> B<cannot> be used to set or
+retrieve the autoflush setting.
+
+=head2 input_line_number
+
+ $z->input_line_number()
+ $z->input_line_number(EXPR)
+
+Returns the current uncompressed line number. If C<EXPR> is present it has
+the effect of setting the line number. Note that setting the line number
+does not change the current position within the file/buffer being read.
+
+The contents of C<$/> are used to to determine what constitutes a line
+terminator.
+
+=head2 fileno
+
+ $z->fileno()
+ fileno($z)
+
+If the C<$z> object is associated with a file or a filehandle, C<fileno>
+will return the underlying file descriptor. Once the C<close> method is
+called C<fileno> will return C<undef>.
+
+If the C<$z> object is is associated with a buffer, this method will return
+C<undef>.
+
+=head2 close
+
+ $z->close() ;
+ close $z ;
+
+Closes the output file/buffer.
+
+For most versions of Perl this method will be automatically invoked if
+the IO::Uncompress::Gunzip object is destroyed (either explicitly or by the
+variable with the reference to the object going out of scope). The
+exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In
+these cases, the C<close> method will be called automatically, but
+not until global destruction of all live objects when the program is
+terminating.
+
+Therefore, if you want your scripts to be able to run on all versions
+of Perl, you should call C<close> explicitly and not rely on automatic
+closing.
+
+Returns true on success, otherwise 0.
+
+If the C<AutoClose> option has been enabled when the IO::Uncompress::Gunzip
+object was created, and the object is associated with a file, the
+underlying file will also be closed.
+
+=head2 nextStream
+
+Usage is
+
+ my $status = $z->nextStream();
+
+Skips to the next compressed data stream in the input file/buffer. If a new
+compressed data stream is found, the eof marker will be cleared and C<$.>
+will be reset to 0.
+
+Returns 1 if a new stream was found, 0 if none was found, and -1 if an
+error was encountered.
+
+=head2 trailingData
+
+Usage is
+
+ my $data = $z->trailingData();
+
+Returns the data, if any, that is present immediately after the compressed
+data stream once uncompression is complete. It only makes sense to call
+this method once the end of the compressed data stream has been
+encountered.
+
+This option can be used when there is useful information immediately
+following the compressed data stream, and you don't know the length of the
+compressed data stream.
+
+If the input is a buffer, C<trailingData> will return everything from the
+end of the compressed data stream to the end of the buffer.
+
+If the input is a filehandle, C<trailingData> will return the data that is
+left in the filehandle input buffer once the end of the compressed data
+stream has been reached. You can then use the filehandle to read the rest
+of the input file.
+
+Don't bother using C<trailingData> if the input is a filename.
+
+If you know the length of the compressed data stream before you start
+uncompressing, you can avoid having to use C<trailingData> by setting the
+C<InputLength> option in the constructor.
+
+=head1 Importing
+
+No symbolic constants are required by this IO::Uncompress::Gunzip at present.
+
+=over 5
+
+=item :all
+
+Imports C<gunzip> and C<$GunzipError>.
+Same as doing this
+
+ use IO::Uncompress::Gunzip qw(gunzip $GunzipError) ;
+
+=back
+
+=head1 EXAMPLES
+
+=head2 Working with Net::FTP
+
+See L<IO::Uncompress::Gunzip::FAQ|IO::Uncompress::Gunzip::FAQ/"Compressed files and Net::FTP">
+
+=head1 SEE ALSO
+
+L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Compress::Deflate>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Compress::Bzip2>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
+
+L<Compress::Zlib::FAQ|Compress::Zlib::FAQ>
+
+L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
+L<Archive::Tar|Archive::Tar>,
+L<IO::Zlib|IO::Zlib>
+
+For RFC 1950, 1951 and 1952 see
+F<http://www.faqs.org/rfcs/rfc1950.html>,
+F<http://www.faqs.org/rfcs/rfc1951.html> and
+F<http://www.faqs.org/rfcs/rfc1952.html>
+
+The I<zlib> compression library was written by Jean-loup Gailly
+F<gzip@prep.ai.mit.edu> and Mark Adler F<madler@alumni.caltech.edu>.
+
+The primary site for the I<zlib> compression library is
+F<http://www.zlib.org>.
+
+The primary site for gzip is F<http://www.gzip.org>.
+
+=head1 AUTHOR
+
+This module was written by Paul Marquess, F<pmqs@cpan.org>.
+
+=head1 MODIFICATION HISTORY
+
+See the Changes file.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2005-2010 Paul Marquess. All rights reserved.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Uncompress/Inflate.pm b/Master/tlpkg/tlperl/lib/IO/Uncompress/Inflate.pm
new file mode 100644
index 00000000000..956f62e0835
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Uncompress/Inflate.pm
@@ -0,0 +1,982 @@
+package IO::Uncompress::Inflate ;
+# for RFC1950
+
+use strict ;
+use warnings;
+use bytes;
+
+use IO::Compress::Base::Common 2.024 qw(:Status createSelfTiedObject);
+use IO::Compress::Zlib::Constants 2.024 ;
+
+use IO::Uncompress::RawInflate 2.024 ;
+
+require Exporter ;
+our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $InflateError);
+
+$VERSION = '2.024';
+$InflateError = '';
+
+@ISA = qw( Exporter IO::Uncompress::RawInflate );
+@EXPORT_OK = qw( $InflateError inflate ) ;
+%EXPORT_TAGS = %IO::Uncompress::RawInflate::DEFLATE_CONSTANTS ;
+push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
+Exporter::export_ok_tags('all');
+
+
+sub new
+{
+ my $class = shift ;
+ my $obj = createSelfTiedObject($class, \$InflateError);
+
+ $obj->_create(undef, 0, @_);
+}
+
+sub inflate
+{
+ my $obj = createSelfTiedObject(undef, \$InflateError);
+ return $obj->_inf(@_);
+}
+
+sub getExtraParams
+{
+ return ();
+}
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ # gunzip always needs adler32
+ $got->value('ADLER32' => 1);
+
+ return 1;
+}
+
+sub ckMagic
+{
+ my $self = shift;
+
+ my $magic ;
+ $self->smartReadExact(\$magic, ZLIB_HEADER_SIZE);
+
+ *$self->{HeaderPending} = $magic ;
+
+ return $self->HeaderError("Header size is " .
+ ZLIB_HEADER_SIZE . " bytes")
+ if length $magic != ZLIB_HEADER_SIZE;
+
+ #return $self->HeaderError("CRC mismatch.")
+ return undef
+ if ! $self->isZlibMagic($magic) ;
+
+ *$self->{Type} = 'rfc1950';
+ return $magic;
+}
+
+sub readHeader
+{
+ my $self = shift;
+ my $magic = shift ;
+
+ return $self->_readDeflateHeader($magic) ;
+}
+
+sub chkTrailer
+{
+ my $self = shift;
+ my $trailer = shift;
+
+ my $ADLER32 = unpack("N", $trailer) ;
+ *$self->{Info}{ADLER32} = $ADLER32;
+ return $self->TrailerError("CRC mismatch")
+ if *$self->{Strict} && $ADLER32 != *$self->{Uncomp}->adler32() ;
+
+ return STATUS_OK;
+}
+
+
+
+sub isZlibMagic
+{
+ my $self = shift;
+ my $buffer = shift ;
+
+ return 0
+ if length $buffer < ZLIB_HEADER_SIZE ;
+
+ my $hdr = unpack("n", $buffer) ;
+ #return 0 if $hdr % 31 != 0 ;
+ return $self->HeaderError("CRC mismatch.")
+ if $hdr % 31 != 0 ;
+
+ my ($CMF, $FLG) = unpack "C C", $buffer;
+ my $cm = bits($CMF, ZLIB_CMF_CM_OFFSET, ZLIB_CMF_CM_BITS) ;
+
+ # Only Deflate supported
+ return $self->HeaderError("Not Deflate (CM is $cm)")
+ if $cm != ZLIB_CMF_CM_DEFLATED ;
+
+ # Max window value is 7 for Deflate.
+ my $cinfo = bits($CMF, ZLIB_CMF_CINFO_OFFSET, ZLIB_CMF_CINFO_BITS) ;
+ return $self->HeaderError("CINFO > " . ZLIB_CMF_CINFO_MAX .
+ " (CINFO is $cinfo)")
+ if $cinfo > ZLIB_CMF_CINFO_MAX ;
+
+ return 1;
+}
+
+sub bits
+{
+ my $data = shift ;
+ my $offset = shift ;
+ my $mask = shift ;
+
+ ($data >> $offset ) & $mask & 0xFF ;
+}
+
+
+sub _readDeflateHeader
+{
+ my ($self, $buffer) = @_ ;
+
+# if (! $buffer) {
+# $self->smartReadExact(\$buffer, ZLIB_HEADER_SIZE);
+#
+# *$self->{HeaderPending} = $buffer ;
+#
+# return $self->HeaderError("Header size is " .
+# ZLIB_HEADER_SIZE . " bytes")
+# if length $buffer != ZLIB_HEADER_SIZE;
+#
+# return $self->HeaderError("CRC mismatch.")
+# if ! isZlibMagic($buffer) ;
+# }
+
+ my ($CMF, $FLG) = unpack "C C", $buffer;
+ my $FDICT = bits($FLG, ZLIB_FLG_FDICT_OFFSET, ZLIB_FLG_FDICT_BITS ),
+
+ my $cm = bits($CMF, ZLIB_CMF_CM_OFFSET, ZLIB_CMF_CM_BITS) ;
+ $cm == ZLIB_CMF_CM_DEFLATED
+ or return $self->HeaderError("Not Deflate (CM is $cm)") ;
+
+ my $DICTID;
+ if ($FDICT) {
+ $self->smartReadExact(\$buffer, ZLIB_FDICT_SIZE)
+ or return $self->TruncatedHeader("FDICT");
+
+ $DICTID = unpack("N", $buffer) ;
+ }
+
+ *$self->{Type} = 'rfc1950';
+
+ return {
+ 'Type' => 'rfc1950',
+ 'FingerprintLength' => ZLIB_HEADER_SIZE,
+ 'HeaderLength' => ZLIB_HEADER_SIZE,
+ 'TrailerLength' => ZLIB_TRAILER_SIZE,
+ 'Header' => $buffer,
+
+ CMF => $CMF ,
+ CM => bits($CMF, ZLIB_CMF_CM_OFFSET, ZLIB_CMF_CM_BITS ),
+ CINFO => bits($CMF, ZLIB_CMF_CINFO_OFFSET, ZLIB_CMF_CINFO_BITS ),
+ FLG => $FLG ,
+ FCHECK => bits($FLG, ZLIB_FLG_FCHECK_OFFSET, ZLIB_FLG_FCHECK_BITS),
+ FDICT => bits($FLG, ZLIB_FLG_FDICT_OFFSET, ZLIB_FLG_FDICT_BITS ),
+ FLEVEL => bits($FLG, ZLIB_FLG_LEVEL_OFFSET, ZLIB_FLG_LEVEL_BITS ),
+ DICTID => $DICTID ,
+
+ };
+}
+
+
+
+
+1 ;
+
+__END__
+
+
+=head1 NAME
+
+IO::Uncompress::Inflate - Read RFC 1950 files/buffers
+
+=head1 SYNOPSIS
+
+ use IO::Uncompress::Inflate qw(inflate $InflateError) ;
+
+ my $status = inflate $input => $output [,OPTS]
+ or die "inflate failed: $InflateError\n";
+
+ my $z = new IO::Uncompress::Inflate $input [OPTS]
+ or die "inflate failed: $InflateError\n";
+
+ $status = $z->read($buffer)
+ $status = $z->read($buffer, $length)
+ $status = $z->read($buffer, $length, $offset)
+ $line = $z->getline()
+ $char = $z->getc()
+ $char = $z->ungetc()
+ $char = $z->opened()
+
+ $status = $z->inflateSync()
+
+ $data = $z->trailingData()
+ $status = $z->nextStream()
+ $data = $z->getHeaderInfo()
+ $z->tell()
+ $z->seek($position, $whence)
+ $z->binmode()
+ $z->fileno()
+ $z->eof()
+ $z->close()
+
+ $InflateError ;
+
+ # IO::File mode
+
+ <$z>
+ read($z, $buffer);
+ read($z, $buffer, $length);
+ read($z, $buffer, $length, $offset);
+ tell($z)
+ seek($z, $position, $whence)
+ binmode($z)
+ fileno($z)
+ eof($z)
+ close($z)
+
+=head1 DESCRIPTION
+
+This module provides a Perl interface that allows the reading of
+files/buffers that conform to RFC 1950.
+
+For writing RFC 1950 files/buffers, see the companion module IO::Compress::Deflate.
+
+=head1 Functional Interface
+
+A top-level function, C<inflate>, is provided to carry out
+"one-shot" uncompression between buffers and/or files. For finer
+control over the uncompression process, see the L</"OO Interface">
+section.
+
+ use IO::Uncompress::Inflate qw(inflate $InflateError) ;
+
+ inflate $input => $output [,OPTS]
+ or die "inflate failed: $InflateError\n";
+
+The functional interface needs Perl5.005 or better.
+
+=head2 inflate $input => $output [, OPTS]
+
+C<inflate> expects at least two parameters, C<$input> and C<$output>.
+
+=head3 The C<$input> parameter
+
+The parameter, C<$input>, is used to define the source of
+the compressed data.
+
+It can take one of the following forms:
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for reading and the input data
+will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the input data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the input data will be read
+from C<$$input>.
+
+=item An array reference
+
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
+The complete array will be walked to ensure that it only
+contains valid filenames before any data is uncompressed.
+
+=item An Input FileGlob string
+
+If C<$input> is a string that is delimited by the characters "<" and ">"
+C<inflate> will assume that it is an I<input fileglob string>. The
+input is the list of files that match the fileglob.
+
+If the fileglob does not match any files ...
+
+See L<File::GlobMapper|File::GlobMapper> for more details.
+
+=back
+
+If the C<$input> parameter is any other type, C<undef> will be returned.
+
+=head3 The C<$output> parameter
+
+The parameter C<$output> is used to control the destination of the
+uncompressed data. This parameter can take one of these forms.
+
+=over 5
+
+=item A filename
+
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the uncompressed
+data will be written to it.
+
+=item A filehandle
+
+If the C<$output> parameter is a filehandle, the uncompressed data
+will be written to it.
+The string '-' can be used as an alias for standard output.
+
+=item A scalar reference
+
+If C<$output> is a scalar reference, the uncompressed data will be
+stored in C<$$output>.
+
+=item An Array Reference
+
+If C<$output> is an array reference, the uncompressed data will be
+pushed onto the array.
+
+=item An Output FileGlob
+
+If C<$output> is a string that is delimited by the characters "<" and ">"
+C<inflate> will assume that it is an I<output fileglob string>. The
+output is the list of files that match the fileglob.
+
+When C<$output> is an fileglob string, C<$input> must also be a fileglob
+string. Anything else is an error.
+
+=back
+
+If the C<$output> parameter is any other type, C<undef> will be returned.
+
+=head2 Notes
+
+When C<$input> maps to multiple compressed files/buffers and C<$output> is
+a single file/buffer, after uncompression C<$output> will contain a
+concatenation of all the uncompressed data from each of the input
+files/buffers.
+
+=head2 Optional Parameters
+
+Unless specified below, the optional parameters for C<inflate>,
+C<OPTS>, are the same as those used with the OO interface defined in the
+L</"Constructor Options"> section below.
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option applies to any input or output data streams to
+C<inflate> that are filehandles.
+
+If C<AutoClose> is specified, and the value is true, it will result in all
+input and/or output filehandles being closed once C<inflate> has
+completed.
+
+This parameter defaults to 0.
+
+=item C<< BinModeOut => 0|1 >>
+
+When writing to a file or filehandle, set C<binmode> before writing to the
+file.
+
+Defaults to 0.
+
+=item C<< Append => 0|1 >>
+
+The behaviour of this option is dependent on the type of output data
+stream.
+
+=over 5
+
+=item * A Buffer
+
+If C<Append> is enabled, all uncompressed data will be append to the end of
+the output buffer. Otherwise the output buffer will be cleared before any
+uncompressed data is written to it.
+
+=item * A Filename
+
+If C<Append> is enabled, the file will be opened in append mode. Otherwise
+the contents of the file, if any, will be truncated before any uncompressed
+data is written to it.
+
+=item * A Filehandle
+
+If C<Append> is enabled, the filehandle will be positioned to the end of
+the file via a call to C<seek> before any uncompressed data is
+written to it. Otherwise the file pointer will not be moved.
+
+=back
+
+When C<Append> is specified, and set to true, it will I<append> all uncompressed
+data to the output data stream.
+
+So when the output is a filehandle it will carry out a seek to the eof
+before writing any uncompressed data. If the output is a filename, it will be opened for
+appending. If the output is a buffer, all uncompressed data will be appened to
+the existing buffer.
+
+Conversely when C<Append> is not specified, or it is present and is set to
+false, it will operate as follows.
+
+When the output is a filename, it will truncate the contents of the file
+before writing any uncompressed data. If the output is a filehandle
+its position will not be changed. If the output is a buffer, it will be
+wiped before any uncompressed data is output.
+
+Defaults to 0.
+
+=item C<< MultiStream => 0|1 >>
+
+If the input file/buffer contains multiple compressed data streams, this
+option will uncompress the whole lot as a single data stream.
+
+Defaults to 0.
+
+=item C<< TrailingData => $scalar >>
+
+Returns the data, if any, that is present immediately after the compressed
+data stream once uncompression is complete.
+
+This option can be used when there is useful information immediately
+following the compressed data stream, and you don't know the length of the
+compressed data stream.
+
+If the input is a buffer, C<trailingData> will return everything from the
+end of the compressed data stream to the end of the buffer.
+
+If the input is a filehandle, C<trailingData> will return the data that is
+left in the filehandle input buffer once the end of the compressed data
+stream has been reached. You can then use the filehandle to read the rest
+of the input file.
+
+Don't bother using C<trailingData> if the input is a filename.
+
+If you know the length of the compressed data stream before you start
+uncompressing, you can avoid having to use C<trailingData> by setting the
+C<InputLength> option.
+
+=back
+
+=head2 Examples
+
+To read the contents of the file C<file1.txt.1950> and write the
+uncompressed data to the file C<file1.txt>.
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::Inflate qw(inflate $InflateError) ;
+
+ my $input = "file1.txt.1950";
+ my $output = "file1.txt";
+ inflate $input => $output
+ or die "inflate failed: $InflateError\n";
+
+To read from an existing Perl filehandle, C<$input>, and write the
+uncompressed data to a buffer, C<$buffer>.
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::Inflate qw(inflate $InflateError) ;
+ use IO::File ;
+
+ my $input = new IO::File "<file1.txt.1950"
+ or die "Cannot open 'file1.txt.1950': $!\n" ;
+ my $buffer ;
+ inflate $input => \$buffer
+ or die "inflate failed: $InflateError\n";
+
+To uncompress all files in the directory "/my/home" that match "*.txt.1950" and store the compressed data in the same directory
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::Inflate qw(inflate $InflateError) ;
+
+ inflate '</my/home/*.txt.1950>' => '</my/home/#1.txt>'
+ or die "inflate failed: $InflateError\n";
+
+and if you want to compress each file one at a time, this will do the trick
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::Inflate qw(inflate $InflateError) ;
+
+ for my $input ( glob "/my/home/*.txt.1950" )
+ {
+ my $output = $input;
+ $output =~ s/.1950// ;
+ inflate $input => $output
+ or die "Error compressing '$input': $InflateError\n";
+ }
+
+=head1 OO Interface
+
+=head2 Constructor
+
+The format of the constructor for IO::Uncompress::Inflate is shown below
+
+ my $z = new IO::Uncompress::Inflate $input [OPTS]
+ or die "IO::Uncompress::Inflate failed: $InflateError\n";
+
+Returns an C<IO::Uncompress::Inflate> object on success and undef on failure.
+The variable C<$InflateError> will contain an error message on failure.
+
+If you are running Perl 5.005 or better the object, C<$z>, returned from
+IO::Uncompress::Inflate can be used exactly like an L<IO::File|IO::File> filehandle.
+This means that all normal input file operations can be carried out with
+C<$z>. For example, to read a line from a compressed file/buffer you can
+use either of these forms
+
+ $line = $z->getline();
+ $line = <$z>;
+
+The mandatory parameter C<$input> is used to determine the source of the
+compressed data. This parameter can take one of three forms.
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a scalar, it is assumed to be a filename. This
+file will be opened for reading and the compressed data will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the compressed data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the compressed data will be read from
+C<$$output>.
+
+=back
+
+=head2 Constructor Options
+
+The option names defined below are case insensitive and can be optionally
+prefixed by a '-'. So all of the following are valid
+
+ -AutoClose
+ -autoclose
+ AUTOCLOSE
+ autoclose
+
+OPTS is a combination of the following options:
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option is only valid when the C<$input> parameter is a filehandle. If
+specified, and the value is true, it will result in the file being closed once
+either the C<close> method is called or the IO::Uncompress::Inflate object is
+destroyed.
+
+This parameter defaults to 0.
+
+=item C<< MultiStream => 0|1 >>
+
+Allows multiple concatenated compressed streams to be treated as a single
+compressed stream. Decompression will stop once either the end of the
+file/buffer is reached, an error is encountered (premature eof, corrupt
+compressed data) or the end of a stream is not immediately followed by the
+start of another stream.
+
+This parameter defaults to 0.
+
+=item C<< Prime => $string >>
+
+This option will uncompress the contents of C<$string> before processing the
+input file/buffer.
+
+This option can be useful when the compressed data is embedded in another
+file/data structure and it is not possible to work out where the compressed
+data begins without having to read the first few bytes. If this is the
+case, the uncompression can be I<primed> with these bytes using this
+option.
+
+=item C<< Transparent => 0|1 >>
+
+If this option is set and the input file/buffer is not compressed data,
+the module will allow reading of it anyway.
+
+In addition, if the input file/buffer does contain compressed data and
+there is non-compressed data immediately following it, setting this option
+will make this module treat the whole file/bufffer as a single data stream.
+
+This option defaults to 1.
+
+=item C<< BlockSize => $num >>
+
+When reading the compressed input data, IO::Uncompress::Inflate will read it in
+blocks of C<$num> bytes.
+
+This option defaults to 4096.
+
+=item C<< InputLength => $size >>
+
+When present this option will limit the number of compressed bytes read
+from the input file/buffer to C<$size>. This option can be used in the
+situation where there is useful data directly after the compressed data
+stream and you know beforehand the exact length of the compressed data
+stream.
+
+This option is mostly used when reading from a filehandle, in which case
+the file pointer will be left pointing to the first byte directly after the
+compressed data stream.
+
+This option defaults to off.
+
+=item C<< Append => 0|1 >>
+
+This option controls what the C<read> method does with uncompressed data.
+
+If set to 1, all uncompressed data will be appended to the output parameter
+of the C<read> method.
+
+If set to 0, the contents of the output parameter of the C<read> method
+will be overwritten by the uncompressed data.
+
+Defaults to 0.
+
+=item C<< Strict => 0|1 >>
+
+This option controls whether the extra checks defined below are used when
+carrying out the decompression. When Strict is on, the extra tests are
+carried out, when Strict is off they are not.
+
+The default for this option is off.
+
+=over 5
+
+=item 1
+
+The ADLER32 checksum field must be present.
+
+=item 2
+
+The value of the ADLER32 field read must match the adler32 value of the
+uncompressed data actually contained in the file.
+
+=back
+
+=back
+
+=head2 Examples
+
+TODO
+
+=head1 Methods
+
+=head2 read
+
+Usage is
+
+ $status = $z->read($buffer)
+
+Reads a block of compressed data (the size the the compressed block is
+determined by the C<Buffer> option in the constructor), uncompresses it and
+writes any uncompressed data into C<$buffer>. If the C<Append> parameter is
+set in the constructor, the uncompressed data will be appended to the
+C<$buffer> parameter. Otherwise C<$buffer> will be overwritten.
+
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
+
+=head2 read
+
+Usage is
+
+ $status = $z->read($buffer, $length)
+ $status = $z->read($buffer, $length, $offset)
+
+ $status = read($z, $buffer, $length)
+ $status = read($z, $buffer, $length, $offset)
+
+Attempt to read C<$length> bytes of uncompressed data into C<$buffer>.
+
+The main difference between this form of the C<read> method and the
+previous one, is that this one will attempt to return I<exactly> C<$length>
+bytes. The only circumstances that this function will not is if end-of-file
+or an IO error is encountered.
+
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
+
+=head2 getline
+
+Usage is
+
+ $line = $z->getline()
+ $line = <$z>
+
+Reads a single line.
+
+This method fully supports the use of of the variable C<$/> (or
+C<$INPUT_RECORD_SEPARATOR> or C<$RS> when C<English> is in use) to
+determine what constitutes an end of line. Paragraph mode, record mode and
+file slurp mode are all supported.
+
+=head2 getc
+
+Usage is
+
+ $char = $z->getc()
+
+Read a single character.
+
+=head2 ungetc
+
+Usage is
+
+ $char = $z->ungetc($string)
+
+=head2 inflateSync
+
+Usage is
+
+ $status = $z->inflateSync()
+
+TODO
+
+=head2 getHeaderInfo
+
+Usage is
+
+ $hdr = $z->getHeaderInfo();
+ @hdrs = $z->getHeaderInfo();
+
+This method returns either a hash reference (in scalar context) or a list
+or hash references (in array context) that contains information about each
+of the header fields in the compressed data stream(s).
+
+=head2 tell
+
+Usage is
+
+ $z->tell()
+ tell $z
+
+Returns the uncompressed file offset.
+
+=head2 eof
+
+Usage is
+
+ $z->eof();
+ eof($z);
+
+Returns true if the end of the compressed input stream has been reached.
+
+=head2 seek
+
+ $z->seek($position, $whence);
+ seek($z, $position, $whence);
+
+Provides a sub-set of the C<seek> functionality, with the restriction
+that it is only legal to seek forward in the input file/buffer.
+It is a fatal error to attempt to seek backward.
+
+The C<$whence> parameter takes one the usual values, namely SEEK_SET,
+SEEK_CUR or SEEK_END.
+
+Returns 1 on success, 0 on failure.
+
+=head2 binmode
+
+Usage is
+
+ $z->binmode
+ binmode $z ;
+
+This is a noop provided for completeness.
+
+=head2 opened
+
+ $z->opened()
+
+Returns true if the object currently refers to a opened file/buffer.
+
+=head2 autoflush
+
+ my $prev = $z->autoflush()
+ my $prev = $z->autoflush(EXPR)
+
+If the C<$z> object is associated with a file or a filehandle, this method
+returns the current autoflush setting for the underlying filehandle. If
+C<EXPR> is present, and is non-zero, it will enable flushing after every
+write/print operation.
+
+If C<$z> is associated with a buffer, this method has no effect and always
+returns C<undef>.
+
+B<Note> that the special variable C<$|> B<cannot> be used to set or
+retrieve the autoflush setting.
+
+=head2 input_line_number
+
+ $z->input_line_number()
+ $z->input_line_number(EXPR)
+
+Returns the current uncompressed line number. If C<EXPR> is present it has
+the effect of setting the line number. Note that setting the line number
+does not change the current position within the file/buffer being read.
+
+The contents of C<$/> are used to to determine what constitutes a line
+terminator.
+
+=head2 fileno
+
+ $z->fileno()
+ fileno($z)
+
+If the C<$z> object is associated with a file or a filehandle, C<fileno>
+will return the underlying file descriptor. Once the C<close> method is
+called C<fileno> will return C<undef>.
+
+If the C<$z> object is is associated with a buffer, this method will return
+C<undef>.
+
+=head2 close
+
+ $z->close() ;
+ close $z ;
+
+Closes the output file/buffer.
+
+For most versions of Perl this method will be automatically invoked if
+the IO::Uncompress::Inflate object is destroyed (either explicitly or by the
+variable with the reference to the object going out of scope). The
+exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In
+these cases, the C<close> method will be called automatically, but
+not until global destruction of all live objects when the program is
+terminating.
+
+Therefore, if you want your scripts to be able to run on all versions
+of Perl, you should call C<close> explicitly and not rely on automatic
+closing.
+
+Returns true on success, otherwise 0.
+
+If the C<AutoClose> option has been enabled when the IO::Uncompress::Inflate
+object was created, and the object is associated with a file, the
+underlying file will also be closed.
+
+=head2 nextStream
+
+Usage is
+
+ my $status = $z->nextStream();
+
+Skips to the next compressed data stream in the input file/buffer. If a new
+compressed data stream is found, the eof marker will be cleared and C<$.>
+will be reset to 0.
+
+Returns 1 if a new stream was found, 0 if none was found, and -1 if an
+error was encountered.
+
+=head2 trailingData
+
+Usage is
+
+ my $data = $z->trailingData();
+
+Returns the data, if any, that is present immediately after the compressed
+data stream once uncompression is complete. It only makes sense to call
+this method once the end of the compressed data stream has been
+encountered.
+
+This option can be used when there is useful information immediately
+following the compressed data stream, and you don't know the length of the
+compressed data stream.
+
+If the input is a buffer, C<trailingData> will return everything from the
+end of the compressed data stream to the end of the buffer.
+
+If the input is a filehandle, C<trailingData> will return the data that is
+left in the filehandle input buffer once the end of the compressed data
+stream has been reached. You can then use the filehandle to read the rest
+of the input file.
+
+Don't bother using C<trailingData> if the input is a filename.
+
+If you know the length of the compressed data stream before you start
+uncompressing, you can avoid having to use C<trailingData> by setting the
+C<InputLength> option in the constructor.
+
+=head1 Importing
+
+No symbolic constants are required by this IO::Uncompress::Inflate at present.
+
+=over 5
+
+=item :all
+
+Imports C<inflate> and C<$InflateError>.
+Same as doing this
+
+ use IO::Uncompress::Inflate qw(inflate $InflateError) ;
+
+=back
+
+=head1 EXAMPLES
+
+=head2 Working with Net::FTP
+
+See L<IO::Uncompress::Inflate::FAQ|IO::Uncompress::Inflate::FAQ/"Compressed files and Net::FTP">
+
+=head1 SEE ALSO
+
+L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Compress::Deflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Compress::Bzip2>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
+
+L<Compress::Zlib::FAQ|Compress::Zlib::FAQ>
+
+L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
+L<Archive::Tar|Archive::Tar>,
+L<IO::Zlib|IO::Zlib>
+
+For RFC 1950, 1951 and 1952 see
+F<http://www.faqs.org/rfcs/rfc1950.html>,
+F<http://www.faqs.org/rfcs/rfc1951.html> and
+F<http://www.faqs.org/rfcs/rfc1952.html>
+
+The I<zlib> compression library was written by Jean-loup Gailly
+F<gzip@prep.ai.mit.edu> and Mark Adler F<madler@alumni.caltech.edu>.
+
+The primary site for the I<zlib> compression library is
+F<http://www.zlib.org>.
+
+The primary site for gzip is F<http://www.gzip.org>.
+
+=head1 AUTHOR
+
+This module was written by Paul Marquess, F<pmqs@cpan.org>.
+
+=head1 MODIFICATION HISTORY
+
+See the Changes file.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2005-2010 Paul Marquess. All rights reserved.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Uncompress/RawInflate.pm b/Master/tlpkg/tlperl/lib/IO/Uncompress/RawInflate.pm
new file mode 100644
index 00000000000..f017fa0f599
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Uncompress/RawInflate.pm
@@ -0,0 +1,1110 @@
+package IO::Uncompress::RawInflate ;
+# for RFC1951
+
+use strict ;
+use warnings;
+use bytes;
+
+use Compress::Raw::Zlib 2.024 ;
+use IO::Compress::Base::Common 2.024 qw(:Status createSelfTiedObject);
+
+use IO::Uncompress::Base 2.024 ;
+use IO::Uncompress::Adapter::Inflate 2.024 ;
+
+require Exporter ;
+our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, %DEFLATE_CONSTANTS, $RawInflateError);
+
+$VERSION = '2.024';
+$RawInflateError = '';
+
+@ISA = qw( Exporter IO::Uncompress::Base );
+@EXPORT_OK = qw( $RawInflateError rawinflate ) ;
+%DEFLATE_CONSTANTS = ();
+%EXPORT_TAGS = %IO::Uncompress::Base::EXPORT_TAGS ;
+push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
+Exporter::export_ok_tags('all');
+
+#{
+# # Execute at runtime
+# my %bad;
+# for my $module (qw(Compress::Raw::Zlib IO::Compress::Base::Common IO::Uncompress::Base IO::Uncompress::Adapter::Inflate))
+# {
+# my $ver = ${ $module . "::VERSION"} ;
+#
+# $bad{$module} = $ver
+# if $ver ne $VERSION;
+# }
+#
+# if (keys %bad)
+# {
+# my $string = join "\n", map { "$_ $bad{$_}" } keys %bad;
+# die caller(0)[0] . "needs version $VERSION mismatch\n$string\n";
+# }
+#}
+
+sub new
+{
+ my $class = shift ;
+ my $obj = createSelfTiedObject($class, \$RawInflateError);
+ $obj->_create(undef, 0, @_);
+}
+
+sub rawinflate
+{
+ my $obj = createSelfTiedObject(undef, \$RawInflateError);
+ return $obj->_inf(@_);
+}
+
+sub getExtraParams
+{
+ return ();
+}
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ return 1;
+}
+
+sub mkUncomp
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ my ($obj, $errstr, $errno) = IO::Uncompress::Adapter::Inflate::mkUncompObject(
+ $got->value('CRC32'),
+ $got->value('ADLER32'),
+ $got->value('Scan'),
+ );
+
+ return $self->saveErrorString(undef, $errstr, $errno)
+ if ! defined $obj;
+
+ *$self->{Uncomp} = $obj;
+
+ my $magic = $self->ckMagic()
+ or return 0;
+
+ *$self->{Info} = $self->readHeader($magic)
+ or return undef ;
+
+ return 1;
+
+}
+
+
+sub ckMagic
+{
+ my $self = shift;
+
+ return $self->_isRaw() ;
+}
+
+sub readHeader
+{
+ my $self = shift;
+ my $magic = shift ;
+
+ return {
+ 'Type' => 'rfc1951',
+ 'FingerprintLength' => 0,
+ 'HeaderLength' => 0,
+ 'TrailerLength' => 0,
+ 'Header' => ''
+ };
+}
+
+sub chkTrailer
+{
+ return STATUS_OK ;
+}
+
+sub _isRaw
+{
+ my $self = shift ;
+
+ my $got = $self->_isRawx(@_);
+
+ if ($got) {
+ *$self->{Pending} = *$self->{HeaderPending} ;
+ }
+ else {
+ $self->pushBack(*$self->{HeaderPending});
+ *$self->{Uncomp}->reset();
+ }
+ *$self->{HeaderPending} = '';
+
+ return $got ;
+}
+
+sub _isRawx
+{
+ my $self = shift ;
+ my $magic = shift ;
+
+ $magic = '' unless defined $magic ;
+
+ my $buffer = '';
+
+ $self->smartRead(\$buffer, *$self->{BlockSize}) >= 0
+ or return $self->saveErrorString(undef, "No data to read");
+
+ my $temp_buf = $magic . $buffer ;
+ *$self->{HeaderPending} = $temp_buf ;
+ $buffer = '';
+ my $status = *$self->{Uncomp}->uncompr(\$temp_buf, \$buffer, $self->smartEof()) ;
+
+ return $self->saveErrorString(undef, *$self->{Uncomp}{Error}, STATUS_ERROR)
+ if $status == STATUS_ERROR;
+
+ $self->pushBack($temp_buf) ;
+
+ return $self->saveErrorString(undef, "unexpected end of file", STATUS_ERROR)
+ if $self->smartEof() && $status != STATUS_ENDSTREAM;
+
+ #my $buf_len = *$self->{Uncomp}->uncompressedBytes();
+ my $buf_len = length $buffer;
+
+ if ($status == STATUS_ENDSTREAM) {
+ if (*$self->{MultiStream}
+ && (length $temp_buf || ! $self->smartEof())){
+ *$self->{NewStream} = 1 ;
+ *$self->{EndStream} = 0 ;
+ }
+ else {
+ *$self->{EndStream} = 1 ;
+ }
+ }
+ *$self->{HeaderPending} = $buffer ;
+ *$self->{InflatedBytesRead} = $buf_len ;
+ *$self->{TotalInflatedBytesRead} += $buf_len ;
+ *$self->{Type} = 'rfc1951';
+
+ $self->saveStatus(STATUS_OK);
+
+ return {
+ 'Type' => 'rfc1951',
+ 'HeaderLength' => 0,
+ 'TrailerLength' => 0,
+ 'Header' => ''
+ };
+}
+
+
+sub inflateSync
+{
+ my $self = shift ;
+
+ # inflateSync is a no-op in Plain mode
+ return 1
+ if *$self->{Plain} ;
+
+ return 0 if *$self->{Closed} ;
+ #return G_EOF if !length *$self->{Pending} && *$self->{EndStream} ;
+ return 0 if ! length *$self->{Pending} && *$self->{EndStream} ;
+
+ # Disable CRC check
+ *$self->{Strict} = 0 ;
+
+ my $status ;
+ while (1)
+ {
+ my $temp_buf ;
+
+ if (length *$self->{Pending} )
+ {
+ $temp_buf = *$self->{Pending} ;
+ *$self->{Pending} = '';
+ }
+ else
+ {
+ $status = $self->smartRead(\$temp_buf, *$self->{BlockSize}) ;
+ return $self->saveErrorString(0, "Error Reading Data")
+ if $status < 0 ;
+
+ if ($status == 0 ) {
+ *$self->{EndStream} = 1 ;
+ return $self->saveErrorString(0, "unexpected end of file", STATUS_ERROR);
+ }
+ }
+
+ $status = *$self->{Uncomp}->sync($temp_buf) ;
+
+ if ($status == STATUS_OK)
+ {
+ *$self->{Pending} .= $temp_buf ;
+ return 1 ;
+ }
+
+ last unless $status == STATUS_ERROR ;
+ }
+
+ return 0;
+}
+
+#sub performScan
+#{
+# my $self = shift ;
+#
+# my $status ;
+# my $end_offset = 0;
+#
+# $status = $self->scan()
+# #or return $self->saveErrorString(undef, "Error Scanning: $$error_ref", $self->errorNo) ;
+# or return $self->saveErrorString(G_ERR, "Error Scanning: $status")
+#
+# $status = $self->zap($end_offset)
+# or return $self->saveErrorString(G_ERR, "Error Zapping: $status");
+# #or return $self->saveErrorString(undef, "Error Zapping: $$error_ref", $self->errorNo) ;
+#
+# #(*$obj->{Deflate}, $status) = $inf->createDeflate();
+#
+## *$obj->{Header} = *$inf->{Info}{Header};
+## *$obj->{UnCompSize_32bit} =
+## *$obj->{BytesWritten} = *$inf->{UnCompSize_32bit} ;
+## *$obj->{CompSize_32bit} = *$inf->{CompSize_32bit} ;
+#
+#
+## if ( $outType eq 'buffer')
+## { substr( ${ *$self->{Buffer} }, $end_offset) = '' }
+## elsif ($outType eq 'handle' || $outType eq 'filename') {
+## *$self->{FH} = *$inf->{FH} ;
+## delete *$inf->{FH};
+## *$obj->{FH}->flush() ;
+## *$obj->{Handle} = 1 if $outType eq 'handle';
+##
+## #seek(*$obj->{FH}, $end_offset, SEEK_SET)
+## *$obj->{FH}->seek($end_offset, SEEK_SET)
+## or return $obj->saveErrorString(undef, $!, $!) ;
+## }
+#
+#}
+
+sub scan
+{
+ my $self = shift ;
+
+ return 1 if *$self->{Closed} ;
+ return 1 if !length *$self->{Pending} && *$self->{EndStream} ;
+
+ my $buffer = '' ;
+ my $len = 0;
+
+ $len = $self->_raw_read(\$buffer, 1)
+ while ! *$self->{EndStream} && $len >= 0 ;
+
+ #return $len if $len < 0 ? $len : 0 ;
+ return $len < 0 ? 0 : 1 ;
+}
+
+sub zap
+{
+ my $self = shift ;
+
+ my $headerLength = *$self->{Info}{HeaderLength};
+ my $block_offset = $headerLength + *$self->{Uncomp}->getLastBlockOffset();
+ $_[0] = $headerLength + *$self->{Uncomp}->getEndOffset();
+ #printf "# End $_[0], headerlen $headerLength \n";;
+ #printf "# block_offset $block_offset %x\n", $block_offset;
+ my $byte ;
+ ( $self->smartSeek($block_offset) &&
+ $self->smartRead(\$byte, 1) )
+ or return $self->saveErrorString(0, $!, $!);
+
+ #printf "#byte is %x\n", unpack('C*',$byte);
+ *$self->{Uncomp}->resetLastBlockByte($byte);
+ #printf "#to byte is %x\n", unpack('C*',$byte);
+
+ ( $self->smartSeek($block_offset) &&
+ $self->smartWrite($byte) )
+ or return $self->saveErrorString(0, $!, $!);
+
+ #$self->smartSeek($end_offset, 1);
+
+ return 1 ;
+}
+
+sub createDeflate
+{
+ my $self = shift ;
+ my ($def, $status) = *$self->{Uncomp}->createDeflateStream(
+ -AppendOutput => 1,
+ -WindowBits => - MAX_WBITS,
+ -CRC32 => *$self->{Params}->value('CRC32'),
+ -ADLER32 => *$self->{Params}->value('ADLER32'),
+ );
+
+ return wantarray ? ($status, $def) : $def ;
+}
+
+
+1;
+
+__END__
+
+
+=head1 NAME
+
+IO::Uncompress::RawInflate - Read RFC 1951 files/buffers
+
+=head1 SYNOPSIS
+
+ use IO::Uncompress::RawInflate qw(rawinflate $RawInflateError) ;
+
+ my $status = rawinflate $input => $output [,OPTS]
+ or die "rawinflate failed: $RawInflateError\n";
+
+ my $z = new IO::Uncompress::RawInflate $input [OPTS]
+ or die "rawinflate failed: $RawInflateError\n";
+
+ $status = $z->read($buffer)
+ $status = $z->read($buffer, $length)
+ $status = $z->read($buffer, $length, $offset)
+ $line = $z->getline()
+ $char = $z->getc()
+ $char = $z->ungetc()
+ $char = $z->opened()
+
+ $status = $z->inflateSync()
+
+ $data = $z->trailingData()
+ $status = $z->nextStream()
+ $data = $z->getHeaderInfo()
+ $z->tell()
+ $z->seek($position, $whence)
+ $z->binmode()
+ $z->fileno()
+ $z->eof()
+ $z->close()
+
+ $RawInflateError ;
+
+ # IO::File mode
+
+ <$z>
+ read($z, $buffer);
+ read($z, $buffer, $length);
+ read($z, $buffer, $length, $offset);
+ tell($z)
+ seek($z, $position, $whence)
+ binmode($z)
+ fileno($z)
+ eof($z)
+ close($z)
+
+=head1 DESCRIPTION
+
+This module provides a Perl interface that allows the reading of
+files/buffers that conform to RFC 1951.
+
+For writing RFC 1951 files/buffers, see the companion module IO::Compress::RawDeflate.
+
+=head1 Functional Interface
+
+A top-level function, C<rawinflate>, is provided to carry out
+"one-shot" uncompression between buffers and/or files. For finer
+control over the uncompression process, see the L</"OO Interface">
+section.
+
+ use IO::Uncompress::RawInflate qw(rawinflate $RawInflateError) ;
+
+ rawinflate $input => $output [,OPTS]
+ or die "rawinflate failed: $RawInflateError\n";
+
+The functional interface needs Perl5.005 or better.
+
+=head2 rawinflate $input => $output [, OPTS]
+
+C<rawinflate> expects at least two parameters, C<$input> and C<$output>.
+
+=head3 The C<$input> parameter
+
+The parameter, C<$input>, is used to define the source of
+the compressed data.
+
+It can take one of the following forms:
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for reading and the input data
+will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the input data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the input data will be read
+from C<$$input>.
+
+=item An array reference
+
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
+The complete array will be walked to ensure that it only
+contains valid filenames before any data is uncompressed.
+
+=item An Input FileGlob string
+
+If C<$input> is a string that is delimited by the characters "<" and ">"
+C<rawinflate> will assume that it is an I<input fileglob string>. The
+input is the list of files that match the fileglob.
+
+If the fileglob does not match any files ...
+
+See L<File::GlobMapper|File::GlobMapper> for more details.
+
+=back
+
+If the C<$input> parameter is any other type, C<undef> will be returned.
+
+=head3 The C<$output> parameter
+
+The parameter C<$output> is used to control the destination of the
+uncompressed data. This parameter can take one of these forms.
+
+=over 5
+
+=item A filename
+
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the uncompressed
+data will be written to it.
+
+=item A filehandle
+
+If the C<$output> parameter is a filehandle, the uncompressed data
+will be written to it.
+The string '-' can be used as an alias for standard output.
+
+=item A scalar reference
+
+If C<$output> is a scalar reference, the uncompressed data will be
+stored in C<$$output>.
+
+=item An Array Reference
+
+If C<$output> is an array reference, the uncompressed data will be
+pushed onto the array.
+
+=item An Output FileGlob
+
+If C<$output> is a string that is delimited by the characters "<" and ">"
+C<rawinflate> will assume that it is an I<output fileglob string>. The
+output is the list of files that match the fileglob.
+
+When C<$output> is an fileglob string, C<$input> must also be a fileglob
+string. Anything else is an error.
+
+=back
+
+If the C<$output> parameter is any other type, C<undef> will be returned.
+
+=head2 Notes
+
+When C<$input> maps to multiple compressed files/buffers and C<$output> is
+a single file/buffer, after uncompression C<$output> will contain a
+concatenation of all the uncompressed data from each of the input
+files/buffers.
+
+=head2 Optional Parameters
+
+Unless specified below, the optional parameters for C<rawinflate>,
+C<OPTS>, are the same as those used with the OO interface defined in the
+L</"Constructor Options"> section below.
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option applies to any input or output data streams to
+C<rawinflate> that are filehandles.
+
+If C<AutoClose> is specified, and the value is true, it will result in all
+input and/or output filehandles being closed once C<rawinflate> has
+completed.
+
+This parameter defaults to 0.
+
+=item C<< BinModeOut => 0|1 >>
+
+When writing to a file or filehandle, set C<binmode> before writing to the
+file.
+
+Defaults to 0.
+
+=item C<< Append => 0|1 >>
+
+The behaviour of this option is dependent on the type of output data
+stream.
+
+=over 5
+
+=item * A Buffer
+
+If C<Append> is enabled, all uncompressed data will be append to the end of
+the output buffer. Otherwise the output buffer will be cleared before any
+uncompressed data is written to it.
+
+=item * A Filename
+
+If C<Append> is enabled, the file will be opened in append mode. Otherwise
+the contents of the file, if any, will be truncated before any uncompressed
+data is written to it.
+
+=item * A Filehandle
+
+If C<Append> is enabled, the filehandle will be positioned to the end of
+the file via a call to C<seek> before any uncompressed data is
+written to it. Otherwise the file pointer will not be moved.
+
+=back
+
+When C<Append> is specified, and set to true, it will I<append> all uncompressed
+data to the output data stream.
+
+So when the output is a filehandle it will carry out a seek to the eof
+before writing any uncompressed data. If the output is a filename, it will be opened for
+appending. If the output is a buffer, all uncompressed data will be appened to
+the existing buffer.
+
+Conversely when C<Append> is not specified, or it is present and is set to
+false, it will operate as follows.
+
+When the output is a filename, it will truncate the contents of the file
+before writing any uncompressed data. If the output is a filehandle
+its position will not be changed. If the output is a buffer, it will be
+wiped before any uncompressed data is output.
+
+Defaults to 0.
+
+=item C<< MultiStream => 0|1 >>
+
+This option is a no-op.
+
+=item C<< TrailingData => $scalar >>
+
+Returns the data, if any, that is present immediately after the compressed
+data stream once uncompression is complete.
+
+This option can be used when there is useful information immediately
+following the compressed data stream, and you don't know the length of the
+compressed data stream.
+
+If the input is a buffer, C<trailingData> will return everything from the
+end of the compressed data stream to the end of the buffer.
+
+If the input is a filehandle, C<trailingData> will return the data that is
+left in the filehandle input buffer once the end of the compressed data
+stream has been reached. You can then use the filehandle to read the rest
+of the input file.
+
+Don't bother using C<trailingData> if the input is a filename.
+
+If you know the length of the compressed data stream before you start
+uncompressing, you can avoid having to use C<trailingData> by setting the
+C<InputLength> option.
+
+=back
+
+=head2 Examples
+
+To read the contents of the file C<file1.txt.1951> and write the
+uncompressed data to the file C<file1.txt>.
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::RawInflate qw(rawinflate $RawInflateError) ;
+
+ my $input = "file1.txt.1951";
+ my $output = "file1.txt";
+ rawinflate $input => $output
+ or die "rawinflate failed: $RawInflateError\n";
+
+To read from an existing Perl filehandle, C<$input>, and write the
+uncompressed data to a buffer, C<$buffer>.
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::RawInflate qw(rawinflate $RawInflateError) ;
+ use IO::File ;
+
+ my $input = new IO::File "<file1.txt.1951"
+ or die "Cannot open 'file1.txt.1951': $!\n" ;
+ my $buffer ;
+ rawinflate $input => \$buffer
+ or die "rawinflate failed: $RawInflateError\n";
+
+To uncompress all files in the directory "/my/home" that match "*.txt.1951" and store the compressed data in the same directory
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::RawInflate qw(rawinflate $RawInflateError) ;
+
+ rawinflate '</my/home/*.txt.1951>' => '</my/home/#1.txt>'
+ or die "rawinflate failed: $RawInflateError\n";
+
+and if you want to compress each file one at a time, this will do the trick
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::RawInflate qw(rawinflate $RawInflateError) ;
+
+ for my $input ( glob "/my/home/*.txt.1951" )
+ {
+ my $output = $input;
+ $output =~ s/.1951// ;
+ rawinflate $input => $output
+ or die "Error compressing '$input': $RawInflateError\n";
+ }
+
+=head1 OO Interface
+
+=head2 Constructor
+
+The format of the constructor for IO::Uncompress::RawInflate is shown below
+
+ my $z = new IO::Uncompress::RawInflate $input [OPTS]
+ or die "IO::Uncompress::RawInflate failed: $RawInflateError\n";
+
+Returns an C<IO::Uncompress::RawInflate> object on success and undef on failure.
+The variable C<$RawInflateError> will contain an error message on failure.
+
+If you are running Perl 5.005 or better the object, C<$z>, returned from
+IO::Uncompress::RawInflate can be used exactly like an L<IO::File|IO::File> filehandle.
+This means that all normal input file operations can be carried out with
+C<$z>. For example, to read a line from a compressed file/buffer you can
+use either of these forms
+
+ $line = $z->getline();
+ $line = <$z>;
+
+The mandatory parameter C<$input> is used to determine the source of the
+compressed data. This parameter can take one of three forms.
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a scalar, it is assumed to be a filename. This
+file will be opened for reading and the compressed data will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the compressed data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the compressed data will be read from
+C<$$output>.
+
+=back
+
+=head2 Constructor Options
+
+The option names defined below are case insensitive and can be optionally
+prefixed by a '-'. So all of the following are valid
+
+ -AutoClose
+ -autoclose
+ AUTOCLOSE
+ autoclose
+
+OPTS is a combination of the following options:
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option is only valid when the C<$input> parameter is a filehandle. If
+specified, and the value is true, it will result in the file being closed once
+either the C<close> method is called or the IO::Uncompress::RawInflate object is
+destroyed.
+
+This parameter defaults to 0.
+
+=item C<< MultiStream => 0|1 >>
+
+Allows multiple concatenated compressed streams to be treated as a single
+compressed stream. Decompression will stop once either the end of the
+file/buffer is reached, an error is encountered (premature eof, corrupt
+compressed data) or the end of a stream is not immediately followed by the
+start of another stream.
+
+This parameter defaults to 0.
+
+=item C<< Prime => $string >>
+
+This option will uncompress the contents of C<$string> before processing the
+input file/buffer.
+
+This option can be useful when the compressed data is embedded in another
+file/data structure and it is not possible to work out where the compressed
+data begins without having to read the first few bytes. If this is the
+case, the uncompression can be I<primed> with these bytes using this
+option.
+
+=item C<< Transparent => 0|1 >>
+
+If this option is set and the input file/buffer is not compressed data,
+the module will allow reading of it anyway.
+
+In addition, if the input file/buffer does contain compressed data and
+there is non-compressed data immediately following it, setting this option
+will make this module treat the whole file/bufffer as a single data stream.
+
+This option defaults to 1.
+
+=item C<< BlockSize => $num >>
+
+When reading the compressed input data, IO::Uncompress::RawInflate will read it in
+blocks of C<$num> bytes.
+
+This option defaults to 4096.
+
+=item C<< InputLength => $size >>
+
+When present this option will limit the number of compressed bytes read
+from the input file/buffer to C<$size>. This option can be used in the
+situation where there is useful data directly after the compressed data
+stream and you know beforehand the exact length of the compressed data
+stream.
+
+This option is mostly used when reading from a filehandle, in which case
+the file pointer will be left pointing to the first byte directly after the
+compressed data stream.
+
+This option defaults to off.
+
+=item C<< Append => 0|1 >>
+
+This option controls what the C<read> method does with uncompressed data.
+
+If set to 1, all uncompressed data will be appended to the output parameter
+of the C<read> method.
+
+If set to 0, the contents of the output parameter of the C<read> method
+will be overwritten by the uncompressed data.
+
+Defaults to 0.
+
+=item C<< Strict => 0|1 >>
+
+This option is a no-op.
+
+=back
+
+=head2 Examples
+
+TODO
+
+=head1 Methods
+
+=head2 read
+
+Usage is
+
+ $status = $z->read($buffer)
+
+Reads a block of compressed data (the size the the compressed block is
+determined by the C<Buffer> option in the constructor), uncompresses it and
+writes any uncompressed data into C<$buffer>. If the C<Append> parameter is
+set in the constructor, the uncompressed data will be appended to the
+C<$buffer> parameter. Otherwise C<$buffer> will be overwritten.
+
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
+
+=head2 read
+
+Usage is
+
+ $status = $z->read($buffer, $length)
+ $status = $z->read($buffer, $length, $offset)
+
+ $status = read($z, $buffer, $length)
+ $status = read($z, $buffer, $length, $offset)
+
+Attempt to read C<$length> bytes of uncompressed data into C<$buffer>.
+
+The main difference between this form of the C<read> method and the
+previous one, is that this one will attempt to return I<exactly> C<$length>
+bytes. The only circumstances that this function will not is if end-of-file
+or an IO error is encountered.
+
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
+
+=head2 getline
+
+Usage is
+
+ $line = $z->getline()
+ $line = <$z>
+
+Reads a single line.
+
+This method fully supports the use of of the variable C<$/> (or
+C<$INPUT_RECORD_SEPARATOR> or C<$RS> when C<English> is in use) to
+determine what constitutes an end of line. Paragraph mode, record mode and
+file slurp mode are all supported.
+
+=head2 getc
+
+Usage is
+
+ $char = $z->getc()
+
+Read a single character.
+
+=head2 ungetc
+
+Usage is
+
+ $char = $z->ungetc($string)
+
+=head2 inflateSync
+
+Usage is
+
+ $status = $z->inflateSync()
+
+TODO
+
+=head2 getHeaderInfo
+
+Usage is
+
+ $hdr = $z->getHeaderInfo();
+ @hdrs = $z->getHeaderInfo();
+
+This method returns either a hash reference (in scalar context) or a list
+or hash references (in array context) that contains information about each
+of the header fields in the compressed data stream(s).
+
+=head2 tell
+
+Usage is
+
+ $z->tell()
+ tell $z
+
+Returns the uncompressed file offset.
+
+=head2 eof
+
+Usage is
+
+ $z->eof();
+ eof($z);
+
+Returns true if the end of the compressed input stream has been reached.
+
+=head2 seek
+
+ $z->seek($position, $whence);
+ seek($z, $position, $whence);
+
+Provides a sub-set of the C<seek> functionality, with the restriction
+that it is only legal to seek forward in the input file/buffer.
+It is a fatal error to attempt to seek backward.
+
+The C<$whence> parameter takes one the usual values, namely SEEK_SET,
+SEEK_CUR or SEEK_END.
+
+Returns 1 on success, 0 on failure.
+
+=head2 binmode
+
+Usage is
+
+ $z->binmode
+ binmode $z ;
+
+This is a noop provided for completeness.
+
+=head2 opened
+
+ $z->opened()
+
+Returns true if the object currently refers to a opened file/buffer.
+
+=head2 autoflush
+
+ my $prev = $z->autoflush()
+ my $prev = $z->autoflush(EXPR)
+
+If the C<$z> object is associated with a file or a filehandle, this method
+returns the current autoflush setting for the underlying filehandle. If
+C<EXPR> is present, and is non-zero, it will enable flushing after every
+write/print operation.
+
+If C<$z> is associated with a buffer, this method has no effect and always
+returns C<undef>.
+
+B<Note> that the special variable C<$|> B<cannot> be used to set or
+retrieve the autoflush setting.
+
+=head2 input_line_number
+
+ $z->input_line_number()
+ $z->input_line_number(EXPR)
+
+Returns the current uncompressed line number. If C<EXPR> is present it has
+the effect of setting the line number. Note that setting the line number
+does not change the current position within the file/buffer being read.
+
+The contents of C<$/> are used to to determine what constitutes a line
+terminator.
+
+=head2 fileno
+
+ $z->fileno()
+ fileno($z)
+
+If the C<$z> object is associated with a file or a filehandle, C<fileno>
+will return the underlying file descriptor. Once the C<close> method is
+called C<fileno> will return C<undef>.
+
+If the C<$z> object is is associated with a buffer, this method will return
+C<undef>.
+
+=head2 close
+
+ $z->close() ;
+ close $z ;
+
+Closes the output file/buffer.
+
+For most versions of Perl this method will be automatically invoked if
+the IO::Uncompress::RawInflate object is destroyed (either explicitly or by the
+variable with the reference to the object going out of scope). The
+exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In
+these cases, the C<close> method will be called automatically, but
+not until global destruction of all live objects when the program is
+terminating.
+
+Therefore, if you want your scripts to be able to run on all versions
+of Perl, you should call C<close> explicitly and not rely on automatic
+closing.
+
+Returns true on success, otherwise 0.
+
+If the C<AutoClose> option has been enabled when the IO::Uncompress::RawInflate
+object was created, and the object is associated with a file, the
+underlying file will also be closed.
+
+=head2 nextStream
+
+Usage is
+
+ my $status = $z->nextStream();
+
+Skips to the next compressed data stream in the input file/buffer. If a new
+compressed data stream is found, the eof marker will be cleared and C<$.>
+will be reset to 0.
+
+Returns 1 if a new stream was found, 0 if none was found, and -1 if an
+error was encountered.
+
+=head2 trailingData
+
+Usage is
+
+ my $data = $z->trailingData();
+
+Returns the data, if any, that is present immediately after the compressed
+data stream once uncompression is complete. It only makes sense to call
+this method once the end of the compressed data stream has been
+encountered.
+
+This option can be used when there is useful information immediately
+following the compressed data stream, and you don't know the length of the
+compressed data stream.
+
+If the input is a buffer, C<trailingData> will return everything from the
+end of the compressed data stream to the end of the buffer.
+
+If the input is a filehandle, C<trailingData> will return the data that is
+left in the filehandle input buffer once the end of the compressed data
+stream has been reached. You can then use the filehandle to read the rest
+of the input file.
+
+Don't bother using C<trailingData> if the input is a filename.
+
+If you know the length of the compressed data stream before you start
+uncompressing, you can avoid having to use C<trailingData> by setting the
+C<InputLength> option in the constructor.
+
+=head1 Importing
+
+No symbolic constants are required by this IO::Uncompress::RawInflate at present.
+
+=over 5
+
+=item :all
+
+Imports C<rawinflate> and C<$RawInflateError>.
+Same as doing this
+
+ use IO::Uncompress::RawInflate qw(rawinflate $RawInflateError) ;
+
+=back
+
+=head1 EXAMPLES
+
+=head2 Working with Net::FTP
+
+See L<IO::Uncompress::RawInflate::FAQ|IO::Uncompress::RawInflate::FAQ/"Compressed files and Net::FTP">
+
+=head1 SEE ALSO
+
+L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Compress::Deflate>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Compress::Bzip2>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
+
+L<Compress::Zlib::FAQ|Compress::Zlib::FAQ>
+
+L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
+L<Archive::Tar|Archive::Tar>,
+L<IO::Zlib|IO::Zlib>
+
+For RFC 1950, 1951 and 1952 see
+F<http://www.faqs.org/rfcs/rfc1950.html>,
+F<http://www.faqs.org/rfcs/rfc1951.html> and
+F<http://www.faqs.org/rfcs/rfc1952.html>
+
+The I<zlib> compression library was written by Jean-loup Gailly
+F<gzip@prep.ai.mit.edu> and Mark Adler F<madler@alumni.caltech.edu>.
+
+The primary site for the I<zlib> compression library is
+F<http://www.zlib.org>.
+
+The primary site for gzip is F<http://www.gzip.org>.
+
+=head1 AUTHOR
+
+This module was written by Paul Marquess, F<pmqs@cpan.org>.
+
+=head1 MODIFICATION HISTORY
+
+See the Changes file.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2005-2010 Paul Marquess. All rights reserved.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Uncompress/Unzip.pm b/Master/tlpkg/tlperl/lib/IO/Uncompress/Unzip.pm
new file mode 100644
index 00000000000..e7d6849f66b
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Uncompress/Unzip.pm
@@ -0,0 +1,1549 @@
+package IO::Uncompress::Unzip;
+
+require 5.004 ;
+
+# for RFC1952
+
+use strict ;
+use warnings;
+use bytes;
+
+use IO::Uncompress::RawInflate 2.024 ;
+use IO::Compress::Base::Common 2.024 qw(:Status createSelfTiedObject);
+use IO::Uncompress::Adapter::Inflate 2.024 ;
+use IO::Uncompress::Adapter::Identity 2.024 ;
+use IO::Compress::Zlib::Extra 2.024 ;
+use IO::Compress::Zip::Constants 2.024 ;
+
+use Compress::Raw::Zlib 2.024 qw(crc32) ;
+
+BEGIN
+{
+ eval { require IO::Uncompress::Adapter::Bunzip2 ;
+ import IO::Uncompress::Adapter::Bunzip2 } ;
+# eval { require IO::Uncompress::Adapter::UnLzma ;
+# import IO::Uncompress::Adapter::UnLzma } ;
+}
+
+
+require Exporter ;
+
+our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS, $UnzipError, %headerLookup);
+
+$VERSION = '2.024';
+$UnzipError = '';
+
+@ISA = qw(Exporter IO::Uncompress::RawInflate);
+@EXPORT_OK = qw( $UnzipError unzip );
+%EXPORT_TAGS = %IO::Uncompress::RawInflate::EXPORT_TAGS ;
+push @{ $EXPORT_TAGS{all} }, @EXPORT_OK ;
+Exporter::export_ok_tags('all');
+
+%headerLookup = (
+ ZIP_CENTRAL_HDR_SIG, \&skipCentralDirectory,
+ ZIP_END_CENTRAL_HDR_SIG, \&skipEndCentralDirectory,
+ ZIP64_END_CENTRAL_REC_HDR_SIG, \&skipCentralDirectory64Rec,
+ ZIP64_END_CENTRAL_LOC_HDR_SIG, \&skipCentralDirectory64Loc,
+ ZIP64_ARCHIVE_EXTRA_SIG, \&skipArchiveExtra,
+ ZIP64_DIGITAL_SIGNATURE_SIG, \&skipDigitalSignature,
+ );
+
+sub new
+{
+ my $class = shift ;
+ my $obj = createSelfTiedObject($class, \$UnzipError);
+ $obj->_create(undef, 0, @_);
+}
+
+sub unzip
+{
+ my $obj = createSelfTiedObject(undef, \$UnzipError);
+ return $obj->_inf(@_) ;
+}
+
+sub getExtraParams
+{
+ use IO::Compress::Base::Common 2.024 qw(:Parse);
+
+
+ return (
+# # Zip header fields
+ 'Name' => [1, 1, Parse_any, undef],
+
+# 'Stream' => [1, 1, Parse_boolean, 1],
+ # This means reading the central directory to get
+ # 1. the local header offsets
+ # 2. The compressed data length
+ );
+}
+
+sub ckParams
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ # unzip always needs crc32
+ $got->value('CRC32' => 1);
+
+ *$self->{UnzipData}{Name} = $got->value('Name');
+
+ return 1;
+}
+
+sub mkUncomp
+{
+ my $self = shift ;
+ my $got = shift ;
+
+ my $magic = $self->ckMagic()
+ or return 0;
+
+ *$self->{Info} = $self->readHeader($magic)
+ or return undef ;
+
+ return 1;
+
+}
+
+sub ckMagic
+{
+ my $self = shift;
+
+ my $magic ;
+ $self->smartReadExact(\$magic, 4);
+
+ *$self->{HeaderPending} = $magic ;
+
+ return $self->HeaderError("Minimum header size is " .
+ 4 . " bytes")
+ if length $magic != 4 ;
+
+ return $self->HeaderError("Bad Magic")
+ if ! _isZipMagic($magic) ;
+
+ *$self->{Type} = 'zip';
+
+ return $magic ;
+}
+
+
+sub fastForward
+{
+ my $self = shift;
+ my $offset = shift;
+
+ # TODO - if Stream isn't enabled & reading from file, use seek
+
+ my $buffer = '';
+ my $c = 1024 * 16;
+
+ while ($offset > 0)
+ {
+ $c = length $offset
+ if length $offset < $c ;
+
+ $offset -= $c;
+
+ $self->smartReadExact(\$buffer, $c)
+ or return 0;
+ }
+
+ return 1;
+}
+
+
+sub readHeader
+{
+ my $self = shift;
+ my $magic = shift ;
+
+ my $name = *$self->{UnzipData}{Name} ;
+ my $hdr = $self->_readZipHeader($magic) ;
+
+ while (defined $hdr)
+ {
+ if (! defined $name || $hdr->{Name} eq $name)
+ {
+ return $hdr ;
+ }
+
+ # skip the data
+ # TODO - when Stream is off, use seek
+ my $buffer;
+ if (*$self->{ZipData}{Streaming}) {
+
+ while (1) {
+
+ my $b;
+ my $status = $self->smartRead(\$b, 1024 * 16);
+ return undef
+ if $status <= 0 ;
+
+ my $temp_buf;
+ my $out;
+ $status = *$self->{Uncomp}->uncompr(\$b, \$temp_buf, 0, $out);
+
+ return $self->saveErrorString(undef, *$self->{Uncomp}{Error},
+ *$self->{Uncomp}{ErrorNo})
+ if $self->saveStatus($status) == STATUS_ERROR;
+
+ if ($status == STATUS_ENDSTREAM) {
+ *$self->{Uncomp}->reset();
+ $self->pushBack($b) ;
+ last;
+ }
+ }
+
+ # skip the trailer
+ $self->smartReadExact(\$buffer, $hdr->{TrailerLength})
+ or return $self->saveErrorString(undef, "Truncated file");
+ }
+ else {
+ my $c = $hdr->{CompressedLength}->get64bit();
+ $self->fastForward($c)
+ or return $self->saveErrorString(undef, "Truncated file");
+ $buffer = '';
+ }
+
+ $self->chkTrailer($buffer) == STATUS_OK
+ or return $self->saveErrorString(undef, "Truncated file");
+
+ $hdr = $self->_readFullZipHeader();
+
+ return $self->saveErrorString(undef, "Cannot find '$name'")
+ if $self->smartEof();
+ }
+
+ return undef;
+}
+
+sub chkTrailer
+{
+ my $self = shift;
+ my $trailer = shift;
+
+ my ($sig, $CRC32, $cSize, $uSize) ;
+ my ($cSizeHi, $uSizeHi) = (0, 0);
+ if (*$self->{ZipData}{Streaming}) {
+ $sig = unpack ("V", substr($trailer, 0, 4));
+ $CRC32 = unpack ("V", substr($trailer, 4, 4));
+
+ if (*$self->{ZipData}{Zip64} ) {
+ $cSize = U64::newUnpack_V64 substr($trailer, 8, 8);
+ $uSize = U64::newUnpack_V64 substr($trailer, 16, 8);
+ }
+ else {
+ $cSize = U64::newUnpack_V32 substr($trailer, 8, 4);
+ $uSize = U64::newUnpack_V32 substr($trailer, 12, 4);
+ }
+
+ return $self->TrailerError("Data Descriptor signature, got $sig")
+ if $sig != ZIP_DATA_HDR_SIG;
+ }
+ else {
+ ($CRC32, $cSize, $uSize) =
+ (*$self->{ZipData}{Crc32},
+ *$self->{ZipData}{CompressedLen},
+ *$self->{ZipData}{UnCompressedLen});
+ }
+
+ *$self->{Info}{CRC32} = *$self->{ZipData}{CRC32} ;
+ *$self->{Info}{CompressedLength} = $cSize->get64bit();
+ *$self->{Info}{UncompressedLength} = $uSize->get64bit();
+
+ if (*$self->{Strict}) {
+ return $self->TrailerError("CRC mismatch")
+ if $CRC32 != *$self->{ZipData}{CRC32} ;
+
+ return $self->TrailerError("CSIZE mismatch.")
+ if ! $cSize->equal(*$self->{CompSize});
+
+ return $self->TrailerError("USIZE mismatch.")
+ if ! $uSize->equal(*$self->{UnCompSize});
+ }
+
+ my $reachedEnd = STATUS_ERROR ;
+ # check for central directory or end of central directory
+ while (1)
+ {
+ my $magic ;
+ my $got = $self->smartRead(\$magic, 4);
+
+ return $self->saveErrorString(STATUS_ERROR, "Truncated file")
+ if $got != 4 && *$self->{Strict};
+
+ if ($got == 0) {
+ return STATUS_EOF ;
+ }
+ elsif ($got < 0) {
+ return STATUS_ERROR ;
+ }
+ elsif ($got < 4) {
+ $self->pushBack($magic) ;
+ return STATUS_OK ;
+ }
+
+ my $sig = unpack("V", $magic) ;
+
+ my $hdr;
+ if ($hdr = $headerLookup{$sig})
+ {
+ if (&$hdr($self, $magic) != STATUS_OK ) {
+ if (*$self->{Strict}) {
+ return STATUS_ERROR ;
+ }
+ else {
+ $self->clearError();
+ return STATUS_OK ;
+ }
+ }
+
+ if ($sig == ZIP_END_CENTRAL_HDR_SIG)
+ {
+ return STATUS_OK ;
+ last;
+ }
+ }
+ elsif ($sig == ZIP_LOCAL_HDR_SIG)
+ {
+ $self->pushBack($magic) ;
+ return STATUS_OK ;
+ }
+ else
+ {
+ # put the data back
+ $self->pushBack($magic) ;
+ last;
+ }
+ }
+
+ return $reachedEnd ;
+}
+
+sub skipCentralDirectory
+{
+ my $self = shift;
+ my $magic = shift ;
+
+ my $buffer;
+ $self->smartReadExact(\$buffer, 46 - 4)
+ or return $self->TrailerError("Minimum header size is " .
+ 46 . " bytes") ;
+
+ my $keep = $magic . $buffer ;
+ *$self->{HeaderPending} = $keep ;
+
+ #my $versionMadeBy = unpack ("v", substr($buffer, 4-4, 2));
+ #my $extractVersion = unpack ("v", substr($buffer, 6-4, 2));
+ #my $gpFlag = unpack ("v", substr($buffer, 8-4, 2));
+ #my $compressedMethod = unpack ("v", substr($buffer, 10-4, 2));
+ #my $lastModTime = unpack ("V", substr($buffer, 12-4, 4));
+ #my $crc32 = unpack ("V", substr($buffer, 16-4, 4));
+ my $compressedLength = unpack ("V", substr($buffer, 20-4, 4));
+ my $uncompressedLength = unpack ("V", substr($buffer, 24-4, 4));
+ my $filename_length = unpack ("v", substr($buffer, 28-4, 2));
+ my $extra_length = unpack ("v", substr($buffer, 30-4, 2));
+ my $comment_length = unpack ("v", substr($buffer, 32-4, 2));
+ #my $disk_start = unpack ("v", substr($buffer, 34-4, 2));
+ #my $int_file_attrib = unpack ("v", substr($buffer, 36-4, 2));
+ #my $ext_file_attrib = unpack ("V", substr($buffer, 38-4, 2));
+ #my $lcl_hdr_offset = unpack ("V", substr($buffer, 42-4, 2));
+
+
+ my $filename;
+ my $extraField;
+ my $comment ;
+ if ($filename_length)
+ {
+ $self->smartReadExact(\$filename, $filename_length)
+ or return $self->TruncatedTrailer("filename");
+ $keep .= $filename ;
+ }
+
+ if ($extra_length)
+ {
+ $self->smartReadExact(\$extraField, $extra_length)
+ or return $self->TruncatedTrailer("extra");
+ $keep .= $extraField ;
+ }
+
+ if ($comment_length)
+ {
+ $self->smartReadExact(\$comment, $comment_length)
+ or return $self->TruncatedTrailer("comment");
+ $keep .= $comment ;
+ }
+
+ return STATUS_OK ;
+}
+
+sub skipArchiveExtra
+{
+ my $self = shift;
+ my $magic = shift ;
+
+ my $buffer;
+ $self->smartReadExact(\$buffer, 4)
+ or return $self->TrailerError("Minimum header size is " .
+ 4 . " bytes") ;
+
+ my $keep = $magic . $buffer ;
+
+ my $size = unpack ("V", $buffer);
+
+ $self->smartReadExact(\$buffer, $size)
+ or return $self->TrailerError("Minimum header size is " .
+ $size . " bytes") ;
+
+ $keep .= $buffer ;
+ *$self->{HeaderPending} = $keep ;
+
+ return STATUS_OK ;
+}
+
+
+sub skipCentralDirectory64Rec
+{
+ my $self = shift;
+ my $magic = shift ;
+
+ my $buffer;
+ $self->smartReadExact(\$buffer, 8)
+ or return $self->TrailerError("Minimum header size is " .
+ 8 . " bytes") ;
+
+ my $keep = $magic . $buffer ;
+
+ my ($sizeLo, $sizeHi) = unpack ("V V", $buffer);
+ my $size = $sizeHi * 0xFFFFFFFF + $sizeLo;
+
+ $self->fastForward($size)
+ or return $self->TrailerError("Minimum header size is " .
+ $size . " bytes") ;
+
+ #$keep .= $buffer ;
+ #*$self->{HeaderPending} = $keep ;
+
+ #my $versionMadeBy = unpack ("v", substr($buffer, 0, 2));
+ #my $extractVersion = unpack ("v", substr($buffer, 2, 2));
+ #my $diskNumber = unpack ("V", substr($buffer, 4, 4));
+ #my $cntrlDirDiskNo = unpack ("V", substr($buffer, 8, 4));
+ #my $entriesInThisCD = unpack ("V V", substr($buffer, 12, 8));
+ #my $entriesInCD = unpack ("V V", substr($buffer, 20, 8));
+ #my $sizeOfCD = unpack ("V V", substr($buffer, 28, 8));
+ #my $offsetToCD = unpack ("V V", substr($buffer, 36, 8));
+
+ return STATUS_OK ;
+}
+
+sub skipCentralDirectory64Loc
+{
+ my $self = shift;
+ my $magic = shift ;
+
+ my $buffer;
+ $self->smartReadExact(\$buffer, 20 - 4)
+ or return $self->TrailerError("Minimum header size is " .
+ 20 . " bytes") ;
+
+ my $keep = $magic . $buffer ;
+ *$self->{HeaderPending} = $keep ;
+
+ #my $startCdDisk = unpack ("V", substr($buffer, 4-4, 4));
+ #my $offsetToCD = unpack ("V V", substr($buffer, 8-4, 8));
+ #my $diskCount = unpack ("V", substr($buffer, 16-4, 4));
+
+ return STATUS_OK ;
+}
+
+sub skipEndCentralDirectory
+{
+ my $self = shift;
+ my $magic = shift ;
+
+ my $buffer;
+ $self->smartReadExact(\$buffer, 22 - 4)
+ or return $self->TrailerError("Minimum header size is " .
+ 22 . " bytes") ;
+
+ my $keep = $magic . $buffer ;
+ *$self->{HeaderPending} = $keep ;
+
+ #my $diskNumber = unpack ("v", substr($buffer, 4-4, 2));
+ #my $cntrlDirDiskNo = unpack ("v", substr($buffer, 6-4, 2));
+ #my $entriesInThisCD = unpack ("v", substr($buffer, 8-4, 2));
+ #my $entriesInCD = unpack ("v", substr($buffer, 10-4, 2));
+ #my $sizeOfCD = unpack ("V", substr($buffer, 12-4, 2));
+ #my $offsetToCD = unpack ("V", substr($buffer, 16-4, 2));
+ my $comment_length = unpack ("v", substr($buffer, 20-4, 2));
+
+
+ my $comment ;
+ if ($comment_length)
+ {
+ $self->smartReadExact(\$comment, $comment_length)
+ or return $self->TruncatedTrailer("comment");
+ $keep .= $comment ;
+ }
+
+ return STATUS_OK ;
+}
+
+
+sub _isZipMagic
+{
+ my $buffer = shift ;
+ return 0 if length $buffer < 4 ;
+ my $sig = unpack("V", $buffer) ;
+ return $sig == ZIP_LOCAL_HDR_SIG ;
+}
+
+
+sub _readFullZipHeader($)
+{
+ my ($self) = @_ ;
+ my $magic = '' ;
+
+ $self->smartReadExact(\$magic, 4);
+
+ *$self->{HeaderPending} = $magic ;
+
+ return $self->HeaderError("Minimum header size is " .
+ 30 . " bytes")
+ if length $magic != 4 ;
+
+
+ return $self->HeaderError("Bad Magic")
+ if ! _isZipMagic($magic) ;
+
+ my $status = $self->_readZipHeader($magic);
+ delete *$self->{Transparent} if ! defined $status ;
+ return $status ;
+}
+
+sub _readZipHeader($)
+{
+ my ($self, $magic) = @_ ;
+ my ($HeaderCRC) ;
+ my ($buffer) = '' ;
+
+ $self->smartReadExact(\$buffer, 30 - 4)
+ or return $self->HeaderError("Minimum header size is " .
+ 30 . " bytes") ;
+
+ my $keep = $magic . $buffer ;
+ *$self->{HeaderPending} = $keep ;
+
+ my $extractVersion = unpack ("v", substr($buffer, 4-4, 2));
+ my $gpFlag = unpack ("v", substr($buffer, 6-4, 2));
+ my $compressedMethod = unpack ("v", substr($buffer, 8-4, 2));
+ my $lastModTime = unpack ("V", substr($buffer, 10-4, 4));
+ my $crc32 = unpack ("V", substr($buffer, 14-4, 4));
+ my $compressedLength = U64::newUnpack_V32 substr($buffer, 18-4, 4);
+ my $uncompressedLength = U64::newUnpack_V32 substr($buffer, 22-4, 4);
+ my $filename_length = unpack ("v", substr($buffer, 26-4, 2));
+ my $extra_length = unpack ("v", substr($buffer, 28-4, 2));
+
+ my $filename;
+ my $extraField;
+ my @EXTRA = ();
+ my $streamingMode = ($gpFlag & ZIP_GP_FLAG_STREAMING_MASK) ? 1 : 0 ;
+
+ return $self->HeaderError("Streamed Stored content not supported")
+ if $streamingMode && $compressedMethod == 0 ;
+
+ return $self->HeaderError("Encrypted content not supported")
+ if $gpFlag & (ZIP_GP_FLAG_ENCRYPTED_MASK|ZIP_GP_FLAG_STRONG_ENCRYPTED_MASK);
+
+ return $self->HeaderError("Patch content not supported")
+ if $gpFlag & ZIP_GP_FLAG_PATCHED_MASK;
+
+ *$self->{ZipData}{Streaming} = $streamingMode;
+
+
+ if ($filename_length)
+ {
+ $self->smartReadExact(\$filename, $filename_length)
+ or return $self->TruncatedHeader("Filename");
+ $keep .= $filename ;
+ }
+
+ my $zip64 = 0 ;
+
+ if ($extra_length)
+ {
+ $self->smartReadExact(\$extraField, $extra_length)
+ or return $self->TruncatedHeader("Extra Field");
+
+ my $bad = IO::Compress::Zlib::Extra::parseRawExtra($extraField,
+ \@EXTRA, 1, 0);
+ return $self->HeaderError($bad)
+ if defined $bad;
+
+ $keep .= $extraField ;
+
+ my %Extra ;
+ for (@EXTRA)
+ {
+ $Extra{$_->[0]} = \$_->[1];
+ }
+
+ if (defined $Extra{ZIP_EXTRA_ID_ZIP64()})
+ {
+ $zip64 = 1 ;
+
+ my $buff = ${ $Extra{ZIP_EXTRA_ID_ZIP64()} };
+
+ # This code assumes that all the fields in the Zip64
+ # extra field aren't necessarily present. The spec says that
+ # they only exist if the equivalent local headers are -1.
+
+ if (! $streamingMode) {
+ my $offset = 0 ;
+
+ if ($uncompressedLength->get32bit() == 0xFFFFFFFF ) {
+ $uncompressedLength
+ = U64::newUnpack_V64 substr($buff, 0, 8);
+
+ $offset += 8 ;
+ }
+
+ if ($compressedLength->get32bit() == 0xFFFFFFFF) {
+
+ $compressedLength
+ = U64::newUnpack_V64 substr($buff, $offset, 8);
+
+ $offset += 8 ;
+ }
+ }
+ }
+ }
+
+ *$self->{ZipData}{Zip64} = $zip64;
+
+ if (! $streamingMode) {
+ *$self->{ZipData}{Streaming} = 0;
+ *$self->{ZipData}{Crc32} = $crc32;
+ *$self->{ZipData}{CompressedLen} = $compressedLength;
+ *$self->{ZipData}{UnCompressedLen} = $uncompressedLength;
+ *$self->{CompressedInputLengthRemaining} =
+ *$self->{CompressedInputLength} = $compressedLength->get64bit();
+ }
+
+ *$self->{ZipData}{CRC32} = crc32(undef);
+ *$self->{ZipData}{Method} = $compressedMethod;
+ if ($compressedMethod == ZIP_CM_DEFLATE)
+ {
+ *$self->{Type} = 'zip-deflate';
+ my $obj = IO::Uncompress::Adapter::Inflate::mkUncompObject(1,0,0);
+
+ *$self->{Uncomp} = $obj;
+ }
+ elsif ($compressedMethod == ZIP_CM_BZIP2)
+ {
+ return $self->HeaderError("Unsupported Compression format $compressedMethod")
+ if ! defined $IO::Uncompress::Adapter::Bunzip2::VERSION ;
+
+ *$self->{Type} = 'zip-bzip2';
+
+ my $obj = IO::Uncompress::Adapter::Bunzip2::mkUncompObject();
+
+ *$self->{Uncomp} = $obj;
+ }
+# elsif ($compressedMethod == ZIP_CM_LZMA)
+# {
+# return $self->HeaderError("Unsupported Compression format $compressedMethod")
+# if ! defined $IO::Uncompress::Adapter::UnLzma::VERSION ;
+#
+# *$self->{Type} = 'zip-lzma';
+# my $LzmaHeader;
+# $self->smartReadExact(\$LzmaHeader, 4)
+# or return $self->saveErrorString(undef, "Truncated file");
+# my ($verHi, $verLo) = unpack ("CC", substr($LzmaHeader, 0, 2));
+# my $LzmaPropertiesSize = unpack ("v", substr($LzmaHeader, 2, 2));
+#
+#
+# my $LzmaPropertyData;
+# $self->smartReadExact(\$LzmaPropertyData, $LzmaPropertiesSize)
+# or return $self->saveErrorString(undef, "Truncated file");
+# #my $LzmaInfo = unpack ("C", substr($LzmaPropertyData, 0, 1));
+# #my $LzmaDictSize = unpack ("V", substr($LzmaPropertyData, 1, 4));
+#
+# # Create an LZMA_Alone header
+# $self->pushBack($LzmaPropertyData .
+# $uncompressedLength->getPacked_V64());
+#
+# my $obj =
+# IO::Uncompress::Adapter::UnLzma::mkUncompObject();
+#
+# *$self->{Uncomp} = $obj;
+# }
+ elsif ($compressedMethod == ZIP_CM_STORE)
+ {
+ # TODO -- add support for reading uncompressed
+
+ *$self->{Type} = 'zip-stored';
+
+ my $obj = IO::Uncompress::Adapter::Identity::mkUncompObject();
+
+ *$self->{Uncomp} = $obj;
+ }
+ else
+ {
+ return $self->HeaderError("Unsupported Compression format $compressedMethod");
+ }
+
+ return {
+ 'Type' => 'zip',
+ 'FingerprintLength' => 4,
+ #'HeaderLength' => $compressedMethod == 8 ? length $keep : 0,
+ 'HeaderLength' => length $keep,
+ 'Zip64' => $zip64,
+ 'TrailerLength' => ! $streamingMode ? 0 : $zip64 ? 24 : 16,
+ 'Header' => $keep,
+ 'CompressedLength' => $compressedLength ,
+ 'UncompressedLength' => $uncompressedLength ,
+ 'CRC32' => $crc32 ,
+ 'Name' => $filename,
+ 'Time' => _dosToUnixTime($lastModTime),
+ 'Stream' => $streamingMode,
+
+ 'MethodID' => $compressedMethod,
+ 'MethodName' => $compressedMethod == ZIP_CM_DEFLATE
+ ? "Deflated"
+ : $compressedMethod == ZIP_CM_BZIP2
+ ? "Bzip2"
+ : $compressedMethod == ZIP_CM_LZMA
+ ? "Lzma"
+ : $compressedMethod == ZIP_CM_STORE
+ ? "Stored"
+ : "Unknown" ,
+
+# 'TextFlag' => $flag & GZIP_FLG_FTEXT ? 1 : 0,
+# 'HeaderCRCFlag' => $flag & GZIP_FLG_FHCRC ? 1 : 0,
+# 'NameFlag' => $flag & GZIP_FLG_FNAME ? 1 : 0,
+# 'CommentFlag' => $flag & GZIP_FLG_FCOMMENT ? 1 : 0,
+# 'ExtraFlag' => $flag & GZIP_FLG_FEXTRA ? 1 : 0,
+# 'Comment' => $comment,
+# 'OsID' => $os,
+# 'OsName' => defined $GZIP_OS_Names{$os}
+# ? $GZIP_OS_Names{$os} : "Unknown",
+# 'HeaderCRC' => $HeaderCRC,
+# 'Flags' => $flag,
+# 'ExtraFlags' => $xfl,
+ 'ExtraFieldRaw' => $extraField,
+ 'ExtraField' => [ @EXTRA ],
+
+
+ }
+}
+
+sub filterUncompressed
+{
+ my $self = shift ;
+
+ if (*$self->{ZipData}{Method} == ZIP_CM_DEFLATE) {
+ *$self->{ZipData}{CRC32} = *$self->{Uncomp}->crc32() ;
+ }
+ else {
+ *$self->{ZipData}{CRC32} = crc32(${$_[0]}, *$self->{ZipData}{CRC32});
+ }
+}
+
+
+# from Archive::Zip & info-zip
+sub _dosToUnixTime
+{
+ my $dt = shift;
+
+ my $year = ( ( $dt >> 25 ) & 0x7f ) + 80;
+ my $mon = ( ( $dt >> 21 ) & 0x0f ) - 1;
+ my $mday = ( ( $dt >> 16 ) & 0x1f );
+
+ my $hour = ( ( $dt >> 11 ) & 0x1f );
+ my $min = ( ( $dt >> 5 ) & 0x3f );
+ my $sec = ( ( $dt << 1 ) & 0x3e );
+
+
+ use POSIX 'mktime';
+
+ my $time_t = mktime( $sec, $min, $hour, $mday, $mon, $year, 0, 0, -1 );
+ return 0 if ! defined $time_t;
+ return $time_t;
+}
+
+
+1;
+
+__END__
+
+
+=head1 NAME
+
+IO::Uncompress::Unzip - Read zip files/buffers
+
+=head1 SYNOPSIS
+
+ use IO::Uncompress::Unzip qw(unzip $UnzipError) ;
+
+ my $status = unzip $input => $output [,OPTS]
+ or die "unzip failed: $UnzipError\n";
+
+ my $z = new IO::Uncompress::Unzip $input [OPTS]
+ or die "unzip failed: $UnzipError\n";
+
+ $status = $z->read($buffer)
+ $status = $z->read($buffer, $length)
+ $status = $z->read($buffer, $length, $offset)
+ $line = $z->getline()
+ $char = $z->getc()
+ $char = $z->ungetc()
+ $char = $z->opened()
+
+ $status = $z->inflateSync()
+
+ $data = $z->trailingData()
+ $status = $z->nextStream()
+ $data = $z->getHeaderInfo()
+ $z->tell()
+ $z->seek($position, $whence)
+ $z->binmode()
+ $z->fileno()
+ $z->eof()
+ $z->close()
+
+ $UnzipError ;
+
+ # IO::File mode
+
+ <$z>
+ read($z, $buffer);
+ read($z, $buffer, $length);
+ read($z, $buffer, $length, $offset);
+ tell($z)
+ seek($z, $position, $whence)
+ binmode($z)
+ fileno($z)
+ eof($z)
+ close($z)
+
+=head1 DESCRIPTION
+
+This module provides a Perl interface that allows the reading of
+zlib files/buffers.
+
+For writing zip files/buffers, see the companion module IO::Compress::Zip.
+
+=head1 Functional Interface
+
+A top-level function, C<unzip>, is provided to carry out
+"one-shot" uncompression between buffers and/or files. For finer
+control over the uncompression process, see the L</"OO Interface">
+section.
+
+ use IO::Uncompress::Unzip qw(unzip $UnzipError) ;
+
+ unzip $input => $output [,OPTS]
+ or die "unzip failed: $UnzipError\n";
+
+The functional interface needs Perl5.005 or better.
+
+=head2 unzip $input => $output [, OPTS]
+
+C<unzip> expects at least two parameters, C<$input> and C<$output>.
+
+=head3 The C<$input> parameter
+
+The parameter, C<$input>, is used to define the source of
+the compressed data.
+
+It can take one of the following forms:
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for reading and the input data
+will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the input data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the input data will be read
+from C<$$input>.
+
+=item An array reference
+
+If C<$input> is an array reference, each element in the array must be a
+filename.
+
+The input data will be read from each file in turn.
+
+The complete array will be walked to ensure that it only
+contains valid filenames before any data is uncompressed.
+
+=item An Input FileGlob string
+
+If C<$input> is a string that is delimited by the characters "<" and ">"
+C<unzip> will assume that it is an I<input fileglob string>. The
+input is the list of files that match the fileglob.
+
+If the fileglob does not match any files ...
+
+See L<File::GlobMapper|File::GlobMapper> for more details.
+
+=back
+
+If the C<$input> parameter is any other type, C<undef> will be returned.
+
+=head3 The C<$output> parameter
+
+The parameter C<$output> is used to control the destination of the
+uncompressed data. This parameter can take one of these forms.
+
+=over 5
+
+=item A filename
+
+If the C<$output> parameter is a simple scalar, it is assumed to be a
+filename. This file will be opened for writing and the uncompressed
+data will be written to it.
+
+=item A filehandle
+
+If the C<$output> parameter is a filehandle, the uncompressed data
+will be written to it.
+The string '-' can be used as an alias for standard output.
+
+=item A scalar reference
+
+If C<$output> is a scalar reference, the uncompressed data will be
+stored in C<$$output>.
+
+=item An Array Reference
+
+If C<$output> is an array reference, the uncompressed data will be
+pushed onto the array.
+
+=item An Output FileGlob
+
+If C<$output> is a string that is delimited by the characters "<" and ">"
+C<unzip> will assume that it is an I<output fileglob string>. The
+output is the list of files that match the fileglob.
+
+When C<$output> is an fileglob string, C<$input> must also be a fileglob
+string. Anything else is an error.
+
+=back
+
+If the C<$output> parameter is any other type, C<undef> will be returned.
+
+=head2 Notes
+
+When C<$input> maps to multiple compressed files/buffers and C<$output> is
+a single file/buffer, after uncompression C<$output> will contain a
+concatenation of all the uncompressed data from each of the input
+files/buffers.
+
+=head2 Optional Parameters
+
+Unless specified below, the optional parameters for C<unzip>,
+C<OPTS>, are the same as those used with the OO interface defined in the
+L</"Constructor Options"> section below.
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option applies to any input or output data streams to
+C<unzip> that are filehandles.
+
+If C<AutoClose> is specified, and the value is true, it will result in all
+input and/or output filehandles being closed once C<unzip> has
+completed.
+
+This parameter defaults to 0.
+
+=item C<< BinModeOut => 0|1 >>
+
+When writing to a file or filehandle, set C<binmode> before writing to the
+file.
+
+Defaults to 0.
+
+=item C<< Append => 0|1 >>
+
+The behaviour of this option is dependent on the type of output data
+stream.
+
+=over 5
+
+=item * A Buffer
+
+If C<Append> is enabled, all uncompressed data will be append to the end of
+the output buffer. Otherwise the output buffer will be cleared before any
+uncompressed data is written to it.
+
+=item * A Filename
+
+If C<Append> is enabled, the file will be opened in append mode. Otherwise
+the contents of the file, if any, will be truncated before any uncompressed
+data is written to it.
+
+=item * A Filehandle
+
+If C<Append> is enabled, the filehandle will be positioned to the end of
+the file via a call to C<seek> before any uncompressed data is
+written to it. Otherwise the file pointer will not be moved.
+
+=back
+
+When C<Append> is specified, and set to true, it will I<append> all uncompressed
+data to the output data stream.
+
+So when the output is a filehandle it will carry out a seek to the eof
+before writing any uncompressed data. If the output is a filename, it will be opened for
+appending. If the output is a buffer, all uncompressed data will be appened to
+the existing buffer.
+
+Conversely when C<Append> is not specified, or it is present and is set to
+false, it will operate as follows.
+
+When the output is a filename, it will truncate the contents of the file
+before writing any uncompressed data. If the output is a filehandle
+its position will not be changed. If the output is a buffer, it will be
+wiped before any uncompressed data is output.
+
+Defaults to 0.
+
+=item C<< MultiStream => 0|1 >>
+
+If the input file/buffer contains multiple compressed data streams, this
+option will uncompress the whole lot as a single data stream.
+
+Defaults to 0.
+
+=item C<< TrailingData => $scalar >>
+
+Returns the data, if any, that is present immediately after the compressed
+data stream once uncompression is complete.
+
+This option can be used when there is useful information immediately
+following the compressed data stream, and you don't know the length of the
+compressed data stream.
+
+If the input is a buffer, C<trailingData> will return everything from the
+end of the compressed data stream to the end of the buffer.
+
+If the input is a filehandle, C<trailingData> will return the data that is
+left in the filehandle input buffer once the end of the compressed data
+stream has been reached. You can then use the filehandle to read the rest
+of the input file.
+
+Don't bother using C<trailingData> if the input is a filename.
+
+If you know the length of the compressed data stream before you start
+uncompressing, you can avoid having to use C<trailingData> by setting the
+C<InputLength> option.
+
+=back
+
+=head2 Examples
+
+To read the contents of the file C<file1.txt.zip> and write the
+uncompressed data to the file C<file1.txt>.
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::Unzip qw(unzip $UnzipError) ;
+
+ my $input = "file1.txt.zip";
+ my $output = "file1.txt";
+ unzip $input => $output
+ or die "unzip failed: $UnzipError\n";
+
+To read from an existing Perl filehandle, C<$input>, and write the
+uncompressed data to a buffer, C<$buffer>.
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::Unzip qw(unzip $UnzipError) ;
+ use IO::File ;
+
+ my $input = new IO::File "<file1.txt.zip"
+ or die "Cannot open 'file1.txt.zip': $!\n" ;
+ my $buffer ;
+ unzip $input => \$buffer
+ or die "unzip failed: $UnzipError\n";
+
+To uncompress all files in the directory "/my/home" that match "*.txt.zip" and store the compressed data in the same directory
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::Unzip qw(unzip $UnzipError) ;
+
+ unzip '</my/home/*.txt.zip>' => '</my/home/#1.txt>'
+ or die "unzip failed: $UnzipError\n";
+
+and if you want to compress each file one at a time, this will do the trick
+
+ use strict ;
+ use warnings ;
+ use IO::Uncompress::Unzip qw(unzip $UnzipError) ;
+
+ for my $input ( glob "/my/home/*.txt.zip" )
+ {
+ my $output = $input;
+ $output =~ s/.zip// ;
+ unzip $input => $output
+ or die "Error compressing '$input': $UnzipError\n";
+ }
+
+=head1 OO Interface
+
+=head2 Constructor
+
+The format of the constructor for IO::Uncompress::Unzip is shown below
+
+ my $z = new IO::Uncompress::Unzip $input [OPTS]
+ or die "IO::Uncompress::Unzip failed: $UnzipError\n";
+
+Returns an C<IO::Uncompress::Unzip> object on success and undef on failure.
+The variable C<$UnzipError> will contain an error message on failure.
+
+If you are running Perl 5.005 or better the object, C<$z>, returned from
+IO::Uncompress::Unzip can be used exactly like an L<IO::File|IO::File> filehandle.
+This means that all normal input file operations can be carried out with
+C<$z>. For example, to read a line from a compressed file/buffer you can
+use either of these forms
+
+ $line = $z->getline();
+ $line = <$z>;
+
+The mandatory parameter C<$input> is used to determine the source of the
+compressed data. This parameter can take one of three forms.
+
+=over 5
+
+=item A filename
+
+If the C<$input> parameter is a scalar, it is assumed to be a filename. This
+file will be opened for reading and the compressed data will be read from it.
+
+=item A filehandle
+
+If the C<$input> parameter is a filehandle, the compressed data will be
+read from it.
+The string '-' can be used as an alias for standard input.
+
+=item A scalar reference
+
+If C<$input> is a scalar reference, the compressed data will be read from
+C<$$output>.
+
+=back
+
+=head2 Constructor Options
+
+The option names defined below are case insensitive and can be optionally
+prefixed by a '-'. So all of the following are valid
+
+ -AutoClose
+ -autoclose
+ AUTOCLOSE
+ autoclose
+
+OPTS is a combination of the following options:
+
+=over 5
+
+=item C<< AutoClose => 0|1 >>
+
+This option is only valid when the C<$input> parameter is a filehandle. If
+specified, and the value is true, it will result in the file being closed once
+either the C<close> method is called or the IO::Uncompress::Unzip object is
+destroyed.
+
+This parameter defaults to 0.
+
+=item C<< MultiStream => 0|1 >>
+
+Treats the complete zip file/buffer as a single compressed data
+stream. When reading in multi-stream mode each member of the zip
+file/buffer will be uncompressed in turn until the end of the file/buffer
+is encountered.
+
+This parameter defaults to 0.
+
+=item C<< Prime => $string >>
+
+This option will uncompress the contents of C<$string> before processing the
+input file/buffer.
+
+This option can be useful when the compressed data is embedded in another
+file/data structure and it is not possible to work out where the compressed
+data begins without having to read the first few bytes. If this is the
+case, the uncompression can be I<primed> with these bytes using this
+option.
+
+=item C<< Transparent => 0|1 >>
+
+If this option is set and the input file/buffer is not compressed data,
+the module will allow reading of it anyway.
+
+In addition, if the input file/buffer does contain compressed data and
+there is non-compressed data immediately following it, setting this option
+will make this module treat the whole file/bufffer as a single data stream.
+
+This option defaults to 1.
+
+=item C<< BlockSize => $num >>
+
+When reading the compressed input data, IO::Uncompress::Unzip will read it in
+blocks of C<$num> bytes.
+
+This option defaults to 4096.
+
+=item C<< InputLength => $size >>
+
+When present this option will limit the number of compressed bytes read
+from the input file/buffer to C<$size>. This option can be used in the
+situation where there is useful data directly after the compressed data
+stream and you know beforehand the exact length of the compressed data
+stream.
+
+This option is mostly used when reading from a filehandle, in which case
+the file pointer will be left pointing to the first byte directly after the
+compressed data stream.
+
+This option defaults to off.
+
+=item C<< Append => 0|1 >>
+
+This option controls what the C<read> method does with uncompressed data.
+
+If set to 1, all uncompressed data will be appended to the output parameter
+of the C<read> method.
+
+If set to 0, the contents of the output parameter of the C<read> method
+will be overwritten by the uncompressed data.
+
+Defaults to 0.
+
+=item C<< Strict => 0|1 >>
+
+This option controls whether the extra checks defined below are used when
+carrying out the decompression. When Strict is on, the extra tests are
+carried out, when Strict is off they are not.
+
+The default for this option is off.
+
+=back
+
+=head2 Examples
+
+TODO
+
+=head1 Methods
+
+=head2 read
+
+Usage is
+
+ $status = $z->read($buffer)
+
+Reads a block of compressed data (the size the the compressed block is
+determined by the C<Buffer> option in the constructor), uncompresses it and
+writes any uncompressed data into C<$buffer>. If the C<Append> parameter is
+set in the constructor, the uncompressed data will be appended to the
+C<$buffer> parameter. Otherwise C<$buffer> will be overwritten.
+
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
+
+=head2 read
+
+Usage is
+
+ $status = $z->read($buffer, $length)
+ $status = $z->read($buffer, $length, $offset)
+
+ $status = read($z, $buffer, $length)
+ $status = read($z, $buffer, $length, $offset)
+
+Attempt to read C<$length> bytes of uncompressed data into C<$buffer>.
+
+The main difference between this form of the C<read> method and the
+previous one, is that this one will attempt to return I<exactly> C<$length>
+bytes. The only circumstances that this function will not is if end-of-file
+or an IO error is encountered.
+
+Returns the number of uncompressed bytes written to C<$buffer>, zero if eof
+or a negative number on error.
+
+=head2 getline
+
+Usage is
+
+ $line = $z->getline()
+ $line = <$z>
+
+Reads a single line.
+
+This method fully supports the use of of the variable C<$/> (or
+C<$INPUT_RECORD_SEPARATOR> or C<$RS> when C<English> is in use) to
+determine what constitutes an end of line. Paragraph mode, record mode and
+file slurp mode are all supported.
+
+=head2 getc
+
+Usage is
+
+ $char = $z->getc()
+
+Read a single character.
+
+=head2 ungetc
+
+Usage is
+
+ $char = $z->ungetc($string)
+
+=head2 inflateSync
+
+Usage is
+
+ $status = $z->inflateSync()
+
+TODO
+
+=head2 getHeaderInfo
+
+Usage is
+
+ $hdr = $z->getHeaderInfo();
+ @hdrs = $z->getHeaderInfo();
+
+This method returns either a hash reference (in scalar context) or a list
+or hash references (in array context) that contains information about each
+of the header fields in the compressed data stream(s).
+
+=head2 tell
+
+Usage is
+
+ $z->tell()
+ tell $z
+
+Returns the uncompressed file offset.
+
+=head2 eof
+
+Usage is
+
+ $z->eof();
+ eof($z);
+
+Returns true if the end of the compressed input stream has been reached.
+
+=head2 seek
+
+ $z->seek($position, $whence);
+ seek($z, $position, $whence);
+
+Provides a sub-set of the C<seek> functionality, with the restriction
+that it is only legal to seek forward in the input file/buffer.
+It is a fatal error to attempt to seek backward.
+
+The C<$whence> parameter takes one the usual values, namely SEEK_SET,
+SEEK_CUR or SEEK_END.
+
+Returns 1 on success, 0 on failure.
+
+=head2 binmode
+
+Usage is
+
+ $z->binmode
+ binmode $z ;
+
+This is a noop provided for completeness.
+
+=head2 opened
+
+ $z->opened()
+
+Returns true if the object currently refers to a opened file/buffer.
+
+=head2 autoflush
+
+ my $prev = $z->autoflush()
+ my $prev = $z->autoflush(EXPR)
+
+If the C<$z> object is associated with a file or a filehandle, this method
+returns the current autoflush setting for the underlying filehandle. If
+C<EXPR> is present, and is non-zero, it will enable flushing after every
+write/print operation.
+
+If C<$z> is associated with a buffer, this method has no effect and always
+returns C<undef>.
+
+B<Note> that the special variable C<$|> B<cannot> be used to set or
+retrieve the autoflush setting.
+
+=head2 input_line_number
+
+ $z->input_line_number()
+ $z->input_line_number(EXPR)
+
+Returns the current uncompressed line number. If C<EXPR> is present it has
+the effect of setting the line number. Note that setting the line number
+does not change the current position within the file/buffer being read.
+
+The contents of C<$/> are used to to determine what constitutes a line
+terminator.
+
+=head2 fileno
+
+ $z->fileno()
+ fileno($z)
+
+If the C<$z> object is associated with a file or a filehandle, C<fileno>
+will return the underlying file descriptor. Once the C<close> method is
+called C<fileno> will return C<undef>.
+
+If the C<$z> object is is associated with a buffer, this method will return
+C<undef>.
+
+=head2 close
+
+ $z->close() ;
+ close $z ;
+
+Closes the output file/buffer.
+
+For most versions of Perl this method will be automatically invoked if
+the IO::Uncompress::Unzip object is destroyed (either explicitly or by the
+variable with the reference to the object going out of scope). The
+exceptions are Perl versions 5.005 through 5.00504 and 5.8.0. In
+these cases, the C<close> method will be called automatically, but
+not until global destruction of all live objects when the program is
+terminating.
+
+Therefore, if you want your scripts to be able to run on all versions
+of Perl, you should call C<close> explicitly and not rely on automatic
+closing.
+
+Returns true on success, otherwise 0.
+
+If the C<AutoClose> option has been enabled when the IO::Uncompress::Unzip
+object was created, and the object is associated with a file, the
+underlying file will also be closed.
+
+=head2 nextStream
+
+Usage is
+
+ my $status = $z->nextStream();
+
+Skips to the next compressed data stream in the input file/buffer. If a new
+compressed data stream is found, the eof marker will be cleared and C<$.>
+will be reset to 0.
+
+Returns 1 if a new stream was found, 0 if none was found, and -1 if an
+error was encountered.
+
+=head2 trailingData
+
+Usage is
+
+ my $data = $z->trailingData();
+
+Returns the data, if any, that is present immediately after the compressed
+data stream once uncompression is complete. It only makes sense to call
+this method once the end of the compressed data stream has been
+encountered.
+
+This option can be used when there is useful information immediately
+following the compressed data stream, and you don't know the length of the
+compressed data stream.
+
+If the input is a buffer, C<trailingData> will return everything from the
+end of the compressed data stream to the end of the buffer.
+
+If the input is a filehandle, C<trailingData> will return the data that is
+left in the filehandle input buffer once the end of the compressed data
+stream has been reached. You can then use the filehandle to read the rest
+of the input file.
+
+Don't bother using C<trailingData> if the input is a filename.
+
+If you know the length of the compressed data stream before you start
+uncompressing, you can avoid having to use C<trailingData> by setting the
+C<InputLength> option in the constructor.
+
+=head1 Importing
+
+No symbolic constants are required by this IO::Uncompress::Unzip at present.
+
+=over 5
+
+=item :all
+
+Imports C<unzip> and C<$UnzipError>.
+Same as doing this
+
+ use IO::Uncompress::Unzip qw(unzip $UnzipError) ;
+
+=back
+
+=head1 EXAMPLES
+
+=head2 Working with Net::FTP
+
+See L<IO::Uncompress::Unzip::FAQ|IO::Uncompress::Unzip::FAQ/"Compressed files and Net::FTP">
+
+=head1 SEE ALSO
+
+L<Compress::Zlib>, L<IO::Compress::Gzip>, L<IO::Uncompress::Gunzip>, L<IO::Compress::Deflate>, L<IO::Uncompress::Inflate>, L<IO::Compress::RawDeflate>, L<IO::Uncompress::RawInflate>, L<IO::Compress::Bzip2>, L<IO::Uncompress::Bunzip2>, L<IO::Compress::Lzma>, L<IO::Uncompress::UnLzma>, L<IO::Compress::Xz>, L<IO::Uncompress::UnXz>, L<IO::Compress::Lzop>, L<IO::Uncompress::UnLzop>, L<IO::Compress::Lzf>, L<IO::Uncompress::UnLzf>, L<IO::Uncompress::AnyInflate>, L<IO::Uncompress::AnyUncompress>
+
+L<Compress::Zlib::FAQ|Compress::Zlib::FAQ>
+
+L<File::GlobMapper|File::GlobMapper>, L<Archive::Zip|Archive::Zip>,
+L<Archive::Tar|Archive::Tar>,
+L<IO::Zlib|IO::Zlib>
+
+For RFC 1950, 1951 and 1952 see
+F<http://www.faqs.org/rfcs/rfc1950.html>,
+F<http://www.faqs.org/rfcs/rfc1951.html> and
+F<http://www.faqs.org/rfcs/rfc1952.html>
+
+The I<zlib> compression library was written by Jean-loup Gailly
+F<gzip@prep.ai.mit.edu> and Mark Adler F<madler@alumni.caltech.edu>.
+
+The primary site for the I<zlib> compression library is
+F<http://www.zlib.org>.
+
+The primary site for gzip is F<http://www.gzip.org>.
+
+=head1 AUTHOR
+
+This module was written by Paul Marquess, F<pmqs@cpan.org>.
+
+=head1 MODIFICATION HISTORY
+
+See the Changes file.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2005-2010 Paul Marquess. All rights reserved.
+
+This program is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
diff --git a/Master/tlpkg/tlperl/lib/IO/Zlib.pm b/Master/tlpkg/tlperl/lib/IO/Zlib.pm
new file mode 100644
index 00000000000..55534b4f374
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/IO/Zlib.pm
@@ -0,0 +1,652 @@
+# IO::Zlib.pm
+#
+# Copyright (c) 1998-2004 Tom Hughes <tom@compton.nu>.
+# All rights reserved. This program is free software; you can redistribute
+# it and/or modify it under the same terms as Perl itself.
+
+package IO::Zlib;
+
+$VERSION = "1.10";
+
+=head1 NAME
+
+IO::Zlib - IO:: style interface to L<Compress::Zlib>
+
+=head1 SYNOPSIS
+
+With any version of Perl 5 you can use the basic OO interface:
+
+ use IO::Zlib;
+
+ $fh = new IO::Zlib;
+ if ($fh->open("file.gz", "rb")) {
+ print <$fh>;
+ $fh->close;
+ }
+
+ $fh = IO::Zlib->new("file.gz", "wb9");
+ if (defined $fh) {
+ print $fh "bar\n";
+ $fh->close;
+ }
+
+ $fh = IO::Zlib->new("file.gz", "rb");
+ if (defined $fh) {
+ print <$fh>;
+ undef $fh; # automatically closes the file
+ }
+
+With Perl 5.004 you can also use the TIEHANDLE interface to access
+compressed files just like ordinary files:
+
+ use IO::Zlib;
+
+ tie *FILE, 'IO::Zlib', "file.gz", "wb";
+ print FILE "line 1\nline2\n";
+
+ tie *FILE, 'IO::Zlib', "file.gz", "rb";
+ while (<FILE>) { print "LINE: ", $_ };
+
+=head1 DESCRIPTION
+
+C<IO::Zlib> provides an IO:: style interface to L<Compress::Zlib> and
+hence to gzip/zlib compressed files. It provides many of the same methods
+as the L<IO::Handle> interface.
+
+Starting from IO::Zlib version 1.02, IO::Zlib can also use an
+external F<gzip> command. The default behaviour is to try to use
+an external F<gzip> if no C<Compress::Zlib> can be loaded, unless
+explicitly disabled by
+
+ use IO::Zlib qw(:gzip_external 0);
+
+If explicitly enabled by
+
+ use IO::Zlib qw(:gzip_external 1);
+
+then the external F<gzip> is used B<instead> of C<Compress::Zlib>.
+
+=head1 CONSTRUCTOR
+
+=over 4
+
+=item new ( [ARGS] )
+
+Creates an C<IO::Zlib> object. If it receives any parameters, they are
+passed to the method C<open>; if the open fails, the object is destroyed.
+Otherwise, it is returned to the caller.
+
+=back
+
+=head1 OBJECT METHODS
+
+=over 4
+
+=item open ( FILENAME, MODE )
+
+C<open> takes two arguments. The first is the name of the file to open
+and the second is the open mode. The mode can be anything acceptable to
+L<Compress::Zlib> and by extension anything acceptable to I<zlib> (that
+basically means POSIX fopen() style mode strings plus an optional number
+to indicate the compression level).
+
+=item opened
+
+Returns true if the object currently refers to a opened file.
+
+=item close
+
+Close the file associated with the object and disassociate
+the file from the handle.
+Done automatically on destroy.
+
+=item getc
+
+Return the next character from the file, or undef if none remain.
+
+=item getline
+
+Return the next line from the file, or undef on end of string.
+Can safely be called in an array context.
+Currently ignores $/ ($INPUT_RECORD_SEPARATOR or $RS when L<English>
+is in use) and treats lines as delimited by "\n".
+
+=item getlines
+
+Get all remaining lines from the file.
+It will croak() if accidentally called in a scalar context.
+
+=item print ( ARGS... )
+
+Print ARGS to the file.
+
+=item read ( BUF, NBYTES, [OFFSET] )
+
+Read some bytes from the file.
+Returns the number of bytes actually read, 0 on end-of-file, undef on error.
+
+=item eof
+
+Returns true if the handle is currently positioned at end of file?
+
+=item seek ( OFFSET, WHENCE )
+
+Seek to a given position in the stream.
+Not yet supported.
+
+=item tell
+
+Return the current position in the stream, as a numeric offset.
+Not yet supported.
+
+=item setpos ( POS )
+
+Set the current position, using the opaque value returned by C<getpos()>.
+Not yet supported.
+
+=item getpos ( POS )
+
+Return the current position in the string, as an opaque object.
+Not yet supported.
+
+=back
+
+=head1 USING THE EXTERNAL GZIP
+
+If the external F<gzip> is used, the following C<open>s are used:
+
+ open(FH, "gzip -dc $filename |") # for read opens
+ open(FH, " | gzip > $filename") # for write opens
+
+You can modify the 'commands' for example to hardwire
+an absolute path by e.g.
+
+ use IO::Zlib ':gzip_read_open' => '/some/where/gunzip -c %s |';
+ use IO::Zlib ':gzip_write_open' => '| /some/where/gzip.exe > %s';
+
+The C<%s> is expanded to be the filename (C<sprintf> is used, so be
+careful to escape any other C<%> signs). The 'commands' are checked
+for sanity - they must contain the C<%s>, and the read open must end
+with the pipe sign, and the write open must begin with the pipe sign.
+
+=head1 CLASS METHODS
+
+=over 4
+
+=item has_Compress_Zlib
+
+Returns true if C<Compress::Zlib> is available. Note that this does
+not mean that C<Compress::Zlib> is being used: see L</gzip_external>
+and L<gzip_used>.
+
+=item gzip_external
+
+Undef if an external F<gzip> B<can> be used if C<Compress::Zlib> is
+not available (see L</has_Compress_Zlib>), true if an external F<gzip>
+is explicitly used, false if an external F<gzip> must not be used.
+See L</gzip_used>.
+
+=item gzip_used
+
+True if an external F<gzip> is being used, false if not.
+
+=item gzip_read_open
+
+Return the 'command' being used for opening a file for reading using an
+external F<gzip>.
+
+=item gzip_write_open
+
+Return the 'command' being used for opening a file for writing using an
+external F<gzip>.
+
+=back
+
+=head1 DIAGNOSTICS
+
+=over 4
+
+=item IO::Zlib::getlines: must be called in list context
+
+If you want read lines, you must read in list context.
+
+=item IO::Zlib::gzopen_external: mode '...' is illegal
+
+Use only modes 'rb' or 'wb' or /wb[1-9]/.
+
+=item IO::Zlib::import: '...' is illegal
+
+The known import symbols are the C<:gzip_external>, C<:gzip_read_open>,
+and C<:gzip_write_open>. Anything else is not recognized.
+
+=item IO::Zlib::import: ':gzip_external' requires an argument
+
+The C<:gzip_external> requires one boolean argument.
+
+=item IO::Zlib::import: 'gzip_read_open' requires an argument
+
+The C<:gzip_external> requires one string argument.
+
+=item IO::Zlib::import: 'gzip_read' '...' is illegal
+
+The C<:gzip_read_open> argument must end with the pipe sign (|)
+and have the C<%s> for the filename. See L</"USING THE EXTERNAL GZIP">.
+
+=item IO::Zlib::import: 'gzip_write_open' requires an argument
+
+The C<:gzip_external> requires one string argument.
+
+=item IO::Zlib::import: 'gzip_write_open' '...' is illegal
+
+The C<:gzip_write_open> argument must begin with the pipe sign (|)
+and have the C<%s> for the filename. An output redirect (>) is also
+often a good idea, depending on your operating system shell syntax.
+See L</"USING THE EXTERNAL GZIP">.
+
+=item IO::Zlib::import: no Compress::Zlib and no external gzip
+
+Given that we failed to load C<Compress::Zlib> and that the use of
+ an external F<gzip> was disabled, IO::Zlib has not much chance of working.
+
+=item IO::Zlib::open: needs a filename
+
+No filename, no open.
+
+=item IO::Zlib::READ: NBYTES must be specified
+
+We must know how much to read.
+
+=item IO::Zlib::WRITE: too long LENGTH
+
+The LENGTH must be less than or equal to the buffer size.
+
+=back
+
+=head1 SEE ALSO
+
+L<perlfunc>,
+L<perlop/"I/O Operators">,
+L<IO::Handle>,
+L<Compress::Zlib>
+
+=head1 HISTORY
+
+Created by Tom Hughes E<lt>F<tom@compton.nu>E<gt>.
+
+Support for external gzip added by Jarkko Hietaniemi E<lt>F<jhi@iki.fi>E<gt>.
+
+=head1 COPYRIGHT
+
+Copyright (c) 1998-2004 Tom Hughes E<lt>F<tom@compton.nu>E<gt>.
+All rights reserved. This program is free software; you can redistribute
+it and/or modify it under the same terms as Perl itself.
+
+=cut
+
+require 5.006;
+
+use strict;
+use vars qw($VERSION $AUTOLOAD @ISA);
+
+use Carp;
+use Fcntl qw(SEEK_SET);
+
+my $has_Compress_Zlib;
+my $aliased;
+
+sub has_Compress_Zlib {
+ $has_Compress_Zlib;
+}
+
+BEGIN {
+ eval { require Compress::Zlib };
+ $has_Compress_Zlib = $@ || $Compress::Zlib::VERSION < 2.000 ? 0 : 1;
+}
+
+use Symbol;
+use Tie::Handle;
+
+# These might use some $^O logic.
+my $gzip_read_open = "gzip -dc %s |";
+my $gzip_write_open = "| gzip > %s";
+
+my $gzip_external;
+my $gzip_used;
+
+sub gzip_read_open {
+ $gzip_read_open;
+}
+
+sub gzip_write_open {
+ $gzip_write_open;
+}
+
+sub gzip_external {
+ $gzip_external;
+}
+
+sub gzip_used {
+ $gzip_used;
+}
+
+sub can_gunzip {
+ $has_Compress_Zlib || $gzip_external;
+}
+
+sub _import {
+ my $import = shift;
+ while (@_) {
+ if ($_[0] eq ':gzip_external') {
+ shift;
+ if (@_) {
+ $gzip_external = shift;
+ } else {
+ croak "$import: ':gzip_external' requires an argument";
+ }
+ }
+ elsif ($_[0] eq ':gzip_read_open') {
+ shift;
+ if (@_) {
+ $gzip_read_open = shift;
+ croak "$import: ':gzip_read_open' '$gzip_read_open' is illegal"
+ unless $gzip_read_open =~ /^.+%s.+\|\s*$/;
+ } else {
+ croak "$import: ':gzip_read_open' requires an argument";
+ }
+ }
+ elsif ($_[0] eq ':gzip_write_open') {
+ shift;
+ if (@_) {
+ $gzip_write_open = shift;
+ croak "$import: ':gzip_write_open' '$gzip_read_open' is illegal"
+ unless $gzip_write_open =~ /^\s*\|.+%s.*$/;
+ } else {
+ croak "$import: ':gzip_write_open' requires an argument";
+ }
+ }
+ else {
+ last;
+ }
+ }
+ return @_;
+}
+
+sub _alias {
+ my $import = shift;
+ if ((!$has_Compress_Zlib && !defined $gzip_external) || $gzip_external) {
+ # The undef *gzopen is really needed only during
+ # testing where we eval several 'use IO::Zlib's.
+ undef *gzopen;
+ *gzopen = \&gzopen_external;
+ *IO::Handle::gzread = \&gzread_external;
+ *IO::Handle::gzwrite = \&gzwrite_external;
+ *IO::Handle::gzreadline = \&gzreadline_external;
+ *IO::Handle::gzeof = \&gzeof_external;
+ *IO::Handle::gzclose = \&gzclose_external;
+ $gzip_used = 1;
+ } else {
+ croak "$import: no Compress::Zlib and no external gzip"
+ unless $has_Compress_Zlib;
+ *gzopen = \&Compress::Zlib::gzopen;
+ *gzread = \&Compress::Zlib::gzread;
+ *gzwrite = \&Compress::Zlib::gzwrite;
+ *gzreadline = \&Compress::Zlib::gzreadline;
+ *gzeof = \&Compress::Zlib::gzeof;
+ }
+ $aliased = 1;
+}
+
+sub import {
+ shift;
+ my $import = "IO::Zlib::import";
+ if (@_) {
+ if (_import($import, @_)) {
+ croak "$import: '@_' is illegal";
+ }
+ }
+ _alias($import);
+}
+
+@ISA = qw(Tie::Handle);
+
+sub TIEHANDLE
+{
+ my $class = shift;
+ my @args = @_;
+
+ my $self = bless {}, $class;
+
+ return @args ? $self->OPEN(@args) : $self;
+}
+
+sub DESTROY
+{
+}
+
+sub OPEN
+{
+ my $self = shift;
+ my $filename = shift;
+ my $mode = shift;
+
+ croak "IO::Zlib::open: needs a filename" unless defined($filename);
+
+ $self->{'file'} = gzopen($filename,$mode);
+
+ return defined($self->{'file'}) ? $self : undef;
+}
+
+sub CLOSE
+{
+ my $self = shift;
+
+ return undef unless defined($self->{'file'});
+
+ my $status = $self->{'file'}->gzclose();
+
+ delete $self->{'file'};
+
+ return ($status == 0) ? 1 : undef;
+}
+
+sub READ
+{
+ my $self = shift;
+ my $bufref = \$_[0];
+ my $nbytes = $_[1];
+ my $offset = $_[2] || 0;
+
+ croak "IO::Zlib::READ: NBYTES must be specified" unless defined($nbytes);
+
+ $$bufref = "" unless defined($$bufref);
+
+ my $bytesread = $self->{'file'}->gzread(substr($$bufref,$offset),$nbytes);
+
+ return undef if $bytesread < 0;
+
+ return $bytesread;
+}
+
+sub READLINE
+{
+ my $self = shift;
+
+ my $line;
+
+ return () if $self->{'file'}->gzreadline($line) <= 0;
+
+ return $line unless wantarray;
+
+ my @lines = $line;
+
+ while ($self->{'file'}->gzreadline($line) > 0)
+ {
+ push @lines, $line;
+ }
+
+ return @lines;
+}
+
+sub WRITE
+{
+ my $self = shift;
+ my $buf = shift;
+ my $length = shift;
+ my $offset = shift;
+
+ croak "IO::Zlib::WRITE: too long LENGTH" unless $offset + $length <= length($buf);
+
+ return $self->{'file'}->gzwrite(substr($buf,$offset,$length));
+}
+
+sub EOF
+{
+ my $self = shift;
+
+ return $self->{'file'}->gzeof();
+}
+
+sub FILENO
+{
+ return undef;
+}
+
+sub new
+{
+ my $class = shift;
+ my @args = @_;
+
+ _alias("new", @_) unless $aliased; # Some call new IO::Zlib directly...
+
+ my $self = gensym();
+
+ tie *{$self}, $class, @args;
+
+ return tied(${$self}) ? bless $self, $class : undef;
+}
+
+sub getline
+{
+ my $self = shift;
+
+ return scalar tied(*{$self})->READLINE();
+}
+
+sub getlines
+{
+ my $self = shift;
+
+ croak "IO::Zlib::getlines: must be called in list context"
+ unless wantarray;
+
+ return tied(*{$self})->READLINE();
+}
+
+sub opened
+{
+ my $self = shift;
+
+ return defined tied(*{$self})->{'file'};
+}
+
+sub AUTOLOAD
+{
+ my $self = shift;
+
+ $AUTOLOAD =~ s/.*:://;
+ $AUTOLOAD =~ tr/a-z/A-Z/;
+
+ return tied(*{$self})->$AUTOLOAD(@_);
+}
+
+sub gzopen_external {
+ my ($filename, $mode) = @_;
+ require IO::Handle;
+ my $fh = IO::Handle->new();
+ if ($mode =~ /r/) {
+ # Because someone will try to read ungzipped files
+ # with this we peek and verify the signature. Yes,
+ # this means that we open the file twice (if it is
+ # gzipped).
+ # Plenty of race conditions exist in this code, but
+ # the alternative would be to capture the stderr of
+ # gzip and parse it, which would be a portability nightmare.
+ if (-e $filename && open($fh, $filename)) {
+ binmode $fh;
+ my $sig;
+ my $rdb = read($fh, $sig, 2);
+ if ($rdb == 2 && $sig eq "\x1F\x8B") {
+ my $ropen = sprintf $gzip_read_open, $filename;
+ if (open($fh, $ropen)) {
+ binmode $fh;
+ return $fh;
+ } else {
+ return undef;
+ }
+ }
+ seek($fh, 0, SEEK_SET) or
+ die "IO::Zlib: open('$filename', 'r'): seek: $!";
+ return $fh;
+ } else {
+ return undef;
+ }
+ } elsif ($mode =~ /w/) {
+ my $level = '';
+ $level = "-$1" if $mode =~ /([1-9])/;
+ # To maximize portability we would need to open
+ # two filehandles here, one for "| gzip $level"
+ # and another for "> $filename", and then when
+ # writing copy bytes from the first to the second.
+ # We are using IO::Handle objects for now, however,
+ # and they can only contain one stream at a time.
+ my $wopen = sprintf $gzip_write_open, $filename;
+ if (open($fh, $wopen)) {
+ $fh->autoflush(1);
+ binmode $fh;
+ return $fh;
+ } else {
+ return undef;
+ }
+ } else {
+ croak "IO::Zlib::gzopen_external: mode '$mode' is illegal";
+ }
+ return undef;
+}
+
+sub gzread_external {
+ # Use read() instead of syswrite() because people may
+ # mix reads and readlines, and we don't want to mess
+ # the stdio buffering. See also gzreadline_external()
+ # and gzwrite_external().
+ my $nread = read($_[0], $_[1], @_ == 3 ? $_[2] : 4096);
+ defined $nread ? $nread : -1;
+}
+
+sub gzwrite_external {
+ # Using syswrite() is okay (cf. gzread_external())
+ # since the bytes leave this process and buffering
+ # is therefore not an issue.
+ my $nwrote = syswrite($_[0], $_[1]);
+ defined $nwrote ? $nwrote : -1;
+}
+
+sub gzreadline_external {
+ # See the comment in gzread_external().
+ $_[1] = readline($_[0]);
+ return defined $_[1] ? length($_[1]) : -1;
+}
+
+sub gzeof_external {
+ return eof($_[0]);
+}
+
+sub gzclose_external {
+ close($_[0]);
+ # I am not entirely certain why this is needed but it seems
+ # the above close() always fails (as if the stream would have
+ # been already closed - something to do with using external
+ # processes via pipes?)
+ return 0;
+}
+
+1;
diff --git a/Master/tlpkg/tlperl/lib/Unicode/Collate.pm b/Master/tlpkg/tlperl/lib/Unicode/Collate.pm
new file mode 100644
index 00000000000..2e989d6bb54
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Unicode/Collate.pm
@@ -0,0 +1,1877 @@
+package Unicode::Collate;
+
+BEGIN {
+ unless ("A" eq pack('U', 0x41)) {
+ die "Unicode::Collate cannot stringify a Unicode code point\n";
+ }
+}
+
+use 5.006;
+use strict;
+use warnings;
+use Carp;
+use File::Spec;
+
+no warnings 'utf8';
+
+our $VERSION = '0.52_01';
+our $PACKAGE = __PACKAGE__;
+
+my @Path = qw(Unicode Collate);
+my $KeyFile = "allkeys.txt";
+
+# Perl's boolean
+use constant TRUE => 1;
+use constant FALSE => "";
+use constant NOMATCHPOS => -1;
+
+# A coderef to get combining class imported from Unicode::Normalize
+# (i.e. \&Unicode::Normalize::getCombinClass).
+# This is also used as a HAS_UNICODE_NORMALIZE flag.
+my $CVgetCombinClass;
+
+# Supported Levels
+use constant MinLevel => 1;
+use constant MaxLevel => 4;
+
+# Minimum weights at level 2 and 3, respectively
+use constant Min2Wt => 0x20;
+use constant Min3Wt => 0x02;
+
+# Shifted weight at 4th level
+use constant Shift4Wt => 0xFFFF;
+
+# A boolean for Variable and 16-bit weights at 4 levels of Collation Element
+# PROBLEM: The Default Unicode Collation Element Table
+# has weights over 0xFFFF at the 4th level.
+# The tie-breaking in the variable weights
+# other than "shift" (as well as "shift-trimmed") is unreliable.
+use constant VCE_TEMPLATE => 'Cn4';
+
+# A sort key: 16-bit weights
+# See also the PROBLEM on VCE_TEMPLATE above.
+use constant KEY_TEMPLATE => 'n*';
+
+# Level separator in a sort key:
+# i.e. pack(KEY_TEMPLATE, 0)
+use constant LEVEL_SEP => "\0\0";
+
+# As Unicode code point separator for hash keys.
+# A joined code point string (denoted by JCPS below)
+# like "65;768" is used for internal processing
+# instead of Perl's Unicode string like "\x41\x{300}",
+# as the native code point is different from the Unicode code point
+# on EBCDIC platform.
+# This character must not be included in any stringified
+# representation of an integer.
+use constant CODE_SEP => ';';
+
+# boolean values of variable weights
+use constant NON_VAR => 0; # Non-Variable character
+use constant VAR => 1; # Variable character
+
+# specific code points
+use constant Hangul_LBase => 0x1100;
+use constant Hangul_LIni => 0x1100;
+use constant Hangul_LFin => 0x1159;
+use constant Hangul_LFill => 0x115F;
+use constant Hangul_VBase => 0x1161;
+use constant Hangul_VIni => 0x1160; # from Vowel Filler
+use constant Hangul_VFin => 0x11A2;
+use constant Hangul_TBase => 0x11A7; # from "no-final" codepoint
+use constant Hangul_TIni => 0x11A8;
+use constant Hangul_TFin => 0x11F9;
+use constant Hangul_TCount => 28;
+use constant Hangul_NCount => 588;
+use constant Hangul_SBase => 0xAC00;
+use constant Hangul_SIni => 0xAC00;
+use constant Hangul_SFin => 0xD7A3;
+use constant CJK_UidIni => 0x4E00;
+use constant CJK_UidFin => 0x9FA5;
+use constant CJK_UidF41 => 0x9FBB;
+use constant CJK_ExtAIni => 0x3400;
+use constant CJK_ExtAFin => 0x4DB5;
+use constant CJK_ExtBIni => 0x20000;
+use constant CJK_ExtBFin => 0x2A6D6;
+use constant BMP_Max => 0xFFFF;
+
+# Logical_Order_Exception in PropList.txt
+my $DefaultRearrange = [ 0x0E40..0x0E44, 0x0EC0..0x0EC4 ];
+
+sub UCA_Version { "14" }
+
+sub Base_Unicode_Version { "4.1.0" }
+
+######
+
+sub pack_U {
+ return pack('U*', @_);
+}
+
+sub unpack_U {
+ return unpack('U*', shift(@_).pack('U*'));
+}
+
+######
+
+my (%VariableOK);
+@VariableOK{ qw/
+ blanked non-ignorable shifted shift-trimmed
+ / } = (); # keys lowercased
+
+our @ChangeOK = qw/
+ alternate backwards level normalization rearrange
+ katakana_before_hiragana upper_before_lower
+ overrideHangul overrideCJK preprocess UCA_Version
+ hangul_terminator variable
+ /;
+
+our @ChangeNG = qw/
+ entry mapping table maxlength
+ ignoreChar ignoreName undefChar undefName variableTable
+ versionTable alternateTable backwardsTable forwardsTable rearrangeTable
+ derivCode normCode rearrangeHash
+ backwardsFlag
+ /;
+# The hash key 'ignored' is deleted at v 0.21.
+# The hash key 'isShift' is deleted at v 0.23.
+# The hash key 'combining' is deleted at v 0.24.
+# The hash key 'entries' is deleted at v 0.30.
+# The hash key 'L3_ignorable' is deleted at v 0.40.
+
+sub version {
+ my $self = shift;
+ return $self->{versionTable} || 'unknown';
+}
+
+my (%ChangeOK, %ChangeNG);
+@ChangeOK{ @ChangeOK } = ();
+@ChangeNG{ @ChangeNG } = ();
+
+sub change {
+ my $self = shift;
+ my %hash = @_;
+ my %old;
+ if (exists $hash{variable} && exists $hash{alternate}) {
+ delete $hash{alternate};
+ }
+ elsif (!exists $hash{variable} && exists $hash{alternate}) {
+ $hash{variable} = $hash{alternate};
+ }
+ foreach my $k (keys %hash) {
+ if (exists $ChangeOK{$k}) {
+ $old{$k} = $self->{$k};
+ $self->{$k} = $hash{$k};
+ }
+ elsif (exists $ChangeNG{$k}) {
+ croak "change of $k via change() is not allowed!";
+ }
+ # else => ignored
+ }
+ $self->checkCollator();
+ return wantarray ? %old : $self;
+}
+
+sub _checkLevel {
+ my $level = shift;
+ my $key = shift; # 'level' or 'backwards'
+ MinLevel <= $level or croak sprintf
+ "Illegal level %d (in value for key '%s') lower than %d.",
+ $level, $key, MinLevel;
+ $level <= MaxLevel or croak sprintf
+ "Unsupported level %d (in value for key '%s') higher than %d.",
+ $level, $key, MaxLevel;
+}
+
+my %DerivCode = (
+ 8 => \&_derivCE_8,
+ 9 => \&_derivCE_9,
+ 11 => \&_derivCE_9, # 11 == 9
+ 14 => \&_derivCE_14,
+);
+
+sub checkCollator {
+ my $self = shift;
+ _checkLevel($self->{level}, "level");
+
+ $self->{derivCode} = $DerivCode{ $self->{UCA_Version} }
+ or croak "Illegal UCA version (passed $self->{UCA_Version}).";
+
+ $self->{variable} ||= $self->{alternate} || $self->{variableTable} ||
+ $self->{alternateTable} || 'shifted';
+ $self->{variable} = $self->{alternate} = lc($self->{variable});
+ exists $VariableOK{ $self->{variable} }
+ or croak "$PACKAGE unknown variable parameter name: $self->{variable}";
+
+ if (! defined $self->{backwards}) {
+ $self->{backwardsFlag} = 0;
+ }
+ elsif (! ref $self->{backwards}) {
+ _checkLevel($self->{backwards}, "backwards");
+ $self->{backwardsFlag} = 1 << $self->{backwards};
+ }
+ else {
+ my %level;
+ $self->{backwardsFlag} = 0;
+ for my $b (@{ $self->{backwards} }) {
+ _checkLevel($b, "backwards");
+ $level{$b} = 1;
+ }
+ for my $v (sort keys %level) {
+ $self->{backwardsFlag} += 1 << $v;
+ }
+ }
+
+ defined $self->{rearrange} or $self->{rearrange} = [];
+ ref $self->{rearrange}
+ or croak "$PACKAGE: list for rearrangement must be store in ARRAYREF";
+
+ # keys of $self->{rearrangeHash} are $self->{rearrange}.
+ $self->{rearrangeHash} = undef;
+
+ if (@{ $self->{rearrange} }) {
+ @{ $self->{rearrangeHash} }{ @{ $self->{rearrange} } } = ();
+ }
+
+ $self->{normCode} = undef;
+
+ if (defined $self->{normalization}) {
+ eval { require Unicode::Normalize };
+ $@ and croak "Unicode::Normalize is required to normalize strings";
+
+ $CVgetCombinClass ||= \&Unicode::Normalize::getCombinClass;
+
+ if ($self->{normalization} =~ /^(?:NF)D\z/) { # tweak for default
+ $self->{normCode} = \&Unicode::Normalize::NFD;
+ }
+ elsif ($self->{normalization} ne 'prenormalized') {
+ my $norm = $self->{normalization};
+ $self->{normCode} = sub {
+ Unicode::Normalize::normalize($norm, shift);
+ };
+ eval { $self->{normCode}->("") }; # try
+ $@ and croak "$PACKAGE unknown normalization form name: $norm";
+ }
+ }
+ return;
+}
+
+sub new
+{
+ my $class = shift;
+ my $self = bless { @_ }, $class;
+
+ # If undef is passed explicitly, no file is read.
+ $self->{table} = $KeyFile if ! exists $self->{table};
+ $self->read_table() if defined $self->{table};
+
+ if ($self->{entry}) {
+ while ($self->{entry} =~ /([^\n]+)/g) {
+ $self->parseEntry($1);
+ }
+ }
+
+ $self->{level} ||= MaxLevel;
+ $self->{UCA_Version} ||= UCA_Version();
+
+ $self->{overrideHangul} = FALSE
+ if ! exists $self->{overrideHangul};
+ $self->{overrideCJK} = FALSE
+ if ! exists $self->{overrideCJK};
+ $self->{normalization} = 'NFD'
+ if ! exists $self->{normalization};
+ $self->{rearrange} = $self->{rearrangeTable} ||
+ ($self->{UCA_Version} <= 11 ? $DefaultRearrange : [])
+ if ! exists $self->{rearrange};
+ $self->{backwards} = $self->{backwardsTable}
+ if ! exists $self->{backwards};
+
+ $self->checkCollator();
+
+ return $self;
+}
+
+sub read_table {
+ my $self = shift;
+
+ my($f, $fh);
+ foreach my $d (@INC) {
+ $f = File::Spec->catfile($d, @Path, $self->{table});
+ last if open($fh, $f);
+ $f = undef;
+ }
+ if (!defined $f) {
+ $f = File::Spec->catfile(@Path, $self->{table});
+ croak("$PACKAGE: Can't locate $f in \@INC (\@INC contains: @INC)");
+ }
+
+ while (my $line = <$fh>) {
+ next if $line =~ /^\s*#/;
+ unless ($line =~ s/^\s*\@//) {
+ $self->parseEntry($line);
+ next;
+ }
+
+ # matched ^\s*\@
+ if ($line =~ /^version\s*(\S*)/) {
+ $self->{versionTable} ||= $1;
+ }
+ elsif ($line =~ /^variable\s+(\S*)/) { # since UTS #10-9
+ $self->{variableTable} ||= $1;
+ }
+ elsif ($line =~ /^alternate\s+(\S*)/) { # till UTS #10-8
+ $self->{alternateTable} ||= $1;
+ }
+ elsif ($line =~ /^backwards\s+(\S*)/) {
+ push @{ $self->{backwardsTable} }, $1;
+ }
+ elsif ($line =~ /^forwards\s+(\S*)/) { # parhaps no use
+ push @{ $self->{forwardsTable} }, $1;
+ }
+ elsif ($line =~ /^rearrange\s+(.*)/) { # (\S*) is NG
+ push @{ $self->{rearrangeTable} }, _getHexArray($1);
+ }
+ }
+ close $fh;
+}
+
+
+##
+## get $line, parse it, and write an entry in $self
+##
+sub parseEntry
+{
+ my $self = shift;
+ my $line = shift;
+ my($name, $entry, @uv, @key);
+
+ return if $line !~ /^\s*[0-9A-Fa-f]/;
+
+ # removes comment and gets name
+ $name = $1
+ if $line =~ s/[#%]\s*(.*)//;
+ return if defined $self->{undefName} && $name =~ /$self->{undefName}/;
+
+ # gets element
+ my($e, $k) = split /;/, $line;
+ croak "Wrong Entry: <charList> must be separated by ';' from <collElement>"
+ if ! $k;
+
+ @uv = _getHexArray($e);
+ return if !@uv;
+
+ $entry = join(CODE_SEP, @uv); # in JCPS
+
+ if (defined $self->{undefChar} || defined $self->{ignoreChar}) {
+ my $ele = pack_U(@uv);
+
+ # regarded as if it were not entried in the table
+ return
+ if defined $self->{undefChar} && $ele =~ /$self->{undefChar}/;
+
+ # replaced as completely ignorable
+ $k = '[.0000.0000.0000.0000]'
+ if defined $self->{ignoreChar} && $ele =~ /$self->{ignoreChar}/;
+ }
+
+ # replaced as completely ignorable
+ $k = '[.0000.0000.0000.0000]'
+ if defined $self->{ignoreName} && $name =~ /$self->{ignoreName}/;
+
+ my $is_L3_ignorable = TRUE;
+
+ foreach my $arr ($k =~ /\[([^\[\]]+)\]/g) { # SPACEs allowed
+ my $var = $arr =~ /\*/; # exactly /^\*/ but be lenient.
+ my @wt = _getHexArray($arr);
+ push @key, pack(VCE_TEMPLATE, $var, @wt);
+ $is_L3_ignorable = FALSE
+ if $wt[0] || $wt[1] || $wt[2];
+ # Conformance Test for 3.1.1 and 4.0.0 shows Level 3 ignorable
+ # is completely ignorable.
+ # For expansion, an entry $is_L3_ignorable
+ # if and only if "all" CEs are [.0000.0000.0000].
+ }
+
+ $self->{mapping}{$entry} = $is_L3_ignorable ? [] : \@key;
+
+ if (@uv > 1) {
+ (!$self->{maxlength}{$uv[0]} || $self->{maxlength}{$uv[0]} < @uv)
+ and $self->{maxlength}{$uv[0]} = @uv;
+ }
+}
+
+
+##
+## VCE = _varCE(variable term, VCE)
+##
+sub _varCE
+{
+ my $vbl = shift;
+ my $vce = shift;
+ if ($vbl eq 'non-ignorable') {
+ return $vce;
+ }
+ my ($var, @wt) = unpack VCE_TEMPLATE, $vce;
+
+ if ($var) {
+ return pack(VCE_TEMPLATE, $var, 0, 0, 0,
+ $vbl eq 'blanked' ? $wt[3] : $wt[0]);
+ }
+ elsif ($vbl eq 'blanked') {
+ return $vce;
+ }
+ else {
+ return pack(VCE_TEMPLATE, $var, @wt[0..2],
+ $vbl eq 'shifted' && $wt[0]+$wt[1]+$wt[2] ? Shift4Wt : 0);
+ }
+}
+
+sub viewSortKey
+{
+ my $self = shift;
+ $self->visualizeSortKey($self->getSortKey(@_));
+}
+
+sub visualizeSortKey
+{
+ my $self = shift;
+ my $view = join " ", map sprintf("%04X", $_), unpack(KEY_TEMPLATE, shift);
+
+ if ($self->{UCA_Version} <= 8) {
+ $view =~ s/ ?0000 ?/|/g;
+ } else {
+ $view =~ s/\b0000\b/|/g;
+ }
+ return "[$view]";
+}
+
+
+##
+## arrayref of JCPS = splitEnt(string to be collated)
+## arrayref of arrayref[JCPS, ini_pos, fin_pos] = splitEnt(string, true)
+##
+sub splitEnt
+{
+ my $self = shift;
+ my $wLen = $_[1];
+
+ my $code = $self->{preprocess};
+ my $norm = $self->{normCode};
+ my $map = $self->{mapping};
+ my $max = $self->{maxlength};
+ my $reH = $self->{rearrangeHash};
+ my $ver9 = $self->{UCA_Version} >= 9 && $self->{UCA_Version} <= 11;
+
+ my ($str, @buf);
+
+ if ($wLen) {
+ $code and croak "Preprocess breaks character positions. "
+ . "Don't use with index(), match(), etc.";
+ $norm and croak "Normalization breaks character positions. "
+ . "Don't use with index(), match(), etc.";
+ $str = $_[0];
+ }
+ else {
+ $str = $_[0];
+ $str = &$code($str) if ref $code;
+ $str = &$norm($str) if ref $norm;
+ }
+
+ # get array of Unicode code point of string.
+ my @src = unpack_U($str);
+
+ # rearrangement:
+ # Character positions are not kept if rearranged,
+ # then neglected if $wLen is true.
+ if ($reH && ! $wLen) {
+ for (my $i = 0; $i < @src; $i++) {
+ if (exists $reH->{ $src[$i] } && $i + 1 < @src) {
+ ($src[$i], $src[$i+1]) = ($src[$i+1], $src[$i]);
+ $i++;
+ }
+ }
+ }
+
+ # remove a code point marked as a completely ignorable.
+ for (my $i = 0; $i < @src; $i++) {
+ $src[$i] = undef
+ if _isIllegal($src[$i]) || ($ver9 &&
+ $map->{ $src[$i] } && @{ $map->{ $src[$i] } } == 0);
+ }
+
+ for (my $i = 0; $i < @src; $i++) {
+ my $jcps = $src[$i];
+
+ # skip removed code point
+ if (! defined $jcps) {
+ if ($wLen && @buf) {
+ $buf[-1][2] = $i + 1;
+ }
+ next;
+ }
+
+ my $i_orig = $i;
+
+ # find contraction
+ if ($max->{$jcps}) {
+ my $temp_jcps = $jcps;
+ my $jcpsLen = 1;
+ my $maxLen = $max->{$jcps};
+
+ for (my $p = $i + 1; $jcpsLen < $maxLen && $p < @src; $p++) {
+ next if ! defined $src[$p];
+ $temp_jcps .= CODE_SEP . $src[$p];
+ $jcpsLen++;
+ if ($map->{$temp_jcps}) {
+ $jcps = $temp_jcps;
+ $i = $p;
+ }
+ }
+
+ # not-contiguous contraction with Combining Char (cf. UTS#10, S2.1).
+ # This process requires Unicode::Normalize.
+ # If "normalization" is undef, here should be skipped *always*
+ # (in spite of bool value of $CVgetCombinClass),
+ # since canonical ordering cannot be expected.
+ # Blocked combining character should not be contracted.
+
+ if ($self->{normalization})
+ # $self->{normCode} is false in the case of "prenormalized".
+ {
+ my $preCC = 0;
+ my $curCC = 0;
+
+ for (my $p = $i + 1; $p < @src; $p++) {
+ next if ! defined $src[$p];
+ $curCC = $CVgetCombinClass->($src[$p]);
+ last unless $curCC;
+ my $tail = CODE_SEP . $src[$p];
+ if ($preCC != $curCC && $map->{$jcps.$tail}) {
+ $jcps .= $tail;
+ $src[$p] = undef;
+ } else {
+ $preCC = $curCC;
+ }
+ }
+ }
+ }
+
+ # skip completely ignorable
+ if ($map->{$jcps} && @{ $map->{$jcps} } == 0) {
+ if ($wLen && @buf) {
+ $buf[-1][2] = $i + 1;
+ }
+ next;
+ }
+
+ push @buf, $wLen ? [$jcps, $i_orig, $i + 1] : $jcps;
+ }
+ return \@buf;
+}
+
+
+##
+## list of VCE = getWt(JCPS)
+##
+sub getWt
+{
+ my $self = shift;
+ my $u = shift;
+ my $vbl = $self->{variable};
+ my $map = $self->{mapping};
+ my $der = $self->{derivCode};
+
+ return if !defined $u;
+ return map(_varCE($vbl, $_), @{ $map->{$u} })
+ if $map->{$u};
+
+ # JCPS must not be a contraction, then it's a code point.
+ if (Hangul_SIni <= $u && $u <= Hangul_SFin) {
+ my $hang = $self->{overrideHangul};
+ my @hangulCE;
+ if ($hang) {
+ @hangulCE = map(pack(VCE_TEMPLATE, NON_VAR, @$_), &$hang($u));
+ }
+ elsif (!defined $hang) {
+ @hangulCE = $der->($u);
+ }
+ else {
+ my $max = $self->{maxlength};
+ my @decH = _decompHangul($u);
+
+ if (@decH == 2) {
+ my $contract = join(CODE_SEP, @decH);
+ @decH = ($contract) if $map->{$contract};
+ } else { # must be <@decH == 3>
+ if ($max->{$decH[0]}) {
+ my $contract = join(CODE_SEP, @decH);
+ if ($map->{$contract}) {
+ @decH = ($contract);
+ } else {
+ $contract = join(CODE_SEP, @decH[0,1]);
+ $map->{$contract} and @decH = ($contract, $decH[2]);
+ }
+ # even if V's ignorable, LT contraction is not supported.
+ # If such a situatution were required, NFD should be used.
+ }
+ if (@decH == 3 && $max->{$decH[1]}) {
+ my $contract = join(CODE_SEP, @decH[1,2]);
+ $map->{$contract} and @decH = ($decH[0], $contract);
+ }
+ }
+
+ @hangulCE = map({
+ $map->{$_} ? @{ $map->{$_} } : $der->($_);
+ } @decH);
+ }
+ return map _varCE($vbl, $_), @hangulCE;
+ }
+ elsif (_isUIdeo($u, $self->{UCA_Version})) {
+ my $cjk = $self->{overrideCJK};
+ return map _varCE($vbl, $_),
+ $cjk
+ ? map(pack(VCE_TEMPLATE, NON_VAR, @$_), &$cjk($u))
+ : defined $cjk && $self->{UCA_Version} <= 8 && $u < 0x10000
+ ? _uideoCE_8($u)
+ : $der->($u);
+ }
+ else {
+ return map _varCE($vbl, $_), $der->($u);
+ }
+}
+
+
+##
+## string sortkey = getSortKey(string arg)
+##
+sub getSortKey
+{
+ my $self = shift;
+ my $lev = $self->{level};
+ my $rEnt = $self->splitEnt(shift); # get an arrayref of JCPS
+ my $v2i = $self->{UCA_Version} >= 9 &&
+ $self->{variable} ne 'non-ignorable';
+
+ my @buf; # weight arrays
+ if ($self->{hangul_terminator}) {
+ my $preHST = '';
+ foreach my $jcps (@$rEnt) {
+ # weird things like VL, TL-contraction are not considered!
+ my $curHST = '';
+ foreach my $u (split /;/, $jcps) {
+ $curHST .= getHST($u);
+ }
+ if ($preHST && !$curHST || # hangul before non-hangul
+ $preHST =~ /L\z/ && $curHST =~ /^T/ ||
+ $preHST =~ /V\z/ && $curHST =~ /^L/ ||
+ $preHST =~ /T\z/ && $curHST =~ /^[LV]/) {
+
+ push @buf, $self->getWtHangulTerm();
+ }
+ $preHST = $curHST;
+
+ push @buf, $self->getWt($jcps);
+ }
+ $preHST # end at hangul
+ and push @buf, $self->getWtHangulTerm();
+ }
+ else {
+ foreach my $jcps (@$rEnt) {
+ push @buf, $self->getWt($jcps);
+ }
+ }
+
+ # make sort key
+ my @ret = ([],[],[],[]);
+ my $last_is_variable;
+
+ foreach my $vwt (@buf) {
+ my($var, @wt) = unpack(VCE_TEMPLATE, $vwt);
+
+ # "Ignorable (L1, L2) after Variable" since track. v. 9
+ if ($v2i) {
+ if ($var) {
+ $last_is_variable = TRUE;
+ }
+ elsif (!$wt[0]) { # ignorable
+ next if $last_is_variable;
+ }
+ else {
+ $last_is_variable = FALSE;
+ }
+ }
+ foreach my $v (0..$lev-1) {
+ 0 < $wt[$v] and push @{ $ret[$v] }, $wt[$v];
+ }
+ }
+
+ # modification of tertiary weights
+ if ($self->{upper_before_lower}) {
+ foreach my $w (@{ $ret[2] }) {
+ if (0x8 <= $w && $w <= 0xC) { $w -= 6 } # lower
+ elsif (0x2 <= $w && $w <= 0x6) { $w += 6 } # upper
+ elsif ($w == 0x1C) { $w += 1 } # square upper
+ elsif ($w == 0x1D) { $w -= 1 } # square lower
+ }
+ }
+ if ($self->{katakana_before_hiragana}) {
+ foreach my $w (@{ $ret[2] }) {
+ if (0x0F <= $w && $w <= 0x13) { $w -= 2 } # katakana
+ elsif (0x0D <= $w && $w <= 0x0E) { $w += 5 } # hiragana
+ }
+ }
+
+ if ($self->{backwardsFlag}) {
+ for (my $v = MinLevel; $v <= MaxLevel; $v++) {
+ if ($self->{backwardsFlag} & (1 << $v)) {
+ @{ $ret[$v-1] } = reverse @{ $ret[$v-1] };
+ }
+ }
+ }
+
+ join LEVEL_SEP, map pack(KEY_TEMPLATE, @$_), @ret;
+}
+
+
+##
+## int compare = cmp(string a, string b)
+##
+sub cmp { $_[0]->getSortKey($_[1]) cmp $_[0]->getSortKey($_[2]) }
+sub eq { $_[0]->getSortKey($_[1]) eq $_[0]->getSortKey($_[2]) }
+sub ne { $_[0]->getSortKey($_[1]) ne $_[0]->getSortKey($_[2]) }
+sub lt { $_[0]->getSortKey($_[1]) lt $_[0]->getSortKey($_[2]) }
+sub le { $_[0]->getSortKey($_[1]) le $_[0]->getSortKey($_[2]) }
+sub gt { $_[0]->getSortKey($_[1]) gt $_[0]->getSortKey($_[2]) }
+sub ge { $_[0]->getSortKey($_[1]) ge $_[0]->getSortKey($_[2]) }
+
+##
+## list[strings] sorted = sort(list[strings] arg)
+##
+sub sort {
+ my $obj = shift;
+ return
+ map { $_->[1] }
+ sort{ $a->[0] cmp $b->[0] }
+ map [ $obj->getSortKey($_), $_ ], @_;
+}
+
+
+sub _derivCE_14 {
+ my $u = shift;
+ my $base =
+ (CJK_UidIni <= $u && $u <= CJK_UidF41)
+ ? 0xFB40 : # CJK
+ (CJK_ExtAIni <= $u && $u <= CJK_ExtAFin ||
+ CJK_ExtBIni <= $u && $u <= CJK_ExtBFin)
+ ? 0xFB80 # CJK ext.
+ : 0xFBC0; # others
+
+ my $aaaa = $base + ($u >> 15);
+ my $bbbb = ($u & 0x7FFF) | 0x8000;
+ return
+ pack(VCE_TEMPLATE, NON_VAR, $aaaa, Min2Wt, Min3Wt, $u),
+ pack(VCE_TEMPLATE, NON_VAR, $bbbb, 0, 0, $u);
+}
+
+sub _derivCE_9 {
+ my $u = shift;
+ my $base =
+ (CJK_UidIni <= $u && $u <= CJK_UidFin)
+ ? 0xFB40 : # CJK
+ (CJK_ExtAIni <= $u && $u <= CJK_ExtAFin ||
+ CJK_ExtBIni <= $u && $u <= CJK_ExtBFin)
+ ? 0xFB80 # CJK ext.
+ : 0xFBC0; # others
+
+ my $aaaa = $base + ($u >> 15);
+ my $bbbb = ($u & 0x7FFF) | 0x8000;
+ return
+ pack(VCE_TEMPLATE, NON_VAR, $aaaa, Min2Wt, Min3Wt, $u),
+ pack(VCE_TEMPLATE, NON_VAR, $bbbb, 0, 0, $u);
+}
+
+sub _derivCE_8 {
+ my $code = shift;
+ my $aaaa = 0xFF80 + ($code >> 15);
+ my $bbbb = ($code & 0x7FFF) | 0x8000;
+ return
+ pack(VCE_TEMPLATE, NON_VAR, $aaaa, 2, 1, $code),
+ pack(VCE_TEMPLATE, NON_VAR, $bbbb, 0, 0, $code);
+}
+
+sub _uideoCE_8 {
+ my $u = shift;
+ return pack(VCE_TEMPLATE, NON_VAR, $u, Min2Wt, Min3Wt, $u);
+}
+
+sub _isUIdeo {
+ my ($u, $uca_vers) = @_;
+ return(
+ (CJK_UidIni <= $u &&
+ ($uca_vers >= 14 ? ( $u <= CJK_UidF41) : ($u <= CJK_UidFin)))
+ ||
+ (CJK_ExtAIni <= $u && $u <= CJK_ExtAFin)
+ ||
+ (CJK_ExtBIni <= $u && $u <= CJK_ExtBFin)
+ );
+}
+
+
+sub getWtHangulTerm {
+ my $self = shift;
+ return _varCE($self->{variable},
+ pack(VCE_TEMPLATE, NON_VAR, $self->{hangul_terminator}, 0,0,0));
+}
+
+
+##
+## "hhhh hhhh hhhh" to (dddd, dddd, dddd)
+##
+sub _getHexArray { map hex, $_[0] =~ /([0-9a-fA-F]+)/g }
+
+#
+# $code *must* be in Hangul syllable.
+# Check it before you enter here.
+#
+sub _decompHangul {
+ my $code = shift;
+ my $si = $code - Hangul_SBase;
+ my $li = int( $si / Hangul_NCount);
+ my $vi = int(($si % Hangul_NCount) / Hangul_TCount);
+ my $ti = $si % Hangul_TCount;
+ return (
+ Hangul_LBase + $li,
+ Hangul_VBase + $vi,
+ $ti ? (Hangul_TBase + $ti) : (),
+ );
+}
+
+sub _isIllegal {
+ my $code = shift;
+ return ! defined $code # removed
+ || ($code < 0 || 0x10FFFF < $code) # out of range
+ || (($code & 0xFFFE) == 0xFFFE) # ??FFF[EF] (cf. utf8.c)
+ || (0xD800 <= $code && $code <= 0xDFFF) # unpaired surrogates
+ || (0xFDD0 <= $code && $code <= 0xFDEF) # other non-characters
+ ;
+}
+
+# Hangul Syllable Type
+sub getHST {
+ my $u = shift;
+ return
+ Hangul_LIni <= $u && $u <= Hangul_LFin || $u == Hangul_LFill ? "L" :
+ Hangul_VIni <= $u && $u <= Hangul_VFin ? "V" :
+ Hangul_TIni <= $u && $u <= Hangul_TFin ? "T" :
+ Hangul_SIni <= $u && $u <= Hangul_SFin ?
+ ($u - Hangul_SBase) % Hangul_TCount ? "LVT" : "LV" : "";
+}
+
+
+##
+## bool _nonIgnorAtLevel(arrayref weights, int level)
+##
+sub _nonIgnorAtLevel($$)
+{
+ my $wt = shift;
+ return if ! defined $wt;
+ my $lv = shift;
+ return grep($wt->[$_-1] != 0, MinLevel..$lv) ? TRUE : FALSE;
+}
+
+##
+## bool _eqArray(
+## arrayref of arrayref[weights] source,
+## arrayref of arrayref[weights] substr,
+## int level)
+## * comparison of graphemes vs graphemes.
+## @$source >= @$substr must be true (check it before call this);
+##
+sub _eqArray($$$)
+{
+ my $source = shift;
+ my $substr = shift;
+ my $lev = shift;
+
+ for my $g (0..@$substr-1){
+ # Do the $g'th graphemes have the same number of AV weigths?
+ return if @{ $source->[$g] } != @{ $substr->[$g] };
+
+ for my $w (0..@{ $substr->[$g] }-1) {
+ for my $v (0..$lev-1) {
+ return if $source->[$g][$w][$v] != $substr->[$g][$w][$v];
+ }
+ }
+ }
+ return 1;
+}
+
+##
+## (int position, int length)
+## int position = index(string, substring, position, [undoc'ed grobal])
+##
+## With "grobal" (only for the list context),
+## returns list of arrayref[position, length].
+##
+sub index
+{
+ my $self = shift;
+ my $str = shift;
+ my $len = length($str);
+ my $subE = $self->splitEnt(shift);
+ my $pos = @_ ? shift : 0;
+ $pos = 0 if $pos < 0;
+ my $grob = shift;
+
+ my $lev = $self->{level};
+ my $v2i = $self->{UCA_Version} >= 9 &&
+ $self->{variable} ne 'non-ignorable';
+
+ if (! @$subE) {
+ my $temp = $pos <= 0 ? 0 : $len <= $pos ? $len : $pos;
+ return $grob
+ ? map([$_, 0], $temp..$len)
+ : wantarray ? ($temp,0) : $temp;
+ }
+ $len < $pos
+ and return wantarray ? () : NOMATCHPOS;
+ my $strE = $self->splitEnt($pos ? substr($str, $pos) : $str, TRUE);
+ @$strE
+ or return wantarray ? () : NOMATCHPOS;
+
+ my(@strWt, @iniPos, @finPos, @subWt, @g_ret);
+
+ my $last_is_variable;
+ for my $vwt (map $self->getWt($_), @$subE) {
+ my($var, @wt) = unpack(VCE_TEMPLATE, $vwt);
+ my $to_be_pushed = _nonIgnorAtLevel(\@wt,$lev);
+
+ # "Ignorable (L1, L2) after Variable" since track. v. 9
+ if ($v2i) {
+ if ($var) {
+ $last_is_variable = TRUE;
+ }
+ elsif (!$wt[0]) { # ignorable
+ $to_be_pushed = FALSE if $last_is_variable;
+ }
+ else {
+ $last_is_variable = FALSE;
+ }
+ }
+
+ if (@subWt && !$var && !$wt[0]) {
+ push @{ $subWt[-1] }, \@wt if $to_be_pushed;
+ } else {
+ push @subWt, [ \@wt ];
+ }
+ }
+
+ my $count = 0;
+ my $end = @$strE - 1;
+
+ $last_is_variable = FALSE; # reuse
+ for (my $i = 0; $i <= $end; ) { # no $i++
+ my $found_base = 0;
+
+ # fetch a grapheme
+ while ($i <= $end && $found_base == 0) {
+ for my $vwt ($self->getWt($strE->[$i][0])) {
+ my($var, @wt) = unpack(VCE_TEMPLATE, $vwt);
+ my $to_be_pushed = _nonIgnorAtLevel(\@wt,$lev);
+
+ # "Ignorable (L1, L2) after Variable" since track. v. 9
+ if ($v2i) {
+ if ($var) {
+ $last_is_variable = TRUE;
+ }
+ elsif (!$wt[0]) { # ignorable
+ $to_be_pushed = FALSE if $last_is_variable;
+ }
+ else {
+ $last_is_variable = FALSE;
+ }
+ }
+
+ if (@strWt && !$var && !$wt[0]) {
+ push @{ $strWt[-1] }, \@wt if $to_be_pushed;
+ $finPos[-1] = $strE->[$i][2];
+ } elsif ($to_be_pushed) {
+ push @strWt, [ \@wt ];
+ push @iniPos, $found_base ? NOMATCHPOS : $strE->[$i][1];
+ $finPos[-1] = NOMATCHPOS if $found_base;
+ push @finPos, $strE->[$i][2];
+ $found_base++;
+ }
+ # else ===> no-op
+ }
+ $i++;
+ }
+
+ # try to match
+ while ( @strWt > @subWt || (@strWt == @subWt && $i > $end) ) {
+ if ($iniPos[0] != NOMATCHPOS &&
+ $finPos[$#subWt] != NOMATCHPOS &&
+ _eqArray(\@strWt, \@subWt, $lev)) {
+ my $temp = $iniPos[0] + $pos;
+
+ if ($grob) {
+ push @g_ret, [$temp, $finPos[$#subWt] - $iniPos[0]];
+ splice @strWt, 0, $#subWt;
+ splice @iniPos, 0, $#subWt;
+ splice @finPos, 0, $#subWt;
+ }
+ else {
+ return wantarray
+ ? ($temp, $finPos[$#subWt] - $iniPos[0])
+ : $temp;
+ }
+ }
+ shift @strWt;
+ shift @iniPos;
+ shift @finPos;
+ }
+ }
+
+ return $grob
+ ? @g_ret
+ : wantarray ? () : NOMATCHPOS;
+}
+
+##
+## scalarref to matching part = match(string, substring)
+##
+sub match
+{
+ my $self = shift;
+ if (my($pos,$len) = $self->index($_[0], $_[1])) {
+ my $temp = substr($_[0], $pos, $len);
+ return wantarray ? $temp : \$temp;
+ # An lvalue ref \substr should be avoided,
+ # since its value is affected by modification of its referent.
+ }
+ else {
+ return;
+ }
+}
+
+##
+## arrayref matching parts = gmatch(string, substring)
+##
+sub gmatch
+{
+ my $self = shift;
+ my $str = shift;
+ my $sub = shift;
+ return map substr($str, $_->[0], $_->[1]),
+ $self->index($str, $sub, 0, 'g');
+}
+
+##
+## bool subst'ed = subst(string, substring, replace)
+##
+sub subst
+{
+ my $self = shift;
+ my $code = ref $_[2] eq 'CODE' ? $_[2] : FALSE;
+
+ if (my($pos,$len) = $self->index($_[0], $_[1])) {
+ if ($code) {
+ my $mat = substr($_[0], $pos, $len);
+ substr($_[0], $pos, $len, $code->($mat));
+ } else {
+ substr($_[0], $pos, $len, $_[2]);
+ }
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+##
+## int count = gsubst(string, substring, replace)
+##
+sub gsubst
+{
+ my $self = shift;
+ my $code = ref $_[2] eq 'CODE' ? $_[2] : FALSE;
+ my $cnt = 0;
+
+ # Replacement is carried out from the end, then use reverse.
+ for my $pos_len (reverse $self->index($_[0], $_[1], 0, 'g')) {
+ if ($code) {
+ my $mat = substr($_[0], $pos_len->[0], $pos_len->[1]);
+ substr($_[0], $pos_len->[0], $pos_len->[1], $code->($mat));
+ } else {
+ substr($_[0], $pos_len->[0], $pos_len->[1], $_[2]);
+ }
+ $cnt++;
+ }
+ return $cnt;
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Unicode::Collate - Unicode Collation Algorithm
+
+=head1 SYNOPSIS
+
+ use Unicode::Collate;
+
+ #construct
+ $Collator = Unicode::Collate->new(%tailoring);
+
+ #sort
+ @sorted = $Collator->sort(@not_sorted);
+
+ #compare
+ $result = $Collator->cmp($a, $b); # returns 1, 0, or -1.
+
+ # If %tailoring is false (i.e. empty),
+ # $Collator should do the default collation.
+
+=head1 DESCRIPTION
+
+This module is an implementation of Unicode Technical Standard #10
+(a.k.a. UTS #10) - Unicode Collation Algorithm (a.k.a. UCA).
+
+=head2 Constructor and Tailoring
+
+The C<new> method returns a collator object.
+
+ $Collator = Unicode::Collate->new(
+ UCA_Version => $UCA_Version,
+ alternate => $alternate, # deprecated: use of 'variable' is recommended.
+ backwards => $levelNumber, # or \@levelNumbers
+ entry => $element,
+ hangul_terminator => $term_primary_weight,
+ ignoreName => qr/$ignoreName/,
+ ignoreChar => qr/$ignoreChar/,
+ katakana_before_hiragana => $bool,
+ level => $collationLevel,
+ normalization => $normalization_form,
+ overrideCJK => \&overrideCJK,
+ overrideHangul => \&overrideHangul,
+ preprocess => \&preprocess,
+ rearrange => \@charList,
+ table => $filename,
+ undefName => qr/$undefName/,
+ undefChar => qr/$undefChar/,
+ upper_before_lower => $bool,
+ variable => $variable,
+ );
+
+=over 4
+
+=item UCA_Version
+
+If the tracking version number of UCA is given,
+behavior of that tracking version is emulated on collating.
+If omitted, the return value of C<UCA_Version()> is used.
+C<UCA_Version()> should return the latest tracking version supported.
+
+The supported tracking version: 8, 9, 11, or 14.
+
+ UCA Unicode Standard DUCET (@version)
+ ---------------------------------------------------
+ 8 3.1 3.0.1 (3.0.1d9)
+ 9 3.1 with Corrigendum 3 3.1.1 (3.1.1)
+ 11 4.0 4.0.0 (4.0.0)
+ 14 4.1.0 4.1.0 (4.1.0)
+
+Note: Recent UTS #10 renames "Tracking Version" to "Revision."
+
+=item alternate
+
+-- see 3.2.2 Alternate Weighting, version 8 of UTS #10
+
+For backward compatibility, C<alternate> (old name) can be used
+as an alias for C<variable>.
+
+=item backwards
+
+-- see 3.1.2 French Accents, UTS #10.
+
+ backwards => $levelNumber or \@levelNumbers
+
+Weights in reverse order; ex. level 2 (diacritic ordering) in French.
+If omitted, forwards at all the levels.
+
+=item entry
+
+-- see 3.1 Linguistic Features; 3.2.1 File Format, UTS #10.
+
+If the same character (or a sequence of characters) exists
+in the collation element table through C<table>,
+mapping to collation elements is overrided.
+If it does not exist, the mapping is defined additionally.
+
+ entry => <<'ENTRY', # for DUCET v4.0.0 (allkeys-4.0.0.txt)
+0063 0068 ; [.0E6A.0020.0002.0063] # ch
+0043 0068 ; [.0E6A.0020.0007.0043] # Ch
+0043 0048 ; [.0E6A.0020.0008.0043] # CH
+006C 006C ; [.0F4C.0020.0002.006C] # ll
+004C 006C ; [.0F4C.0020.0007.004C] # Ll
+004C 004C ; [.0F4C.0020.0008.004C] # LL
+00F1 ; [.0F7B.0020.0002.00F1] # n-tilde
+006E 0303 ; [.0F7B.0020.0002.00F1] # n-tilde
+00D1 ; [.0F7B.0020.0008.00D1] # N-tilde
+004E 0303 ; [.0F7B.0020.0008.00D1] # N-tilde
+ENTRY
+
+ entry => <<'ENTRY', # for DUCET v4.0.0 (allkeys-4.0.0.txt)
+00E6 ; [.0E33.0020.0002.00E6][.0E8B.0020.0002.00E6] # ae ligature as <a><e>
+00C6 ; [.0E33.0020.0008.00C6][.0E8B.0020.0008.00C6] # AE ligature as <A><E>
+ENTRY
+
+B<NOTE:> The code point in the UCA file format (before C<';'>)
+B<must> be a Unicode code point (defined as hexadecimal),
+but not a native code point.
+So C<0063> must always denote C<U+0063>,
+but not a character of C<"\x63">.
+
+Weighting may vary depending on collation element table.
+So ensure the weights defined in C<entry> will be consistent with
+those in the collation element table loaded via C<table>.
+
+In DUCET v4.0.0, primary weight of C<C> is C<0E60>
+and that of C<D> is C<0E6D>. So setting primary weight of C<CH> to C<0E6A>
+(as a value between C<0E60> and C<0E6D>)
+makes ordering as C<C E<lt> CH E<lt> D>.
+Exactly speaking DUCET already has some characters between C<C> and C<D>:
+C<small capital C> (C<U+1D04>) with primary weight C<0E64>,
+C<c-hook/C-hook> (C<U+0188/U+0187>) with C<0E65>,
+and C<c-curl> (C<U+0255>) with C<0E69>.
+Then primary weight C<0E6A> for C<CH> makes C<CH>
+ordered between C<c-curl> and C<D>.
+
+=item hangul_terminator
+
+-- see 7.1.4 Trailing Weights, UTS #10.
+
+If a true value is given (non-zero but should be positive),
+it will be added as a terminator primary weight to the end of
+every standard Hangul syllable. Secondary and any higher weights
+for terminator are set to zero.
+If the value is false or C<hangul_terminator> key does not exist,
+insertion of terminator weights will not be performed.
+
+Boundaries of Hangul syllables are determined
+according to conjoining Jamo behavior in F<the Unicode Standard>
+and F<HangulSyllableType.txt>.
+
+B<Implementation Note:>
+(1) For expansion mapping (Unicode character mapped
+to a sequence of collation elements), a terminator will not be added
+between collation elements, even if Hangul syllable boundary exists there.
+Addition of terminator is restricted to the next position
+to the last collation element.
+
+(2) Non-conjoining Hangul letters
+(Compatibility Jamo, halfwidth Jamo, and enclosed letters) are not
+automatically terminated with a terminator primary weight.
+These characters may need terminator included in a collation element
+table beforehand.
+
+=item ignoreChar
+
+=item ignoreName
+
+-- see 3.2.2 Variable Weighting, UTS #10.
+
+Makes the entry in the table completely ignorable;
+i.e. as if the weights were zero at all level.
+
+Through C<ignoreChar>, any character matching C<qr/$ignoreChar/>
+will be ignored. Through C<ignoreName>, any character whose name
+(given in the C<table> file as a comment) matches C<qr/$ignoreName/>
+will be ignored.
+
+E.g. when 'a' and 'e' are ignorable,
+'element' is equal to 'lament' (or 'lmnt').
+
+=item katakana_before_hiragana
+
+-- see 7.3.1 Tertiary Weight Table, UTS #10.
+
+By default, hiragana is before katakana.
+If the parameter is made true, this is reversed.
+
+B<NOTE>: This parameter simplemindedly assumes that any hiragana/katakana
+distinctions must occur in level 3, and their weights at level 3 must be
+same as those mentioned in 7.3.1, UTS #10.
+If you define your collation elements which violate this requirement,
+this parameter does not work validly.
+
+=item level
+
+-- see 4.3 Form Sort Key, UTS #10.
+
+Set the maximum level.
+Any higher levels than the specified one are ignored.
+
+ Level 1: alphabetic ordering
+ Level 2: diacritic ordering
+ Level 3: case ordering
+ Level 4: tie-breaking (e.g. in the case when variable is 'shifted')
+
+ ex.level => 2,
+
+If omitted, the maximum is the 4th.
+
+=item normalization
+
+-- see 4.1 Normalize, UTS #10.
+
+If specified, strings are normalized before preparation of sort keys
+(the normalization is executed after preprocess).
+
+A form name C<Unicode::Normalize::normalize()> accepts will be applied
+as C<$normalization_form>.
+Acceptable names include C<'NFD'>, C<'NFC'>, C<'NFKD'>, and C<'NFKC'>.
+See C<Unicode::Normalize::normalize()> for detail.
+If omitted, C<'NFD'> is used.
+
+C<normalization> is performed after C<preprocess> (if defined).
+
+Furthermore, special values, C<undef> and C<"prenormalized">, can be used,
+though they are not concerned with C<Unicode::Normalize::normalize()>.
+
+If C<undef> (not a string C<"undef">) is passed explicitly
+as the value for this key,
+any normalization is not carried out (this may make tailoring easier
+if any normalization is not desired). Under C<(normalization =E<gt> undef)>,
+only contiguous contractions are resolved;
+e.g. even if C<A-ring> (and C<A-ring-cedilla>) is ordered after C<Z>,
+C<A-cedilla-ring> would be primary equal to C<A>.
+In this point,
+C<(normalization =E<gt> undef, preprocess =E<gt> sub { NFD(shift) })>
+B<is not> equivalent to C<(normalization =E<gt> 'NFD')>.
+
+In the case of C<(normalization =E<gt> "prenormalized")>,
+any normalization is not performed, but
+non-contiguous contractions with combining characters are performed.
+Therefore
+C<(normalization =E<gt> 'prenormalized', preprocess =E<gt> sub { NFD(shift) })>
+B<is> equivalent to C<(normalization =E<gt> 'NFD')>.
+If source strings are finely prenormalized,
+C<(normalization =E<gt> 'prenormalized')> may save time for normalization.
+
+Except C<(normalization =E<gt> undef)>,
+B<Unicode::Normalize> is required (see also B<CAVEAT>).
+
+=item overrideCJK
+
+-- see 7.1 Derived Collation Elements, UTS #10.
+
+By default, CJK Unified Ideographs are ordered in Unicode codepoint order
+but C<CJK Unified Ideographs> (if C<UCA_Version> is 8 to 11, its range is
+C<U+4E00..U+9FA5>; if C<UCA_Version> is 14, its range is C<U+4E00..U+9FBB>)
+are lesser than C<CJK Unified Ideographs Extension> (its range is
+C<U+3400..U+4DB5> and C<U+20000..U+2A6D6>).
+
+Through C<overrideCJK>, ordering of CJK Unified Ideographs can be overrided.
+
+ex. CJK Unified Ideographs in the JIS code point order.
+
+ overrideCJK => sub {
+ my $u = shift; # get a Unicode codepoint
+ my $b = pack('n', $u); # to UTF-16BE
+ my $s = your_unicode_to_sjis_converter($b); # convert
+ my $n = unpack('n', $s); # convert sjis to short
+ [ $n, 0x20, 0x2, $u ]; # return the collation element
+ },
+
+ex. ignores all CJK Unified Ideographs.
+
+ overrideCJK => sub {()}, # CODEREF returning empty list
+
+ # where ->eq("Pe\x{4E00}rl", "Perl") is true
+ # as U+4E00 is a CJK Unified Ideograph and to be ignorable.
+
+If C<undef> is passed explicitly as the value for this key,
+weights for CJK Unified Ideographs are treated as undefined.
+But assignment of weight for CJK Unified Ideographs
+in table or C<entry> is still valid.
+
+=item overrideHangul
+
+-- see 7.1 Derived Collation Elements, UTS #10.
+
+By default, Hangul Syllables are decomposed into Hangul Jamo,
+even if C<(normalization =E<gt> undef)>.
+But the mapping of Hangul Syllables may be overrided.
+
+This parameter works like C<overrideCJK>, so see there for examples.
+
+If you want to override the mapping of Hangul Syllables,
+NFD, NFKD, and FCD are not appropriate,
+since they will decompose Hangul Syllables before overriding.
+
+If C<undef> is passed explicitly as the value for this key,
+weight for Hangul Syllables is treated as undefined
+without decomposition into Hangul Jamo.
+But definition of weight for Hangul Syllables
+in table or C<entry> is still valid.
+
+=item preprocess
+
+-- see 5.1 Preprocessing, UTS #10.
+
+If specified, the coderef is used to preprocess
+before the formation of sort keys.
+
+ex. dropping English articles, such as "a" or "the".
+Then, "the pen" is before "a pencil".
+
+ preprocess => sub {
+ my $str = shift;
+ $str =~ s/\b(?:an?|the)\s+//gi;
+ return $str;
+ },
+
+C<preprocess> is performed before C<normalization> (if defined).
+
+=item rearrange
+
+-- see 3.1.3 Rearrangement, UTS #10.
+
+Characters that are not coded in logical order and to be rearranged.
+If C<UCA_Version> is equal to or lesser than 11, default is:
+
+ rearrange => [ 0x0E40..0x0E44, 0x0EC0..0x0EC4 ],
+
+If you want to disallow any rearrangement, pass C<undef> or C<[]>
+(a reference to empty list) as the value for this key.
+
+If C<UCA_Version> is equal to 14, default is C<[]> (i.e. no rearrangement).
+
+B<According to the version 9 of UCA, this parameter shall not be used;
+but it is not warned at present.>
+
+=item table
+
+-- see 3.2 Default Unicode Collation Element Table, UTS #10.
+
+You can use another collation element table if desired.
+
+The table file should locate in the F<Unicode/Collate> directory
+on C<@INC>. Say, if the filename is F<Foo.txt>,
+the table file is searched as F<Unicode/Collate/Foo.txt> in C<@INC>.
+
+By default, F<allkeys.txt> (as the filename of DUCET) is used.
+If you will prepare your own table file, any name other than F<allkeys.txt>
+may be better to avoid namespace conflict.
+
+If C<undef> is passed explicitly as the value for this key,
+no file is read (but you can define collation elements via C<entry>).
+
+A typical way to define a collation element table
+without any file of table:
+
+ $onlyABC = Unicode::Collate->new(
+ table => undef,
+ entry => << 'ENTRIES',
+0061 ; [.0101.0020.0002.0061] # LATIN SMALL LETTER A
+0041 ; [.0101.0020.0008.0041] # LATIN CAPITAL LETTER A
+0062 ; [.0102.0020.0002.0062] # LATIN SMALL LETTER B
+0042 ; [.0102.0020.0008.0042] # LATIN CAPITAL LETTER B
+0063 ; [.0103.0020.0002.0063] # LATIN SMALL LETTER C
+0043 ; [.0103.0020.0008.0043] # LATIN CAPITAL LETTER C
+ENTRIES
+ );
+
+If C<ignoreName> or C<undefName> is used, character names should be
+specified as a comment (following C<#>) on each line.
+
+=item undefChar
+
+=item undefName
+
+-- see 6.3.4 Reducing the Repertoire, UTS #10.
+
+Undefines the collation element as if it were unassigned in the table.
+This reduces the size of the table.
+If an unassigned character appears in the string to be collated,
+the sort key is made from its codepoint
+as a single-character collation element,
+as it is greater than any other assigned collation elements
+(in the codepoint order among the unassigned characters).
+But, it'd be better to ignore characters
+unfamiliar to you and maybe never used.
+
+Through C<undefChar>, any character matching C<qr/$undefChar/>
+will be undefined. Through C<undefName>, any character whose name
+(given in the C<table> file as a comment) matches C<qr/$undefName/>
+will be undefined.
+
+ex. Collation weights for beyond-BMP characters are not stored in object:
+
+ undefChar => qr/[^\0-\x{fffd}]/,
+
+=item upper_before_lower
+
+-- see 6.6 Case Comparisons, UTS #10.
+
+By default, lowercase is before uppercase.
+If the parameter is made true, this is reversed.
+
+B<NOTE>: This parameter simplemindedly assumes that any lowercase/uppercase
+distinctions must occur in level 3, and their weights at level 3 must be
+same as those mentioned in 7.3.1, UTS #10.
+If you define your collation elements which differs from this requirement,
+this parameter doesn't work validly.
+
+=item variable
+
+-- see 3.2.2 Variable Weighting, UTS #10.
+
+This key allows to variable weighting for variable collation elements,
+which are marked with an ASTERISK in the table
+(NOTE: Many punction marks and symbols are variable in F<allkeys.txt>).
+
+ variable => 'blanked', 'non-ignorable', 'shifted', or 'shift-trimmed'.
+
+These names are case-insensitive.
+By default (if specification is omitted), 'shifted' is adopted.
+
+ 'Blanked' Variable elements are made ignorable at levels 1 through 3;
+ considered at the 4th level.
+
+ 'Non-Ignorable' Variable elements are not reset to ignorable.
+
+ 'Shifted' Variable elements are made ignorable at levels 1 through 3
+ their level 4 weight is replaced by the old level 1 weight.
+ Level 4 weight for Non-Variable elements is 0xFFFF.
+
+ 'Shift-Trimmed' Same as 'shifted', but all FFFF's at the 4th level
+ are trimmed.
+
+=back
+
+=head2 Methods for Collation
+
+=over 4
+
+=item C<@sorted = $Collator-E<gt>sort(@not_sorted)>
+
+Sorts a list of strings.
+
+=item C<$result = $Collator-E<gt>cmp($a, $b)>
+
+Returns 1 (when C<$a> is greater than C<$b>)
+or 0 (when C<$a> is equal to C<$b>)
+or -1 (when C<$a> is lesser than C<$b>).
+
+=item C<$result = $Collator-E<gt>eq($a, $b)>
+
+=item C<$result = $Collator-E<gt>ne($a, $b)>
+
+=item C<$result = $Collator-E<gt>lt($a, $b)>
+
+=item C<$result = $Collator-E<gt>le($a, $b)>
+
+=item C<$result = $Collator-E<gt>gt($a, $b)>
+
+=item C<$result = $Collator-E<gt>ge($a, $b)>
+
+They works like the same name operators as theirs.
+
+ eq : whether $a is equal to $b.
+ ne : whether $a is not equal to $b.
+ lt : whether $a is lesser than $b.
+ le : whether $a is lesser than $b or equal to $b.
+ gt : whether $a is greater than $b.
+ ge : whether $a is greater than $b or equal to $b.
+
+=item C<$sortKey = $Collator-E<gt>getSortKey($string)>
+
+-- see 4.3 Form Sort Key, UTS #10.
+
+Returns a sort key.
+
+You compare the sort keys using a binary comparison
+and get the result of the comparison of the strings using UCA.
+
+ $Collator->getSortKey($a) cmp $Collator->getSortKey($b)
+
+ is equivalent to
+
+ $Collator->cmp($a, $b)
+
+=item C<$sortKeyForm = $Collator-E<gt>viewSortKey($string)>
+
+Converts a sorting key into its representation form.
+If C<UCA_Version> is 8, the output is slightly different.
+
+ use Unicode::Collate;
+ my $c = Unicode::Collate->new();
+ print $c->viewSortKey("Perl"),"\n";
+
+ # output:
+ # [0B67 0A65 0B7F 0B03 | 0020 0020 0020 0020 | 0008 0002 0002 0002 | FFFF FFFF FFFF FFFF]
+ # Level 1 Level 2 Level 3 Level 4
+
+=back
+
+=head2 Methods for Searching
+
+B<DISCLAIMER:> If C<preprocess> or C<normalization> parameter is true
+for C<$Collator>, calling these methods (C<index>, C<match>, C<gmatch>,
+C<subst>, C<gsubst>) is croaked,
+as the position and the length might differ
+from those on the specified string.
+(And C<rearrange> and C<hangul_terminator> parameters are neglected.)
+
+The C<match>, C<gmatch>, C<subst>, C<gsubst> methods work
+like C<m//>, C<m//g>, C<s///>, C<s///g>, respectively,
+but they are not aware of any pattern, but only a literal substring.
+
+=over 4
+
+=item C<$position = $Collator-E<gt>index($string, $substring[, $position])>
+
+=item C<($position, $length) = $Collator-E<gt>index($string, $substring[, $position])>
+
+If C<$substring> matches a part of C<$string>, returns
+the position of the first occurrence of the matching part in scalar context;
+in list context, returns a two-element list of
+the position and the length of the matching part.
+
+If C<$substring> does not match any part of C<$string>,
+returns C<-1> in scalar context and
+an empty list in list context.
+
+e.g. you say
+
+ my $Collator = Unicode::Collate->new( normalization => undef, level => 1 );
+ # (normalization => undef) is REQUIRED.
+ my $str = "Ich muß studieren Perl.";
+ my $sub = "MÜSS";
+ my $match;
+ if (my($pos,$len) = $Collator->index($str, $sub)) {
+ $match = substr($str, $pos, $len);
+ }
+
+and get C<"muß"> in C<$match> since C<"muß">
+is primary equal to C<"MÜSS">.
+
+=item C<$match_ref = $Collator-E<gt>match($string, $substring)>
+
+=item C<($match) = $Collator-E<gt>match($string, $substring)>
+
+If C<$substring> matches a part of C<$string>, in scalar context, returns
+B<a reference to> the first occurrence of the matching part
+(C<$match_ref> is always true if matches,
+since every reference is B<true>);
+in list context, returns the first occurrence of the matching part.
+
+If C<$substring> does not match any part of C<$string>,
+returns C<undef> in scalar context and
+an empty list in list context.
+
+e.g.
+
+ if ($match_ref = $Collator->match($str, $sub)) { # scalar context
+ print "matches [$$match_ref].\n";
+ } else {
+ print "doesn't match.\n";
+ }
+
+ or
+
+ if (($match) = $Collator->match($str, $sub)) { # list context
+ print "matches [$match].\n";
+ } else {
+ print "doesn't match.\n";
+ }
+
+=item C<@match = $Collator-E<gt>gmatch($string, $substring)>
+
+If C<$substring> matches a part of C<$string>, returns
+all the matching parts (or matching count in scalar context).
+
+If C<$substring> does not match any part of C<$string>,
+returns an empty list.
+
+=item C<$count = $Collator-E<gt>subst($string, $substring, $replacement)>
+
+If C<$substring> matches a part of C<$string>,
+the first occurrence of the matching part is replaced by C<$replacement>
+(C<$string> is modified) and return C<$count> (always equals to C<1>).
+
+C<$replacement> can be a C<CODEREF>,
+taking the matching part as an argument,
+and returning a string to replace the matching part
+(a bit similar to C<s/(..)/$coderef-E<gt>($1)/e>).
+
+=item C<$count = $Collator-E<gt>gsubst($string, $substring, $replacement)>
+
+If C<$substring> matches a part of C<$string>,
+all the occurrences of the matching part is replaced by C<$replacement>
+(C<$string> is modified) and return C<$count>.
+
+C<$replacement> can be a C<CODEREF>,
+taking the matching part as an argument,
+and returning a string to replace the matching part
+(a bit similar to C<s/(..)/$coderef-E<gt>($1)/eg>).
+
+e.g.
+
+ my $Collator = Unicode::Collate->new( normalization => undef, level => 1 );
+ # (normalization => undef) is REQUIRED.
+ my $str = "Camel donkey zebra came\x{301}l CAMEL horse cAm\0E\0L...";
+ $Collator->gsubst($str, "camel", sub { "<b>$_[0]</b>" });
+
+ # now $str is "<b>Camel</b> donkey zebra <b>came\x{301}l</b> <b>CAMEL</b> horse <b>cAm\0E\0L</b>...";
+ # i.e., all the camels are made bold-faced.
+
+=back
+
+=head2 Other Methods
+
+=over 4
+
+=item C<%old_tailoring = $Collator-E<gt>change(%new_tailoring)>
+
+Change the value of specified keys and returns the changed part.
+
+ $Collator = Unicode::Collate->new(level => 4);
+
+ $Collator->eq("perl", "PERL"); # false
+
+ %old = $Collator->change(level => 2); # returns (level => 4).
+
+ $Collator->eq("perl", "PERL"); # true
+
+ $Collator->change(%old); # returns (level => 2).
+
+ $Collator->eq("perl", "PERL"); # false
+
+Not all C<(key,value)>s are allowed to be changed.
+See also C<@Unicode::Collate::ChangeOK> and C<@Unicode::Collate::ChangeNG>.
+
+In the scalar context, returns the modified collator
+(but it is B<not> a clone from the original).
+
+ $Collator->change(level => 2)->eq("perl", "PERL"); # true
+
+ $Collator->eq("perl", "PERL"); # true; now max level is 2nd.
+
+ $Collator->change(level => 4)->eq("perl", "PERL"); # false
+
+=item C<$version = $Collator-E<gt>version()>
+
+Returns the version number (a string) of the Unicode Standard
+which the C<table> file used by the collator object is based on.
+If the table does not include a version line (starting with C<@version>),
+returns C<"unknown">.
+
+=item C<UCA_Version()>
+
+Returns the tracking version number of UTS #10 this module consults.
+
+=item C<Base_Unicode_Version()>
+
+Returns the version number of UTS #10 this module consults.
+
+=back
+
+=head1 EXPORT
+
+No method will be exported.
+
+=head1 INSTALL
+
+Though this module can be used without any C<table> file,
+to use this module easily, it is recommended to install a table file
+in the UCA format, by copying it under the directory
+<a place in @INC>/Unicode/Collate.
+
+The most preferable one is "The Default Unicode Collation Element Table"
+(aka DUCET), available from the Unicode Consortium's website:
+
+ http://www.unicode.org/Public/UCA/
+
+ http://www.unicode.org/Public/UCA/latest/allkeys.txt (latest version)
+
+If DUCET is not installed, it is recommended to copy the file
+from http://www.unicode.org/Public/UCA/latest/allkeys.txt
+to <a place in @INC>/Unicode/Collate/allkeys.txt
+manually.
+
+=head1 CAVEATS
+
+=over 4
+
+=item Normalization
+
+Use of the C<normalization> parameter requires the B<Unicode::Normalize>
+module (see L<Unicode::Normalize>).
+
+If you need not it (say, in the case when you need not
+handle any combining characters),
+assign C<normalization =E<gt> undef> explicitly.
+
+-- see 6.5 Avoiding Normalization, UTS #10.
+
+=item Conformance Test
+
+The Conformance Test for the UCA is available
+under L<http://www.unicode.org/Public/UCA/>.
+
+For F<CollationTest_SHIFTED.txt>,
+a collator via C<Unicode::Collate-E<gt>new( )> should be used;
+for F<CollationTest_NON_IGNORABLE.txt>, a collator via
+C<Unicode::Collate-E<gt>new(variable =E<gt> "non-ignorable", level =E<gt> 3)>.
+
+B<Unicode::Normalize is required to try The Conformance Test.>
+
+=back
+
+=head1 AUTHOR, COPYRIGHT AND LICENSE
+
+The Unicode::Collate module for perl was written by SADAHIRO Tomoyuki,
+<SADAHIRO@cpan.org>. This module is Copyright(C) 2001-2005,
+SADAHIRO Tomoyuki. Japan. All rights reserved.
+
+This module is free software; you can redistribute it and/or
+modify it under the same terms as Perl itself.
+
+The file Unicode/Collate/allkeys.txt was copied directly
+from L<http://www.unicode.org/Public/UCA/4.1.0/allkeys.txt>.
+This file is Copyright (c) 1991-2005 Unicode, Inc. All rights reserved.
+Distributed under the Terms of Use in L<http://www.unicode.org/copyright.html>.
+
+=head1 SEE ALSO
+
+=over 4
+
+=item Unicode Collation Algorithm - UTS #10
+
+L<http://www.unicode.org/reports/tr10/>
+
+=item The Default Unicode Collation Element Table (DUCET)
+
+L<http://www.unicode.org/Public/UCA/latest/allkeys.txt>
+
+=item The conformance test for the UCA
+
+L<http://www.unicode.org/Public/UCA/latest/CollationTest.html>
+
+L<http://www.unicode.org/Public/UCA/latest/CollationTest.zip>
+
+=item Hangul Syllable Type
+
+L<http://www.unicode.org/Public/UNIDATA/HangulSyllableType.txt>
+
+=item Unicode Normalization Forms - UAX #15
+
+L<http://www.unicode.org/reports/tr15/>
+
+=back
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Unicode/Collate/allkeys.txt b/Master/tlpkg/tlperl/lib/Unicode/Collate/allkeys.txt
new file mode 100644
index 00000000000..f4c63f890c1
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Unicode/Collate/allkeys.txt
@@ -0,0 +1,18191 @@
+# allkeys-5.0.0.txt
+# Date: 2006-06-09, 15:29:02 PDT [KW]
+#
+# This file defines the Default Unicode Collation Element Table
+# (DUCET) for the Unicode Collation Algorithm
+#
+# Copyright (c) 2001-2006 Unicode, Inc.
+# For terms of use, see http://www.unicode.org/terms_of_use.html
+#
+# See UTS #10, Unicode Collation Algorithm, for more information.
+#
+# Diagnostic weight ranges
+# Primary weight range: 0200..2D56 (11095)
+# Secondary weight range: 0020..01BF (416)
+# Variant secondaries: 0199..019E (6)
+# Digit secondaries: 019F..01BF (33)
+# Tertiary weight range: 0002..001F (30)
+#
+@version 5.0.0
+
+0000 ; [.0000.0000.0000.0000] # [0000] NULL (in 6429)
+0001 ; [.0000.0000.0000.0000] # [0001] START OF HEADING (in 6429)
+0002 ; [.0000.0000.0000.0000] # [0002] START OF TEXT (in 6429)
+0003 ; [.0000.0000.0000.0000] # [0003] END OF TEXT (in 6429)
+0004 ; [.0000.0000.0000.0000] # [0004] END OF TRANSMISSION (in 6429)
+0005 ; [.0000.0000.0000.0000] # [0005] ENQUIRY (in 6429)
+0006 ; [.0000.0000.0000.0000] # [0006] ACKNOWLEDGE (in 6429)
+0007 ; [.0000.0000.0000.0000] # [0007] BELL (in 6429)
+0008 ; [.0000.0000.0000.0000] # [0008] BACKSPACE (in 6429)
+000E ; [.0000.0000.0000.0000] # [000E] SHIFT OUT (in 6429)
+000F ; [.0000.0000.0000.0000] # [000F] SHIFT IN (in 6429)
+0010 ; [.0000.0000.0000.0000] # [0010] DATA LINK ESCAPE (in 6429)
+0011 ; [.0000.0000.0000.0000] # [0011] DEVICE CONTROL ONE (in 6429)
+0012 ; [.0000.0000.0000.0000] # [0012] DEVICE CONTROL TWO (in 6429)
+0013 ; [.0000.0000.0000.0000] # [0013] DEVICE CONTROL THREE (in 6429)
+0014 ; [.0000.0000.0000.0000] # [0014] DEVICE CONTROL FOUR (in 6429)
+0015 ; [.0000.0000.0000.0000] # [0015] NEGATIVE ACKNOWLEDGE (in 6429)
+0016 ; [.0000.0000.0000.0000] # [0016] SYNCHRONOUS IDLE (in 6429)
+0017 ; [.0000.0000.0000.0000] # [0017] END OF TRANSMISSION BLOCK (in 6429)
+0018 ; [.0000.0000.0000.0000] # [0018] CANCEL (in 6429)
+0019 ; [.0000.0000.0000.0000] # [0019] END OF MEDIUM (in 6429)
+001A ; [.0000.0000.0000.0000] # [001A] SUBSTITUTE (in 6429)
+001B ; [.0000.0000.0000.0000] # [001B] ESCAPE (in 6429)
+001C ; [.0000.0000.0000.0000] # [001C] FILE SEPARATOR (in 6429)
+001D ; [.0000.0000.0000.0000] # [001D] GROUP SEPARATOR (in 6429)
+001E ; [.0000.0000.0000.0000] # [001E] RECORD SEPARATOR (in 6429)
+001F ; [.0000.0000.0000.0000] # [001F] UNIT SEPARATOR (in 6429)
+007F ; [.0000.0000.0000.0000] # [007F] DELETE (in 6429)
+0080 ; [.0000.0000.0000.0000] # [0080] <control>
+0081 ; [.0000.0000.0000.0000] # [0081] <control>
+0082 ; [.0000.0000.0000.0000] # [0082] BREAK PERMITTED HERE (in 6429)
+0083 ; [.0000.0000.0000.0000] # [0083] NO BREAK HERE (in 6429)
+0084 ; [.0000.0000.0000.0000] # [0084] <control>
+0086 ; [.0000.0000.0000.0000] # [0086] START OF SELECTED AREA (in 6429)
+0087 ; [.0000.0000.0000.0000] # [0087] END OF SELECTED AREA (in 6429)
+0088 ; [.0000.0000.0000.0000] # [0088] CHARACTER TABULATION SET (in 6429)
+0089 ; [.0000.0000.0000.0000] # [0089] CHARACTER TABULATION WITH JUSTIFICATION (in 6429)
+008A ; [.0000.0000.0000.0000] # [008A] LINE TABULATION SET (in 6429)
+008B ; [.0000.0000.0000.0000] # [008B] PARTIAL LINE FORWARD (in 6429)
+008C ; [.0000.0000.0000.0000] # [008C] PARTIAL LINE BACKWARD (in 6429)
+008D ; [.0000.0000.0000.0000] # [008D] PARTIAL LINE FEED (in 6429)
+008E ; [.0000.0000.0000.0000] # [008E] SINGLE SHIFT TWO (in 6429)
+008F ; [.0000.0000.0000.0000] # [008F] SINGLE SHIFT THREE (in 6429)
+0090 ; [.0000.0000.0000.0000] # [0090] DEVICE CONTROL STRING (in 6429)
+0091 ; [.0000.0000.0000.0000] # [0091] PRIVATE USE ONE (in 6429)
+0092 ; [.0000.0000.0000.0000] # [0092] PRIVATE USE TWO (in 6429)
+0093 ; [.0000.0000.0000.0000] # [0093] SET TRANSMIT STATE (in 6429)
+0094 ; [.0000.0000.0000.0000] # [0094] CANCEL CHARACTER (in 6429)
+0095 ; [.0000.0000.0000.0000] # [0095] MESSAGE WAITING (in 6429)
+0096 ; [.0000.0000.0000.0000] # [0096] START OF GUARDED AREA (in 6429)
+0097 ; [.0000.0000.0000.0000] # [0097] END OF GUARDED AREA (in 6429)
+0098 ; [.0000.0000.0000.0000] # [0098] START OF STRING (in 6429)
+0099 ; [.0000.0000.0000.0000] # [0099] <control>
+009A ; [.0000.0000.0000.0000] # [009A] SINGLE CHARACTER INTRODUCER (in 6429)
+009B ; [.0000.0000.0000.0000] # [009B] CONTROL SEQUENCE INTRODUCER (in 6429)
+009C ; [.0000.0000.0000.0000] # [009C] STRING TERMINATOR (in 6429)
+009D ; [.0000.0000.0000.0000] # [009D] OPERATING SYSTEM COMMAND (in 6429)
+009E ; [.0000.0000.0000.0000] # [009E] PRIVACY MESSAGE (in 6429)
+009F ; [.0000.0000.0000.0000] # [009F] APPLICATION PROGRAM COMMAND (in 6429)
+070F ; [.0000.0000.0000.0000] # [070F] SYRIAC ABBREVIATION MARK
+180B ; [.0000.0000.0000.0000] # [180B] MONGOLIAN FREE VARIATION SELECTOR ONE
+180C ; [.0000.0000.0000.0000] # [180C] MONGOLIAN FREE VARIATION SELECTOR TWO
+180D ; [.0000.0000.0000.0000] # [180D] MONGOLIAN FREE VARIATION SELECTOR THREE
+180E ; [.0000.0000.0000.0000] # [180E] MONGOLIAN VOWEL SEPARATOR
+200B ; [.0000.0000.0000.0000] # [200B] ZERO WIDTH SPACE
+200C ; [.0000.0000.0000.0000] # [200C] ZERO WIDTH NON-JOINER
+200D ; [.0000.0000.0000.0000] # [200D] ZERO WIDTH JOINER
+200E ; [.0000.0000.0000.0000] # [200E] LEFT-TO-RIGHT MARK
+200F ; [.0000.0000.0000.0000] # [200F] RIGHT-TO-LEFT MARK
+202A ; [.0000.0000.0000.0000] # [202A] LEFT-TO-RIGHT EMBEDDING
+202B ; [.0000.0000.0000.0000] # [202B] RIGHT-TO-LEFT EMBEDDING
+202C ; [.0000.0000.0000.0000] # [202C] POP DIRECTIONAL FORMATTING
+202D ; [.0000.0000.0000.0000] # [202D] LEFT-TO-RIGHT OVERRIDE
+202E ; [.0000.0000.0000.0000] # [202E] RIGHT-TO-LEFT OVERRIDE
+2060 ; [.0000.0000.0000.0000] # [2060] WORD JOINER
+206A ; [.0000.0000.0000.0000] # [206A] INHIBIT SYMMETRIC SWAPPING
+206B ; [.0000.0000.0000.0000] # [206B] ACTIVATE SYMMETRIC SWAPPING
+206C ; [.0000.0000.0000.0000] # [206C] INHIBIT ARABIC FORM SHAPING
+206D ; [.0000.0000.0000.0000] # [206D] ACTIVATE ARABIC FORM SHAPING
+206E ; [.0000.0000.0000.0000] # [206E] NATIONAL DIGIT SHAPES
+206F ; [.0000.0000.0000.0000] # [206F] NOMINAL DIGIT SHAPES
+FE00 ; [.0000.0000.0000.0000] # [FE00] VARIATION SELECTOR-1
+FE01 ; [.0000.0000.0000.0000] # [FE01] VARIATION SELECTOR-2
+FE02 ; [.0000.0000.0000.0000] # [FE02] VARIATION SELECTOR-3
+FE03 ; [.0000.0000.0000.0000] # [FE03] VARIATION SELECTOR-4
+FE04 ; [.0000.0000.0000.0000] # [FE04] VARIATION SELECTOR-5
+FE05 ; [.0000.0000.0000.0000] # [FE05] VARIATION SELECTOR-6
+FE06 ; [.0000.0000.0000.0000] # [FE06] VARIATION SELECTOR-7
+FE07 ; [.0000.0000.0000.0000] # [FE07] VARIATION SELECTOR-8
+FE08 ; [.0000.0000.0000.0000] # [FE08] VARIATION SELECTOR-9
+FE09 ; [.0000.0000.0000.0000] # [FE09] VARIATION SELECTOR-10
+FE0A ; [.0000.0000.0000.0000] # [FE0A] VARIATION SELECTOR-11
+FE0B ; [.0000.0000.0000.0000] # [FE0B] VARIATION SELECTOR-12
+FE0C ; [.0000.0000.0000.0000] # [FE0C] VARIATION SELECTOR-13
+FE0D ; [.0000.0000.0000.0000] # [FE0D] VARIATION SELECTOR-14
+FE0E ; [.0000.0000.0000.0000] # [FE0E] VARIATION SELECTOR-15
+FE0F ; [.0000.0000.0000.0000] # [FE0F] VARIATION SELECTOR-16
+FEFF ; [.0000.0000.0000.0000] # [FEFF] ZERO WIDTH NO-BREAK SPACE
+FFF9 ; [.0000.0000.0000.0000] # [FFF9] INTERLINEAR ANNOTATION ANCHOR
+FFFA ; [.0000.0000.0000.0000] # [FFFA] INTERLINEAR ANNOTATION SEPARATOR
+FFFB ; [.0000.0000.0000.0000] # [FFFB] INTERLINEAR ANNOTATION TERMINATOR
+1D173 ; [.0000.0000.0000.0000] # [1D173] MUSICAL SYMBOL BEGIN BEAM
+1D174 ; [.0000.0000.0000.0000] # [1D174] MUSICAL SYMBOL END BEAM
+1D175 ; [.0000.0000.0000.0000] # [1D175] MUSICAL SYMBOL BEGIN TIE
+1D176 ; [.0000.0000.0000.0000] # [1D176] MUSICAL SYMBOL END TIE
+1D177 ; [.0000.0000.0000.0000] # [1D177] MUSICAL SYMBOL BEGIN SLUR
+1D178 ; [.0000.0000.0000.0000] # [1D178] MUSICAL SYMBOL END SLUR
+1D179 ; [.0000.0000.0000.0000] # [1D179] MUSICAL SYMBOL BEGIN PHRASE
+1D17A ; [.0000.0000.0000.0000] # [1D17A] MUSICAL SYMBOL END PHRASE
+E0001 ; [.0000.0000.0000.0000] # [E0001] LANGUAGE TAG
+E0020 ; [.0000.0000.0000.0000] # [E0020] TAG SPACE
+E0021 ; [.0000.0000.0000.0000] # [E0021] TAG EXCLAMATION MARK
+E0022 ; [.0000.0000.0000.0000] # [E0022] TAG QUOTATION MARK
+E0023 ; [.0000.0000.0000.0000] # [E0023] TAG NUMBER SIGN
+E0024 ; [.0000.0000.0000.0000] # [E0024] TAG DOLLAR SIGN
+E0025 ; [.0000.0000.0000.0000] # [E0025] TAG PERCENT SIGN
+E0026 ; [.0000.0000.0000.0000] # [E0026] TAG AMPERSAND
+E0027 ; [.0000.0000.0000.0000] # [E0027] TAG APOSTROPHE
+E0028 ; [.0000.0000.0000.0000] # [E0028] TAG LEFT PARENTHESIS
+E0029 ; [.0000.0000.0000.0000] # [E0029] TAG RIGHT PARENTHESIS
+E002A ; [.0000.0000.0000.0000] # [E002A] TAG ASTERISK
+E002B ; [.0000.0000.0000.0000] # [E002B] TAG PLUS SIGN
+E002C ; [.0000.0000.0000.0000] # [E002C] TAG COMMA
+E002D ; [.0000.0000.0000.0000] # [E002D] TAG HYPHEN-MINUS
+E002E ; [.0000.0000.0000.0000] # [E002E] TAG FULL STOP
+E002F ; [.0000.0000.0000.0000] # [E002F] TAG SOLIDUS
+E0030 ; [.0000.0000.0000.0000] # [E0030] TAG DIGIT ZERO
+E0031 ; [.0000.0000.0000.0000] # [E0031] TAG DIGIT ONE
+E0032 ; [.0000.0000.0000.0000] # [E0032] TAG DIGIT TWO
+E0033 ; [.0000.0000.0000.0000] # [E0033] TAG DIGIT THREE
+E0034 ; [.0000.0000.0000.0000] # [E0034] TAG DIGIT FOUR
+E0035 ; [.0000.0000.0000.0000] # [E0035] TAG DIGIT FIVE
+E0036 ; [.0000.0000.0000.0000] # [E0036] TAG DIGIT SIX
+E0037 ; [.0000.0000.0000.0000] # [E0037] TAG DIGIT SEVEN
+E0038 ; [.0000.0000.0000.0000] # [E0038] TAG DIGIT EIGHT
+E0039 ; [.0000.0000.0000.0000] # [E0039] TAG DIGIT NINE
+E003A ; [.0000.0000.0000.0000] # [E003A] TAG COLON
+E003B ; [.0000.0000.0000.0000] # [E003B] TAG SEMICOLON
+E003C ; [.0000.0000.0000.0000] # [E003C] TAG LESS-THAN SIGN
+E003D ; [.0000.0000.0000.0000] # [E003D] TAG EQUALS SIGN
+E003E ; [.0000.0000.0000.0000] # [E003E] TAG GREATER-THAN SIGN
+E003F ; [.0000.0000.0000.0000] # [E003F] TAG QUESTION MARK
+E0040 ; [.0000.0000.0000.0000] # [E0040] TAG COMMERCIAL AT
+E0041 ; [.0000.0000.0000.0000] # [E0041] TAG LATIN CAPITAL LETTER A
+E0042 ; [.0000.0000.0000.0000] # [E0042] TAG LATIN CAPITAL LETTER B
+E0043 ; [.0000.0000.0000.0000] # [E0043] TAG LATIN CAPITAL LETTER C
+E0044 ; [.0000.0000.0000.0000] # [E0044] TAG LATIN CAPITAL LETTER D
+E0045 ; [.0000.0000.0000.0000] # [E0045] TAG LATIN CAPITAL LETTER E
+E0046 ; [.0000.0000.0000.0000] # [E0046] TAG LATIN CAPITAL LETTER F
+E0047 ; [.0000.0000.0000.0000] # [E0047] TAG LATIN CAPITAL LETTER G
+E0048 ; [.0000.0000.0000.0000] # [E0048] TAG LATIN CAPITAL LETTER H
+E0049 ; [.0000.0000.0000.0000] # [E0049] TAG LATIN CAPITAL LETTER I
+E004A ; [.0000.0000.0000.0000] # [E004A] TAG LATIN CAPITAL LETTER J
+E004B ; [.0000.0000.0000.0000] # [E004B] TAG LATIN CAPITAL LETTER K
+E004C ; [.0000.0000.0000.0000] # [E004C] TAG LATIN CAPITAL LETTER L
+E004D ; [.0000.0000.0000.0000] # [E004D] TAG LATIN CAPITAL LETTER M
+E004E ; [.0000.0000.0000.0000] # [E004E] TAG LATIN CAPITAL LETTER N
+E004F ; [.0000.0000.0000.0000] # [E004F] TAG LATIN CAPITAL LETTER O
+E0050 ; [.0000.0000.0000.0000] # [E0050] TAG LATIN CAPITAL LETTER P
+E0051 ; [.0000.0000.0000.0000] # [E0051] TAG LATIN CAPITAL LETTER Q
+E0052 ; [.0000.0000.0000.0000] # [E0052] TAG LATIN CAPITAL LETTER R
+E0053 ; [.0000.0000.0000.0000] # [E0053] TAG LATIN CAPITAL LETTER S
+E0054 ; [.0000.0000.0000.0000] # [E0054] TAG LATIN CAPITAL LETTER T
+E0055 ; [.0000.0000.0000.0000] # [E0055] TAG LATIN CAPITAL LETTER U
+E0056 ; [.0000.0000.0000.0000] # [E0056] TAG LATIN CAPITAL LETTER V
+E0057 ; [.0000.0000.0000.0000] # [E0057] TAG LATIN CAPITAL LETTER W
+E0058 ; [.0000.0000.0000.0000] # [E0058] TAG LATIN CAPITAL LETTER X
+E0059 ; [.0000.0000.0000.0000] # [E0059] TAG LATIN CAPITAL LETTER Y
+E005A ; [.0000.0000.0000.0000] # [E005A] TAG LATIN CAPITAL LETTER Z
+E005B ; [.0000.0000.0000.0000] # [E005B] TAG LEFT SQUARE BRACKET
+E005C ; [.0000.0000.0000.0000] # [E005C] TAG REVERSE SOLIDUS
+E005D ; [.0000.0000.0000.0000] # [E005D] TAG RIGHT SQUARE BRACKET
+E005E ; [.0000.0000.0000.0000] # [E005E] TAG CIRCUMFLEX ACCENT
+E005F ; [.0000.0000.0000.0000] # [E005F] TAG LOW LINE
+E0060 ; [.0000.0000.0000.0000] # [E0060] TAG GRAVE ACCENT
+E0061 ; [.0000.0000.0000.0000] # [E0061] TAG LATIN SMALL LETTER A
+E0062 ; [.0000.0000.0000.0000] # [E0062] TAG LATIN SMALL LETTER B
+E0063 ; [.0000.0000.0000.0000] # [E0063] TAG LATIN SMALL LETTER C
+E0064 ; [.0000.0000.0000.0000] # [E0064] TAG LATIN SMALL LETTER D
+E0065 ; [.0000.0000.0000.0000] # [E0065] TAG LATIN SMALL LETTER E
+E0066 ; [.0000.0000.0000.0000] # [E0066] TAG LATIN SMALL LETTER F
+E0067 ; [.0000.0000.0000.0000] # [E0067] TAG LATIN SMALL LETTER G
+E0068 ; [.0000.0000.0000.0000] # [E0068] TAG LATIN SMALL LETTER H
+E0069 ; [.0000.0000.0000.0000] # [E0069] TAG LATIN SMALL LETTER I
+E006A ; [.0000.0000.0000.0000] # [E006A] TAG LATIN SMALL LETTER J
+E006B ; [.0000.0000.0000.0000] # [E006B] TAG LATIN SMALL LETTER K
+E006C ; [.0000.0000.0000.0000] # [E006C] TAG LATIN SMALL LETTER L
+E006D ; [.0000.0000.0000.0000] # [E006D] TAG LATIN SMALL LETTER M
+E006E ; [.0000.0000.0000.0000] # [E006E] TAG LATIN SMALL LETTER N
+E006F ; [.0000.0000.0000.0000] # [E006F] TAG LATIN SMALL LETTER O
+E0070 ; [.0000.0000.0000.0000] # [E0070] TAG LATIN SMALL LETTER P
+E0071 ; [.0000.0000.0000.0000] # [E0071] TAG LATIN SMALL LETTER Q
+E0072 ; [.0000.0000.0000.0000] # [E0072] TAG LATIN SMALL LETTER R
+E0073 ; [.0000.0000.0000.0000] # [E0073] TAG LATIN SMALL LETTER S
+E0074 ; [.0000.0000.0000.0000] # [E0074] TAG LATIN SMALL LETTER T
+E0075 ; [.0000.0000.0000.0000] # [E0075] TAG LATIN SMALL LETTER U
+E0076 ; [.0000.0000.0000.0000] # [E0076] TAG LATIN SMALL LETTER V
+E0077 ; [.0000.0000.0000.0000] # [E0077] TAG LATIN SMALL LETTER W
+E0078 ; [.0000.0000.0000.0000] # [E0078] TAG LATIN SMALL LETTER X
+E0079 ; [.0000.0000.0000.0000] # [E0079] TAG LATIN SMALL LETTER Y
+E007A ; [.0000.0000.0000.0000] # [E007A] TAG LATIN SMALL LETTER Z
+E007B ; [.0000.0000.0000.0000] # [E007B] TAG LEFT CURLY BRACKET
+E007C ; [.0000.0000.0000.0000] # [E007C] TAG VERTICAL LINE
+E007D ; [.0000.0000.0000.0000] # [E007D] TAG RIGHT CURLY BRACKET
+E007E ; [.0000.0000.0000.0000] # [E007E] TAG TILDE
+E007F ; [.0000.0000.0000.0000] # [E007F] CANCEL TAG
+E0100 ; [.0000.0000.0000.0000] # [E0100] VARIATION SELECTOR-17
+E0101 ; [.0000.0000.0000.0000] # [E0101] VARIATION SELECTOR-18
+E0102 ; [.0000.0000.0000.0000] # [E0102] VARIATION SELECTOR-19
+E0103 ; [.0000.0000.0000.0000] # [E0103] VARIATION SELECTOR-20
+E0104 ; [.0000.0000.0000.0000] # [E0104] VARIATION SELECTOR-21
+E0105 ; [.0000.0000.0000.0000] # [E0105] VARIATION SELECTOR-22
+E0106 ; [.0000.0000.0000.0000] # [E0106] VARIATION SELECTOR-23
+E0107 ; [.0000.0000.0000.0000] # [E0107] VARIATION SELECTOR-24
+E0108 ; [.0000.0000.0000.0000] # [E0108] VARIATION SELECTOR-25
+E0109 ; [.0000.0000.0000.0000] # [E0109] VARIATION SELECTOR-26
+E010A ; [.0000.0000.0000.0000] # [E010A] VARIATION SELECTOR-27
+E010B ; [.0000.0000.0000.0000] # [E010B] VARIATION SELECTOR-28
+E010C ; [.0000.0000.0000.0000] # [E010C] VARIATION SELECTOR-29
+E010D ; [.0000.0000.0000.0000] # [E010D] VARIATION SELECTOR-30
+E010E ; [.0000.0000.0000.0000] # [E010E] VARIATION SELECTOR-31
+E010F ; [.0000.0000.0000.0000] # [E010F] VARIATION SELECTOR-32
+E0110 ; [.0000.0000.0000.0000] # [E0110] VARIATION SELECTOR-33
+E0111 ; [.0000.0000.0000.0000] # [E0111] VARIATION SELECTOR-34
+E0112 ; [.0000.0000.0000.0000] # [E0112] VARIATION SELECTOR-35
+E0113 ; [.0000.0000.0000.0000] # [E0113] VARIATION SELECTOR-36
+E0114 ; [.0000.0000.0000.0000] # [E0114] VARIATION SELECTOR-37
+E0115 ; [.0000.0000.0000.0000] # [E0115] VARIATION SELECTOR-38
+E0116 ; [.0000.0000.0000.0000] # [E0116] VARIATION SELECTOR-39
+E0117 ; [.0000.0000.0000.0000] # [E0117] VARIATION SELECTOR-40
+E0118 ; [.0000.0000.0000.0000] # [E0118] VARIATION SELECTOR-41
+E0119 ; [.0000.0000.0000.0000] # [E0119] VARIATION SELECTOR-42
+E011A ; [.0000.0000.0000.0000] # [E011A] VARIATION SELECTOR-43
+E011B ; [.0000.0000.0000.0000] # [E011B] VARIATION SELECTOR-44
+E011C ; [.0000.0000.0000.0000] # [E011C] VARIATION SELECTOR-45
+E011D ; [.0000.0000.0000.0000] # [E011D] VARIATION SELECTOR-46
+E011E ; [.0000.0000.0000.0000] # [E011E] VARIATION SELECTOR-47
+E011F ; [.0000.0000.0000.0000] # [E011F] VARIATION SELECTOR-48
+E0120 ; [.0000.0000.0000.0000] # [E0120] VARIATION SELECTOR-49
+E0121 ; [.0000.0000.0000.0000] # [E0121] VARIATION SELECTOR-50
+E0122 ; [.0000.0000.0000.0000] # [E0122] VARIATION SELECTOR-51
+E0123 ; [.0000.0000.0000.0000] # [E0123] VARIATION SELECTOR-52
+E0124 ; [.0000.0000.0000.0000] # [E0124] VARIATION SELECTOR-53
+E0125 ; [.0000.0000.0000.0000] # [E0125] VARIATION SELECTOR-54
+E0126 ; [.0000.0000.0000.0000] # [E0126] VARIATION SELECTOR-55
+E0127 ; [.0000.0000.0000.0000] # [E0127] VARIATION SELECTOR-56
+E0128 ; [.0000.0000.0000.0000] # [E0128] VARIATION SELECTOR-57
+E0129 ; [.0000.0000.0000.0000] # [E0129] VARIATION SELECTOR-58
+E012A ; [.0000.0000.0000.0000] # [E012A] VARIATION SELECTOR-59
+E012B ; [.0000.0000.0000.0000] # [E012B] VARIATION SELECTOR-60
+E012C ; [.0000.0000.0000.0000] # [E012C] VARIATION SELECTOR-61
+E012D ; [.0000.0000.0000.0000] # [E012D] VARIATION SELECTOR-62
+E012E ; [.0000.0000.0000.0000] # [E012E] VARIATION SELECTOR-63
+E012F ; [.0000.0000.0000.0000] # [E012F] VARIATION SELECTOR-64
+E0130 ; [.0000.0000.0000.0000] # [E0130] VARIATION SELECTOR-65
+E0131 ; [.0000.0000.0000.0000] # [E0131] VARIATION SELECTOR-66
+E0132 ; [.0000.0000.0000.0000] # [E0132] VARIATION SELECTOR-67
+E0133 ; [.0000.0000.0000.0000] # [E0133] VARIATION SELECTOR-68
+E0134 ; [.0000.0000.0000.0000] # [E0134] VARIATION SELECTOR-69
+E0135 ; [.0000.0000.0000.0000] # [E0135] VARIATION SELECTOR-70
+E0136 ; [.0000.0000.0000.0000] # [E0136] VARIATION SELECTOR-71
+E0137 ; [.0000.0000.0000.0000] # [E0137] VARIATION SELECTOR-72
+E0138 ; [.0000.0000.0000.0000] # [E0138] VARIATION SELECTOR-73
+E0139 ; [.0000.0000.0000.0000] # [E0139] VARIATION SELECTOR-74
+E013A ; [.0000.0000.0000.0000] # [E013A] VARIATION SELECTOR-75
+E013B ; [.0000.0000.0000.0000] # [E013B] VARIATION SELECTOR-76
+E013C ; [.0000.0000.0000.0000] # [E013C] VARIATION SELECTOR-77
+E013D ; [.0000.0000.0000.0000] # [E013D] VARIATION SELECTOR-78
+E013E ; [.0000.0000.0000.0000] # [E013E] VARIATION SELECTOR-79
+E013F ; [.0000.0000.0000.0000] # [E013F] VARIATION SELECTOR-80
+E0140 ; [.0000.0000.0000.0000] # [E0140] VARIATION SELECTOR-81
+E0141 ; [.0000.0000.0000.0000] # [E0141] VARIATION SELECTOR-82
+E0142 ; [.0000.0000.0000.0000] # [E0142] VARIATION SELECTOR-83
+E0143 ; [.0000.0000.0000.0000] # [E0143] VARIATION SELECTOR-84
+E0144 ; [.0000.0000.0000.0000] # [E0144] VARIATION SELECTOR-85
+E0145 ; [.0000.0000.0000.0000] # [E0145] VARIATION SELECTOR-86
+E0146 ; [.0000.0000.0000.0000] # [E0146] VARIATION SELECTOR-87
+E0147 ; [.0000.0000.0000.0000] # [E0147] VARIATION SELECTOR-88
+E0148 ; [.0000.0000.0000.0000] # [E0148] VARIATION SELECTOR-89
+E0149 ; [.0000.0000.0000.0000] # [E0149] VARIATION SELECTOR-90
+E014A ; [.0000.0000.0000.0000] # [E014A] VARIATION SELECTOR-91
+E014B ; [.0000.0000.0000.0000] # [E014B] VARIATION SELECTOR-92
+E014C ; [.0000.0000.0000.0000] # [E014C] VARIATION SELECTOR-93
+E014D ; [.0000.0000.0000.0000] # [E014D] VARIATION SELECTOR-94
+E014E ; [.0000.0000.0000.0000] # [E014E] VARIATION SELECTOR-95
+E014F ; [.0000.0000.0000.0000] # [E014F] VARIATION SELECTOR-96
+E0150 ; [.0000.0000.0000.0000] # [E0150] VARIATION SELECTOR-97
+E0151 ; [.0000.0000.0000.0000] # [E0151] VARIATION SELECTOR-98
+E0152 ; [.0000.0000.0000.0000] # [E0152] VARIATION SELECTOR-99
+E0153 ; [.0000.0000.0000.0000] # [E0153] VARIATION SELECTOR-100
+E0154 ; [.0000.0000.0000.0000] # [E0154] VARIATION SELECTOR-101
+E0155 ; [.0000.0000.0000.0000] # [E0155] VARIATION SELECTOR-102
+E0156 ; [.0000.0000.0000.0000] # [E0156] VARIATION SELECTOR-103
+E0157 ; [.0000.0000.0000.0000] # [E0157] VARIATION SELECTOR-104
+E0158 ; [.0000.0000.0000.0000] # [E0158] VARIATION SELECTOR-105
+E0159 ; [.0000.0000.0000.0000] # [E0159] VARIATION SELECTOR-106
+E015A ; [.0000.0000.0000.0000] # [E015A] VARIATION SELECTOR-107
+E015B ; [.0000.0000.0000.0000] # [E015B] VARIATION SELECTOR-108
+E015C ; [.0000.0000.0000.0000] # [E015C] VARIATION SELECTOR-109
+E015D ; [.0000.0000.0000.0000] # [E015D] VARIATION SELECTOR-110
+E015E ; [.0000.0000.0000.0000] # [E015E] VARIATION SELECTOR-111
+E015F ; [.0000.0000.0000.0000] # [E015F] VARIATION SELECTOR-112
+E0160 ; [.0000.0000.0000.0000] # [E0160] VARIATION SELECTOR-113
+E0161 ; [.0000.0000.0000.0000] # [E0161] VARIATION SELECTOR-114
+E0162 ; [.0000.0000.0000.0000] # [E0162] VARIATION SELECTOR-115
+E0163 ; [.0000.0000.0000.0000] # [E0163] VARIATION SELECTOR-116
+E0164 ; [.0000.0000.0000.0000] # [E0164] VARIATION SELECTOR-117
+E0165 ; [.0000.0000.0000.0000] # [E0165] VARIATION SELECTOR-118
+E0166 ; [.0000.0000.0000.0000] # [E0166] VARIATION SELECTOR-119
+E0167 ; [.0000.0000.0000.0000] # [E0167] VARIATION SELECTOR-120
+E0168 ; [.0000.0000.0000.0000] # [E0168] VARIATION SELECTOR-121
+E0169 ; [.0000.0000.0000.0000] # [E0169] VARIATION SELECTOR-122
+E016A ; [.0000.0000.0000.0000] # [E016A] VARIATION SELECTOR-123
+E016B ; [.0000.0000.0000.0000] # [E016B] VARIATION SELECTOR-124
+E016C ; [.0000.0000.0000.0000] # [E016C] VARIATION SELECTOR-125
+E016D ; [.0000.0000.0000.0000] # [E016D] VARIATION SELECTOR-126
+E016E ; [.0000.0000.0000.0000] # [E016E] VARIATION SELECTOR-127
+E016F ; [.0000.0000.0000.0000] # [E016F] VARIATION SELECTOR-128
+E0170 ; [.0000.0000.0000.0000] # [E0170] VARIATION SELECTOR-129
+E0171 ; [.0000.0000.0000.0000] # [E0171] VARIATION SELECTOR-130
+E0172 ; [.0000.0000.0000.0000] # [E0172] VARIATION SELECTOR-131
+E0173 ; [.0000.0000.0000.0000] # [E0173] VARIATION SELECTOR-132
+E0174 ; [.0000.0000.0000.0000] # [E0174] VARIATION SELECTOR-133
+E0175 ; [.0000.0000.0000.0000] # [E0175] VARIATION SELECTOR-134
+E0176 ; [.0000.0000.0000.0000] # [E0176] VARIATION SELECTOR-135
+E0177 ; [.0000.0000.0000.0000] # [E0177] VARIATION SELECTOR-136
+E0178 ; [.0000.0000.0000.0000] # [E0178] VARIATION SELECTOR-137
+E0179 ; [.0000.0000.0000.0000] # [E0179] VARIATION SELECTOR-138
+E017A ; [.0000.0000.0000.0000] # [E017A] VARIATION SELECTOR-139
+E017B ; [.0000.0000.0000.0000] # [E017B] VARIATION SELECTOR-140
+E017C ; [.0000.0000.0000.0000] # [E017C] VARIATION SELECTOR-141
+E017D ; [.0000.0000.0000.0000] # [E017D] VARIATION SELECTOR-142
+E017E ; [.0000.0000.0000.0000] # [E017E] VARIATION SELECTOR-143
+E017F ; [.0000.0000.0000.0000] # [E017F] VARIATION SELECTOR-144
+E0180 ; [.0000.0000.0000.0000] # [E0180] VARIATION SELECTOR-145
+E0181 ; [.0000.0000.0000.0000] # [E0181] VARIATION SELECTOR-146
+E0182 ; [.0000.0000.0000.0000] # [E0182] VARIATION SELECTOR-147
+E0183 ; [.0000.0000.0000.0000] # [E0183] VARIATION SELECTOR-148
+E0184 ; [.0000.0000.0000.0000] # [E0184] VARIATION SELECTOR-149
+E0185 ; [.0000.0000.0000.0000] # [E0185] VARIATION SELECTOR-150
+E0186 ; [.0000.0000.0000.0000] # [E0186] VARIATION SELECTOR-151
+E0187 ; [.0000.0000.0000.0000] # [E0187] VARIATION SELECTOR-152
+E0188 ; [.0000.0000.0000.0000] # [E0188] VARIATION SELECTOR-153
+E0189 ; [.0000.0000.0000.0000] # [E0189] VARIATION SELECTOR-154
+E018A ; [.0000.0000.0000.0000] # [E018A] VARIATION SELECTOR-155
+E018B ; [.0000.0000.0000.0000] # [E018B] VARIATION SELECTOR-156
+E018C ; [.0000.0000.0000.0000] # [E018C] VARIATION SELECTOR-157
+E018D ; [.0000.0000.0000.0000] # [E018D] VARIATION SELECTOR-158
+E018E ; [.0000.0000.0000.0000] # [E018E] VARIATION SELECTOR-159
+E018F ; [.0000.0000.0000.0000] # [E018F] VARIATION SELECTOR-160
+E0190 ; [.0000.0000.0000.0000] # [E0190] VARIATION SELECTOR-161
+E0191 ; [.0000.0000.0000.0000] # [E0191] VARIATION SELECTOR-162
+E0192 ; [.0000.0000.0000.0000] # [E0192] VARIATION SELECTOR-163
+E0193 ; [.0000.0000.0000.0000] # [E0193] VARIATION SELECTOR-164
+E0194 ; [.0000.0000.0000.0000] # [E0194] VARIATION SELECTOR-165
+E0195 ; [.0000.0000.0000.0000] # [E0195] VARIATION SELECTOR-166
+E0196 ; [.0000.0000.0000.0000] # [E0196] VARIATION SELECTOR-167
+E0197 ; [.0000.0000.0000.0000] # [E0197] VARIATION SELECTOR-168
+E0198 ; [.0000.0000.0000.0000] # [E0198] VARIATION SELECTOR-169
+E0199 ; [.0000.0000.0000.0000] # [E0199] VARIATION SELECTOR-170
+E019A ; [.0000.0000.0000.0000] # [E019A] VARIATION SELECTOR-171
+E019B ; [.0000.0000.0000.0000] # [E019B] VARIATION SELECTOR-172
+E019C ; [.0000.0000.0000.0000] # [E019C] VARIATION SELECTOR-173
+E019D ; [.0000.0000.0000.0000] # [E019D] VARIATION SELECTOR-174
+E019E ; [.0000.0000.0000.0000] # [E019E] VARIATION SELECTOR-175
+E019F ; [.0000.0000.0000.0000] # [E019F] VARIATION SELECTOR-176
+E01A0 ; [.0000.0000.0000.0000] # [E01A0] VARIATION SELECTOR-177
+E01A1 ; [.0000.0000.0000.0000] # [E01A1] VARIATION SELECTOR-178
+E01A2 ; [.0000.0000.0000.0000] # [E01A2] VARIATION SELECTOR-179
+E01A3 ; [.0000.0000.0000.0000] # [E01A3] VARIATION SELECTOR-180
+E01A4 ; [.0000.0000.0000.0000] # [E01A4] VARIATION SELECTOR-181
+E01A5 ; [.0000.0000.0000.0000] # [E01A5] VARIATION SELECTOR-182
+E01A6 ; [.0000.0000.0000.0000] # [E01A6] VARIATION SELECTOR-183
+E01A7 ; [.0000.0000.0000.0000] # [E01A7] VARIATION SELECTOR-184
+E01A8 ; [.0000.0000.0000.0000] # [E01A8] VARIATION SELECTOR-185
+E01A9 ; [.0000.0000.0000.0000] # [E01A9] VARIATION SELECTOR-186
+E01AA ; [.0000.0000.0000.0000] # [E01AA] VARIATION SELECTOR-187
+E01AB ; [.0000.0000.0000.0000] # [E01AB] VARIATION SELECTOR-188
+E01AC ; [.0000.0000.0000.0000] # [E01AC] VARIATION SELECTOR-189
+E01AD ; [.0000.0000.0000.0000] # [E01AD] VARIATION SELECTOR-190
+E01AE ; [.0000.0000.0000.0000] # [E01AE] VARIATION SELECTOR-191
+E01AF ; [.0000.0000.0000.0000] # [E01AF] VARIATION SELECTOR-192
+E01B0 ; [.0000.0000.0000.0000] # [E01B0] VARIATION SELECTOR-193
+E01B1 ; [.0000.0000.0000.0000] # [E01B1] VARIATION SELECTOR-194
+E01B2 ; [.0000.0000.0000.0000] # [E01B2] VARIATION SELECTOR-195
+E01B3 ; [.0000.0000.0000.0000] # [E01B3] VARIATION SELECTOR-196
+E01B4 ; [.0000.0000.0000.0000] # [E01B4] VARIATION SELECTOR-197
+E01B5 ; [.0000.0000.0000.0000] # [E01B5] VARIATION SELECTOR-198
+E01B6 ; [.0000.0000.0000.0000] # [E01B6] VARIATION SELECTOR-199
+E01B7 ; [.0000.0000.0000.0000] # [E01B7] VARIATION SELECTOR-200
+E01B8 ; [.0000.0000.0000.0000] # [E01B8] VARIATION SELECTOR-201
+E01B9 ; [.0000.0000.0000.0000] # [E01B9] VARIATION SELECTOR-202
+E01BA ; [.0000.0000.0000.0000] # [E01BA] VARIATION SELECTOR-203
+E01BB ; [.0000.0000.0000.0000] # [E01BB] VARIATION SELECTOR-204
+E01BC ; [.0000.0000.0000.0000] # [E01BC] VARIATION SELECTOR-205
+E01BD ; [.0000.0000.0000.0000] # [E01BD] VARIATION SELECTOR-206
+E01BE ; [.0000.0000.0000.0000] # [E01BE] VARIATION SELECTOR-207
+E01BF ; [.0000.0000.0000.0000] # [E01BF] VARIATION SELECTOR-208
+E01C0 ; [.0000.0000.0000.0000] # [E01C0] VARIATION SELECTOR-209
+E01C1 ; [.0000.0000.0000.0000] # [E01C1] VARIATION SELECTOR-210
+E01C2 ; [.0000.0000.0000.0000] # [E01C2] VARIATION SELECTOR-211
+E01C3 ; [.0000.0000.0000.0000] # [E01C3] VARIATION SELECTOR-212
+E01C4 ; [.0000.0000.0000.0000] # [E01C4] VARIATION SELECTOR-213
+E01C5 ; [.0000.0000.0000.0000] # [E01C5] VARIATION SELECTOR-214
+E01C6 ; [.0000.0000.0000.0000] # [E01C6] VARIATION SELECTOR-215
+E01C7 ; [.0000.0000.0000.0000] # [E01C7] VARIATION SELECTOR-216
+E01C8 ; [.0000.0000.0000.0000] # [E01C8] VARIATION SELECTOR-217
+E01C9 ; [.0000.0000.0000.0000] # [E01C9] VARIATION SELECTOR-218
+E01CA ; [.0000.0000.0000.0000] # [E01CA] VARIATION SELECTOR-219
+E01CB ; [.0000.0000.0000.0000] # [E01CB] VARIATION SELECTOR-220
+E01CC ; [.0000.0000.0000.0000] # [E01CC] VARIATION SELECTOR-221
+E01CD ; [.0000.0000.0000.0000] # [E01CD] VARIATION SELECTOR-222
+E01CE ; [.0000.0000.0000.0000] # [E01CE] VARIATION SELECTOR-223
+E01CF ; [.0000.0000.0000.0000] # [E01CF] VARIATION SELECTOR-224
+E01D0 ; [.0000.0000.0000.0000] # [E01D0] VARIATION SELECTOR-225
+E01D1 ; [.0000.0000.0000.0000] # [E01D1] VARIATION SELECTOR-226
+E01D2 ; [.0000.0000.0000.0000] # [E01D2] VARIATION SELECTOR-227
+E01D3 ; [.0000.0000.0000.0000] # [E01D3] VARIATION SELECTOR-228
+E01D4 ; [.0000.0000.0000.0000] # [E01D4] VARIATION SELECTOR-229
+E01D5 ; [.0000.0000.0000.0000] # [E01D5] VARIATION SELECTOR-230
+E01D6 ; [.0000.0000.0000.0000] # [E01D6] VARIATION SELECTOR-231
+E01D7 ; [.0000.0000.0000.0000] # [E01D7] VARIATION SELECTOR-232
+E01D8 ; [.0000.0000.0000.0000] # [E01D8] VARIATION SELECTOR-233
+E01D9 ; [.0000.0000.0000.0000] # [E01D9] VARIATION SELECTOR-234
+E01DA ; [.0000.0000.0000.0000] # [E01DA] VARIATION SELECTOR-235
+E01DB ; [.0000.0000.0000.0000] # [E01DB] VARIATION SELECTOR-236
+E01DC ; [.0000.0000.0000.0000] # [E01DC] VARIATION SELECTOR-237
+E01DD ; [.0000.0000.0000.0000] # [E01DD] VARIATION SELECTOR-238
+E01DE ; [.0000.0000.0000.0000] # [E01DE] VARIATION SELECTOR-239
+E01DF ; [.0000.0000.0000.0000] # [E01DF] VARIATION SELECTOR-240
+E01E0 ; [.0000.0000.0000.0000] # [E01E0] VARIATION SELECTOR-241
+E01E1 ; [.0000.0000.0000.0000] # [E01E1] VARIATION SELECTOR-242
+E01E2 ; [.0000.0000.0000.0000] # [E01E2] VARIATION SELECTOR-243
+E01E3 ; [.0000.0000.0000.0000] # [E01E3] VARIATION SELECTOR-244
+E01E4 ; [.0000.0000.0000.0000] # [E01E4] VARIATION SELECTOR-245
+E01E5 ; [.0000.0000.0000.0000] # [E01E5] VARIATION SELECTOR-246
+E01E6 ; [.0000.0000.0000.0000] # [E01E6] VARIATION SELECTOR-247
+E01E7 ; [.0000.0000.0000.0000] # [E01E7] VARIATION SELECTOR-248
+E01E8 ; [.0000.0000.0000.0000] # [E01E8] VARIATION SELECTOR-249
+E01E9 ; [.0000.0000.0000.0000] # [E01E9] VARIATION SELECTOR-250
+E01EA ; [.0000.0000.0000.0000] # [E01EA] VARIATION SELECTOR-251
+E01EB ; [.0000.0000.0000.0000] # [E01EB] VARIATION SELECTOR-252
+E01EC ; [.0000.0000.0000.0000] # [E01EC] VARIATION SELECTOR-253
+E01ED ; [.0000.0000.0000.0000] # [E01ED] VARIATION SELECTOR-254
+E01EE ; [.0000.0000.0000.0000] # [E01EE] VARIATION SELECTOR-255
+E01EF ; [.0000.0000.0000.0000] # [E01EF] VARIATION SELECTOR-256
+0009 ; [*0201.0020.0002.0009] # HORIZONTAL TABULATION (in 6429)
+000A ; [*0202.0020.0002.000A] # LINE FEED (in 6429)
+000B ; [*0203.0020.0002.000B] # VERTICAL TABULATION (in 6429)
+000C ; [*0204.0020.0002.000C] # FORM FEED (in 6429)
+000D ; [*0205.0020.0002.000D] # CARRIAGE RETURN (in 6429)
+0020 ; [*0209.0020.0002.0020] # SPACE
+0021 ; [*0257.0020.0002.0021] # EXCLAMATION MARK
+0022 ; [*02A7.0020.0002.0022] # QUOTATION MARK
+0023 ; [*0305.0020.0002.0023] # NUMBER SIGN
+0025 ; [*0306.0020.0002.0025] # PERCENT SIGN
+0026 ; [*0302.0020.0002.0026] # AMPERSAND
+0027 ; [*02A0.0020.0002.0027] # APOSTROPHE
+0028 ; [*02B1.0020.0002.0028] # LEFT PARENTHESIS
+0029 ; [*02B2.0020.0002.0029] # RIGHT PARENTHESIS
+002A ; [*02FB.0020.0002.002A] # ASTERISK
+002B ; [*04B8.0020.0002.002B] # PLUS SIGN
+002C ; [*0232.0020.0002.002C] # COMMA
+002D ; [*0222.0020.0002.002D] # HYPHEN-MINUS
+002E ; [*0266.0020.0002.002E] # FULL STOP
+002F ; [*02FF.0020.0002.002F] # SOLIDUS
+003A ; [*0241.0020.0002.003A] # COLON
+003B ; [*023E.0020.0002.003B] # SEMICOLON
+003C ; [*04BC.0020.0002.003C] # LESS-THAN SIGN
+003D ; [*04BD.0020.0002.003D] # EQUALS SIGN
+003E ; [*04BE.0020.0002.003E] # GREATER-THAN SIGN
+003F ; [*025C.0020.0002.003F] # QUESTION MARK
+0040 ; [*02FA.0020.0002.0040] # COMMERCIAL AT
+005B ; [*02B3.0020.0002.005B] # LEFT SQUARE BRACKET
+005C ; [*0301.0020.0002.005C] # REVERSE SOLIDUS
+005D ; [*02B4.0020.0002.005D] # RIGHT SQUARE BRACKET
+005E ; [*0210.0020.0002.005E] # CIRCUMFLEX ACCENT
+005F ; [*021C.0020.0002.005F] # LOW LINE
+0060 ; [*020D.0020.0002.0060] # GRAVE ACCENT
+007B ; [*02B5.0020.0002.007B] # LEFT CURLY BRACKET
+007C ; [*04C0.0020.0002.007C] # VERTICAL LINE
+007D ; [*02B6.0020.0002.007D] # RIGHT CURLY BRACKET
+007E ; [*04C3.0020.0002.007E] # TILDE
+0085 ; [*0206.0020.0002.0085] # NEXT LINE (in 6429)
+00A0 ; [*0209.0020.001B.00A0] # NO-BREAK SPACE; QQK
+00A1 ; [*0258.0020.0002.00A1] # INVERTED EXCLAMATION MARK
+00A6 ; [*04C1.0020.0002.00A6] # BROKEN BAR
+00A7 ; [*02F5.0020.0002.00A7] # SECTION SIGN
+00A8 ; [*0215.0020.0002.00A8] # DIAERESIS
+00A9 ; [*02F8.0020.0002.00A9] # COPYRIGHT SIGN
+00AB ; [*02AF.0020.0002.00AB] # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+00AC ; [*04BF.0020.0002.00AC] # NOT SIGN
+00AD ; [*0221.0020.0002.00AD] # SOFT HYPHEN
+00AE ; [*02F9.0020.0002.00AE] # REGISTERED SIGN
+00AF ; [*0211.0020.0002.00AF] # MACRON
+00B0 ; [*03BF.0020.0002.00B0] # DEGREE SIGN
+00B1 ; [*04B9.0020.0002.00B1] # PLUS-MINUS SIGN
+00B4 ; [*020E.0020.0002.00B4] # ACUTE ACCENT
+00B6 ; [*02F6.0020.0002.00B6] # PILCROW SIGN
+00B7 ; [*0273.0020.0002.00B7] # MIDDLE DOT
+00B8 ; [*021A.0020.0002.00B8] # CEDILLA
+00BB ; [*02B0.0020.0002.00BB] # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+00BF ; [*025D.0020.0002.00BF] # INVERTED QUESTION MARK
+00D7 ; [*04BB.0020.0002.00D7] # MULTIPLICATION SIGN
+00F7 ; [*04BA.0020.0002.00F7] # DIVISION SIGN
+02B9 ; [*0365.0020.0002.02B9] # MODIFIER LETTER PRIME
+02BA ; [*0367.0020.0002.02BA] # MODIFIER LETTER DOUBLE PRIME
+02C2 ; [*0368.0020.0002.02C2] # MODIFIER LETTER LEFT ARROWHEAD
+02C3 ; [*0369.0020.0002.02C3] # MODIFIER LETTER RIGHT ARROWHEAD
+02C4 ; [*036A.0020.0002.02C4] # MODIFIER LETTER UP ARROWHEAD
+02C5 ; [*036B.0020.0002.02C5] # MODIFIER LETTER DOWN ARROWHEAD
+02C6 ; [*036C.0020.0002.02C6] # MODIFIER LETTER CIRCUMFLEX ACCENT
+02C7 ; [*036D.0020.0002.02C7] # CARON
+02C8 ; [*036E.0020.0002.02C8] # MODIFIER LETTER VERTICAL LINE
+02C9 ; [*036F.0020.0002.02C9] # MODIFIER LETTER MACRON
+02CA ; [*0370.0020.0002.02CA] # MODIFIER LETTER ACUTE ACCENT
+02CB ; [*0371.0020.0002.02CB] # MODIFIER LETTER GRAVE ACCENT
+02CC ; [*0372.0020.0002.02CC] # MODIFIER LETTER LOW VERTICAL LINE
+02CD ; [*0373.0020.0002.02CD] # MODIFIER LETTER LOW MACRON
+02CE ; [*0374.0020.0002.02CE] # MODIFIER LETTER LOW GRAVE ACCENT
+02CF ; [*0375.0020.0002.02CF] # MODIFIER LETTER LOW ACUTE ACCENT
+02D2 ; [*0376.0020.0002.02D2] # MODIFIER LETTER CENTRED RIGHT HALF RING
+02D3 ; [*0377.0020.0002.02D3] # MODIFIER LETTER CENTRED LEFT HALF RING
+02D4 ; [*0378.0020.0002.02D4] # MODIFIER LETTER UP TACK
+02D5 ; [*0379.0020.0002.02D5] # MODIFIER LETTER DOWN TACK
+02D6 ; [*037A.0020.0002.02D6] # MODIFIER LETTER PLUS SIGN
+02D7 ; [*037B.0020.0002.02D7] # MODIFIER LETTER MINUS SIGN
+02D8 ; [*0213.0020.0002.02D8] # BREVE
+02D9 ; [*0214.0020.0002.02D9] # DOT ABOVE
+02DA ; [*0216.0020.0002.02DA] # RING ABOVE
+02DB ; [*021B.0020.0002.02DB] # OGONEK
+02DC ; [*020F.0020.0002.02DC] # SMALL TILDE
+02DD ; [*0217.0020.0002.02DD] # DOUBLE ACUTE ACCENT
+02DE ; [*037C.0020.0002.02DE] # MODIFIER LETTER RHOTIC HOOK
+02DF ; [*037D.0020.0002.02DF] # MODIFIER LETTER CROSS ACCENT
+02E5 ; [*037E.0020.0002.02E5] # MODIFIER LETTER EXTRA-HIGH TONE BAR
+02E6 ; [*037F.0020.0002.02E6] # MODIFIER LETTER HIGH TONE BAR
+02E7 ; [*0380.0020.0002.02E7] # MODIFIER LETTER MID TONE BAR
+02E8 ; [*0381.0020.0002.02E8] # MODIFIER LETTER LOW TONE BAR
+02E9 ; [*0382.0020.0002.02E9] # MODIFIER LETTER EXTRA-LOW TONE BAR
+02EA ; [*0383.0020.0002.02EA] # MODIFIER LETTER YIN DEPARTING TONE MARK
+02EB ; [*0384.0020.0002.02EB] # MODIFIER LETTER YANG DEPARTING TONE MARK
+02EC ; [*0385.0020.0002.02EC] # MODIFIER LETTER VOICING
+02ED ; [*0386.0020.0002.02ED] # MODIFIER LETTER UNASPIRATED
+02EF ; [*0387.0020.0002.02EF] # MODIFIER LETTER LOW DOWN ARROWHEAD
+02F0 ; [*0388.0020.0002.02F0] # MODIFIER LETTER LOW UP ARROWHEAD
+02F1 ; [*0389.0020.0002.02F1] # MODIFIER LETTER LOW LEFT ARROWHEAD
+02F2 ; [*038A.0020.0002.02F2] # MODIFIER LETTER LOW RIGHT ARROWHEAD
+02F3 ; [*038B.0020.0002.02F3] # MODIFIER LETTER LOW RING
+02F4 ; [*038C.0020.0002.02F4] # MODIFIER LETTER MIDDLE GRAVE ACCENT
+02F5 ; [*038D.0020.0002.02F5] # MODIFIER LETTER MIDDLE DOUBLE GRAVE ACCENT
+02F6 ; [*038E.0020.0002.02F6] # MODIFIER LETTER MIDDLE DOUBLE ACUTE ACCENT
+02F7 ; [*038F.0020.0002.02F7] # MODIFIER LETTER LOW TILDE
+02F8 ; [*0390.0020.0002.02F8] # MODIFIER LETTER RAISED COLON
+02F9 ; [*0391.0020.0002.02F9] # MODIFIER LETTER BEGIN HIGH TONE
+02FA ; [*0392.0020.0002.02FA] # MODIFIER LETTER END HIGH TONE
+02FB ; [*0393.0020.0002.02FB] # MODIFIER LETTER BEGIN LOW TONE
+02FC ; [*0394.0020.0002.02FC] # MODIFIER LETTER END LOW TONE
+02FD ; [*0395.0020.0002.02FD] # MODIFIER LETTER SHELF
+02FE ; [*0396.0020.0002.02FE] # MODIFIER LETTER OPEN SHELF
+02FF ; [*0397.0020.0002.02FF] # MODIFIER LETTER LOW LEFT ARROW
+034F ; [.0000.0000.0000.034F] # COMBINING GRAPHEME JOINER
+0374 ; [*0365.0020.0002.0374] # GREEK NUMERAL SIGN; QQC
+0375 ; [*0366.0020.0002.0375] # GREEK LOWER NUMERAL SIGN
+037E ; [*023E.0020.0002.037E] # GREEK QUESTION MARK; QQC
+0384 ; [*020E.0020.0002.0384] # GREEK TONOS; QQC
+0385 ; [*0215.0020.0002.00A8][.0000.0032.0002.0301] # GREEK DIALYTIKA TONOS; QQCM
+0387 ; [*0273.0020.0002.0387] # GREEK ANO TELEIA; QQC
+03F6 ; [*04B3.0020.0002.03F6] # GREEK REVERSED LUNATE EPSILON SYMBOL
+0482 ; [*03C0.0020.0002.0482] # CYRILLIC THOUSANDS SIGN
+0488 ; [.0000.0000.0000.0488] # COMBINING CYRILLIC HUNDRED THOUSANDS SIGN
+0489 ; [.0000.0000.0000.0489] # COMBINING CYRILLIC MILLIONS SIGN
+055A ; [*032E.0020.0002.055A] # ARMENIAN APOSTROPHE
+055B ; [*032F.0020.0002.055B] # ARMENIAN EMPHASIS MARK
+055C ; [*0259.0020.0002.055C] # ARMENIAN EXCLAMATION MARK
+055D ; [*0233.0020.0002.055D] # ARMENIAN COMMA
+055E ; [*025E.0020.0002.055E] # ARMENIAN QUESTION MARK
+055F ; [*0330.0020.0002.055F] # ARMENIAN ABBREVIATION MARK
+0589 ; [*0242.0020.0002.0589] # ARMENIAN FULL STOP
+058A ; [*0223.0020.0002.058A] # ARMENIAN HYPHEN
+0591 ; [.0000.0000.0000.0591] # HEBREW ACCENT ETNAHTA
+0592 ; [.0000.0000.0000.0592] # HEBREW ACCENT SEGOL
+0593 ; [.0000.0000.0000.0593] # HEBREW ACCENT SHALSHELET
+0594 ; [.0000.0000.0000.0594] # HEBREW ACCENT ZAQEF QATAN
+0595 ; [.0000.0000.0000.0595] # HEBREW ACCENT ZAQEF GADOL
+0596 ; [.0000.0000.0000.0596] # HEBREW ACCENT TIPEHA
+0597 ; [.0000.0000.0000.0597] # HEBREW ACCENT REVIA
+0598 ; [.0000.0000.0000.0598] # HEBREW ACCENT ZARQA
+0599 ; [.0000.0000.0000.0599] # HEBREW ACCENT PASHTA
+059A ; [.0000.0000.0000.059A] # HEBREW ACCENT YETIV
+059B ; [.0000.0000.0000.059B] # HEBREW ACCENT TEVIR
+059C ; [.0000.0000.0000.059C] # HEBREW ACCENT GERESH
+059D ; [.0000.0000.0000.059D] # HEBREW ACCENT GERESH MUQDAM
+059E ; [.0000.0000.0000.059E] # HEBREW ACCENT GERSHAYIM
+059F ; [.0000.0000.0000.059F] # HEBREW ACCENT QARNEY PARA
+05A0 ; [.0000.0000.0000.05A0] # HEBREW ACCENT TELISHA GEDOLA
+05A1 ; [.0000.0000.0000.05A1] # HEBREW ACCENT PAZER
+05A2 ; [.0000.0000.0000.05A2] # HEBREW ACCENT ATNAH HAFUKH
+05A3 ; [.0000.0000.0000.05A3] # HEBREW ACCENT MUNAH
+05A4 ; [.0000.0000.0000.05A4] # HEBREW ACCENT MAHAPAKH
+05A5 ; [.0000.0000.0000.05A5] # HEBREW ACCENT MERKHA
+05A6 ; [.0000.0000.0000.05A6] # HEBREW ACCENT MERKHA KEFULA
+05A7 ; [.0000.0000.0000.05A7] # HEBREW ACCENT DARGA
+05A8 ; [.0000.0000.0000.05A8] # HEBREW ACCENT QADMA
+05A9 ; [.0000.0000.0000.05A9] # HEBREW ACCENT TELISHA QETANA
+05AA ; [.0000.0000.0000.05AA] # HEBREW ACCENT YERAH BEN YOMO
+05AB ; [.0000.0000.0000.05AB] # HEBREW ACCENT OLE
+05AC ; [.0000.0000.0000.05AC] # HEBREW ACCENT ILUY
+05AD ; [.0000.0000.0000.05AD] # HEBREW ACCENT DEHI
+05AE ; [.0000.0000.0000.05AE] # HEBREW ACCENT ZINOR
+05AF ; [.0000.0000.0000.05AF] # HEBREW MARK MASORA CIRCLE
+05BD ; [.0000.0000.0000.05BD] # HEBREW POINT METEG
+05BE ; [*0331.0020.0002.05BE] # HEBREW PUNCTUATION MAQAF
+05C0 ; [*0332.0020.0002.05C0] # HEBREW PUNCTUATION PASEQ
+05C3 ; [*0333.0020.0002.05C3] # HEBREW PUNCTUATION SOF PASUQ
+05C4 ; [.0000.0000.0000.05C4] # HEBREW MARK UPPER DOT
+05C5 ; [.0000.0000.0000.05C5] # HEBREW MARK LOWER DOT
+05C6 ; [*0334.0020.0002.05C6] # HEBREW PUNCTUATION NUN HAFUKHA
+05F3 ; [*0335.0020.0002.05F3] # HEBREW PUNCTUATION GERESH
+05F4 ; [*0336.0020.0002.05F4] # HEBREW PUNCTUATION GERSHAYIM
+0600 ; [.0000.0000.0000.0600] # ARABIC NUMBER SIGN
+0601 ; [.0000.0000.0000.0601] # ARABIC SIGN SANAH
+0602 ; [.0000.0000.0000.0602] # ARABIC FOOTNOTE MARKER
+0603 ; [.0000.0000.0000.0603] # ARABIC SIGN SAFHA
+060C ; [*0234.0020.0002.060C] # ARABIC COMMA
+060D ; [*0235.0020.0002.060D] # ARABIC DATE SEPARATOR
+060E ; [*03C1.0020.0002.060E] # ARABIC POETIC VERSE SIGN
+060F ; [*03C2.0020.0002.060F] # ARABIC SIGN MISRA
+0610 ; [.0000.0000.0000.0610] # ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM
+0611 ; [.0000.0000.0000.0611] # ARABIC SIGN ALAYHE ASSALLAM
+0612 ; [.0000.0000.0000.0612] # ARABIC SIGN RAHMATULLAH ALAYHE
+0613 ; [.0000.0000.0000.0613] # ARABIC SIGN RADI ALLAHOU ANHU
+0614 ; [.0000.0000.0000.0614] # ARABIC SIGN TAKHALLUS
+0615 ; [.0000.0000.0000.0615] # ARABIC SMALL HIGH TAH
+061B ; [*023F.0020.0002.061B] # ARABIC SEMICOLON
+061E ; [*0243.0020.0002.061E] # ARABIC TRIPLE DOT PUNCTUATION MARK
+061F ; [*025F.0020.0002.061F] # ARABIC QUESTION MARK
+0640 ; [*020B.0020.0002.0640] # ARABIC TATWEEL
+066A ; [*0307.0020.0002.066A] # ARABIC PERCENT SIGN
+066B ; [*0236.0020.0002.066B] # ARABIC DECIMAL SEPARATOR
+066C ; [*0237.0020.0002.066C] # ARABIC THOUSANDS SEPARATOR
+066D ; [*02FE.0020.0002.066D] # ARABIC FIVE POINTED STAR
+06D4 ; [*0268.0020.0002.06D4] # ARABIC FULL STOP
+06D6 ; [.0000.0000.0000.06D6] # ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA
+06D7 ; [.0000.0000.0000.06D7] # ARABIC SMALL HIGH LIGATURE QAF WITH LAM WITH ALEF MAKSURA
+06D8 ; [.0000.0000.0000.06D8] # ARABIC SMALL HIGH MEEM INITIAL FORM
+06D9 ; [.0000.0000.0000.06D9] # ARABIC SMALL HIGH LAM ALEF
+06DA ; [.0000.0000.0000.06DA] # ARABIC SMALL HIGH JEEM
+06DB ; [.0000.0000.0000.06DB] # ARABIC SMALL HIGH THREE DOTS
+06DC ; [.0000.0000.0000.06DC] # ARABIC SMALL HIGH SEEN
+06DD ; [.0000.0000.0000.06DD] # ARABIC END OF AYAH
+06DE ; [.0000.0000.0000.06DE] # ARABIC START OF RUB EL HIZB
+06DF ; [.0000.0000.0000.06DF] # ARABIC SMALL HIGH ROUNDED ZERO
+06E0 ; [.0000.0000.0000.06E0] # ARABIC SMALL HIGH UPRIGHT RECTANGULAR ZERO
+06E1 ; [.0000.0000.0000.06E1] # ARABIC SMALL HIGH DOTLESS HEAD OF KHAH
+06E2 ; [.0000.0000.0000.06E2] # ARABIC SMALL HIGH MEEM ISOLATED FORM
+06E3 ; [.0000.0000.0000.06E3] # ARABIC SMALL LOW SEEN
+06E4 ; [.0000.0000.0000.06E4] # ARABIC SMALL HIGH MADDA
+06E7 ; [.0000.0000.0000.06E7] # ARABIC SMALL HIGH YEH
+06E8 ; [.0000.0000.0000.06E8] # ARABIC SMALL HIGH NOON
+06E9 ; [*03C3.0020.0002.06E9] # ARABIC PLACE OF SAJDAH
+06EA ; [.0000.0000.0000.06EA] # ARABIC EMPTY CENTRE LOW STOP
+06EB ; [.0000.0000.0000.06EB] # ARABIC EMPTY CENTRE HIGH STOP
+06EC ; [.0000.0000.0000.06EC] # ARABIC ROUNDED HIGH STOP WITH FILLED CENTRE
+06ED ; [.0000.0000.0000.06ED] # ARABIC SMALL LOW MEEM
+0700 ; [*0282.0020.0002.0700] # SYRIAC END OF PARAGRAPH
+0701 ; [*0269.0020.0002.0701] # SYRIAC SUPRALINEAR FULL STOP
+0702 ; [*026A.0020.0002.0702] # SYRIAC SUBLINEAR FULL STOP
+0703 ; [*0244.0020.0002.0703] # SYRIAC SUPRALINEAR COLON
+0704 ; [*0245.0020.0002.0704] # SYRIAC SUBLINEAR COLON
+0705 ; [*0246.0020.0002.0705] # SYRIAC HORIZONTAL COLON
+0706 ; [*0247.0020.0002.0706] # SYRIAC COLON SKEWED LEFT
+0707 ; [*0248.0020.0002.0707] # SYRIAC COLON SKEWED RIGHT
+0708 ; [*0249.0020.0002.0708] # SYRIAC SUPRALINEAR COLON SKEWED LEFT
+0709 ; [*0260.0020.0002.0709] # SYRIAC SUBLINEAR COLON SKEWED RIGHT
+070A ; [*0337.0020.0002.070A] # SYRIAC CONTRACTION
+070B ; [*0338.0020.0002.070B] # SYRIAC HARKLEAN OBELUS
+070C ; [*0339.0020.0002.070C] # SYRIAC HARKLEAN METOBELUS
+070D ; [*033A.0020.0002.070D] # SYRIAC HARKLEAN ASTERISCUS
+07F6 ; [*03C5.0020.0002.07F6] # NKO SYMBOL OO DENNEN
+07F7 ; [*0283.0020.0002.07F7] # NKO SYMBOL GBAKURUNEN
+07F8 ; [*0238.0020.0002.07F8] # NKO COMMA
+07F9 ; [*025A.0020.0002.07F9] # NKO EXCLAMATION MARK
+07FA ; [*020C.0020.0002.07FA] # NKO LAJANYALAN
+0964 ; [*0274.0020.0002.0964] # DEVANAGARI DANDA
+0965 ; [*0275.0020.0002.0965] # DEVANAGARI DOUBLE DANDA
+0970 ; [*033D.0020.0002.0970] # DEVANAGARI ABBREVIATION SIGN
+09F8 ; [*0F13.0020.0002.09F8] # BENGALI CURRENCY NUMERATOR ONE LESS THAN THE DENOMINATOR
+09F9 ; [*0F14.0020.0002.09F9] # BENGALI CURRENCY DENOMINATOR SIXTEEN
+09FA ; [*03C6.0020.0002.09FA] # BENGALI ISSHAR
+0B70 ; [*03C7.0020.0002.0B70] # ORIYA ISSHAR
+0BF0 ; [*0F15.0020.0002.0BF0] # TAMIL NUMBER TEN
+0BF1 ; [*0F16.0020.0002.0BF1] # TAMIL NUMBER ONE HUNDRED
+0BF2 ; [*0F17.0020.0002.0BF2] # TAMIL NUMBER ONE THOUSAND
+0BF3 ; [*03C8.0020.0002.0BF3] # TAMIL DAY SIGN
+0BF4 ; [*03C9.0020.0002.0BF4] # TAMIL MONTH SIGN
+0BF5 ; [*03CA.0020.0002.0BF5] # TAMIL YEAR SIGN
+0BF6 ; [*03CB.0020.0002.0BF6] # TAMIL DEBIT SIGN
+0BF7 ; [*03CC.0020.0002.0BF7] # TAMIL CREDIT SIGN
+0BF8 ; [*03CD.0020.0002.0BF8] # TAMIL AS ABOVE SIGN
+0BFA ; [*03CE.0020.0002.0BFA] # TAMIL NUMBER SIGN
+0CF1 ; [*03CF.0020.0002.0CF1] # KANNADA SIGN JIHVAMULIYA
+0CF2 ; [*03D0.0020.0002.0CF2] # KANNADA SIGN UPADHMANIYA
+0DF4 ; [*033E.0020.0002.0DF4] # SINHALA PUNCTUATION KUNDDALIYA
+0E4F ; [*03D5.0020.0002.0E4F] # THAI CHARACTER FONGMAN
+0E5A ; [*033F.0020.0002.0E5A] # THAI CHARACTER ANGKHANKHU
+0E5B ; [*0340.0020.0002.0E5B] # THAI CHARACTER KHOMUT
+0F01 ; [*03D6.0020.0002.0F01] # TIBETAN MARK GTER YIG MGO TRUNCATED A
+0F02 ; [*03D7.0020.0002.0F02] # TIBETAN MARK GTER YIG MGO -UM RNAM BCAD MA
+0F03 ; [*03D8.0020.0002.0F03] # TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA
+0F04 ; [*0341.0020.0002.0F04] # TIBETAN MARK INITIAL YIG MGO MDUN MA
+0F05 ; [*0342.0020.0002.0F05] # TIBETAN MARK CLOSING YIG MGO SGAB MA
+0F06 ; [*0343.0020.0002.0F06] # TIBETAN MARK CARET YIG MGO PHUR SHAD MA
+0F07 ; [*0344.0020.0002.0F07] # TIBETAN MARK YIG MGO TSHEG SHAD MA
+0F08 ; [*0345.0020.0002.0F08] # TIBETAN MARK SBRUL SHAD
+0F09 ; [*0346.0020.0002.0F09] # TIBETAN MARK BSKUR YIG MGO
+0F0A ; [*0347.0020.0002.0F0A] # TIBETAN MARK BKA- SHOG YIG MGO
+0F0B ; [*034A.0020.0002.0F0B] # TIBETAN MARK INTERSYLLABIC TSHEG
+0F0C ; [*034A.0020.001B.0F0C] # TIBETAN MARK DELIMITER TSHEG BSTAR; QQK
+0F0D ; [*034B.0020.0002.0F0D] # TIBETAN MARK SHAD
+0F0E ; [*034C.0020.0002.0F0E] # TIBETAN MARK NYIS SHAD
+0F0F ; [*034D.0020.0002.0F0F] # TIBETAN MARK TSHEG SHAD
+0F10 ; [*034E.0020.0002.0F10] # TIBETAN MARK NYIS TSHEG SHAD
+0F11 ; [*034F.0020.0002.0F11] # TIBETAN MARK RIN CHEN SPUNGS SHAD
+0F12 ; [*0350.0020.0002.0F12] # TIBETAN MARK RGYA GRAM SHAD
+0F13 ; [*03D9.0020.0002.0F13] # TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN
+0F14 ; [*0251.0020.0002.0F14] # TIBETAN MARK GTER TSHEG
+0F15 ; [*03DA.0020.0002.0F15] # TIBETAN LOGOTYPE SIGN CHAD RTAGS
+0F16 ; [*03DB.0020.0002.0F16] # TIBETAN LOGOTYPE SIGN LHAG RTAGS
+0F17 ; [*03DC.0020.0002.0F17] # TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS
+0F18 ; [.0000.0000.0000.0F18] # TIBETAN ASTROLOGICAL SIGN -KHYUD PA
+0F19 ; [.0000.0000.0000.0F19] # TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS
+0F1A ; [*03DD.0020.0002.0F1A] # TIBETAN SIGN RDEL DKAR GCIG
+0F1B ; [*03DE.0020.0002.0F1B] # TIBETAN SIGN RDEL DKAR GNYIS
+0F1C ; [*03DF.0020.0002.0F1C] # TIBETAN SIGN RDEL DKAR GSUM
+0F1D ; [*03E0.0020.0002.0F1D] # TIBETAN SIGN RDEL NAG GCIG
+0F1E ; [*03E1.0020.0002.0F1E] # TIBETAN SIGN RDEL NAG GNYIS
+0F1F ; [*03E2.0020.0002.0F1F] # TIBETAN SIGN RDEL DKAR RDEL NAG
+0F34 ; [*03E3.0020.0002.0F34] # TIBETAN MARK BSDUS RTAGS
+0F35 ; [.0000.0000.0000.0F35] # TIBETAN MARK NGAS BZUNG NYI ZLA
+0F36 ; [*03E4.0020.0002.0F36] # TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN
+0F37 ; [.0000.0000.0000.0F37] # TIBETAN MARK NGAS BZUNG SGOR RTAGS
+0F38 ; [*03E5.0020.0002.0F38] # TIBETAN MARK CHE MGO
+0F3A ; [*02B7.0020.0002.0F3A] # TIBETAN MARK GUG RTAGS GYON
+0F3B ; [*02B8.0020.0002.0F3B] # TIBETAN MARK GUG RTAGS GYAS
+0F3C ; [*02B9.0020.0002.0F3C] # TIBETAN MARK ANG KHANG GYON
+0F3D ; [*02BA.0020.0002.0F3D] # TIBETAN MARK ANG KHANG GYAS
+0F3E ; [*03E6.0020.0002.0F3E] # TIBETAN SIGN YAR TSHES
+0F3F ; [*03E7.0020.0002.0F3F] # TIBETAN SIGN MAR TSHES
+0F82 ; [.0000.0000.0000.0F82] # TIBETAN SIGN NYI ZLA NAA DA
+0F83 ; [.0000.0000.0000.0F83] # TIBETAN SIGN SNA LDAN
+0F85 ; [*0351.0020.0002.0F85] # TIBETAN MARK PALUTA
+0F86 ; [.0000.0000.0000.0F86] # TIBETAN SIGN LCI RTAGS
+0F87 ; [.0000.0000.0000.0F87] # TIBETAN SIGN YANG RTAGS
+0FBE ; [*03E8.0020.0002.0FBE] # TIBETAN KU RU KHA
+0FBF ; [*03E9.0020.0002.0FBF] # TIBETAN KU RU KHA BZHI MIG CAN
+0FC0 ; [*03EA.0020.0002.0FC0] # TIBETAN CANTILLATION SIGN HEAVY BEAT
+0FC1 ; [*03EB.0020.0002.0FC1] # TIBETAN CANTILLATION SIGN LIGHT BEAT
+0FC2 ; [*03EC.0020.0002.0FC2] # TIBETAN CANTILLATION SIGN CANG TE-U
+0FC3 ; [*03ED.0020.0002.0FC3] # TIBETAN CANTILLATION SIGN SBUB -CHAL
+0FC4 ; [*03EE.0020.0002.0FC4] # TIBETAN SYMBOL DRIL BU
+0FC5 ; [*03EF.0020.0002.0FC5] # TIBETAN SYMBOL RDO RJE
+0FC6 ; [.0000.0000.0000.0FC6] # TIBETAN SYMBOL PADMA GDAN
+0FC7 ; [*03F0.0020.0002.0FC7] # TIBETAN SYMBOL RDO RJE RGYA GRAM
+0FC8 ; [*03F1.0020.0002.0FC8] # TIBETAN SYMBOL PHUR PA
+0FC9 ; [*03F2.0020.0002.0FC9] # TIBETAN SYMBOL NOR BU
+0FCA ; [*03F3.0020.0002.0FCA] # TIBETAN SYMBOL NOR BU NYIS -KHYIL
+0FCB ; [*03F4.0020.0002.0FCB] # TIBETAN SYMBOL NOR BU GSUM -KHYIL
+0FCC ; [*03F5.0020.0002.0FCC] # TIBETAN SYMBOL NOR BU BZHI -KHYIL
+0FCF ; [*03F6.0020.0002.0FCF] # TIBETAN SIGN RDEL NAG GSUM
+0FD0 ; [*0348.0020.0002.0FD0] # TIBETAN MARK BSKA- SHOG GI MGO RGYAN
+0FD1 ; [*0349.0020.0002.0FD1] # TIBETAN MARK MNYAM YIG GI MGO RGYAN
+104A ; [*027A.0020.0002.104A] # MYANMAR SIGN LITTLE SECTION
+104B ; [*027B.0020.0002.104B] # MYANMAR SIGN SECTION
+104C ; [*0353.0020.0002.104C] # MYANMAR SYMBOL LOCATIVE
+104D ; [*0354.0020.0002.104D] # MYANMAR SYMBOL COMPLETED
+104E ; [*0355.0020.0002.104E] # MYANMAR SYMBOL AFOREMENTIONED
+104F ; [*0356.0020.0002.104F] # MYANMAR SYMBOL GENITIVE
+10FB ; [*0284.0020.0002.10FB] # GEORGIAN PARAGRAPH SEPARATOR
+1360 ; [*0285.0020.0002.1360] # ETHIOPIC SECTION MARK
+1361 ; [*024A.0020.0002.1361] # ETHIOPIC WORDSPACE
+1362 ; [*026B.0020.0002.1362] # ETHIOPIC FULL STOP
+1363 ; [*024B.0020.0002.1363] # ETHIOPIC COMMA
+1364 ; [*024C.0020.0002.1364] # ETHIOPIC SEMICOLON
+1365 ; [*024D.0020.0002.1365] # ETHIOPIC COLON
+1366 ; [*024E.0020.0002.1366] # ETHIOPIC PREFACE COLON
+1367 ; [*0261.0020.0002.1367] # ETHIOPIC QUESTION MARK
+1368 ; [*0286.0020.0002.1368] # ETHIOPIC PARAGRAPH SEPARATOR
+1372 ; [*0F18.0020.0002.1372] # ETHIOPIC NUMBER TEN
+1373 ; [*0F19.0020.0002.1373] # ETHIOPIC NUMBER TWENTY
+1374 ; [*0F1A.0020.0002.1374] # ETHIOPIC NUMBER THIRTY
+1375 ; [*0F1B.0020.0002.1375] # ETHIOPIC NUMBER FORTY
+1376 ; [*0F1C.0020.0002.1376] # ETHIOPIC NUMBER FIFTY
+1377 ; [*0F1D.0020.0002.1377] # ETHIOPIC NUMBER SIXTY
+1378 ; [*0F1E.0020.0002.1378] # ETHIOPIC NUMBER SEVENTY
+1379 ; [*0F1F.0020.0002.1379] # ETHIOPIC NUMBER EIGHTY
+137A ; [*0F20.0020.0002.137A] # ETHIOPIC NUMBER NINETY
+137B ; [*0F21.0020.0002.137B] # ETHIOPIC NUMBER HUNDRED
+137C ; [*0F22.0020.0002.137C] # ETHIOPIC NUMBER TEN THOUSAND
+1390 ; [*0398.0020.0002.1390] # ETHIOPIC TONAL MARK YIZET
+1391 ; [*0399.0020.0002.1391] # ETHIOPIC TONAL MARK DERET
+1392 ; [*039A.0020.0002.1392] # ETHIOPIC TONAL MARK RIKRIK
+1393 ; [*039B.0020.0002.1393] # ETHIOPIC TONAL MARK SHORT RIKRIK
+1394 ; [*039C.0020.0002.1394] # ETHIOPIC TONAL MARK DIFAT
+1395 ; [*039D.0020.0002.1395] # ETHIOPIC TONAL MARK KENAT
+1396 ; [*039E.0020.0002.1396] # ETHIOPIC TONAL MARK CHIRET
+1397 ; [*039F.0020.0002.1397] # ETHIOPIC TONAL MARK HIDET
+1398 ; [*03A0.0020.0002.1398] # ETHIOPIC TONAL MARK DERET-HIDET
+1399 ; [*03A1.0020.0002.1399] # ETHIOPIC TONAL MARK KURT
+166D ; [*035B.0020.0002.166D] # CANADIAN SYLLABICS CHI SIGN
+166E ; [*026E.0020.0002.166E] # CANADIAN SYLLABICS FULL STOP
+1680 ; [*020A.0020.0002.1680] # OGHAM SPACE MARK
+169B ; [*02BB.0020.0002.169B] # OGHAM FEATHER MARK
+169C ; [*02BC.0020.0002.169C] # OGHAM REVERSED FEATHER MARK
+16EB ; [*0254.0020.0002.16EB] # RUNIC SINGLE PUNCTUATION
+16EC ; [*0255.0020.0002.16EC] # RUNIC MULTIPLE PUNCTUATION
+16ED ; [*0256.0020.0002.16ED] # RUNIC CROSS PUNCTUATION
+1735 ; [*0278.0020.0002.1735] # PHILIPPINE SINGLE PUNCTUATION
+1736 ; [*0279.0020.0002.1736] # PHILIPPINE DOUBLE PUNCTUATION
+17D4 ; [*027C.0020.0002.17D4] # KHMER SIGN KHAN
+17D5 ; [*027D.0020.0002.17D5] # KHMER SIGN BARIYOOSAN
+17D6 ; [*0252.0020.0002.17D6] # KHMER SIGN CAMNUC PII KUUH
+17D7 ; [*0357.0020.0002.17D7] # KHMER SIGN LEK TOO
+17D8 ; [*0358.0020.0002.17D8] # KHMER SIGN BEYYAL
+17D9 ; [*0359.0020.0002.17D9] # KHMER SIGN PHNAEK MUAN
+17DA ; [*035A.0020.0002.17DA] # KHMER SIGN KOOMUUT
+1800 ; [*033B.0020.0002.1800] # MONGOLIAN BIRGA
+1801 ; [*0267.0020.0002.1801] # MONGOLIAN ELLIPSIS
+1802 ; [*0239.0020.0002.1802] # MONGOLIAN COMMA
+1803 ; [*026C.0020.0002.1803] # MONGOLIAN FULL STOP
+1804 ; [*024F.0020.0002.1804] # MONGOLIAN COLON
+1805 ; [*0250.0020.0002.1805] # MONGOLIAN FOUR DOTS
+1806 ; [*0225.0020.0002.1806] # MONGOLIAN TODO SOFT HYPHEN
+1807 ; [*0226.0020.0002.1807] # MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER
+1808 ; [*023A.0020.0002.1808] # MONGOLIAN MANCHU COMMA
+1809 ; [*026D.0020.0002.1809] # MONGOLIAN MANCHU FULL STOP
+180A ; [*033C.0020.0002.180A] # MONGOLIAN NIRUGU
+1940 ; [*0352.0020.0002.1940] # LIMBU SIGN LOO
+1944 ; [*025B.0020.0002.1944] # LIMBU EXCLAMATION MARK
+1945 ; [*0262.0020.0002.1945] # LIMBU QUESTION MARK
+19E0 ; [*03F7.0020.0002.19E0] # KHMER SYMBOL PATHAMASAT
+19E1 ; [*03F8.0020.0002.19E1] # KHMER SYMBOL MUOY KOET
+19E2 ; [*03F9.0020.0002.19E2] # KHMER SYMBOL PII KOET
+19E3 ; [*03FA.0020.0002.19E3] # KHMER SYMBOL BEI KOET
+19E4 ; [*03FB.0020.0002.19E4] # KHMER SYMBOL BUON KOET
+19E5 ; [*03FC.0020.0002.19E5] # KHMER SYMBOL PRAM KOET
+19E6 ; [*03FD.0020.0002.19E6] # KHMER SYMBOL PRAM-MUOY KOET
+19E7 ; [*03FE.0020.0002.19E7] # KHMER SYMBOL PRAM-PII KOET
+19E8 ; [*03FF.0020.0002.19E8] # KHMER SYMBOL PRAM-BEI KOET
+19E9 ; [*0400.0020.0002.19E9] # KHMER SYMBOL PRAM-BUON KOET
+19EA ; [*0401.0020.0002.19EA] # KHMER SYMBOL DAP KOET
+19EB ; [*0402.0020.0002.19EB] # KHMER SYMBOL DAP-MUOY KOET
+19EC ; [*0403.0020.0002.19EC] # KHMER SYMBOL DAP-PII KOET
+19ED ; [*0404.0020.0002.19ED] # KHMER SYMBOL DAP-BEI KOET
+19EE ; [*0405.0020.0002.19EE] # KHMER SYMBOL DAP-BUON KOET
+19EF ; [*0406.0020.0002.19EF] # KHMER SYMBOL DAP-PRAM KOET
+19F0 ; [*0407.0020.0002.19F0] # KHMER SYMBOL TUTEYASAT
+19F1 ; [*0408.0020.0002.19F1] # KHMER SYMBOL MUOY ROC
+19F2 ; [*0409.0020.0002.19F2] # KHMER SYMBOL PII ROC
+19F3 ; [*040A.0020.0002.19F3] # KHMER SYMBOL BEI ROC
+19F4 ; [*040B.0020.0002.19F4] # KHMER SYMBOL BUON ROC
+19F5 ; [*040C.0020.0002.19F5] # KHMER SYMBOL PRAM ROC
+19F6 ; [*040D.0020.0002.19F6] # KHMER SYMBOL PRAM-MUOY ROC
+19F7 ; [*040E.0020.0002.19F7] # KHMER SYMBOL PRAM-PII ROC
+19F8 ; [*040F.0020.0002.19F8] # KHMER SYMBOL PRAM-BEI ROC
+19F9 ; [*0410.0020.0002.19F9] # KHMER SYMBOL PRAM-BUON ROC
+19FA ; [*0411.0020.0002.19FA] # KHMER SYMBOL DAP ROC
+19FB ; [*0412.0020.0002.19FB] # KHMER SYMBOL DAP-MUOY ROC
+19FC ; [*0413.0020.0002.19FC] # KHMER SYMBOL DAP-PII ROC
+19FD ; [*0414.0020.0002.19FD] # KHMER SYMBOL DAP-BEI ROC
+19FE ; [*0415.0020.0002.19FE] # KHMER SYMBOL DAP-BUON ROC
+19FF ; [*0416.0020.0002.19FF] # KHMER SYMBOL DAP-PRAM ROC
+1A1E ; [*0287.0020.0002.1A1E] # BUGINESE PALLAWA
+1A1F ; [*0288.0020.0002.1A1F] # BUGINESE END OF SECTION
+1B5A ; [*0289.0020.0002.1B5A] # BALINESE PANTI
+1B5B ; [*028A.0020.0002.1B5B] # BALINESE PAMADA
+1B5C ; [*026F.0020.0002.1B5C] # BALINESE WINDU
+1B5D ; [*0253.0020.0002.1B5D] # BALINESE CARIK PAMUNGKAH
+1B5E ; [*027E.0020.0002.1B5E] # BALINESE CARIK SIKI
+1B5F ; [*027F.0020.0002.1B5F] # BALINESE CARIK PAREREN
+1B60 ; [*0224.0020.0002.1B60] # BALINESE PAMENENG
+1B61 ; [*0417.0020.0002.1B61] # BALINESE MUSICAL SYMBOL DONG
+1B62 ; [*0418.0020.0002.1B62] # BALINESE MUSICAL SYMBOL DENG
+1B63 ; [*0419.0020.0002.1B63] # BALINESE MUSICAL SYMBOL DUNG
+1B64 ; [*041A.0020.0002.1B64] # BALINESE MUSICAL SYMBOL DANG
+1B65 ; [*041B.0020.0002.1B65] # BALINESE MUSICAL SYMBOL DANG SURANG
+1B66 ; [*041C.0020.0002.1B66] # BALINESE MUSICAL SYMBOL DING
+1B67 ; [*041D.0020.0002.1B67] # BALINESE MUSICAL SYMBOL DAENG
+1B68 ; [*041E.0020.0002.1B68] # BALINESE MUSICAL SYMBOL DEUNG
+1B69 ; [*041F.0020.0002.1B69] # BALINESE MUSICAL SYMBOL DAING
+1B6A ; [*0420.0020.0002.1B6A] # BALINESE MUSICAL SYMBOL DANG GEDE
+1B6B ; [.0000.0000.0000.1B6B] # BALINESE MUSICAL SYMBOL COMBINING TEGEH
+1B6C ; [.0000.0000.0000.1B6C] # BALINESE MUSICAL SYMBOL COMBINING ENDEP
+1B6D ; [.0000.0000.0000.1B6D] # BALINESE MUSICAL SYMBOL COMBINING KEMPUL
+1B6E ; [.0000.0000.0000.1B6E] # BALINESE MUSICAL SYMBOL COMBINING KEMPLI
+1B6F ; [.0000.0000.0000.1B6F] # BALINESE MUSICAL SYMBOL COMBINING JEGOGAN
+1B70 ; [.0000.0000.0000.1B70] # BALINESE MUSICAL SYMBOL COMBINING KEMPUL WITH JEGOGAN
+1B71 ; [.0000.0000.0000.1B71] # BALINESE MUSICAL SYMBOL COMBINING KEMPLI WITH JEGOGAN
+1B72 ; [.0000.0000.0000.1B72] # BALINESE MUSICAL SYMBOL COMBINING BENDE
+1B73 ; [.0000.0000.0000.1B73] # BALINESE MUSICAL SYMBOL COMBINING GONG
+1B74 ; [*0421.0020.0002.1B74] # BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG
+1B75 ; [*0422.0020.0002.1B75] # BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DAG
+1B76 ; [*0423.0020.0002.1B76] # BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TUK
+1B77 ; [*0424.0020.0002.1B77] # BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TAK
+1B78 ; [*0425.0020.0002.1B78] # BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PANG
+1B79 ; [*0426.0020.0002.1B79] # BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PUNG
+1B7A ; [*0427.0020.0002.1B7A] # BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLAK
+1B7B ; [*0428.0020.0002.1B7B] # BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLUK
+1B7C ; [*0429.0020.0002.1B7C] # BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING
+1FBD ; [*0218.0020.0002.1FBD] # GREEK KORONIS; QQC
+1FBF ; [*0218.0020.0002.1FBF] # GREEK PSILI
+1FC0 ; [*021E.0020.0002.1FC0] # GREEK PERISPOMENI
+1FC1 ; [*0215.0020.0002.00A8][.0000.0045.0002.0342] # GREEK DIALYTIKA AND PERISPOMENI; QQCM
+1FCD ; [*0218.0020.0002.1FBF][.0000.0035.0002.0300] # GREEK PSILI AND VARIA; QQCM
+1FCE ; [*0218.0020.0002.1FBF][.0000.0032.0002.0301] # GREEK PSILI AND OXIA; QQCM
+1FCF ; [*0218.0020.0002.1FBF][.0000.0045.0002.0342] # GREEK PSILI AND PERISPOMENI; QQCM
+1FDD ; [*0219.0020.0002.1FFE][.0000.0035.0002.0300] # GREEK DASIA AND VARIA; QQCM
+1FDE ; [*0219.0020.0002.1FFE][.0000.0032.0002.0301] # GREEK DASIA AND OXIA; QQCM
+1FDF ; [*0219.0020.0002.1FFE][.0000.0045.0002.0342] # GREEK DASIA AND PERISPOMENI; QQCM
+1FED ; [*0215.0020.0002.00A8][.0000.0035.0002.0300] # GREEK DIALYTIKA AND VARIA; QQCM
+1FEE ; [*0215.0020.0002.00A8][.0000.0032.0002.0301] # GREEK DIALYTIKA AND OXIA; QQCM
+1FEF ; [*020D.0020.0002.1FEF] # GREEK VARIA; QQC
+1FFD ; [*020E.0020.0002.1FFD] # GREEK OXIA; QQC
+1FFE ; [*0219.0020.0002.1FFE] # GREEK DASIA
+2000 ; [*0209.0020.0004.2000] # EN QUAD; QQK
+2001 ; [*0209.0020.0004.2001] # EM QUAD; QQK
+2002 ; [*0209.0020.0004.2002] # EN SPACE; QQK
+2003 ; [*0209.0020.0004.2003] # EM SPACE; QQK
+2004 ; [*0209.0020.0004.2004] # THREE-PER-EM SPACE; QQK
+2005 ; [*0209.0020.0004.2005] # FOUR-PER-EM SPACE; QQK
+2006 ; [*0209.0020.0004.2006] # SIX-PER-EM SPACE; QQK
+2007 ; [*0209.0020.001B.2007] # FIGURE SPACE; QQK
+2008 ; [*0209.0020.0004.2008] # PUNCTUATION SPACE; QQK
+2009 ; [*0209.0020.0004.2009] # THIN SPACE; QQK
+200A ; [*0209.0020.0004.200A] # HAIR SPACE; QQK
+2010 ; [*0227.0020.0002.2010] # HYPHEN
+2011 ; [*0227.0020.001B.2011] # NON-BREAKING HYPHEN; QQK
+2012 ; [*0228.0020.0002.2012] # FIGURE DASH
+2013 ; [*0229.0020.0002.2013] # EN DASH
+2014 ; [*022A.0020.0002.2014] # EM DASH
+2015 ; [*022B.0020.0002.2015] # HORIZONTAL BAR
+2016 ; [*04C2.0020.0002.2016] # DOUBLE VERTICAL LINE
+2017 ; [*021D.0020.0002.2017] # DOUBLE LOW LINE
+2018 ; [*02A1.0020.0002.2018] # LEFT SINGLE QUOTATION MARK
+2019 ; [*02A2.0020.0002.2019] # RIGHT SINGLE QUOTATION MARK
+201A ; [*02A3.0020.0002.201A] # SINGLE LOW-9 QUOTATION MARK
+201B ; [*02A4.0020.0002.201B] # SINGLE HIGH-REVERSED-9 QUOTATION MARK
+201C ; [*02A8.0020.0002.201C] # LEFT DOUBLE QUOTATION MARK
+201D ; [*02A9.0020.0002.201D] # RIGHT DOUBLE QUOTATION MARK
+201E ; [*02AA.0020.0002.201E] # DOUBLE LOW-9 QUOTATION MARK
+201F ; [*02AB.0020.0002.201F] # DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+2020 ; [*030B.0020.0002.2020] # DAGGER
+2021 ; [*030C.0020.0002.2021] # DOUBLE DAGGER
+2022 ; [*030D.0020.0002.2022] # BULLET
+2023 ; [*030E.0020.0002.2023] # TRIANGULAR BULLET
+2024 ; [*0266.0020.0004.2024] # ONE DOT LEADER; QQK
+2025 ; [*0266.0020.0004.2025][*0266.0020.0004.2025] # TWO DOT LEADER; QQKN
+2026 ; [*0266.0020.0004.2026][*0266.0020.0004.2026][*0266.0020.001F.2026] # HORIZONTAL ELLIPSIS; QQKN
+2027 ; [*030F.0020.0002.2027] # HYPHENATION POINT
+2028 ; [*0207.0020.0002.2028] # LINE SEPARATOR
+2029 ; [*0208.0020.0002.2029] # PARAGRAPH SEPARATOR
+202F ; [*0209.0020.001B.202F] # NARROW NO-BREAK SPACE; QQK
+2030 ; [*0308.0020.0002.2030] # PER MILLE SIGN
+2031 ; [*0309.0020.0002.2031] # PER TEN THOUSAND SIGN
+2032 ; [*0313.0020.0002.2032] # PRIME
+2033 ; [*0313.0020.0004.2033][*0313.0020.0004.2033] # DOUBLE PRIME; QQKN
+2034 ; [*0313.0020.0004.2034][*0313.0020.0004.2034][*0313.0020.001F.2034] # TRIPLE PRIME; QQKN
+2035 ; [*0314.0020.0002.2035] # REVERSED PRIME
+2036 ; [*0314.0020.0004.2036][*0314.0020.0004.2036] # REVERSED DOUBLE PRIME; QQKN
+2037 ; [*0314.0020.0004.2037][*0314.0020.0004.2037][*0314.0020.001F.2037] # REVERSED TRIPLE PRIME; QQKN
+2038 ; [*0317.0020.0002.2038] # CARET
+2039 ; [*02A5.0020.0002.2039] # SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+203A ; [*02A6.0020.0002.203A] # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+203B ; [*0318.0020.0002.203B] # REFERENCE MARK
+203C ; [*0257.0020.0004.203C][*0257.0020.0004.203C] # DOUBLE EXCLAMATION MARK; QQKN
+203D ; [*0265.0020.0002.203D] # INTERROBANG
+203E ; [*0212.0020.0002.203E] # OVERLINE
+203F ; [*0319.0020.0002.203F] # UNDERTIE
+2040 ; [*031B.0020.0002.2040] # CHARACTER TIE
+2041 ; [*031D.0020.0002.2041] # CARET INSERTION POINT
+2042 ; [*031E.0020.0002.2042] # ASTERISM
+2043 ; [*0310.0020.0002.2043] # HYPHEN BULLET
+2044 ; [*0300.0020.0002.2044] # FRACTION SLASH
+2045 ; [*02BD.0020.0002.2045] # LEFT SQUARE BRACKET WITH QUILL
+2046 ; [*02BE.0020.0002.2046] # RIGHT SQUARE BRACKET WITH QUILL
+2047 ; [*025C.0020.0004.2047][*025C.0020.0004.2047] # DOUBLE QUESTION MARK; QQKN
+2048 ; [*025C.0020.0004.2048][*0257.0020.0004.2048] # QUESTION EXCLAMATION MARK; QQKN
+2049 ; [*0257.0020.0004.2049][*025C.0020.0004.2049] # EXCLAMATION QUESTION MARK; QQKN
+204A ; [*0304.0020.0002.204A] # TIRONIAN SIGN ET
+204B ; [*02F7.0020.0002.204B] # REVERSED PILCROW SIGN
+204C ; [*0311.0020.0002.204C] # BLACK LEFTWARDS BULLET
+204D ; [*0312.0020.0002.204D] # BLACK RIGHTWARDS BULLET
+204E ; [*02FC.0020.0002.204E] # LOW ASTERISK
+204F ; [*0240.0020.0002.204F] # REVERSED SEMICOLON
+2050 ; [*031C.0020.0002.2050] # CLOSE UP
+2051 ; [*02FD.0020.0002.2051] # TWO ASTERISKS ALIGNED VERTICALLY
+2052 ; [*030A.0020.0002.2052] # COMMERCIAL MINUS SIGN
+2053 ; [*022C.0020.0002.2053] # SWUNG DASH
+2054 ; [*031A.0020.0002.2054] # INVERTED UNDERTIE
+2055 ; [*028B.0020.0002.2055] # FLOWER PUNCTUATION MARK
+2056 ; [*028C.0020.0002.2056] # THREE DOT PUNCTUATION
+2057 ; [*0313.0020.0004.2057][*0313.0020.0004.2057][*0313.0020.001F.2057][*0313.0020.001F.2057] # QUADRUPLE PRIME; QQKN
+2058 ; [*028D.0020.0002.2058] # FOUR DOT PUNCTUATION
+2059 ; [*028E.0020.0002.2059] # FIVE DOT PUNCTUATION
+205A ; [*028F.0020.0002.205A] # TWO DOT PUNCTUATION
+205B ; [*0290.0020.0002.205B] # FOUR DOT MARK
+205C ; [*0291.0020.0002.205C] # DOTTED CROSS
+205D ; [*0292.0020.0002.205D] # TRICOLON
+205E ; [*0293.0020.0002.205E] # VERTICAL FOUR DOTS
+205F ; [*0209.0020.0004.205F] # MEDIUM MATHEMATICAL SPACE; QQK
+2061 ; [.0000.0000.0000.2061] # FUNCTION APPLICATION
+2062 ; [.0000.0000.0000.2062] # INVISIBLE TIMES
+2063 ; [.0000.0000.0000.2063] # INVISIBLE SEPARATOR
+207A ; [*04B8.0020.0014.207A] # SUPERSCRIPT PLUS SIGN; QQK
+207B ; [*04C4.0020.0014.207B] # SUPERSCRIPT MINUS; QQK
+207C ; [*04BD.0020.0014.207C] # SUPERSCRIPT EQUALS SIGN; QQK
+207D ; [*02B1.0020.0014.207D] # SUPERSCRIPT LEFT PARENTHESIS; QQK
+207E ; [*02B2.0020.0014.207E] # SUPERSCRIPT RIGHT PARENTHESIS; QQK
+208A ; [*04B8.0020.0015.208A] # SUBSCRIPT PLUS SIGN; QQK
+208B ; [*04C4.0020.0015.208B] # SUBSCRIPT MINUS; QQK
+208C ; [*04BD.0020.0015.208C] # SUBSCRIPT EQUALS SIGN; QQK
+208D ; [*02B1.0020.0015.208D] # SUBSCRIPT LEFT PARENTHESIS; QQK
+208E ; [*02B2.0020.0015.208E] # SUBSCRIPT RIGHT PARENTHESIS; QQK
+2104 ; [*042A.0020.0002.2104] # CENTRE LINE SYMBOL
+2108 ; [*042B.0020.0002.2108] # SCRUPLE
+2114 ; [*042C.0020.0002.2114] # L B BAR SYMBOL
+2117 ; [*042D.0020.0002.2117] # SOUND RECORDING COPYRIGHT
+2118 ; [*042E.0020.0002.2118] # SCRIPT CAPITAL P
+211E ; [*042F.0020.0002.211E] # PRESCRIPTION TAKE
+211F ; [*0430.0020.0002.211F] # RESPONSE
+2123 ; [*0431.0020.0002.2123] # VERSICLE
+2125 ; [*0432.0020.0002.2125] # OUNCE SIGN
+2127 ; [*0433.0020.0002.2127] # INVERTED OHM SIGN
+2129 ; [*0434.0020.0002.2129] # TURNED GREEK SMALL LETTER IOTA
+212E ; [*0435.0020.0002.212E] # ESTIMATED SYMBOL
+213A ; [*0436.0020.0002.213A] # ROTATED CAPITAL Q
+2140 ; [*04B7.0020.0005.2140] # DOUBLE-STRUCK N-ARY SUMMATION; QQK
+2141 ; [*0437.0020.0002.2141] # TURNED SANS-SERIF CAPITAL G
+2142 ; [*0438.0020.0002.2142] # TURNED SANS-SERIF CAPITAL L
+2143 ; [*0439.0020.0002.2143] # REVERSED SANS-SERIF CAPITAL L
+2144 ; [*043A.0020.0002.2144] # TURNED SANS-SERIF CAPITAL Y
+214A ; [*043B.0020.0002.214A] # PROPERTY LINE
+214B ; [*0303.0020.0002.214B] # TURNED AMPERSAND
+214C ; [*043C.0020.0002.214C] # PER SIGN
+214D ; [*043D.0020.0002.214D] # AKTIESELSKAB
+2180 ; [*0F23.0020.0002.2180] # ROMAN NUMERAL ONE THOUSAND C D
+2181 ; [*0F24.0020.0002.2181] # ROMAN NUMERAL FIVE THOUSAND
+2182 ; [*0F25.0020.0002.2182] # ROMAN NUMERAL TEN THOUSAND
+2190 ; [*043E.0020.0002.2190] # LEFTWARDS ARROW
+2191 ; [*0440.0020.0002.2191] # UPWARDS ARROW
+2192 ; [*043F.0020.0002.2192] # RIGHTWARDS ARROW
+2193 ; [*0441.0020.0002.2193] # DOWNWARDS ARROW
+2194 ; [*0442.0020.0002.2194] # LEFT RIGHT ARROW
+2195 ; [*0443.0020.0002.2195] # UP DOWN ARROW
+2196 ; [*0444.0020.0002.2196] # NORTH WEST ARROW
+2197 ; [*0445.0020.0002.2197] # NORTH EAST ARROW
+2198 ; [*0446.0020.0002.2198] # SOUTH EAST ARROW
+2199 ; [*0447.0020.0002.2199] # SOUTH WEST ARROW
+219A ; [*043E.0020.0002.2190][.0000.0054.0002.0338] # LEFTWARDS ARROW WITH STROKE; QQCM
+219B ; [*043F.0020.0002.2192][.0000.0054.0002.0338] # RIGHTWARDS ARROW WITH STROKE; QQCM
+219C ; [*0448.0020.0002.219C] # LEFTWARDS WAVE ARROW
+219D ; [*0449.0020.0002.219D] # RIGHTWARDS WAVE ARROW
+219E ; [*044A.0020.0002.219E] # LEFTWARDS TWO HEADED ARROW
+219F ; [*044B.0020.0002.219F] # UPWARDS TWO HEADED ARROW
+21A0 ; [*044C.0020.0002.21A0] # RIGHTWARDS TWO HEADED ARROW
+21A1 ; [*044D.0020.0002.21A1] # DOWNWARDS TWO HEADED ARROW
+21A2 ; [*044E.0020.0002.21A2] # LEFTWARDS ARROW WITH TAIL
+21A3 ; [*044F.0020.0002.21A3] # RIGHTWARDS ARROW WITH TAIL
+21A4 ; [*0450.0020.0002.21A4] # LEFTWARDS ARROW FROM BAR
+21A5 ; [*0451.0020.0002.21A5] # UPWARDS ARROW FROM BAR
+21A6 ; [*0452.0020.0002.21A6] # RIGHTWARDS ARROW FROM BAR
+21A7 ; [*0453.0020.0002.21A7] # DOWNWARDS ARROW FROM BAR
+21A8 ; [*0454.0020.0002.21A8] # UP DOWN ARROW WITH BASE
+21A9 ; [*0455.0020.0002.21A9] # LEFTWARDS ARROW WITH HOOK
+21AA ; [*0456.0020.0002.21AA] # RIGHTWARDS ARROW WITH HOOK
+21AB ; [*0457.0020.0002.21AB] # LEFTWARDS ARROW WITH LOOP
+21AC ; [*0458.0020.0002.21AC] # RIGHTWARDS ARROW WITH LOOP
+21AD ; [*0459.0020.0002.21AD] # LEFT RIGHT WAVE ARROW
+21AE ; [*0442.0020.0002.2194][.0000.0054.0002.0338] # LEFT RIGHT ARROW WITH STROKE; QQCM
+21AF ; [*045A.0020.0002.21AF] # DOWNWARDS ZIGZAG ARROW
+21B0 ; [*045B.0020.0002.21B0] # UPWARDS ARROW WITH TIP LEFTWARDS
+21B1 ; [*045C.0020.0002.21B1] # UPWARDS ARROW WITH TIP RIGHTWARDS
+21B2 ; [*045D.0020.0002.21B2] # DOWNWARDS ARROW WITH TIP LEFTWARDS
+21B3 ; [*045E.0020.0002.21B3] # DOWNWARDS ARROW WITH TIP RIGHTWARDS
+21B4 ; [*045F.0020.0002.21B4] # RIGHTWARDS ARROW WITH CORNER DOWNWARDS
+21B5 ; [*0460.0020.0002.21B5] # DOWNWARDS ARROW WITH CORNER LEFTWARDS
+21B6 ; [*0461.0020.0002.21B6] # ANTICLOCKWISE TOP SEMICIRCLE ARROW
+21B7 ; [*0462.0020.0002.21B7] # CLOCKWISE TOP SEMICIRCLE ARROW
+21B8 ; [*0463.0020.0002.21B8] # NORTH WEST ARROW TO LONG BAR
+21B9 ; [*0464.0020.0002.21B9] # LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR
+21BA ; [*0465.0020.0002.21BA] # ANTICLOCKWISE OPEN CIRCLE ARROW
+21BB ; [*0466.0020.0002.21BB] # CLOCKWISE OPEN CIRCLE ARROW
+21BC ; [*0467.0020.0002.21BC] # LEFTWARDS HARPOON WITH BARB UPWARDS
+21BD ; [*0468.0020.0002.21BD] # LEFTWARDS HARPOON WITH BARB DOWNWARDS
+21BE ; [*0469.0020.0002.21BE] # UPWARDS HARPOON WITH BARB RIGHTWARDS
+21BF ; [*046A.0020.0002.21BF] # UPWARDS HARPOON WITH BARB LEFTWARDS
+21C0 ; [*046B.0020.0002.21C0] # RIGHTWARDS HARPOON WITH BARB UPWARDS
+21C1 ; [*046C.0020.0002.21C1] # RIGHTWARDS HARPOON WITH BARB DOWNWARDS
+21C2 ; [*046D.0020.0002.21C2] # DOWNWARDS HARPOON WITH BARB RIGHTWARDS
+21C3 ; [*046E.0020.0002.21C3] # DOWNWARDS HARPOON WITH BARB LEFTWARDS
+21C4 ; [*046F.0020.0002.21C4] # RIGHTWARDS ARROW OVER LEFTWARDS ARROW
+21C5 ; [*0470.0020.0002.21C5] # UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW
+21C6 ; [*0471.0020.0002.21C6] # LEFTWARDS ARROW OVER RIGHTWARDS ARROW
+21C7 ; [*0472.0020.0002.21C7] # LEFTWARDS PAIRED ARROWS
+21C8 ; [*0473.0020.0002.21C8] # UPWARDS PAIRED ARROWS
+21C9 ; [*0474.0020.0002.21C9] # RIGHTWARDS PAIRED ARROWS
+21CA ; [*0475.0020.0002.21CA] # DOWNWARDS PAIRED ARROWS
+21CB ; [*0476.0020.0002.21CB] # LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON
+21CC ; [*0477.0020.0002.21CC] # RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON
+21CD ; [*0478.0020.0002.21D0][.0000.0054.0002.0338] # LEFTWARDS DOUBLE ARROW WITH STROKE; QQCM
+21CE ; [*047C.0020.0002.21D4][.0000.0054.0002.0338] # LEFT RIGHT DOUBLE ARROW WITH STROKE; QQCM
+21CF ; [*047A.0020.0002.21D2][.0000.0054.0002.0338] # RIGHTWARDS DOUBLE ARROW WITH STROKE; QQCM
+21D0 ; [*0478.0020.0002.21D0] # LEFTWARDS DOUBLE ARROW
+21D1 ; [*0479.0020.0002.21D1] # UPWARDS DOUBLE ARROW
+21D2 ; [*047A.0020.0002.21D2] # RIGHTWARDS DOUBLE ARROW
+21D3 ; [*047B.0020.0002.21D3] # DOWNWARDS DOUBLE ARROW
+21D4 ; [*047C.0020.0002.21D4] # LEFT RIGHT DOUBLE ARROW
+21D5 ; [*047D.0020.0002.21D5] # UP DOWN DOUBLE ARROW
+21D6 ; [*047E.0020.0002.21D6] # NORTH WEST DOUBLE ARROW
+21D7 ; [*047F.0020.0002.21D7] # NORTH EAST DOUBLE ARROW
+21D8 ; [*0480.0020.0002.21D8] # SOUTH EAST DOUBLE ARROW
+21D9 ; [*0481.0020.0002.21D9] # SOUTH WEST DOUBLE ARROW
+21DA ; [*0482.0020.0002.21DA] # LEFTWARDS TRIPLE ARROW
+21DB ; [*0483.0020.0002.21DB] # RIGHTWARDS TRIPLE ARROW
+21DC ; [*0484.0020.0002.21DC] # LEFTWARDS SQUIGGLE ARROW
+21DD ; [*0485.0020.0002.21DD] # RIGHTWARDS SQUIGGLE ARROW
+21DE ; [*0486.0020.0002.21DE] # UPWARDS ARROW WITH DOUBLE STROKE
+21DF ; [*0487.0020.0002.21DF] # DOWNWARDS ARROW WITH DOUBLE STROKE
+21E0 ; [*0488.0020.0002.21E0] # LEFTWARDS DASHED ARROW
+21E1 ; [*0489.0020.0002.21E1] # UPWARDS DASHED ARROW
+21E2 ; [*048A.0020.0002.21E2] # RIGHTWARDS DASHED ARROW
+21E3 ; [*048B.0020.0002.21E3] # DOWNWARDS DASHED ARROW
+21E4 ; [*048C.0020.0002.21E4] # LEFTWARDS ARROW TO BAR
+21E5 ; [*048D.0020.0002.21E5] # RIGHTWARDS ARROW TO BAR
+21E6 ; [*048E.0020.0002.21E6] # LEFTWARDS WHITE ARROW
+21E7 ; [*048F.0020.0002.21E7] # UPWARDS WHITE ARROW
+21E8 ; [*0490.0020.0002.21E8] # RIGHTWARDS WHITE ARROW
+21E9 ; [*0491.0020.0002.21E9] # DOWNWARDS WHITE ARROW
+21EA ; [*0492.0020.0002.21EA] # UPWARDS WHITE ARROW FROM BAR
+21EB ; [*0493.0020.0002.21EB] # UPWARDS WHITE ARROW ON PEDESTAL
+21EC ; [*0494.0020.0002.21EC] # UPWARDS WHITE ARROW ON PEDESTAL WITH HORIZONTAL BAR
+21ED ; [*0495.0020.0002.21ED] # UPWARDS WHITE ARROW ON PEDESTAL WITH VERTICAL BAR
+21EE ; [*0496.0020.0002.21EE] # UPWARDS WHITE DOUBLE ARROW
+21EF ; [*0497.0020.0002.21EF] # UPWARDS WHITE DOUBLE ARROW ON PEDESTAL
+21F0 ; [*0498.0020.0002.21F0] # RIGHTWARDS WHITE ARROW FROM WALL
+21F1 ; [*0499.0020.0002.21F1] # NORTH WEST ARROW TO CORNER
+21F2 ; [*049A.0020.0002.21F2] # SOUTH EAST ARROW TO CORNER
+21F3 ; [*049B.0020.0002.21F3] # UP DOWN WHITE ARROW
+21F4 ; [*049C.0020.0002.21F4] # RIGHT ARROW WITH SMALL CIRCLE
+21F5 ; [*049D.0020.0002.21F5] # DOWNWARDS ARROW LEFTWARDS OF UPWARDS ARROW
+21F6 ; [*049E.0020.0002.21F6] # THREE RIGHTWARDS ARROWS
+21F7 ; [*049F.0020.0002.21F7] # LEFTWARDS ARROW WITH VERTICAL STROKE
+21F8 ; [*04A0.0020.0002.21F8] # RIGHTWARDS ARROW WITH VERTICAL STROKE
+21F9 ; [*04A1.0020.0002.21F9] # LEFT RIGHT ARROW WITH VERTICAL STROKE
+21FA ; [*04A2.0020.0002.21FA] # LEFTWARDS ARROW WITH DOUBLE VERTICAL STROKE
+21FB ; [*04A3.0020.0002.21FB] # RIGHTWARDS ARROW WITH DOUBLE VERTICAL STROKE
+21FC ; [*04A4.0020.0002.21FC] # LEFT RIGHT ARROW WITH DOUBLE VERTICAL STROKE
+21FD ; [*04A5.0020.0002.21FD] # LEFTWARDS OPEN-HEADED ARROW
+21FE ; [*04A6.0020.0002.21FE] # RIGHTWARDS OPEN-HEADED ARROW
+21FF ; [*04A7.0020.0002.21FF] # LEFT RIGHT OPEN-HEADED ARROW
+2200 ; [*04A8.0020.0002.2200] # FOR ALL
+2201 ; [*04A9.0020.0002.2201] # COMPLEMENT
+2202 ; [*04AA.0020.0002.2202] # PARTIAL DIFFERENTIAL
+2203 ; [*04AB.0020.0002.2203] # THERE EXISTS
+2204 ; [*04AB.0020.0002.2203][.0000.0054.0002.0338] # THERE DOES NOT EXIST; QQCM
+2205 ; [*04AC.0020.0002.2205] # EMPTY SET
+2206 ; [*04AD.0020.0002.2206] # INCREMENT
+2207 ; [*04AE.0020.0002.2207] # NABLA
+2208 ; [*04AF.0020.0002.2208] # ELEMENT OF
+2209 ; [*04AF.0020.0002.2208][.0000.0054.0002.0338] # NOT AN ELEMENT OF; QQCM
+220A ; [*04B0.0020.0002.220A] # SMALL ELEMENT OF
+220B ; [*04B1.0020.0002.220B] # CONTAINS AS MEMBER
+220C ; [*04B1.0020.0002.220B][.0000.0054.0002.0338] # DOES NOT CONTAIN AS MEMBER; QQCM
+220D ; [*04B2.0020.0002.220D] # SMALL CONTAINS AS MEMBER
+220E ; [*04B4.0020.0002.220E] # END OF PROOF
+220F ; [*04B5.0020.0002.220F] # N-ARY PRODUCT
+2210 ; [*04B6.0020.0002.2210] # N-ARY COPRODUCT
+2211 ; [*04B7.0020.0002.2211] # N-ARY SUMMATION
+2212 ; [*04C4.0020.0002.2212] # MINUS SIGN
+2213 ; [*04C5.0020.0002.2213] # MINUS-OR-PLUS SIGN
+2214 ; [*04C6.0020.0002.2214] # DOT PLUS
+2215 ; [*04C7.0020.0002.2215] # DIVISION SLASH
+2216 ; [*04C8.0020.0002.2216] # SET MINUS
+2217 ; [*04C9.0020.0002.2217] # ASTERISK OPERATOR
+2218 ; [*04CA.0020.0002.2218] # RING OPERATOR
+2219 ; [*04CB.0020.0002.2219] # BULLET OPERATOR
+221A ; [*04CC.0020.0002.221A] # SQUARE ROOT
+221B ; [*04CD.0020.0002.221B] # CUBE ROOT
+221C ; [*04CE.0020.0002.221C] # FOURTH ROOT
+221D ; [*04CF.0020.0002.221D] # PROPORTIONAL TO
+221E ; [*04D0.0020.0002.221E] # INFINITY
+221F ; [*04D1.0020.0002.221F] # RIGHT ANGLE
+2220 ; [*04D2.0020.0002.2220] # ANGLE
+2221 ; [*04D3.0020.0002.2221] # MEASURED ANGLE
+2222 ; [*04D4.0020.0002.2222] # SPHERICAL ANGLE
+2223 ; [*04D5.0020.0002.2223] # DIVIDES
+2224 ; [*04D5.0020.0002.2223][.0000.0054.0002.0338] # DOES NOT DIVIDE; QQCM
+2225 ; [*04D6.0020.0002.2225] # PARALLEL TO
+2226 ; [*04D6.0020.0002.2225][.0000.0054.0002.0338] # NOT PARALLEL TO; QQCM
+2227 ; [*04D7.0020.0002.2227] # LOGICAL AND
+2228 ; [*04D8.0020.0002.2228] # LOGICAL OR
+2229 ; [*04D9.0020.0002.2229] # INTERSECTION
+222A ; [*04DA.0020.0002.222A] # UNION
+222B ; [*04DB.0020.0002.222B] # INTEGRAL
+222C ; [*04DB.0020.0004.222C][*04DB.0020.0004.222C] # DOUBLE INTEGRAL; QQKN
+222D ; [*04DB.0020.0004.222D][*04DB.0020.0004.222D][*04DB.0020.001F.222D] # TRIPLE INTEGRAL; QQKN
+222E ; [*04DC.0020.0002.222E] # CONTOUR INTEGRAL
+222F ; [*04DC.0020.0004.222F][*04DC.0020.0004.222F] # SURFACE INTEGRAL; QQKN
+2230 ; [*04DC.0020.0004.2230][*04DC.0020.0004.2230][*04DC.0020.001F.2230] # VOLUME INTEGRAL; QQKN
+2231 ; [*04DD.0020.0002.2231] # CLOCKWISE INTEGRAL
+2232 ; [*04DE.0020.0002.2232] # CLOCKWISE CONTOUR INTEGRAL
+2233 ; [*04DF.0020.0002.2233] # ANTICLOCKWISE CONTOUR INTEGRAL
+2234 ; [*04E0.0020.0002.2234] # THEREFORE
+2235 ; [*04E1.0020.0002.2235] # BECAUSE
+2236 ; [*04E2.0020.0002.2236] # RATIO
+2237 ; [*04E3.0020.0002.2237] # PROPORTION
+2238 ; [*04E4.0020.0002.2238] # DOT MINUS
+2239 ; [*04E5.0020.0002.2239] # EXCESS
+223A ; [*04E6.0020.0002.223A] # GEOMETRIC PROPORTION
+223B ; [*04E7.0020.0002.223B] # HOMOTHETIC
+223C ; [*04E8.0020.0002.223C] # TILDE OPERATOR
+223D ; [*04E9.0020.0002.223D] # REVERSED TILDE
+223E ; [*04EA.0020.0002.223E] # INVERTED LAZY S
+223F ; [*04EB.0020.0002.223F] # SINE WAVE
+2240 ; [*04EC.0020.0002.2240] # WREATH PRODUCT
+2241 ; [*04E8.0020.0002.223C][.0000.0054.0002.0338] # NOT TILDE; QQCM
+2242 ; [*04ED.0020.0002.2242] # MINUS TILDE
+2243 ; [*04EE.0020.0002.2243] # ASYMPTOTICALLY EQUAL TO
+2244 ; [*04EE.0020.0002.2243][.0000.0054.0002.0338] # NOT ASYMPTOTICALLY EQUAL TO; QQCM
+2245 ; [*04EF.0020.0002.2245] # APPROXIMATELY EQUAL TO
+2246 ; [*04F0.0020.0002.2246] # APPROXIMATELY BUT NOT ACTUALLY EQUAL TO
+2247 ; [*04EF.0020.0002.2245][.0000.0054.0002.0338] # NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO; QQCM
+2248 ; [*04F1.0020.0002.2248] # ALMOST EQUAL TO
+2249 ; [*04F1.0020.0002.2248][.0000.0054.0002.0338] # NOT ALMOST EQUAL TO; QQCM
+224A ; [*04F2.0020.0002.224A] # ALMOST EQUAL OR EQUAL TO
+224B ; [*04F3.0020.0002.224B] # TRIPLE TILDE
+224C ; [*04F4.0020.0002.224C] # ALL EQUAL TO
+224D ; [*04F5.0020.0002.224D] # EQUIVALENT TO
+224E ; [*04F6.0020.0002.224E] # GEOMETRICALLY EQUIVALENT TO
+224F ; [*04F7.0020.0002.224F] # DIFFERENCE BETWEEN
+2250 ; [*04F8.0020.0002.2250] # APPROACHES THE LIMIT
+2251 ; [*04F9.0020.0002.2251] # GEOMETRICALLY EQUAL TO
+2252 ; [*04FA.0020.0002.2252] # APPROXIMATELY EQUAL TO OR THE IMAGE OF
+2253 ; [*04FB.0020.0002.2253] # IMAGE OF OR APPROXIMATELY EQUAL TO
+2254 ; [*04FC.0020.0002.2254] # COLON EQUALS
+2255 ; [*04FD.0020.0002.2255] # EQUALS COLON
+2256 ; [*04FE.0020.0002.2256] # RING IN EQUAL TO
+2257 ; [*04FF.0020.0002.2257] # RING EQUAL TO
+2258 ; [*0500.0020.0002.2258] # CORRESPONDS TO
+2259 ; [*0501.0020.0002.2259] # ESTIMATES
+225A ; [*0502.0020.0002.225A] # EQUIANGULAR TO
+225B ; [*0503.0020.0002.225B] # STAR EQUALS
+225C ; [*0504.0020.0002.225C] # DELTA EQUAL TO
+225D ; [*0505.0020.0002.225D] # EQUAL TO BY DEFINITION
+225E ; [*0506.0020.0002.225E] # MEASURED BY
+225F ; [*0507.0020.0002.225F] # QUESTIONED EQUAL TO
+2260 ; [*04BD.0020.0002.003D][.0000.0054.0002.0338] # NOT EQUAL TO; QQCM
+2261 ; [*0508.0020.0002.2261] # IDENTICAL TO
+2262 ; [*0508.0020.0002.2261][.0000.0054.0002.0338] # NOT IDENTICAL TO; QQCM
+2263 ; [*0509.0020.0002.2263] # STRICTLY EQUIVALENT TO
+2264 ; [*050A.0020.0002.2264] # LESS-THAN OR EQUAL TO
+2265 ; [*050B.0020.0002.2265] # GREATER-THAN OR EQUAL TO
+2266 ; [*050C.0020.0002.2266] # LESS-THAN OVER EQUAL TO
+2267 ; [*050D.0020.0002.2267] # GREATER-THAN OVER EQUAL TO
+2268 ; [*050E.0020.0002.2268] # LESS-THAN BUT NOT EQUAL TO
+2269 ; [*050F.0020.0002.2269] # GREATER-THAN BUT NOT EQUAL TO
+226A ; [*0510.0020.0002.226A] # MUCH LESS-THAN
+226B ; [*0511.0020.0002.226B] # MUCH GREATER-THAN
+226C ; [*0512.0020.0002.226C] # BETWEEN
+226D ; [*04F5.0020.0002.224D][.0000.0054.0002.0338] # NOT EQUIVALENT TO; QQCM
+226E ; [*04BC.0020.0002.003C][.0000.0054.0002.0338] # NOT LESS-THAN; QQCM
+226F ; [*04BE.0020.0002.003E][.0000.0054.0002.0338] # NOT GREATER-THAN; QQCM
+2270 ; [*050A.0020.0002.2264][.0000.0054.0002.0338] # NEITHER LESS-THAN NOR EQUAL TO; QQCM
+2271 ; [*050B.0020.0002.2265][.0000.0054.0002.0338] # NEITHER GREATER-THAN NOR EQUAL TO; QQCM
+2272 ; [*0513.0020.0002.2272] # LESS-THAN OR EQUIVALENT TO
+2273 ; [*0514.0020.0002.2273] # GREATER-THAN OR EQUIVALENT TO
+2274 ; [*0513.0020.0002.2272][.0000.0054.0002.0338] # NEITHER LESS-THAN NOR EQUIVALENT TO; QQCM
+2275 ; [*0514.0020.0002.2273][.0000.0054.0002.0338] # NEITHER GREATER-THAN NOR EQUIVALENT TO; QQCM
+2276 ; [*0515.0020.0002.2276] # LESS-THAN OR GREATER-THAN
+2277 ; [*0516.0020.0002.2277] # GREATER-THAN OR LESS-THAN
+2278 ; [*0515.0020.0002.2276][.0000.0054.0002.0338] # NEITHER LESS-THAN NOR GREATER-THAN; QQCM
+2279 ; [*0516.0020.0002.2277][.0000.0054.0002.0338] # NEITHER GREATER-THAN NOR LESS-THAN; QQCM
+227A ; [*0517.0020.0002.227A] # PRECEDES
+227B ; [*0518.0020.0002.227B] # SUCCEEDS
+227C ; [*0519.0020.0002.227C] # PRECEDES OR EQUAL TO
+227D ; [*051A.0020.0002.227D] # SUCCEEDS OR EQUAL TO
+227E ; [*051B.0020.0002.227E] # PRECEDES OR EQUIVALENT TO
+227F ; [*051C.0020.0002.227F] # SUCCEEDS OR EQUIVALENT TO
+2280 ; [*0517.0020.0002.227A][.0000.0054.0002.0338] # DOES NOT PRECEDE; QQCM
+2281 ; [*0518.0020.0002.227B][.0000.0054.0002.0338] # DOES NOT SUCCEED; QQCM
+2282 ; [*051D.0020.0002.2282] # SUBSET OF
+2283 ; [*051E.0020.0002.2283] # SUPERSET OF
+2284 ; [*051D.0020.0002.2282][.0000.0054.0002.0338] # NOT A SUBSET OF; QQCM
+2285 ; [*051E.0020.0002.2283][.0000.0054.0002.0338] # NOT A SUPERSET OF; QQCM
+2286 ; [*051F.0020.0002.2286] # SUBSET OF OR EQUAL TO
+2287 ; [*0520.0020.0002.2287] # SUPERSET OF OR EQUAL TO
+2288 ; [*051F.0020.0002.2286][.0000.0054.0002.0338] # NEITHER A SUBSET OF NOR EQUAL TO; QQCM
+2289 ; [*0520.0020.0002.2287][.0000.0054.0002.0338] # NEITHER A SUPERSET OF NOR EQUAL TO; QQCM
+228A ; [*0521.0020.0002.228A] # SUBSET OF WITH NOT EQUAL TO
+228B ; [*0522.0020.0002.228B] # SUPERSET OF WITH NOT EQUAL TO
+228C ; [*0523.0020.0002.228C] # MULTISET
+228D ; [*0524.0020.0002.228D] # MULTISET MULTIPLICATION
+228E ; [*0525.0020.0002.228E] # MULTISET UNION
+228F ; [*0526.0020.0002.228F] # SQUARE IMAGE OF
+2290 ; [*0527.0020.0002.2290] # SQUARE ORIGINAL OF
+2291 ; [*0528.0020.0002.2291] # SQUARE IMAGE OF OR EQUAL TO
+2292 ; [*0529.0020.0002.2292] # SQUARE ORIGINAL OF OR EQUAL TO
+2293 ; [*052A.0020.0002.2293] # SQUARE CAP
+2294 ; [*052B.0020.0002.2294] # SQUARE CUP
+2295 ; [*052C.0020.0002.2295] # CIRCLED PLUS
+2296 ; [*052D.0020.0002.2296] # CIRCLED MINUS
+2297 ; [*052E.0020.0002.2297] # CIRCLED TIMES
+2298 ; [*052F.0020.0002.2298] # CIRCLED DIVISION SLASH
+2299 ; [*0530.0020.0002.2299] # CIRCLED DOT OPERATOR
+229A ; [*0531.0020.0002.229A] # CIRCLED RING OPERATOR
+229B ; [*0532.0020.0002.229B] # CIRCLED ASTERISK OPERATOR
+229C ; [*0533.0020.0002.229C] # CIRCLED EQUALS
+229D ; [*0534.0020.0002.229D] # CIRCLED DASH
+229E ; [*0535.0020.0002.229E] # SQUARED PLUS
+229F ; [*0536.0020.0002.229F] # SQUARED MINUS
+22A0 ; [*0537.0020.0002.22A0] # SQUARED TIMES
+22A1 ; [*0538.0020.0002.22A1] # SQUARED DOT OPERATOR
+22A2 ; [*0539.0020.0002.22A2] # RIGHT TACK
+22A3 ; [*053A.0020.0002.22A3] # LEFT TACK
+22A4 ; [*053B.0020.0002.22A4] # DOWN TACK
+22A5 ; [*053C.0020.0002.22A5] # UP TACK
+22A6 ; [*053D.0020.0002.22A6] # ASSERTION
+22A7 ; [*053E.0020.0002.22A7] # MODELS
+22A8 ; [*053F.0020.0002.22A8] # TRUE
+22A9 ; [*0540.0020.0002.22A9] # FORCES
+22AA ; [*0541.0020.0002.22AA] # TRIPLE VERTICAL BAR RIGHT TURNSTILE
+22AB ; [*0542.0020.0002.22AB] # DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
+22AC ; [*0539.0020.0002.22A2][.0000.0054.0002.0338] # DOES NOT PROVE; QQCM
+22AD ; [*053F.0020.0002.22A8][.0000.0054.0002.0338] # NOT TRUE; QQCM
+22AE ; [*0540.0020.0002.22A9][.0000.0054.0002.0338] # DOES NOT FORCE; QQCM
+22AF ; [*0542.0020.0002.22AB][.0000.0054.0002.0338] # NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE; QQCM
+22B0 ; [*0543.0020.0002.22B0] # PRECEDES UNDER RELATION
+22B1 ; [*0544.0020.0002.22B1] # SUCCEEDS UNDER RELATION
+22B2 ; [*0545.0020.0002.22B2] # NORMAL SUBGROUP OF
+22B3 ; [*0546.0020.0002.22B3] # CONTAINS AS NORMAL SUBGROUP
+22B4 ; [*0547.0020.0002.22B4] # NORMAL SUBGROUP OF OR EQUAL TO
+22B5 ; [*0548.0020.0002.22B5] # CONTAINS AS NORMAL SUBGROUP OR EQUAL TO
+22B6 ; [*0549.0020.0002.22B6] # ORIGINAL OF
+22B7 ; [*054A.0020.0002.22B7] # IMAGE OF
+22B8 ; [*054B.0020.0002.22B8] # MULTIMAP
+22B9 ; [*054C.0020.0002.22B9] # HERMITIAN CONJUGATE MATRIX
+22BA ; [*054D.0020.0002.22BA] # INTERCALATE
+22BB ; [*054E.0020.0002.22BB] # XOR
+22BC ; [*054F.0020.0002.22BC] # NAND
+22BD ; [*0550.0020.0002.22BD] # NOR
+22BE ; [*0551.0020.0002.22BE] # RIGHT ANGLE WITH ARC
+22BF ; [*0552.0020.0002.22BF] # RIGHT TRIANGLE
+22C0 ; [*0553.0020.0002.22C0] # N-ARY LOGICAL AND
+22C1 ; [*0554.0020.0002.22C1] # N-ARY LOGICAL OR
+22C2 ; [*0555.0020.0002.22C2] # N-ARY INTERSECTION
+22C3 ; [*0556.0020.0002.22C3] # N-ARY UNION
+22C4 ; [*0557.0020.0002.22C4] # DIAMOND OPERATOR
+22C5 ; [*0558.0020.0002.22C5] # DOT OPERATOR
+22C6 ; [*0559.0020.0002.22C6] # STAR OPERATOR
+22C7 ; [*055A.0020.0002.22C7] # DIVISION TIMES
+22C8 ; [*055B.0020.0002.22C8] # BOWTIE
+22C9 ; [*055C.0020.0002.22C9] # LEFT NORMAL FACTOR SEMIDIRECT PRODUCT
+22CA ; [*055D.0020.0002.22CA] # RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT
+22CB ; [*055E.0020.0002.22CB] # LEFT SEMIDIRECT PRODUCT
+22CC ; [*055F.0020.0002.22CC] # RIGHT SEMIDIRECT PRODUCT
+22CD ; [*0560.0020.0002.22CD] # REVERSED TILDE EQUALS
+22CE ; [*0561.0020.0002.22CE] # CURLY LOGICAL OR
+22CF ; [*0562.0020.0002.22CF] # CURLY LOGICAL AND
+22D0 ; [*0563.0020.0002.22D0] # DOUBLE SUBSET
+22D1 ; [*0564.0020.0002.22D1] # DOUBLE SUPERSET
+22D2 ; [*0565.0020.0002.22D2] # DOUBLE INTERSECTION
+22D3 ; [*0566.0020.0002.22D3] # DOUBLE UNION
+22D4 ; [*0567.0020.0002.22D4] # PITCHFORK
+22D5 ; [*0568.0020.0002.22D5] # EQUAL AND PARALLEL TO
+22D6 ; [*0569.0020.0002.22D6] # LESS-THAN WITH DOT
+22D7 ; [*056A.0020.0002.22D7] # GREATER-THAN WITH DOT
+22D8 ; [*056B.0020.0002.22D8] # VERY MUCH LESS-THAN
+22D9 ; [*056C.0020.0002.22D9] # VERY MUCH GREATER-THAN
+22DA ; [*056D.0020.0002.22DA] # LESS-THAN EQUAL TO OR GREATER-THAN
+22DB ; [*056E.0020.0002.22DB] # GREATER-THAN EQUAL TO OR LESS-THAN
+22DC ; [*056F.0020.0002.22DC] # EQUAL TO OR LESS-THAN
+22DD ; [*0570.0020.0002.22DD] # EQUAL TO OR GREATER-THAN
+22DE ; [*0571.0020.0002.22DE] # EQUAL TO OR PRECEDES
+22DF ; [*0572.0020.0002.22DF] # EQUAL TO OR SUCCEEDS
+22E0 ; [*0519.0020.0002.227C][.0000.0054.0002.0338] # DOES NOT PRECEDE OR EQUAL; QQCM
+22E1 ; [*051A.0020.0002.227D][.0000.0054.0002.0338] # DOES NOT SUCCEED OR EQUAL; QQCM
+22E2 ; [*0528.0020.0002.2291][.0000.0054.0002.0338] # NOT SQUARE IMAGE OF OR EQUAL TO; QQCM
+22E3 ; [*0529.0020.0002.2292][.0000.0054.0002.0338] # NOT SQUARE ORIGINAL OF OR EQUAL TO; QQCM
+22E4 ; [*0573.0020.0002.22E4] # SQUARE IMAGE OF OR NOT EQUAL TO
+22E5 ; [*0574.0020.0002.22E5] # SQUARE ORIGINAL OF OR NOT EQUAL TO
+22E6 ; [*0575.0020.0002.22E6] # LESS-THAN BUT NOT EQUIVALENT TO
+22E7 ; [*0576.0020.0002.22E7] # GREATER-THAN BUT NOT EQUIVALENT TO
+22E8 ; [*0577.0020.0002.22E8] # PRECEDES BUT NOT EQUIVALENT TO
+22E9 ; [*0578.0020.0002.22E9] # SUCCEEDS BUT NOT EQUIVALENT TO
+22EA ; [*0545.0020.0002.22B2][.0000.0054.0002.0338] # NOT NORMAL SUBGROUP OF; QQCM
+22EB ; [*0546.0020.0002.22B3][.0000.0054.0002.0338] # DOES NOT CONTAIN AS NORMAL SUBGROUP; QQCM
+22EC ; [*0547.0020.0002.22B4][.0000.0054.0002.0338] # NOT NORMAL SUBGROUP OF OR EQUAL TO; QQCM
+22ED ; [*0548.0020.0002.22B5][.0000.0054.0002.0338] # DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL; QQCM
+22EE ; [*0579.0020.0002.22EE] # VERTICAL ELLIPSIS
+22EF ; [*057A.0020.0002.22EF] # MIDLINE HORIZONTAL ELLIPSIS
+22F0 ; [*057B.0020.0002.22F0] # UP RIGHT DIAGONAL ELLIPSIS
+22F1 ; [*057C.0020.0002.22F1] # DOWN RIGHT DIAGONAL ELLIPSIS
+22F2 ; [*057D.0020.0002.22F2] # ELEMENT OF WITH LONG HORIZONTAL STROKE
+22F3 ; [*057E.0020.0002.22F3] # ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
+22F4 ; [*057F.0020.0002.22F4] # SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
+22F5 ; [*0580.0020.0002.22F5] # ELEMENT OF WITH DOT ABOVE
+22F6 ; [*0581.0020.0002.22F6] # ELEMENT OF WITH OVERBAR
+22F7 ; [*0582.0020.0002.22F7] # SMALL ELEMENT OF WITH OVERBAR
+22F8 ; [*0583.0020.0002.22F8] # ELEMENT OF WITH UNDERBAR
+22F9 ; [*0584.0020.0002.22F9] # ELEMENT OF WITH TWO HORIZONTAL STROKES
+22FA ; [*0585.0020.0002.22FA] # CONTAINS WITH LONG HORIZONTAL STROKE
+22FB ; [*0586.0020.0002.22FB] # CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
+22FC ; [*0587.0020.0002.22FC] # SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
+22FD ; [*0588.0020.0002.22FD] # CONTAINS WITH OVERBAR
+22FE ; [*0589.0020.0002.22FE] # SMALL CONTAINS WITH OVERBAR
+22FF ; [*058A.0020.0002.22FF] # Z NOTATION BAG MEMBERSHIP
+2300 ; [*058B.0020.0002.2300] # DIAMETER SIGN
+2301 ; [*058C.0020.0002.2301] # ELECTRIC ARROW
+2302 ; [*058D.0020.0002.2302] # HOUSE
+2303 ; [*058E.0020.0002.2303] # UP ARROWHEAD
+2304 ; [*058F.0020.0002.2304] # DOWN ARROWHEAD
+2305 ; [*0590.0020.0002.2305] # PROJECTIVE
+2306 ; [*0591.0020.0002.2306] # PERSPECTIVE
+2307 ; [*0592.0020.0002.2307] # WAVY LINE
+2308 ; [*0593.0020.0002.2308] # LEFT CEILING
+2309 ; [*0594.0020.0002.2309] # RIGHT CEILING
+230A ; [*0595.0020.0002.230A] # LEFT FLOOR
+230B ; [*0596.0020.0002.230B] # RIGHT FLOOR
+230C ; [*0597.0020.0002.230C] # BOTTOM RIGHT CROP
+230D ; [*0598.0020.0002.230D] # BOTTOM LEFT CROP
+230E ; [*0599.0020.0002.230E] # TOP RIGHT CROP
+230F ; [*059A.0020.0002.230F] # TOP LEFT CROP
+2310 ; [*059B.0020.0002.2310] # REVERSED NOT SIGN
+2311 ; [*059C.0020.0002.2311] # SQUARE LOZENGE
+2312 ; [*059D.0020.0002.2312] # ARC
+2313 ; [*059E.0020.0002.2313] # SEGMENT
+2314 ; [*059F.0020.0002.2314] # SECTOR
+2315 ; [*05A0.0020.0002.2315] # TELEPHONE RECORDER
+2316 ; [*05A1.0020.0002.2316] # POSITION INDICATOR
+2317 ; [*05A2.0020.0002.2317] # VIEWDATA SQUARE
+2318 ; [*05A3.0020.0002.2318] # PLACE OF INTEREST SIGN
+2319 ; [*05A4.0020.0002.2319] # TURNED NOT SIGN
+231A ; [*05A5.0020.0002.231A] # WATCH
+231B ; [*05A6.0020.0002.231B] # HOURGLASS
+231C ; [*05A7.0020.0002.231C] # TOP LEFT CORNER
+231D ; [*05A8.0020.0002.231D] # TOP RIGHT CORNER
+231E ; [*05A9.0020.0002.231E] # BOTTOM LEFT CORNER
+231F ; [*05AA.0020.0002.231F] # BOTTOM RIGHT CORNER
+2320 ; [*05AB.0020.0002.2320] # TOP HALF INTEGRAL
+2321 ; [*05AC.0020.0002.2321] # BOTTOM HALF INTEGRAL
+2322 ; [*05AD.0020.0002.2322] # FROWN
+2323 ; [*05AE.0020.0002.2323] # SMILE
+2324 ; [*05AF.0020.0002.2324] # UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS
+2325 ; [*05B0.0020.0002.2325] # OPTION KEY
+2326 ; [*05B1.0020.0002.2326] # ERASE TO THE RIGHT
+2327 ; [*05B2.0020.0002.2327] # X IN A RECTANGLE BOX
+2328 ; [*05B3.0020.0002.2328] # KEYBOARD
+2329 ; [*02E1.0020.0002.2329] # LEFT-POINTING ANGLE BRACKET; QQC
+232A ; [*02E2.0020.0002.232A] # RIGHT-POINTING ANGLE BRACKET; QQC
+232B ; [*05B4.0020.0002.232B] # ERASE TO THE LEFT
+232C ; [*05B5.0020.0002.232C] # BENZENE RING
+232D ; [*05B6.0020.0002.232D] # CYLINDRICITY
+232E ; [*05B7.0020.0002.232E] # ALL AROUND-PROFILE
+232F ; [*05B8.0020.0002.232F] # SYMMETRY
+2330 ; [*05B9.0020.0002.2330] # TOTAL RUNOUT
+2331 ; [*05BA.0020.0002.2331] # DIMENSION ORIGIN
+2332 ; [*05BB.0020.0002.2332] # CONICAL TAPER
+2333 ; [*05BC.0020.0002.2333] # SLOPE
+2334 ; [*05BD.0020.0002.2334] # COUNTERBORE
+2335 ; [*05BE.0020.0002.2335] # COUNTERSINK
+2336 ; [*05BF.0020.0002.2336] # APL FUNCTIONAL SYMBOL I-BEAM
+2337 ; [*05C0.0020.0002.2337] # APL FUNCTIONAL SYMBOL SQUISH QUAD
+2338 ; [*05C1.0020.0002.2338] # APL FUNCTIONAL SYMBOL QUAD EQUAL
+2339 ; [*05C2.0020.0002.2339] # APL FUNCTIONAL SYMBOL QUAD DIVIDE
+233A ; [*05C3.0020.0002.233A] # APL FUNCTIONAL SYMBOL QUAD DIAMOND
+233B ; [*05C4.0020.0002.233B] # APL FUNCTIONAL SYMBOL QUAD JOT
+233C ; [*05C5.0020.0002.233C] # APL FUNCTIONAL SYMBOL QUAD CIRCLE
+233D ; [*05C6.0020.0002.233D] # APL FUNCTIONAL SYMBOL CIRCLE STILE
+233E ; [*05C7.0020.0002.233E] # APL FUNCTIONAL SYMBOL CIRCLE JOT
+233F ; [*05C8.0020.0002.233F] # APL FUNCTIONAL SYMBOL SLASH BAR
+2340 ; [*05C9.0020.0002.2340] # APL FUNCTIONAL SYMBOL BACKSLASH BAR
+2341 ; [*05CA.0020.0002.2341] # APL FUNCTIONAL SYMBOL QUAD SLASH
+2342 ; [*05CB.0020.0002.2342] # APL FUNCTIONAL SYMBOL QUAD BACKSLASH
+2343 ; [*05CC.0020.0002.2343] # APL FUNCTIONAL SYMBOL QUAD LESS-THAN
+2344 ; [*05CD.0020.0002.2344] # APL FUNCTIONAL SYMBOL QUAD GREATER-THAN
+2345 ; [*05CE.0020.0002.2345] # APL FUNCTIONAL SYMBOL LEFTWARDS VANE
+2346 ; [*05CF.0020.0002.2346] # APL FUNCTIONAL SYMBOL RIGHTWARDS VANE
+2347 ; [*05D0.0020.0002.2347] # APL FUNCTIONAL SYMBOL QUAD LEFTWARDS ARROW
+2348 ; [*05D1.0020.0002.2348] # APL FUNCTIONAL SYMBOL QUAD RIGHTWARDS ARROW
+2349 ; [*05D2.0020.0002.2349] # APL FUNCTIONAL SYMBOL CIRCLE BACKSLASH
+234A ; [*05D3.0020.0002.234A] # APL FUNCTIONAL SYMBOL DOWN TACK UNDERBAR
+234B ; [*05D4.0020.0002.234B] # APL FUNCTIONAL SYMBOL DELTA STILE
+234C ; [*05D5.0020.0002.234C] # APL FUNCTIONAL SYMBOL QUAD DOWN CARET
+234D ; [*05D6.0020.0002.234D] # APL FUNCTIONAL SYMBOL QUAD DELTA
+234E ; [*05D7.0020.0002.234E] # APL FUNCTIONAL SYMBOL DOWN TACK JOT
+234F ; [*05D8.0020.0002.234F] # APL FUNCTIONAL SYMBOL UPWARDS VANE
+2350 ; [*05D9.0020.0002.2350] # APL FUNCTIONAL SYMBOL QUAD UPWARDS ARROW
+2351 ; [*05DA.0020.0002.2351] # APL FUNCTIONAL SYMBOL UP TACK OVERBAR
+2352 ; [*05DB.0020.0002.2352] # APL FUNCTIONAL SYMBOL DEL STILE
+2353 ; [*05DC.0020.0002.2353] # APL FUNCTIONAL SYMBOL QUAD UP CARET
+2354 ; [*05DD.0020.0002.2354] # APL FUNCTIONAL SYMBOL QUAD DEL
+2355 ; [*05DE.0020.0002.2355] # APL FUNCTIONAL SYMBOL UP TACK JOT
+2356 ; [*05DF.0020.0002.2356] # APL FUNCTIONAL SYMBOL DOWNWARDS VANE
+2357 ; [*05E0.0020.0002.2357] # APL FUNCTIONAL SYMBOL QUAD DOWNWARDS ARROW
+2358 ; [*05E1.0020.0002.2358] # APL FUNCTIONAL SYMBOL QUOTE UNDERBAR
+2359 ; [*05E2.0020.0002.2359] # APL FUNCTIONAL SYMBOL DELTA UNDERBAR
+235A ; [*05E3.0020.0002.235A] # APL FUNCTIONAL SYMBOL DIAMOND UNDERBAR
+235B ; [*05E4.0020.0002.235B] # APL FUNCTIONAL SYMBOL JOT UNDERBAR
+235C ; [*05E5.0020.0002.235C] # APL FUNCTIONAL SYMBOL CIRCLE UNDERBAR
+235D ; [*05E6.0020.0002.235D] # APL FUNCTIONAL SYMBOL UP SHOE JOT
+235E ; [*05E7.0020.0002.235E] # APL FUNCTIONAL SYMBOL QUOTE QUAD
+235F ; [*05E8.0020.0002.235F] # APL FUNCTIONAL SYMBOL CIRCLE STAR
+2360 ; [*05E9.0020.0002.2360] # APL FUNCTIONAL SYMBOL QUAD COLON
+2361 ; [*05EA.0020.0002.2361] # APL FUNCTIONAL SYMBOL UP TACK DIAERESIS
+2362 ; [*05EB.0020.0002.2362] # APL FUNCTIONAL SYMBOL DEL DIAERESIS
+2363 ; [*05EC.0020.0002.2363] # APL FUNCTIONAL SYMBOL STAR DIAERESIS
+2364 ; [*05ED.0020.0002.2364] # APL FUNCTIONAL SYMBOL JOT DIAERESIS
+2365 ; [*05EE.0020.0002.2365] # APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS
+2366 ; [*05EF.0020.0002.2366] # APL FUNCTIONAL SYMBOL DOWN SHOE STILE
+2367 ; [*05F0.0020.0002.2367] # APL FUNCTIONAL SYMBOL LEFT SHOE STILE
+2368 ; [*05F1.0020.0002.2368] # APL FUNCTIONAL SYMBOL TILDE DIAERESIS
+2369 ; [*05F2.0020.0002.2369] # APL FUNCTIONAL SYMBOL GREATER-THAN DIAERESIS
+236A ; [*05F3.0020.0002.236A] # APL FUNCTIONAL SYMBOL COMMA BAR
+236B ; [*05F4.0020.0002.236B] # APL FUNCTIONAL SYMBOL DEL TILDE
+236C ; [*05F5.0020.0002.236C] # APL FUNCTIONAL SYMBOL ZILDE
+236D ; [*05F6.0020.0002.236D] # APL FUNCTIONAL SYMBOL STILE TILDE
+236E ; [*05F7.0020.0002.236E] # APL FUNCTIONAL SYMBOL SEMICOLON UNDERBAR
+236F ; [*05F8.0020.0002.236F] # APL FUNCTIONAL SYMBOL QUAD NOT EQUAL
+2370 ; [*05F9.0020.0002.2370] # APL FUNCTIONAL SYMBOL QUAD QUESTION
+2371 ; [*05FA.0020.0002.2371] # APL FUNCTIONAL SYMBOL DOWN CARET TILDE
+2372 ; [*05FB.0020.0002.2372] # APL FUNCTIONAL SYMBOL UP CARET TILDE
+2373 ; [*05FC.0020.0002.2373] # APL FUNCTIONAL SYMBOL IOTA
+2374 ; [*05FD.0020.0002.2374] # APL FUNCTIONAL SYMBOL RHO
+2375 ; [*05FE.0020.0002.2375] # APL FUNCTIONAL SYMBOL OMEGA
+2376 ; [*05FF.0020.0002.2376] # APL FUNCTIONAL SYMBOL ALPHA UNDERBAR
+2377 ; [*0600.0020.0002.2377] # APL FUNCTIONAL SYMBOL EPSILON UNDERBAR
+2378 ; [*0601.0020.0002.2378] # APL FUNCTIONAL SYMBOL IOTA UNDERBAR
+2379 ; [*0602.0020.0002.2379] # APL FUNCTIONAL SYMBOL OMEGA UNDERBAR
+237A ; [*0603.0020.0002.237A] # APL FUNCTIONAL SYMBOL ALPHA
+237B ; [*0604.0020.0002.237B] # NOT CHECK MARK
+237C ; [*0605.0020.0002.237C] # RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW
+237D ; [*0606.0020.0002.237D] # SHOULDERED OPEN BOX
+237E ; [*0607.0020.0002.237E] # BELL SYMBOL
+237F ; [*0608.0020.0002.237F] # VERTICAL LINE WITH MIDDLE DOT
+2380 ; [*0609.0020.0002.2380] # INSERTION SYMBOL
+2381 ; [*060A.0020.0002.2381] # CONTINUOUS UNDERLINE SYMBOL
+2382 ; [*060B.0020.0002.2382] # DISCONTINUOUS UNDERLINE SYMBOL
+2383 ; [*060C.0020.0002.2383] # EMPHASIS SYMBOL
+2384 ; [*060D.0020.0002.2384] # COMPOSITION SYMBOL
+2385 ; [*060E.0020.0002.2385] # WHITE SQUARE WITH CENTRE VERTICAL LINE
+2386 ; [*060F.0020.0002.2386] # ENTER SYMBOL
+2387 ; [*0610.0020.0002.2387] # ALTERNATIVE KEY SYMBOL
+2388 ; [*0611.0020.0002.2388] # HELM SYMBOL
+2389 ; [*0612.0020.0002.2389] # CIRCLED HORIZONTAL BAR WITH NOTCH
+238A ; [*0613.0020.0002.238A] # CIRCLED TRIANGLE DOWN
+238B ; [*0614.0020.0002.238B] # BROKEN CIRCLE WITH NORTHWEST ARROW
+238C ; [*0615.0020.0002.238C] # UNDO SYMBOL
+238D ; [*0616.0020.0002.238D] # MONOSTABLE SYMBOL
+238E ; [*0617.0020.0002.238E] # HYSTERESIS SYMBOL
+238F ; [*0618.0020.0002.238F] # OPEN-CIRCUIT-OUTPUT H-TYPE SYMBOL
+2390 ; [*0619.0020.0002.2390] # OPEN-CIRCUIT-OUTPUT L-TYPE SYMBOL
+2391 ; [*061A.0020.0002.2391] # PASSIVE-PULL-DOWN-OUTPUT SYMBOL
+2392 ; [*061B.0020.0002.2392] # PASSIVE-PULL-UP-OUTPUT SYMBOL
+2393 ; [*061C.0020.0002.2393] # DIRECT CURRENT SYMBOL FORM TWO
+2394 ; [*061D.0020.0002.2394] # SOFTWARE-FUNCTION SYMBOL
+2395 ; [*061E.0020.0002.2395] # APL FUNCTIONAL SYMBOL QUAD
+2396 ; [*061F.0020.0002.2396] # DECIMAL SEPARATOR KEY SYMBOL
+2397 ; [*0620.0020.0002.2397] # PREVIOUS PAGE
+2398 ; [*0621.0020.0002.2398] # NEXT PAGE
+2399 ; [*0622.0020.0002.2399] # PRINT SCREEN SYMBOL
+239A ; [*0623.0020.0002.239A] # CLEAR SCREEN SYMBOL
+239B ; [*0624.0020.0002.239B] # LEFT PARENTHESIS UPPER HOOK
+239C ; [*0625.0020.0002.239C] # LEFT PARENTHESIS EXTENSION
+239D ; [*0626.0020.0002.239D] # LEFT PARENTHESIS LOWER HOOK
+239E ; [*0627.0020.0002.239E] # RIGHT PARENTHESIS UPPER HOOK
+239F ; [*0628.0020.0002.239F] # RIGHT PARENTHESIS EXTENSION
+23A0 ; [*0629.0020.0002.23A0] # RIGHT PARENTHESIS LOWER HOOK
+23A1 ; [*062A.0020.0002.23A1] # LEFT SQUARE BRACKET UPPER CORNER
+23A2 ; [*062B.0020.0002.23A2] # LEFT SQUARE BRACKET EXTENSION
+23A3 ; [*062C.0020.0002.23A3] # LEFT SQUARE BRACKET LOWER CORNER
+23A4 ; [*062D.0020.0002.23A4] # RIGHT SQUARE BRACKET UPPER CORNER
+23A5 ; [*062E.0020.0002.23A5] # RIGHT SQUARE BRACKET EXTENSION
+23A6 ; [*062F.0020.0002.23A6] # RIGHT SQUARE BRACKET LOWER CORNER
+23A7 ; [*0630.0020.0002.23A7] # LEFT CURLY BRACKET UPPER HOOK
+23A8 ; [*0631.0020.0002.23A8] # LEFT CURLY BRACKET MIDDLE PIECE
+23A9 ; [*0632.0020.0002.23A9] # LEFT CURLY BRACKET LOWER HOOK
+23AA ; [*0633.0020.0002.23AA] # CURLY BRACKET EXTENSION
+23AB ; [*0634.0020.0002.23AB] # RIGHT CURLY BRACKET UPPER HOOK
+23AC ; [*0635.0020.0002.23AC] # RIGHT CURLY BRACKET MIDDLE PIECE
+23AD ; [*0636.0020.0002.23AD] # RIGHT CURLY BRACKET LOWER HOOK
+23AE ; [*0637.0020.0002.23AE] # INTEGRAL EXTENSION
+23AF ; [*0638.0020.0002.23AF] # HORIZONTAL LINE EXTENSION
+23B0 ; [*0639.0020.0002.23B0] # UPPER LEFT OR LOWER RIGHT CURLY BRACKET SECTION
+23B1 ; [*063A.0020.0002.23B1] # UPPER RIGHT OR LOWER LEFT CURLY BRACKET SECTION
+23B2 ; [*063B.0020.0002.23B2] # SUMMATION TOP
+23B3 ; [*063C.0020.0002.23B3] # SUMMATION BOTTOM
+23B4 ; [*063D.0020.0002.23B4] # TOP SQUARE BRACKET
+23B5 ; [*063E.0020.0002.23B5] # BOTTOM SQUARE BRACKET
+23B6 ; [*063F.0020.0002.23B6] # BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET
+23B7 ; [*0640.0020.0002.23B7] # RADICAL SYMBOL BOTTOM
+23B8 ; [*0641.0020.0002.23B8] # LEFT VERTICAL BOX LINE
+23B9 ; [*0642.0020.0002.23B9] # RIGHT VERTICAL BOX LINE
+23BA ; [*0643.0020.0002.23BA] # HORIZONTAL SCAN LINE-1
+23BB ; [*0644.0020.0002.23BB] # HORIZONTAL SCAN LINE-3
+23BC ; [*0645.0020.0002.23BC] # HORIZONTAL SCAN LINE-7
+23BD ; [*0646.0020.0002.23BD] # HORIZONTAL SCAN LINE-9
+23BE ; [*0647.0020.0002.23BE] # DENTISTRY SYMBOL LIGHT VERTICAL AND TOP RIGHT
+23BF ; [*0648.0020.0002.23BF] # DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM RIGHT
+23C0 ; [*0649.0020.0002.23C0] # DENTISTRY SYMBOL LIGHT VERTICAL WITH CIRCLE
+23C1 ; [*064A.0020.0002.23C1] # DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH CIRCLE
+23C2 ; [*064B.0020.0002.23C2] # DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH CIRCLE
+23C3 ; [*064C.0020.0002.23C3] # DENTISTRY SYMBOL LIGHT VERTICAL WITH TRIANGLE
+23C4 ; [*064D.0020.0002.23C4] # DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH TRIANGLE
+23C5 ; [*064E.0020.0002.23C5] # DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH TRIANGLE
+23C6 ; [*064F.0020.0002.23C6] # DENTISTRY SYMBOL LIGHT VERTICAL AND WAVE
+23C7 ; [*0650.0020.0002.23C7] # DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH WAVE
+23C8 ; [*0651.0020.0002.23C8] # DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH WAVE
+23C9 ; [*0652.0020.0002.23C9] # DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL
+23CA ; [*0653.0020.0002.23CA] # DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL
+23CB ; [*0654.0020.0002.23CB] # DENTISTRY SYMBOL LIGHT VERTICAL AND TOP LEFT
+23CC ; [*0655.0020.0002.23CC] # DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM LEFT
+23CD ; [*0656.0020.0002.23CD] # SQUARE FOOT
+23CE ; [*0657.0020.0002.23CE] # RETURN SYMBOL
+23CF ; [*0658.0020.0002.23CF] # EJECT SYMBOL
+23D0 ; [*0659.0020.0002.23D0] # VERTICAL LINE EXTENSION
+23D1 ; [*065A.0020.0002.23D1] # METRICAL BREVE
+23D2 ; [*065B.0020.0002.23D2] # METRICAL LONG OVER SHORT
+23D3 ; [*065C.0020.0002.23D3] # METRICAL SHORT OVER LONG
+23D4 ; [*065D.0020.0002.23D4] # METRICAL LONG OVER TWO SHORTS
+23D5 ; [*065E.0020.0002.23D5] # METRICAL TWO SHORTS OVER LONG
+23D6 ; [*065F.0020.0002.23D6] # METRICAL TWO SHORTS JOINED
+23D7 ; [*0660.0020.0002.23D7] # METRICAL TRISEME
+23D8 ; [*0661.0020.0002.23D8] # METRICAL TETRASEME
+23D9 ; [*0662.0020.0002.23D9] # METRICAL PENTASEME
+23DA ; [*0663.0020.0002.23DA] # EARTH GROUND
+23DB ; [*0664.0020.0002.23DB] # FUSE
+23DC ; [*0665.0020.0002.23DC] # TOP PARENTHESIS
+23DD ; [*0666.0020.0002.23DD] # BOTTOM PARENTHESIS
+23DE ; [*0667.0020.0002.23DE] # TOP CURLY BRACKET
+23DF ; [*0668.0020.0002.23DF] # BOTTOM CURLY BRACKET
+23E0 ; [*0669.0020.0002.23E0] # TOP TORTOISE SHELL BRACKET
+23E1 ; [*066A.0020.0002.23E1] # BOTTOM TORTOISE SHELL BRACKET
+23E2 ; [*066B.0020.0002.23E2] # WHITE TRAPEZIUM
+23E3 ; [*066C.0020.0002.23E3] # BENZENE RING WITH CIRCLE
+23E4 ; [*066D.0020.0002.23E4] # STRAIGHTNESS
+23E5 ; [*066E.0020.0002.23E5] # FLATNESS
+23E6 ; [*066F.0020.0002.23E6] # AC CURRENT
+23E7 ; [*0670.0020.0002.23E7] # ELECTRICAL INTERSECTION
+2400 ; [*0671.0020.0002.2400] # SYMBOL FOR NULL
+2401 ; [*0672.0020.0002.2401] # SYMBOL FOR START OF HEADING
+2402 ; [*0673.0020.0002.2402] # SYMBOL FOR START OF TEXT
+2403 ; [*0674.0020.0002.2403] # SYMBOL FOR END OF TEXT
+2404 ; [*0675.0020.0002.2404] # SYMBOL FOR END OF TRANSMISSION
+2405 ; [*0676.0020.0002.2405] # SYMBOL FOR ENQUIRY
+2406 ; [*0677.0020.0002.2406] # SYMBOL FOR ACKNOWLEDGE
+2407 ; [*0678.0020.0002.2407] # SYMBOL FOR BELL
+2408 ; [*0679.0020.0002.2408] # SYMBOL FOR BACKSPACE
+2409 ; [*067A.0020.0002.2409] # SYMBOL FOR HORIZONTAL TABULATION
+240A ; [*067B.0020.0002.240A] # SYMBOL FOR LINE FEED
+240B ; [*067C.0020.0002.240B] # SYMBOL FOR VERTICAL TABULATION
+240C ; [*067D.0020.0002.240C] # SYMBOL FOR FORM FEED
+240D ; [*067E.0020.0002.240D] # SYMBOL FOR CARRIAGE RETURN
+240E ; [*067F.0020.0002.240E] # SYMBOL FOR SHIFT OUT
+240F ; [*0680.0020.0002.240F] # SYMBOL FOR SHIFT IN
+2410 ; [*0681.0020.0002.2410] # SYMBOL FOR DATA LINK ESCAPE
+2411 ; [*0682.0020.0002.2411] # SYMBOL FOR DEVICE CONTROL ONE
+2412 ; [*0683.0020.0002.2412] # SYMBOL FOR DEVICE CONTROL TWO
+2413 ; [*0684.0020.0002.2413] # SYMBOL FOR DEVICE CONTROL THREE
+2414 ; [*0685.0020.0002.2414] # SYMBOL FOR DEVICE CONTROL FOUR
+2415 ; [*0686.0020.0002.2415] # SYMBOL FOR NEGATIVE ACKNOWLEDGE
+2416 ; [*0687.0020.0002.2416] # SYMBOL FOR SYNCHRONOUS IDLE
+2417 ; [*0688.0020.0002.2417] # SYMBOL FOR END OF TRANSMISSION BLOCK
+2418 ; [*0689.0020.0002.2418] # SYMBOL FOR CANCEL
+2419 ; [*068A.0020.0002.2419] # SYMBOL FOR END OF MEDIUM
+241A ; [*068B.0020.0002.241A] # SYMBOL FOR SUBSTITUTE
+241B ; [*068C.0020.0002.241B] # SYMBOL FOR ESCAPE
+241C ; [*068D.0020.0002.241C] # SYMBOL FOR FILE SEPARATOR
+241D ; [*068E.0020.0002.241D] # SYMBOL FOR GROUP SEPARATOR
+241E ; [*068F.0020.0002.241E] # SYMBOL FOR RECORD SEPARATOR
+241F ; [*0690.0020.0002.241F] # SYMBOL FOR UNIT SEPARATOR
+2420 ; [*0691.0020.0002.2420] # SYMBOL FOR SPACE
+2421 ; [*0692.0020.0002.2421] # SYMBOL FOR DELETE
+2422 ; [*0693.0020.0002.2422] # BLANK SYMBOL
+2423 ; [*0694.0020.0002.2423] # OPEN BOX
+2424 ; [*0695.0020.0002.2424] # SYMBOL FOR NEWLINE
+2425 ; [*0696.0020.0002.2425] # SYMBOL FOR DELETE FORM TWO
+2426 ; [*0697.0020.0002.2426] # SYMBOL FOR SUBSTITUTE FORM TWO
+2440 ; [*0698.0020.0002.2440] # OCR HOOK
+2441 ; [*0699.0020.0002.2441] # OCR CHAIR
+2442 ; [*069A.0020.0002.2442] # OCR FORK
+2443 ; [*069B.0020.0002.2443] # OCR INVERTED FORK
+2444 ; [*069C.0020.0002.2444] # OCR BELT BUCKLE
+2445 ; [*069D.0020.0002.2445] # OCR BOW TIE
+2446 ; [*069E.0020.0002.2446] # OCR BRANCH BANK IDENTIFICATION
+2447 ; [*069F.0020.0002.2447] # OCR AMOUNT OF CHECK
+2448 ; [*06A0.0020.0002.2448] # OCR DASH
+2449 ; [*06A1.0020.0002.2449] # OCR CUSTOMER ACCOUNT NUMBER
+244A ; [*06A2.0020.0002.244A] # OCR DOUBLE BACKSLASH
+2500 ; [*06A3.0020.0002.2500] # BOX DRAWINGS LIGHT HORIZONTAL
+2501 ; [*06A4.0020.0002.2501] # BOX DRAWINGS HEAVY HORIZONTAL
+2502 ; [*06A5.0020.0002.2502] # BOX DRAWINGS LIGHT VERTICAL
+2503 ; [*06A6.0020.0002.2503] # BOX DRAWINGS HEAVY VERTICAL
+2504 ; [*06A7.0020.0002.2504] # BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL
+2505 ; [*06A8.0020.0002.2505] # BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL
+2506 ; [*06A9.0020.0002.2506] # BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL
+2507 ; [*06AA.0020.0002.2507] # BOX DRAWINGS HEAVY TRIPLE DASH VERTICAL
+2508 ; [*06AB.0020.0002.2508] # BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL
+2509 ; [*06AC.0020.0002.2509] # BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL
+250A ; [*06AD.0020.0002.250A] # BOX DRAWINGS LIGHT QUADRUPLE DASH VERTICAL
+250B ; [*06AE.0020.0002.250B] # BOX DRAWINGS HEAVY QUADRUPLE DASH VERTICAL
+250C ; [*06AF.0020.0002.250C] # BOX DRAWINGS LIGHT DOWN AND RIGHT
+250D ; [*06B0.0020.0002.250D] # BOX DRAWINGS DOWN LIGHT AND RIGHT HEAVY
+250E ; [*06B1.0020.0002.250E] # BOX DRAWINGS DOWN HEAVY AND RIGHT LIGHT
+250F ; [*06B2.0020.0002.250F] # BOX DRAWINGS HEAVY DOWN AND RIGHT
+2510 ; [*06B3.0020.0002.2510] # BOX DRAWINGS LIGHT DOWN AND LEFT
+2511 ; [*06B4.0020.0002.2511] # BOX DRAWINGS DOWN LIGHT AND LEFT HEAVY
+2512 ; [*06B5.0020.0002.2512] # BOX DRAWINGS DOWN HEAVY AND LEFT LIGHT
+2513 ; [*06B6.0020.0002.2513] # BOX DRAWINGS HEAVY DOWN AND LEFT
+2514 ; [*06B7.0020.0002.2514] # BOX DRAWINGS LIGHT UP AND RIGHT
+2515 ; [*06B8.0020.0002.2515] # BOX DRAWINGS UP LIGHT AND RIGHT HEAVY
+2516 ; [*06B9.0020.0002.2516] # BOX DRAWINGS UP HEAVY AND RIGHT LIGHT
+2517 ; [*06BA.0020.0002.2517] # BOX DRAWINGS HEAVY UP AND RIGHT
+2518 ; [*06BB.0020.0002.2518] # BOX DRAWINGS LIGHT UP AND LEFT
+2519 ; [*06BC.0020.0002.2519] # BOX DRAWINGS UP LIGHT AND LEFT HEAVY
+251A ; [*06BD.0020.0002.251A] # BOX DRAWINGS UP HEAVY AND LEFT LIGHT
+251B ; [*06BE.0020.0002.251B] # BOX DRAWINGS HEAVY UP AND LEFT
+251C ; [*06BF.0020.0002.251C] # BOX DRAWINGS LIGHT VERTICAL AND RIGHT
+251D ; [*06C0.0020.0002.251D] # BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY
+251E ; [*06C1.0020.0002.251E] # BOX DRAWINGS UP HEAVY AND RIGHT DOWN LIGHT
+251F ; [*06C2.0020.0002.251F] # BOX DRAWINGS DOWN HEAVY AND RIGHT UP LIGHT
+2520 ; [*06C3.0020.0002.2520] # BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT
+2521 ; [*06C4.0020.0002.2521] # BOX DRAWINGS DOWN LIGHT AND RIGHT UP HEAVY
+2522 ; [*06C5.0020.0002.2522] # BOX DRAWINGS UP LIGHT AND RIGHT DOWN HEAVY
+2523 ; [*06C6.0020.0002.2523] # BOX DRAWINGS HEAVY VERTICAL AND RIGHT
+2524 ; [*06C7.0020.0002.2524] # BOX DRAWINGS LIGHT VERTICAL AND LEFT
+2525 ; [*06C8.0020.0002.2525] # BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY
+2526 ; [*06C9.0020.0002.2526] # BOX DRAWINGS UP HEAVY AND LEFT DOWN LIGHT
+2527 ; [*06CA.0020.0002.2527] # BOX DRAWINGS DOWN HEAVY AND LEFT UP LIGHT
+2528 ; [*06CB.0020.0002.2528] # BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT
+2529 ; [*06CC.0020.0002.2529] # BOX DRAWINGS DOWN LIGHT AND LEFT UP HEAVY
+252A ; [*06CD.0020.0002.252A] # BOX DRAWINGS UP LIGHT AND LEFT DOWN HEAVY
+252B ; [*06CE.0020.0002.252B] # BOX DRAWINGS HEAVY VERTICAL AND LEFT
+252C ; [*06CF.0020.0002.252C] # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
+252D ; [*06D0.0020.0002.252D] # BOX DRAWINGS LEFT HEAVY AND RIGHT DOWN LIGHT
+252E ; [*06D1.0020.0002.252E] # BOX DRAWINGS RIGHT HEAVY AND LEFT DOWN LIGHT
+252F ; [*06D2.0020.0002.252F] # BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY
+2530 ; [*06D3.0020.0002.2530] # BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT
+2531 ; [*06D4.0020.0002.2531] # BOX DRAWINGS RIGHT LIGHT AND LEFT DOWN HEAVY
+2532 ; [*06D5.0020.0002.2532] # BOX DRAWINGS LEFT LIGHT AND RIGHT DOWN HEAVY
+2533 ; [*06D6.0020.0002.2533] # BOX DRAWINGS HEAVY DOWN AND HORIZONTAL
+2534 ; [*06D7.0020.0002.2534] # BOX DRAWINGS LIGHT UP AND HORIZONTAL
+2535 ; [*06D8.0020.0002.2535] # BOX DRAWINGS LEFT HEAVY AND RIGHT UP LIGHT
+2536 ; [*06D9.0020.0002.2536] # BOX DRAWINGS RIGHT HEAVY AND LEFT UP LIGHT
+2537 ; [*06DA.0020.0002.2537] # BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY
+2538 ; [*06DB.0020.0002.2538] # BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT
+2539 ; [*06DC.0020.0002.2539] # BOX DRAWINGS RIGHT LIGHT AND LEFT UP HEAVY
+253A ; [*06DD.0020.0002.253A] # BOX DRAWINGS LEFT LIGHT AND RIGHT UP HEAVY
+253B ; [*06DE.0020.0002.253B] # BOX DRAWINGS HEAVY UP AND HORIZONTAL
+253C ; [*06DF.0020.0002.253C] # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
+253D ; [*06E0.0020.0002.253D] # BOX DRAWINGS LEFT HEAVY AND RIGHT VERTICAL LIGHT
+253E ; [*06E1.0020.0002.253E] # BOX DRAWINGS RIGHT HEAVY AND LEFT VERTICAL LIGHT
+253F ; [*06E2.0020.0002.253F] # BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY
+2540 ; [*06E3.0020.0002.2540] # BOX DRAWINGS UP HEAVY AND DOWN HORIZONTAL LIGHT
+2541 ; [*06E4.0020.0002.2541] # BOX DRAWINGS DOWN HEAVY AND UP HORIZONTAL LIGHT
+2542 ; [*06E5.0020.0002.2542] # BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT
+2543 ; [*06E6.0020.0002.2543] # BOX DRAWINGS LEFT UP HEAVY AND RIGHT DOWN LIGHT
+2544 ; [*06E7.0020.0002.2544] # BOX DRAWINGS RIGHT UP HEAVY AND LEFT DOWN LIGHT
+2545 ; [*06E8.0020.0002.2545] # BOX DRAWINGS LEFT DOWN HEAVY AND RIGHT UP LIGHT
+2546 ; [*06E9.0020.0002.2546] # BOX DRAWINGS RIGHT DOWN HEAVY AND LEFT UP LIGHT
+2547 ; [*06EA.0020.0002.2547] # BOX DRAWINGS DOWN LIGHT AND UP HORIZONTAL HEAVY
+2548 ; [*06EB.0020.0002.2548] # BOX DRAWINGS UP LIGHT AND DOWN HORIZONTAL HEAVY
+2549 ; [*06EC.0020.0002.2549] # BOX DRAWINGS RIGHT LIGHT AND LEFT VERTICAL HEAVY
+254A ; [*06ED.0020.0002.254A] # BOX DRAWINGS LEFT LIGHT AND RIGHT VERTICAL HEAVY
+254B ; [*06EE.0020.0002.254B] # BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL
+254C ; [*06EF.0020.0002.254C] # BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL
+254D ; [*06F0.0020.0002.254D] # BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL
+254E ; [*06F1.0020.0002.254E] # BOX DRAWINGS LIGHT DOUBLE DASH VERTICAL
+254F ; [*06F2.0020.0002.254F] # BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL
+2550 ; [*06F3.0020.0002.2550] # BOX DRAWINGS DOUBLE HORIZONTAL
+2551 ; [*06F4.0020.0002.2551] # BOX DRAWINGS DOUBLE VERTICAL
+2552 ; [*06F5.0020.0002.2552] # BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
+2553 ; [*06F6.0020.0002.2553] # BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
+2554 ; [*06F7.0020.0002.2554] # BOX DRAWINGS DOUBLE DOWN AND RIGHT
+2555 ; [*06F8.0020.0002.2555] # BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
+2556 ; [*06F9.0020.0002.2556] # BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
+2557 ; [*06FA.0020.0002.2557] # BOX DRAWINGS DOUBLE DOWN AND LEFT
+2558 ; [*06FB.0020.0002.2558] # BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
+2559 ; [*06FC.0020.0002.2559] # BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
+255A ; [*06FD.0020.0002.255A] # BOX DRAWINGS DOUBLE UP AND RIGHT
+255B ; [*06FE.0020.0002.255B] # BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
+255C ; [*06FF.0020.0002.255C] # BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
+255D ; [*0700.0020.0002.255D] # BOX DRAWINGS DOUBLE UP AND LEFT
+255E ; [*0701.0020.0002.255E] # BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
+255F ; [*0702.0020.0002.255F] # BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
+2560 ; [*0703.0020.0002.2560] # BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
+2561 ; [*0704.0020.0002.2561] # BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
+2562 ; [*0705.0020.0002.2562] # BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
+2563 ; [*0706.0020.0002.2563] # BOX DRAWINGS DOUBLE VERTICAL AND LEFT
+2564 ; [*0707.0020.0002.2564] # BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
+2565 ; [*0708.0020.0002.2565] # BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
+2566 ; [*0709.0020.0002.2566] # BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
+2567 ; [*070A.0020.0002.2567] # BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
+2568 ; [*070B.0020.0002.2568] # BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
+2569 ; [*070C.0020.0002.2569] # BOX DRAWINGS DOUBLE UP AND HORIZONTAL
+256A ; [*070D.0020.0002.256A] # BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
+256B ; [*070E.0020.0002.256B] # BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
+256C ; [*070F.0020.0002.256C] # BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
+256D ; [*0710.0020.0002.256D] # BOX DRAWINGS LIGHT ARC DOWN AND RIGHT
+256E ; [*0711.0020.0002.256E] # BOX DRAWINGS LIGHT ARC DOWN AND LEFT
+256F ; [*0712.0020.0002.256F] # BOX DRAWINGS LIGHT ARC UP AND LEFT
+2570 ; [*0713.0020.0002.2570] # BOX DRAWINGS LIGHT ARC UP AND RIGHT
+2571 ; [*0714.0020.0002.2571] # BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT
+2572 ; [*0715.0020.0002.2572] # BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT
+2573 ; [*0716.0020.0002.2573] # BOX DRAWINGS LIGHT DIAGONAL CROSS
+2574 ; [*0717.0020.0002.2574] # BOX DRAWINGS LIGHT LEFT
+2575 ; [*0718.0020.0002.2575] # BOX DRAWINGS LIGHT UP
+2576 ; [*0719.0020.0002.2576] # BOX DRAWINGS LIGHT RIGHT
+2577 ; [*071A.0020.0002.2577] # BOX DRAWINGS LIGHT DOWN
+2578 ; [*071B.0020.0002.2578] # BOX DRAWINGS HEAVY LEFT
+2579 ; [*071C.0020.0002.2579] # BOX DRAWINGS HEAVY UP
+257A ; [*071D.0020.0002.257A] # BOX DRAWINGS HEAVY RIGHT
+257B ; [*071E.0020.0002.257B] # BOX DRAWINGS HEAVY DOWN
+257C ; [*071F.0020.0002.257C] # BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT
+257D ; [*0720.0020.0002.257D] # BOX DRAWINGS LIGHT UP AND HEAVY DOWN
+257E ; [*0721.0020.0002.257E] # BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT
+257F ; [*0722.0020.0002.257F] # BOX DRAWINGS HEAVY UP AND LIGHT DOWN
+2580 ; [*0723.0020.0002.2580] # UPPER HALF BLOCK
+2581 ; [*0724.0020.0002.2581] # LOWER ONE EIGHTH BLOCK
+2582 ; [*0725.0020.0002.2582] # LOWER ONE QUARTER BLOCK
+2583 ; [*0726.0020.0002.2583] # LOWER THREE EIGHTHS BLOCK
+2584 ; [*0727.0020.0002.2584] # LOWER HALF BLOCK
+2585 ; [*0728.0020.0002.2585] # LOWER FIVE EIGHTHS BLOCK
+2586 ; [*0729.0020.0002.2586] # LOWER THREE QUARTERS BLOCK
+2587 ; [*072A.0020.0002.2587] # LOWER SEVEN EIGHTHS BLOCK
+2588 ; [*072B.0020.0002.2588] # FULL BLOCK
+2589 ; [*072C.0020.0002.2589] # LEFT SEVEN EIGHTHS BLOCK
+258A ; [*072D.0020.0002.258A] # LEFT THREE QUARTERS BLOCK
+258B ; [*072E.0020.0002.258B] # LEFT FIVE EIGHTHS BLOCK
+258C ; [*072F.0020.0002.258C] # LEFT HALF BLOCK
+258D ; [*0730.0020.0002.258D] # LEFT THREE EIGHTHS BLOCK
+258E ; [*0731.0020.0002.258E] # LEFT ONE QUARTER BLOCK
+258F ; [*0732.0020.0002.258F] # LEFT ONE EIGHTH BLOCK
+2590 ; [*0733.0020.0002.2590] # RIGHT HALF BLOCK
+2591 ; [*0734.0020.0002.2591] # LIGHT SHADE
+2592 ; [*0735.0020.0002.2592] # MEDIUM SHADE
+2593 ; [*0736.0020.0002.2593] # DARK SHADE
+2594 ; [*0737.0020.0002.2594] # UPPER ONE EIGHTH BLOCK
+2595 ; [*0738.0020.0002.2595] # RIGHT ONE EIGHTH BLOCK
+2596 ; [*0739.0020.0002.2596] # QUADRANT LOWER LEFT
+2597 ; [*073A.0020.0002.2597] # QUADRANT LOWER RIGHT
+2598 ; [*073B.0020.0002.2598] # QUADRANT UPPER LEFT
+2599 ; [*073C.0020.0002.2599] # QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT
+259A ; [*073D.0020.0002.259A] # QUADRANT UPPER LEFT AND LOWER RIGHT
+259B ; [*073E.0020.0002.259B] # QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT
+259C ; [*073F.0020.0002.259C] # QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT
+259D ; [*0740.0020.0002.259D] # QUADRANT UPPER RIGHT
+259E ; [*0741.0020.0002.259E] # QUADRANT UPPER RIGHT AND LOWER LEFT
+259F ; [*0742.0020.0002.259F] # QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT
+25A0 ; [*0743.0020.0002.25A0] # BLACK SQUARE
+25A1 ; [*0744.0020.0002.25A1] # WHITE SQUARE
+25A2 ; [*0745.0020.0002.25A2] # WHITE SQUARE WITH ROUNDED CORNERS
+25A3 ; [*0746.0020.0002.25A3] # WHITE SQUARE CONTAINING BLACK SMALL SQUARE
+25A4 ; [*0747.0020.0002.25A4] # SQUARE WITH HORIZONTAL FILL
+25A5 ; [*0748.0020.0002.25A5] # SQUARE WITH VERTICAL FILL
+25A6 ; [*0749.0020.0002.25A6] # SQUARE WITH ORTHOGONAL CROSSHATCH FILL
+25A7 ; [*074A.0020.0002.25A7] # SQUARE WITH UPPER LEFT TO LOWER RIGHT FILL
+25A8 ; [*074B.0020.0002.25A8] # SQUARE WITH UPPER RIGHT TO LOWER LEFT FILL
+25A9 ; [*074C.0020.0002.25A9] # SQUARE WITH DIAGONAL CROSSHATCH FILL
+25AA ; [*074D.0020.0002.25AA] # BLACK SMALL SQUARE
+25AB ; [*074E.0020.0002.25AB] # WHITE SMALL SQUARE
+25AC ; [*074F.0020.0002.25AC] # BLACK RECTANGLE
+25AD ; [*0750.0020.0002.25AD] # WHITE RECTANGLE
+25AE ; [*0751.0020.0002.25AE] # BLACK VERTICAL RECTANGLE
+25AF ; [*0752.0020.0002.25AF] # WHITE VERTICAL RECTANGLE
+25B0 ; [*0753.0020.0002.25B0] # BLACK PARALLELOGRAM
+25B1 ; [*0754.0020.0002.25B1] # WHITE PARALLELOGRAM
+25B2 ; [*0755.0020.0002.25B2] # BLACK UP-POINTING TRIANGLE
+25B3 ; [*0756.0020.0002.25B3] # WHITE UP-POINTING TRIANGLE
+25B4 ; [*0757.0020.0002.25B4] # BLACK UP-POINTING SMALL TRIANGLE
+25B5 ; [*0758.0020.0002.25B5] # WHITE UP-POINTING SMALL TRIANGLE
+25B6 ; [*0759.0020.0002.25B6] # BLACK RIGHT-POINTING TRIANGLE
+25B7 ; [*075A.0020.0002.25B7] # WHITE RIGHT-POINTING TRIANGLE
+25B8 ; [*075B.0020.0002.25B8] # BLACK RIGHT-POINTING SMALL TRIANGLE
+25B9 ; [*075C.0020.0002.25B9] # WHITE RIGHT-POINTING SMALL TRIANGLE
+25BA ; [*075D.0020.0002.25BA] # BLACK RIGHT-POINTING POINTER
+25BB ; [*075E.0020.0002.25BB] # WHITE RIGHT-POINTING POINTER
+25BC ; [*075F.0020.0002.25BC] # BLACK DOWN-POINTING TRIANGLE
+25BD ; [*0760.0020.0002.25BD] # WHITE DOWN-POINTING TRIANGLE
+25BE ; [*0761.0020.0002.25BE] # BLACK DOWN-POINTING SMALL TRIANGLE
+25BF ; [*0762.0020.0002.25BF] # WHITE DOWN-POINTING SMALL TRIANGLE
+25C0 ; [*0763.0020.0002.25C0] # BLACK LEFT-POINTING TRIANGLE
+25C1 ; [*0764.0020.0002.25C1] # WHITE LEFT-POINTING TRIANGLE
+25C2 ; [*0765.0020.0002.25C2] # BLACK LEFT-POINTING SMALL TRIANGLE
+25C3 ; [*0766.0020.0002.25C3] # WHITE LEFT-POINTING SMALL TRIANGLE
+25C4 ; [*0767.0020.0002.25C4] # BLACK LEFT-POINTING POINTER
+25C5 ; [*0768.0020.0002.25C5] # WHITE LEFT-POINTING POINTER
+25C6 ; [*0769.0020.0002.25C6] # BLACK DIAMOND
+25C7 ; [*076A.0020.0002.25C7] # WHITE DIAMOND
+25C8 ; [*076B.0020.0002.25C8] # WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND
+25C9 ; [*076C.0020.0002.25C9] # FISHEYE
+25CA ; [*076D.0020.0002.25CA] # LOZENGE
+25CB ; [*076E.0020.0002.25CB] # WHITE CIRCLE
+25CC ; [*076F.0020.0002.25CC] # DOTTED CIRCLE
+25CD ; [*0770.0020.0002.25CD] # CIRCLE WITH VERTICAL FILL
+25CE ; [*0771.0020.0002.25CE] # BULLSEYE
+25CF ; [*0772.0020.0002.25CF] # BLACK CIRCLE
+25D0 ; [*0773.0020.0002.25D0] # CIRCLE WITH LEFT HALF BLACK
+25D1 ; [*0774.0020.0002.25D1] # CIRCLE WITH RIGHT HALF BLACK
+25D2 ; [*0775.0020.0002.25D2] # CIRCLE WITH LOWER HALF BLACK
+25D3 ; [*0776.0020.0002.25D3] # CIRCLE WITH UPPER HALF BLACK
+25D4 ; [*0777.0020.0002.25D4] # CIRCLE WITH UPPER RIGHT QUADRANT BLACK
+25D5 ; [*0778.0020.0002.25D5] # CIRCLE WITH ALL BUT UPPER LEFT QUADRANT BLACK
+25D6 ; [*0779.0020.0002.25D6] # LEFT HALF BLACK CIRCLE
+25D7 ; [*077A.0020.0002.25D7] # RIGHT HALF BLACK CIRCLE
+25D8 ; [*077B.0020.0002.25D8] # INVERSE BULLET
+25D9 ; [*077C.0020.0002.25D9] # INVERSE WHITE CIRCLE
+25DA ; [*077D.0020.0002.25DA] # UPPER HALF INVERSE WHITE CIRCLE
+25DB ; [*077E.0020.0002.25DB] # LOWER HALF INVERSE WHITE CIRCLE
+25DC ; [*077F.0020.0002.25DC] # UPPER LEFT QUADRANT CIRCULAR ARC
+25DD ; [*0780.0020.0002.25DD] # UPPER RIGHT QUADRANT CIRCULAR ARC
+25DE ; [*0781.0020.0002.25DE] # LOWER RIGHT QUADRANT CIRCULAR ARC
+25DF ; [*0782.0020.0002.25DF] # LOWER LEFT QUADRANT CIRCULAR ARC
+25E0 ; [*0783.0020.0002.25E0] # UPPER HALF CIRCLE
+25E1 ; [*0784.0020.0002.25E1] # LOWER HALF CIRCLE
+25E2 ; [*0785.0020.0002.25E2] # BLACK LOWER RIGHT TRIANGLE
+25E3 ; [*0786.0020.0002.25E3] # BLACK LOWER LEFT TRIANGLE
+25E4 ; [*0787.0020.0002.25E4] # BLACK UPPER LEFT TRIANGLE
+25E5 ; [*0788.0020.0002.25E5] # BLACK UPPER RIGHT TRIANGLE
+25E6 ; [*0789.0020.0002.25E6] # WHITE BULLET
+25E7 ; [*078A.0020.0002.25E7] # SQUARE WITH LEFT HALF BLACK
+25E8 ; [*078B.0020.0002.25E8] # SQUARE WITH RIGHT HALF BLACK
+25E9 ; [*078C.0020.0002.25E9] # SQUARE WITH UPPER LEFT DIAGONAL HALF BLACK
+25EA ; [*078D.0020.0002.25EA] # SQUARE WITH LOWER RIGHT DIAGONAL HALF BLACK
+25EB ; [*078E.0020.0002.25EB] # WHITE SQUARE WITH VERTICAL BISECTING LINE
+25EC ; [*078F.0020.0002.25EC] # WHITE UP-POINTING TRIANGLE WITH DOT
+25ED ; [*0790.0020.0002.25ED] # UP-POINTING TRIANGLE WITH LEFT HALF BLACK
+25EE ; [*0791.0020.0002.25EE] # UP-POINTING TRIANGLE WITH RIGHT HALF BLACK
+25EF ; [*0792.0020.0002.25EF] # LARGE CIRCLE
+25F0 ; [*0793.0020.0002.25F0] # WHITE SQUARE WITH UPPER LEFT QUADRANT
+25F1 ; [*0794.0020.0002.25F1] # WHITE SQUARE WITH LOWER LEFT QUADRANT
+25F2 ; [*0795.0020.0002.25F2] # WHITE SQUARE WITH LOWER RIGHT QUADRANT
+25F3 ; [*0796.0020.0002.25F3] # WHITE SQUARE WITH UPPER RIGHT QUADRANT
+25F4 ; [*0797.0020.0002.25F4] # WHITE CIRCLE WITH UPPER LEFT QUADRANT
+25F5 ; [*0798.0020.0002.25F5] # WHITE CIRCLE WITH LOWER LEFT QUADRANT
+25F6 ; [*0799.0020.0002.25F6] # WHITE CIRCLE WITH LOWER RIGHT QUADRANT
+25F7 ; [*079A.0020.0002.25F7] # WHITE CIRCLE WITH UPPER RIGHT QUADRANT
+25F8 ; [*079B.0020.0002.25F8] # UPPER LEFT TRIANGLE
+25F9 ; [*079C.0020.0002.25F9] # UPPER RIGHT TRIANGLE
+25FA ; [*079D.0020.0002.25FA] # LOWER LEFT TRIANGLE
+25FB ; [*079E.0020.0002.25FB] # WHITE MEDIUM SQUARE
+25FC ; [*079F.0020.0002.25FC] # BLACK MEDIUM SQUARE
+25FD ; [*07A0.0020.0002.25FD] # WHITE MEDIUM SMALL SQUARE
+25FE ; [*07A1.0020.0002.25FE] # BLACK MEDIUM SMALL SQUARE
+25FF ; [*07A2.0020.0002.25FF] # LOWER RIGHT TRIANGLE
+2600 ; [*07A3.0020.0002.2600] # BLACK SUN WITH RAYS
+2601 ; [*07A4.0020.0002.2601] # CLOUD
+2602 ; [*07A5.0020.0002.2602] # UMBRELLA
+2603 ; [*07A6.0020.0002.2603] # SNOWMAN
+2604 ; [*07A7.0020.0002.2604] # COMET
+2605 ; [*07A8.0020.0002.2605] # BLACK STAR
+2606 ; [*07A9.0020.0002.2606] # WHITE STAR
+2607 ; [*07AA.0020.0002.2607] # LIGHTNING
+2608 ; [*07AB.0020.0002.2608] # THUNDERSTORM
+2609 ; [*07AC.0020.0002.2609] # SUN
+260A ; [*07AD.0020.0002.260A] # ASCENDING NODE
+260B ; [*07AE.0020.0002.260B] # DESCENDING NODE
+260C ; [*07AF.0020.0002.260C] # CONJUNCTION
+260D ; [*07B0.0020.0002.260D] # OPPOSITION
+260E ; [*07B1.0020.0002.260E] # BLACK TELEPHONE
+260F ; [*07B2.0020.0002.260F] # WHITE TELEPHONE
+2610 ; [*07B3.0020.0002.2610] # BALLOT BOX
+2611 ; [*07B4.0020.0002.2611] # BALLOT BOX WITH CHECK
+2612 ; [*07B5.0020.0002.2612] # BALLOT BOX WITH X
+2613 ; [*07B6.0020.0002.2613] # SALTIRE
+2614 ; [*07B7.0020.0002.2614] # UMBRELLA WITH RAIN DROPS
+2615 ; [*07B8.0020.0002.2615] # HOT BEVERAGE
+2616 ; [*07B9.0020.0002.2616] # WHITE SHOGI PIECE
+2617 ; [*07BA.0020.0002.2617] # BLACK SHOGI PIECE
+2618 ; [*07BB.0020.0002.2618] # SHAMROCK
+2619 ; [*07BC.0020.0002.2619] # REVERSED ROTATED FLORAL HEART BULLET
+261A ; [*07BD.0020.0002.261A] # BLACK LEFT POINTING INDEX
+261B ; [*07BE.0020.0002.261B] # BLACK RIGHT POINTING INDEX
+261C ; [*07BF.0020.0002.261C] # WHITE LEFT POINTING INDEX
+261D ; [*07C0.0020.0002.261D] # WHITE UP POINTING INDEX
+261E ; [*07C1.0020.0002.261E] # WHITE RIGHT POINTING INDEX
+261F ; [*07C2.0020.0002.261F] # WHITE DOWN POINTING INDEX
+2620 ; [*07C3.0020.0002.2620] # SKULL AND CROSSBONES
+2621 ; [*07C4.0020.0002.2621] # CAUTION SIGN
+2622 ; [*07C5.0020.0002.2622] # RADIOACTIVE SIGN
+2623 ; [*07C6.0020.0002.2623] # BIOHAZARD SIGN
+2624 ; [*07C7.0020.0002.2624] # CADUCEUS
+2625 ; [*07C8.0020.0002.2625] # ANKH
+2626 ; [*07C9.0020.0002.2626] # ORTHODOX CROSS
+2627 ; [*07CA.0020.0002.2627] # CHI RHO
+2628 ; [*07CB.0020.0002.2628] # CROSS OF LORRAINE
+2629 ; [*07CC.0020.0002.2629] # CROSS OF JERUSALEM
+262A ; [*07CD.0020.0002.262A] # STAR AND CRESCENT
+262B ; [*07CE.0020.0002.262B] # FARSI SYMBOL
+262C ; [*07CF.0020.0002.262C] # ADI SHAKTI
+262D ; [*07D0.0020.0002.262D] # HAMMER AND SICKLE
+262E ; [*07D1.0020.0002.262E] # PEACE SYMBOL
+262F ; [*07D2.0020.0002.262F] # YIN YANG
+2630 ; [*0C17.0020.0002.2630] # TRIGRAM FOR HEAVEN
+2631 ; [*0C18.0020.0002.2631] # TRIGRAM FOR LAKE
+2632 ; [*0C19.0020.0002.2632] # TRIGRAM FOR FIRE
+2633 ; [*0C1A.0020.0002.2633] # TRIGRAM FOR THUNDER
+2634 ; [*0C1B.0020.0002.2634] # TRIGRAM FOR WIND
+2635 ; [*0C1C.0020.0002.2635] # TRIGRAM FOR WATER
+2636 ; [*0C1D.0020.0002.2636] # TRIGRAM FOR MOUNTAIN
+2637 ; [*0C1E.0020.0002.2637] # TRIGRAM FOR EARTH
+2638 ; [*07D3.0020.0002.2638] # WHEEL OF DHARMA
+2639 ; [*07D4.0020.0002.2639] # WHITE FROWNING FACE
+263A ; [*07D5.0020.0002.263A] # WHITE SMILING FACE
+263B ; [*07D6.0020.0002.263B] # BLACK SMILING FACE
+263C ; [*07D7.0020.0002.263C] # WHITE SUN WITH RAYS
+263D ; [*07D8.0020.0002.263D] # FIRST QUARTER MOON
+263E ; [*07D9.0020.0002.263E] # LAST QUARTER MOON
+263F ; [*07DA.0020.0002.263F] # MERCURY
+2640 ; [*07DB.0020.0002.2640] # FEMALE SIGN
+2641 ; [*07DC.0020.0002.2641] # EARTH
+2642 ; [*07DD.0020.0002.2642] # MALE SIGN
+2643 ; [*07DE.0020.0002.2643] # JUPITER
+2644 ; [*07DF.0020.0002.2644] # SATURN
+2645 ; [*07E0.0020.0002.2645] # URANUS
+2646 ; [*07E1.0020.0002.2646] # NEPTUNE
+2647 ; [*07E2.0020.0002.2647] # PLUTO
+2648 ; [*07E3.0020.0002.2648] # ARIES
+2649 ; [*07E4.0020.0002.2649] # TAURUS
+264A ; [*07E5.0020.0002.264A] # GEMINI
+264B ; [*07E6.0020.0002.264B] # CANCER
+264C ; [*07E7.0020.0002.264C] # LEO
+264D ; [*07E8.0020.0002.264D] # VIRGO
+264E ; [*07E9.0020.0002.264E] # LIBRA
+264F ; [*07EA.0020.0002.264F] # SCORPIUS
+2650 ; [*07EB.0020.0002.2650] # SAGITTARIUS
+2651 ; [*07EC.0020.0002.2651] # CAPRICORN
+2652 ; [*07ED.0020.0002.2652] # AQUARIUS
+2653 ; [*07EE.0020.0002.2653] # PISCES
+2654 ; [*07EF.0020.0002.2654] # WHITE CHESS KING
+2655 ; [*07F0.0020.0002.2655] # WHITE CHESS QUEEN
+2656 ; [*07F1.0020.0002.2656] # WHITE CHESS ROOK
+2657 ; [*07F2.0020.0002.2657] # WHITE CHESS BISHOP
+2658 ; [*07F3.0020.0002.2658] # WHITE CHESS KNIGHT
+2659 ; [*07F4.0020.0002.2659] # WHITE CHESS PAWN
+265A ; [*07F5.0020.0002.265A] # BLACK CHESS KING
+265B ; [*07F6.0020.0002.265B] # BLACK CHESS QUEEN
+265C ; [*07F7.0020.0002.265C] # BLACK CHESS ROOK
+265D ; [*07F8.0020.0002.265D] # BLACK CHESS BISHOP
+265E ; [*07F9.0020.0002.265E] # BLACK CHESS KNIGHT
+265F ; [*07FA.0020.0002.265F] # BLACK CHESS PAWN
+2660 ; [*07FB.0020.0002.2660] # BLACK SPADE SUIT
+2661 ; [*07FC.0020.0002.2661] # WHITE HEART SUIT
+2662 ; [*07FD.0020.0002.2662] # WHITE DIAMOND SUIT
+2663 ; [*07FE.0020.0002.2663] # BLACK CLUB SUIT
+2664 ; [*07FF.0020.0002.2664] # WHITE SPADE SUIT
+2665 ; [*0800.0020.0002.2665] # BLACK HEART SUIT
+2666 ; [*0801.0020.0002.2666] # BLACK DIAMOND SUIT
+2667 ; [*0802.0020.0002.2667] # WHITE CLUB SUIT
+2668 ; [*0803.0020.0002.2668] # HOT SPRINGS
+2669 ; [*0804.0020.0002.2669] # QUARTER NOTE
+266A ; [*0805.0020.0002.266A] # EIGHTH NOTE
+266B ; [*0806.0020.0002.266B] # BEAMED EIGHTH NOTES
+266C ; [*0807.0020.0002.266C] # BEAMED SIXTEENTH NOTES
+266D ; [*0E24.0020.0002.266D] # MUSIC FLAT SIGN
+266E ; [*0E25.0020.0002.266E] # MUSIC NATURAL SIGN
+266F ; [*0E26.0020.0002.266F] # MUSIC SHARP SIGN
+2670 ; [*0808.0020.0002.2670] # WEST SYRIAC CROSS
+2671 ; [*0809.0020.0002.2671] # EAST SYRIAC CROSS
+2672 ; [*080A.0020.0002.2672] # UNIVERSAL RECYCLING SYMBOL
+2673 ; [*080B.0020.0002.2673] # RECYCLING SYMBOL FOR TYPE-1 PLASTICS
+2674 ; [*080C.0020.0002.2674] # RECYCLING SYMBOL FOR TYPE-2 PLASTICS
+2675 ; [*080D.0020.0002.2675] # RECYCLING SYMBOL FOR TYPE-3 PLASTICS
+2676 ; [*080E.0020.0002.2676] # RECYCLING SYMBOL FOR TYPE-4 PLASTICS
+2677 ; [*080F.0020.0002.2677] # RECYCLING SYMBOL FOR TYPE-5 PLASTICS
+2678 ; [*0810.0020.0002.2678] # RECYCLING SYMBOL FOR TYPE-6 PLASTICS
+2679 ; [*0811.0020.0002.2679] # RECYCLING SYMBOL FOR TYPE-7 PLASTICS
+267A ; [*0812.0020.0002.267A] # RECYCLING SYMBOL FOR GENERIC MATERIALS
+267B ; [*0813.0020.0002.267B] # BLACK UNIVERSAL RECYCLING SYMBOL
+267C ; [*0814.0020.0002.267C] # RECYCLED PAPER SYMBOL
+267D ; [*0815.0020.0002.267D] # PARTIALLY-RECYCLED PAPER SYMBOL
+267E ; [*0816.0020.0002.267E] # PERMANENT PAPER SIGN
+267F ; [*0817.0020.0002.267F] # WHEELCHAIR SYMBOL
+2680 ; [*0818.0020.0002.2680] # DIE FACE-1
+2681 ; [*0819.0020.0002.2681] # DIE FACE-2
+2682 ; [*081A.0020.0002.2682] # DIE FACE-3
+2683 ; [*081B.0020.0002.2683] # DIE FACE-4
+2684 ; [*081C.0020.0002.2684] # DIE FACE-5
+2685 ; [*081D.0020.0002.2685] # DIE FACE-6
+2686 ; [*081E.0020.0002.2686] # WHITE CIRCLE WITH DOT RIGHT
+2687 ; [*081F.0020.0002.2687] # WHITE CIRCLE WITH TWO DOTS
+2688 ; [*0820.0020.0002.2688] # BLACK CIRCLE WITH WHITE DOT RIGHT
+2689 ; [*0821.0020.0002.2689] # BLACK CIRCLE WITH TWO WHITE DOTS
+268A ; [*0C11.0020.0002.268A] # MONOGRAM FOR YANG
+268B ; [*0C12.0020.0002.268B] # MONOGRAM FOR YIN
+268C ; [*0C13.0020.0002.268C] # DIGRAM FOR GREATER YANG
+268D ; [*0C14.0020.0002.268D] # DIGRAM FOR LESSER YIN
+268E ; [*0C15.0020.0002.268E] # DIGRAM FOR LESSER YANG
+268F ; [*0C16.0020.0002.268F] # DIGRAM FOR GREATER YIN
+2690 ; [*0822.0020.0002.2690] # WHITE FLAG
+2691 ; [*0823.0020.0002.2691] # BLACK FLAG
+2692 ; [*0824.0020.0002.2692] # HAMMER AND PICK
+2693 ; [*0825.0020.0002.2693] # ANCHOR
+2694 ; [*0826.0020.0002.2694] # CROSSED SWORDS
+2695 ; [*0827.0020.0002.2695] # STAFF OF AESCULAPIUS
+2696 ; [*0828.0020.0002.2696] # SCALES
+2697 ; [*0829.0020.0002.2697] # ALEMBIC
+2698 ; [*082A.0020.0002.2698] # FLOWER
+2699 ; [*082B.0020.0002.2699] # GEAR
+269A ; [*082C.0020.0002.269A] # STAFF OF HERMES
+269B ; [*082D.0020.0002.269B] # ATOM SYMBOL
+269C ; [*082E.0020.0002.269C] # FLEUR-DE-LIS
+26A0 ; [*082F.0020.0002.26A0] # WARNING SIGN
+26A1 ; [*0830.0020.0002.26A1] # HIGH VOLTAGE SIGN
+26A2 ; [*0831.0020.0002.26A2] # DOUBLED FEMALE SIGN
+26A3 ; [*0832.0020.0002.26A3] # DOUBLED MALE SIGN
+26A4 ; [*0833.0020.0002.26A4] # INTERLOCKED FEMALE AND MALE SIGN
+26A5 ; [*0834.0020.0002.26A5] # MALE AND FEMALE SIGN
+26A6 ; [*0835.0020.0002.26A6] # MALE WITH STROKE SIGN
+26A7 ; [*0836.0020.0002.26A7] # MALE WITH STROKE AND MALE AND FEMALE SIGN
+26A8 ; [*0837.0020.0002.26A8] # VERTICAL MALE WITH STROKE SIGN
+26A9 ; [*0838.0020.0002.26A9] # HORIZONTAL MALE WITH STROKE SIGN
+26AA ; [*0839.0020.0002.26AA] # MEDIUM WHITE CIRCLE
+26AB ; [*083A.0020.0002.26AB] # MEDIUM BLACK CIRCLE
+26AC ; [*083B.0020.0002.26AC] # MEDIUM SMALL WHITE CIRCLE
+26AD ; [*083C.0020.0002.26AD] # MARRIAGE SYMBOL
+26AE ; [*083D.0020.0002.26AE] # DIVORCE SYMBOL
+26AF ; [*083E.0020.0002.26AF] # UNMARRIED PARTNERSHIP SYMBOL
+26B0 ; [*083F.0020.0002.26B0] # COFFIN
+26B1 ; [*0840.0020.0002.26B1] # FUNERAL URN
+26B2 ; [*0841.0020.0002.26B2] # NEUTER
+2701 ; [*0842.0020.0002.2701] # UPPER BLADE SCISSORS
+2702 ; [*0843.0020.0002.2702] # BLACK SCISSORS
+2703 ; [*0844.0020.0002.2703] # LOWER BLADE SCISSORS
+2704 ; [*0845.0020.0002.2704] # WHITE SCISSORS
+2706 ; [*0846.0020.0002.2706] # TELEPHONE LOCATION SIGN
+2707 ; [*0847.0020.0002.2707] # TAPE DRIVE
+2708 ; [*0848.0020.0002.2708] # AIRPLANE
+2709 ; [*0849.0020.0002.2709] # ENVELOPE
+270C ; [*084A.0020.0002.270C] # VICTORY HAND
+270D ; [*084B.0020.0002.270D] # WRITING HAND
+270E ; [*084C.0020.0002.270E] # LOWER RIGHT PENCIL
+270F ; [*084D.0020.0002.270F] # PENCIL
+2710 ; [*084E.0020.0002.2710] # UPPER RIGHT PENCIL
+2711 ; [*084F.0020.0002.2711] # WHITE NIB
+2712 ; [*0850.0020.0002.2712] # BLACK NIB
+2713 ; [*0851.0020.0002.2713] # CHECK MARK
+2714 ; [*0852.0020.0002.2714] # HEAVY CHECK MARK
+2715 ; [*0853.0020.0002.2715] # MULTIPLICATION X
+2716 ; [*0854.0020.0002.2716] # HEAVY MULTIPLICATION X
+2717 ; [*0855.0020.0002.2717] # BALLOT X
+2718 ; [*0856.0020.0002.2718] # HEAVY BALLOT X
+2719 ; [*0857.0020.0002.2719] # OUTLINED GREEK CROSS
+271A ; [*0858.0020.0002.271A] # HEAVY GREEK CROSS
+271B ; [*0859.0020.0002.271B] # OPEN CENTRE CROSS
+271C ; [*085A.0020.0002.271C] # HEAVY OPEN CENTRE CROSS
+271D ; [*085B.0020.0002.271D] # LATIN CROSS
+271E ; [*085C.0020.0002.271E] # SHADOWED WHITE LATIN CROSS
+271F ; [*085D.0020.0002.271F] # OUTLINED LATIN CROSS
+2720 ; [*085E.0020.0002.2720] # MALTESE CROSS
+2721 ; [*085F.0020.0002.2721] # STAR OF DAVID
+2722 ; [*0860.0020.0002.2722] # FOUR TEARDROP-SPOKED ASTERISK
+2723 ; [*0861.0020.0002.2723] # FOUR BALLOON-SPOKED ASTERISK
+2724 ; [*0862.0020.0002.2724] # HEAVY FOUR BALLOON-SPOKED ASTERISK
+2725 ; [*0863.0020.0002.2725] # FOUR CLUB-SPOKED ASTERISK
+2726 ; [*0864.0020.0002.2726] # BLACK FOUR POINTED STAR
+2727 ; [*0865.0020.0002.2727] # WHITE FOUR POINTED STAR
+2729 ; [*0866.0020.0002.2729] # STRESS OUTLINED WHITE STAR
+272A ; [*0867.0020.0002.272A] # CIRCLED WHITE STAR
+272B ; [*0868.0020.0002.272B] # OPEN CENTRE BLACK STAR
+272C ; [*0869.0020.0002.272C] # BLACK CENTRE WHITE STAR
+272D ; [*086A.0020.0002.272D] # OUTLINED BLACK STAR
+272E ; [*086B.0020.0002.272E] # HEAVY OUTLINED BLACK STAR
+272F ; [*086C.0020.0002.272F] # PINWHEEL STAR
+2730 ; [*086D.0020.0002.2730] # SHADOWED WHITE STAR
+2731 ; [*086E.0020.0002.2731] # HEAVY ASTERISK
+2732 ; [*086F.0020.0002.2732] # OPEN CENTRE ASTERISK
+2733 ; [*0870.0020.0002.2733] # EIGHT SPOKED ASTERISK
+2734 ; [*0871.0020.0002.2734] # EIGHT POINTED BLACK STAR
+2735 ; [*0872.0020.0002.2735] # EIGHT POINTED PINWHEEL STAR
+2736 ; [*0873.0020.0002.2736] # SIX POINTED BLACK STAR
+2737 ; [*0874.0020.0002.2737] # EIGHT POINTED RECTILINEAR BLACK STAR
+2738 ; [*0875.0020.0002.2738] # HEAVY EIGHT POINTED RECTILINEAR BLACK STAR
+2739 ; [*0876.0020.0002.2739] # TWELVE POINTED BLACK STAR
+273A ; [*0877.0020.0002.273A] # SIXTEEN POINTED ASTERISK
+273B ; [*0878.0020.0002.273B] # TEARDROP-SPOKED ASTERISK
+273C ; [*0879.0020.0002.273C] # OPEN CENTRE TEARDROP-SPOKED ASTERISK
+273D ; [*087A.0020.0002.273D] # HEAVY TEARDROP-SPOKED ASTERISK
+273E ; [*087B.0020.0002.273E] # SIX PETALLED BLACK AND WHITE FLORETTE
+273F ; [*087C.0020.0002.273F] # BLACK FLORETTE
+2740 ; [*087D.0020.0002.2740] # WHITE FLORETTE
+2741 ; [*087E.0020.0002.2741] # EIGHT PETALLED OUTLINED BLACK FLORETTE
+2742 ; [*087F.0020.0002.2742] # CIRCLED OPEN CENTRE EIGHT POINTED STAR
+2743 ; [*0880.0020.0002.2743] # HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK
+2744 ; [*0881.0020.0002.2744] # SNOWFLAKE
+2745 ; [*0882.0020.0002.2745] # TIGHT TRIFOLIATE SNOWFLAKE
+2746 ; [*0883.0020.0002.2746] # HEAVY CHEVRON SNOWFLAKE
+2747 ; [*0884.0020.0002.2747] # SPARKLE
+2748 ; [*0885.0020.0002.2748] # HEAVY SPARKLE
+2749 ; [*0886.0020.0002.2749] # BALLOON-SPOKED ASTERISK
+274A ; [*0887.0020.0002.274A] # EIGHT TEARDROP-SPOKED PROPELLER ASTERISK
+274B ; [*0888.0020.0002.274B] # HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK
+274D ; [*0889.0020.0002.274D] # SHADOWED WHITE CIRCLE
+274F ; [*088A.0020.0002.274F] # LOWER RIGHT DROP-SHADOWED WHITE SQUARE
+2750 ; [*088B.0020.0002.2750] # UPPER RIGHT DROP-SHADOWED WHITE SQUARE
+2751 ; [*088C.0020.0002.2751] # LOWER RIGHT SHADOWED WHITE SQUARE
+2752 ; [*088D.0020.0002.2752] # UPPER RIGHT SHADOWED WHITE SQUARE
+2756 ; [*088E.0020.0002.2756] # BLACK DIAMOND MINUS WHITE X
+2758 ; [*088F.0020.0002.2758] # LIGHT VERTICAL BAR
+2759 ; [*0890.0020.0002.2759] # MEDIUM VERTICAL BAR
+275A ; [*0891.0020.0002.275A] # HEAVY VERTICAL BAR
+275B ; [*0892.0020.0002.275B] # HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT
+275C ; [*0893.0020.0002.275C] # HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT
+275D ; [*0894.0020.0002.275D] # HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT
+275E ; [*0895.0020.0002.275E] # HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT
+2761 ; [*0896.0020.0002.2761] # CURVED STEM PARAGRAPH SIGN ORNAMENT
+2762 ; [*0897.0020.0002.2762] # HEAVY EXCLAMATION MARK ORNAMENT
+2763 ; [*0898.0020.0002.2763] # HEAVY HEART EXCLAMATION MARK ORNAMENT
+2764 ; [*0899.0020.0002.2764] # HEAVY BLACK HEART
+2765 ; [*089A.0020.0002.2765] # ROTATED HEAVY BLACK HEART BULLET
+2766 ; [*089B.0020.0002.2766] # FLORAL HEART
+2767 ; [*089C.0020.0002.2767] # ROTATED FLORAL HEART BULLET
+2768 ; [*089D.0020.0002.2768] # MEDIUM LEFT PARENTHESIS ORNAMENT
+2769 ; [*089E.0020.0002.2769] # MEDIUM RIGHT PARENTHESIS ORNAMENT
+276A ; [*089F.0020.0002.276A] # MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT
+276B ; [*08A0.0020.0002.276B] # MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT
+276C ; [*08A1.0020.0002.276C] # MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT
+276D ; [*08A2.0020.0002.276D] # MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT
+276E ; [*08A3.0020.0002.276E] # HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT
+276F ; [*08A4.0020.0002.276F] # HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT
+2770 ; [*08A5.0020.0002.2770] # HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT
+2771 ; [*08A6.0020.0002.2771] # HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT
+2772 ; [*08A7.0020.0002.2772] # LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT
+2773 ; [*08A8.0020.0002.2773] # LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT
+2774 ; [*08A9.0020.0002.2774] # MEDIUM LEFT CURLY BRACKET ORNAMENT
+2775 ; [*08AA.0020.0002.2775] # MEDIUM RIGHT CURLY BRACKET ORNAMENT
+2794 ; [*08AB.0020.0002.2794] # HEAVY WIDE-HEADED RIGHTWARDS ARROW
+2798 ; [*08AC.0020.0002.2798] # HEAVY SOUTH EAST ARROW
+2799 ; [*08AD.0020.0002.2799] # HEAVY RIGHTWARDS ARROW
+279A ; [*08AE.0020.0002.279A] # HEAVY NORTH EAST ARROW
+279B ; [*08AF.0020.0002.279B] # DRAFTING POINT RIGHTWARDS ARROW
+279C ; [*08B0.0020.0002.279C] # HEAVY ROUND-TIPPED RIGHTWARDS ARROW
+279D ; [*08B1.0020.0002.279D] # TRIANGLE-HEADED RIGHTWARDS ARROW
+279E ; [*08B2.0020.0002.279E] # HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW
+279F ; [*08B3.0020.0002.279F] # DASHED TRIANGLE-HEADED RIGHTWARDS ARROW
+27A0 ; [*08B4.0020.0002.27A0] # HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW
+27A1 ; [*08B5.0020.0002.27A1] # BLACK RIGHTWARDS ARROW
+27A2 ; [*08B6.0020.0002.27A2] # THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD
+27A3 ; [*08B7.0020.0002.27A3] # THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD
+27A4 ; [*08B8.0020.0002.27A4] # BLACK RIGHTWARDS ARROWHEAD
+27A5 ; [*08B9.0020.0002.27A5] # HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW
+27A6 ; [*08BA.0020.0002.27A6] # HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW
+27A7 ; [*08BB.0020.0002.27A7] # SQUAT BLACK RIGHTWARDS ARROW
+27A8 ; [*08BC.0020.0002.27A8] # HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW
+27A9 ; [*08BD.0020.0002.27A9] # RIGHT-SHADED WHITE RIGHTWARDS ARROW
+27AA ; [*08BE.0020.0002.27AA] # LEFT-SHADED WHITE RIGHTWARDS ARROW
+27AB ; [*08BF.0020.0002.27AB] # BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW
+27AC ; [*08C0.0020.0002.27AC] # FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW
+27AD ; [*08C1.0020.0002.27AD] # HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW
+27AE ; [*08C2.0020.0002.27AE] # HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW
+27AF ; [*08C3.0020.0002.27AF] # NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW
+27B1 ; [*08C4.0020.0002.27B1] # NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW
+27B2 ; [*08C5.0020.0002.27B2] # CIRCLED HEAVY WHITE RIGHTWARDS ARROW
+27B3 ; [*08C6.0020.0002.27B3] # WHITE-FEATHERED RIGHTWARDS ARROW
+27B4 ; [*08C7.0020.0002.27B4] # BLACK-FEATHERED SOUTH EAST ARROW
+27B5 ; [*08C8.0020.0002.27B5] # BLACK-FEATHERED RIGHTWARDS ARROW
+27B6 ; [*08C9.0020.0002.27B6] # BLACK-FEATHERED NORTH EAST ARROW
+27B7 ; [*08CA.0020.0002.27B7] # HEAVY BLACK-FEATHERED SOUTH EAST ARROW
+27B8 ; [*08CB.0020.0002.27B8] # HEAVY BLACK-FEATHERED RIGHTWARDS ARROW
+27B9 ; [*08CC.0020.0002.27B9] # HEAVY BLACK-FEATHERED NORTH EAST ARROW
+27BA ; [*08CD.0020.0002.27BA] # TEARDROP-BARBED RIGHTWARDS ARROW
+27BB ; [*08CE.0020.0002.27BB] # HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW
+27BC ; [*08CF.0020.0002.27BC] # WEDGE-TAILED RIGHTWARDS ARROW
+27BD ; [*08D0.0020.0002.27BD] # HEAVY WEDGE-TAILED RIGHTWARDS ARROW
+27BE ; [*08D1.0020.0002.27BE] # OPEN-OUTLINED RIGHTWARDS ARROW
+27C0 ; [*08D2.0020.0002.27C0] # THREE DIMENSIONAL ANGLE
+27C1 ; [*08D3.0020.0002.27C1] # WHITE TRIANGLE CONTAINING SMALL WHITE TRIANGLE
+27C2 ; [*08D4.0020.0002.27C2] # PERPENDICULAR
+27C3 ; [*08D5.0020.0002.27C3] # OPEN SUBSET
+27C4 ; [*08D6.0020.0002.27C4] # OPEN SUPERSET
+27C5 ; [*08D7.0020.0002.27C5] # LEFT S-SHAPED BAG DELIMITER
+27C6 ; [*08D8.0020.0002.27C6] # RIGHT S-SHAPED BAG DELIMITER
+27C7 ; [*08D9.0020.0002.27C7] # OR WITH DOT INSIDE
+27C8 ; [*08DA.0020.0002.27C8] # REVERSE SOLIDUS PRECEDING SUBSET
+27C9 ; [*08DB.0020.0002.27C9] # SUPERSET PRECEDING SOLIDUS
+27CA ; [*08DC.0020.0002.27CA] # VERTICAL BAR WITH HORIZONTAL STROKE
+27D0 ; [*08DD.0020.0002.27D0] # WHITE DIAMOND WITH CENTRED DOT
+27D1 ; [*08DE.0020.0002.27D1] # AND WITH DOT
+27D2 ; [*08DF.0020.0002.27D2] # ELEMENT OF OPENING UPWARDS
+27D3 ; [*08E0.0020.0002.27D3] # LOWER RIGHT CORNER WITH DOT
+27D4 ; [*08E1.0020.0002.27D4] # UPPER LEFT CORNER WITH DOT
+27D5 ; [*08E2.0020.0002.27D5] # LEFT OUTER JOIN
+27D6 ; [*08E3.0020.0002.27D6] # RIGHT OUTER JOIN
+27D7 ; [*08E4.0020.0002.27D7] # FULL OUTER JOIN
+27D8 ; [*08E5.0020.0002.27D8] # LARGE UP TACK
+27D9 ; [*08E6.0020.0002.27D9] # LARGE DOWN TACK
+27DA ; [*08E7.0020.0002.27DA] # LEFT AND RIGHT DOUBLE TURNSTILE
+27DB ; [*08E8.0020.0002.27DB] # LEFT AND RIGHT TACK
+27DC ; [*08E9.0020.0002.27DC] # LEFT MULTIMAP
+27DD ; [*08EA.0020.0002.27DD] # LONG RIGHT TACK
+27DE ; [*08EB.0020.0002.27DE] # LONG LEFT TACK
+27DF ; [*08EC.0020.0002.27DF] # UP TACK WITH CIRCLE ABOVE
+27E0 ; [*08ED.0020.0002.27E0] # LOZENGE DIVIDED BY HORIZONTAL RULE
+27E1 ; [*08EE.0020.0002.27E1] # WHITE CONCAVE-SIDED DIAMOND
+27E2 ; [*08EF.0020.0002.27E2] # WHITE CONCAVE-SIDED DIAMOND WITH LEFTWARDS TICK
+27E3 ; [*08F0.0020.0002.27E3] # WHITE CONCAVE-SIDED DIAMOND WITH RIGHTWARDS TICK
+27E4 ; [*08F1.0020.0002.27E4] # WHITE SQUARE WITH LEFTWARDS TICK
+27E5 ; [*08F2.0020.0002.27E5] # WHITE SQUARE WITH RIGHTWARDS TICK
+27E6 ; [*08F3.0020.0002.27E6] # MATHEMATICAL LEFT WHITE SQUARE BRACKET
+27E7 ; [*08F4.0020.0002.27E7] # MATHEMATICAL RIGHT WHITE SQUARE BRACKET
+27E8 ; [*08F5.0020.0002.27E8] # MATHEMATICAL LEFT ANGLE BRACKET
+27E9 ; [*08F6.0020.0002.27E9] # MATHEMATICAL RIGHT ANGLE BRACKET
+27EA ; [*08F7.0020.0002.27EA] # MATHEMATICAL LEFT DOUBLE ANGLE BRACKET
+27EB ; [*08F8.0020.0002.27EB] # MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET
+27F0 ; [*08F9.0020.0002.27F0] # UPWARDS QUADRUPLE ARROW
+27F1 ; [*08FA.0020.0002.27F1] # DOWNWARDS QUADRUPLE ARROW
+27F2 ; [*08FB.0020.0002.27F2] # ANTICLOCKWISE GAPPED CIRCLE ARROW
+27F3 ; [*08FC.0020.0002.27F3] # CLOCKWISE GAPPED CIRCLE ARROW
+27F4 ; [*08FD.0020.0002.27F4] # RIGHT ARROW WITH CIRCLED PLUS
+27F5 ; [*08FE.0020.0002.27F5] # LONG LEFTWARDS ARROW
+27F6 ; [*08FF.0020.0002.27F6] # LONG RIGHTWARDS ARROW
+27F7 ; [*0900.0020.0002.27F7] # LONG LEFT RIGHT ARROW
+27F8 ; [*0901.0020.0002.27F8] # LONG LEFTWARDS DOUBLE ARROW
+27F9 ; [*0902.0020.0002.27F9] # LONG RIGHTWARDS DOUBLE ARROW
+27FA ; [*0903.0020.0002.27FA] # LONG LEFT RIGHT DOUBLE ARROW
+27FB ; [*0904.0020.0002.27FB] # LONG LEFTWARDS ARROW FROM BAR
+27FC ; [*0905.0020.0002.27FC] # LONG RIGHTWARDS ARROW FROM BAR
+27FD ; [*0906.0020.0002.27FD] # LONG LEFTWARDS DOUBLE ARROW FROM BAR
+27FE ; [*0907.0020.0002.27FE] # LONG RIGHTWARDS DOUBLE ARROW FROM BAR
+27FF ; [*0908.0020.0002.27FF] # LONG RIGHTWARDS SQUIGGLE ARROW
+2800 ; [*0B11.0020.0002.2800] # BRAILLE PATTERN BLANK
+2801 ; [*0B12.0020.0002.2801] # BRAILLE PATTERN DOTS-1
+2802 ; [*0B13.0020.0002.2802] # BRAILLE PATTERN DOTS-2
+2803 ; [*0B14.0020.0002.2803] # BRAILLE PATTERN DOTS-12
+2804 ; [*0B15.0020.0002.2804] # BRAILLE PATTERN DOTS-3
+2805 ; [*0B16.0020.0002.2805] # BRAILLE PATTERN DOTS-13
+2806 ; [*0B17.0020.0002.2806] # BRAILLE PATTERN DOTS-23
+2807 ; [*0B18.0020.0002.2807] # BRAILLE PATTERN DOTS-123
+2808 ; [*0B19.0020.0002.2808] # BRAILLE PATTERN DOTS-4
+2809 ; [*0B1A.0020.0002.2809] # BRAILLE PATTERN DOTS-14
+280A ; [*0B1B.0020.0002.280A] # BRAILLE PATTERN DOTS-24
+280B ; [*0B1C.0020.0002.280B] # BRAILLE PATTERN DOTS-124
+280C ; [*0B1D.0020.0002.280C] # BRAILLE PATTERN DOTS-34
+280D ; [*0B1E.0020.0002.280D] # BRAILLE PATTERN DOTS-134
+280E ; [*0B1F.0020.0002.280E] # BRAILLE PATTERN DOTS-234
+280F ; [*0B20.0020.0002.280F] # BRAILLE PATTERN DOTS-1234
+2810 ; [*0B21.0020.0002.2810] # BRAILLE PATTERN DOTS-5
+2811 ; [*0B22.0020.0002.2811] # BRAILLE PATTERN DOTS-15
+2812 ; [*0B23.0020.0002.2812] # BRAILLE PATTERN DOTS-25
+2813 ; [*0B24.0020.0002.2813] # BRAILLE PATTERN DOTS-125
+2814 ; [*0B25.0020.0002.2814] # BRAILLE PATTERN DOTS-35
+2815 ; [*0B26.0020.0002.2815] # BRAILLE PATTERN DOTS-135
+2816 ; [*0B27.0020.0002.2816] # BRAILLE PATTERN DOTS-235
+2817 ; [*0B28.0020.0002.2817] # BRAILLE PATTERN DOTS-1235
+2818 ; [*0B29.0020.0002.2818] # BRAILLE PATTERN DOTS-45
+2819 ; [*0B2A.0020.0002.2819] # BRAILLE PATTERN DOTS-145
+281A ; [*0B2B.0020.0002.281A] # BRAILLE PATTERN DOTS-245
+281B ; [*0B2C.0020.0002.281B] # BRAILLE PATTERN DOTS-1245
+281C ; [*0B2D.0020.0002.281C] # BRAILLE PATTERN DOTS-345
+281D ; [*0B2E.0020.0002.281D] # BRAILLE PATTERN DOTS-1345
+281E ; [*0B2F.0020.0002.281E] # BRAILLE PATTERN DOTS-2345
+281F ; [*0B30.0020.0002.281F] # BRAILLE PATTERN DOTS-12345
+2820 ; [*0B31.0020.0002.2820] # BRAILLE PATTERN DOTS-6
+2821 ; [*0B32.0020.0002.2821] # BRAILLE PATTERN DOTS-16
+2822 ; [*0B33.0020.0002.2822] # BRAILLE PATTERN DOTS-26
+2823 ; [*0B34.0020.0002.2823] # BRAILLE PATTERN DOTS-126
+2824 ; [*0B35.0020.0002.2824] # BRAILLE PATTERN DOTS-36
+2825 ; [*0B36.0020.0002.2825] # BRAILLE PATTERN DOTS-136
+2826 ; [*0B37.0020.0002.2826] # BRAILLE PATTERN DOTS-236
+2827 ; [*0B38.0020.0002.2827] # BRAILLE PATTERN DOTS-1236
+2828 ; [*0B39.0020.0002.2828] # BRAILLE PATTERN DOTS-46
+2829 ; [*0B3A.0020.0002.2829] # BRAILLE PATTERN DOTS-146
+282A ; [*0B3B.0020.0002.282A] # BRAILLE PATTERN DOTS-246
+282B ; [*0B3C.0020.0002.282B] # BRAILLE PATTERN DOTS-1246
+282C ; [*0B3D.0020.0002.282C] # BRAILLE PATTERN DOTS-346
+282D ; [*0B3E.0020.0002.282D] # BRAILLE PATTERN DOTS-1346
+282E ; [*0B3F.0020.0002.282E] # BRAILLE PATTERN DOTS-2346
+282F ; [*0B40.0020.0002.282F] # BRAILLE PATTERN DOTS-12346
+2830 ; [*0B41.0020.0002.2830] # BRAILLE PATTERN DOTS-56
+2831 ; [*0B42.0020.0002.2831] # BRAILLE PATTERN DOTS-156
+2832 ; [*0B43.0020.0002.2832] # BRAILLE PATTERN DOTS-256
+2833 ; [*0B44.0020.0002.2833] # BRAILLE PATTERN DOTS-1256
+2834 ; [*0B45.0020.0002.2834] # BRAILLE PATTERN DOTS-356
+2835 ; [*0B46.0020.0002.2835] # BRAILLE PATTERN DOTS-1356
+2836 ; [*0B47.0020.0002.2836] # BRAILLE PATTERN DOTS-2356
+2837 ; [*0B48.0020.0002.2837] # BRAILLE PATTERN DOTS-12356
+2838 ; [*0B49.0020.0002.2838] # BRAILLE PATTERN DOTS-456
+2839 ; [*0B4A.0020.0002.2839] # BRAILLE PATTERN DOTS-1456
+283A ; [*0B4B.0020.0002.283A] # BRAILLE PATTERN DOTS-2456
+283B ; [*0B4C.0020.0002.283B] # BRAILLE PATTERN DOTS-12456
+283C ; [*0B4D.0020.0002.283C] # BRAILLE PATTERN DOTS-3456
+283D ; [*0B4E.0020.0002.283D] # BRAILLE PATTERN DOTS-13456
+283E ; [*0B4F.0020.0002.283E] # BRAILLE PATTERN DOTS-23456
+283F ; [*0B50.0020.0002.283F] # BRAILLE PATTERN DOTS-123456
+2840 ; [*0B51.0020.0002.2840] # BRAILLE PATTERN DOTS-7
+2841 ; [*0B52.0020.0002.2841] # BRAILLE PATTERN DOTS-17
+2842 ; [*0B53.0020.0002.2842] # BRAILLE PATTERN DOTS-27
+2843 ; [*0B54.0020.0002.2843] # BRAILLE PATTERN DOTS-127
+2844 ; [*0B55.0020.0002.2844] # BRAILLE PATTERN DOTS-37
+2845 ; [*0B56.0020.0002.2845] # BRAILLE PATTERN DOTS-137
+2846 ; [*0B57.0020.0002.2846] # BRAILLE PATTERN DOTS-237
+2847 ; [*0B58.0020.0002.2847] # BRAILLE PATTERN DOTS-1237
+2848 ; [*0B59.0020.0002.2848] # BRAILLE PATTERN DOTS-47
+2849 ; [*0B5A.0020.0002.2849] # BRAILLE PATTERN DOTS-147
+284A ; [*0B5B.0020.0002.284A] # BRAILLE PATTERN DOTS-247
+284B ; [*0B5C.0020.0002.284B] # BRAILLE PATTERN DOTS-1247
+284C ; [*0B5D.0020.0002.284C] # BRAILLE PATTERN DOTS-347
+284D ; [*0B5E.0020.0002.284D] # BRAILLE PATTERN DOTS-1347
+284E ; [*0B5F.0020.0002.284E] # BRAILLE PATTERN DOTS-2347
+284F ; [*0B60.0020.0002.284F] # BRAILLE PATTERN DOTS-12347
+2850 ; [*0B61.0020.0002.2850] # BRAILLE PATTERN DOTS-57
+2851 ; [*0B62.0020.0002.2851] # BRAILLE PATTERN DOTS-157
+2852 ; [*0B63.0020.0002.2852] # BRAILLE PATTERN DOTS-257
+2853 ; [*0B64.0020.0002.2853] # BRAILLE PATTERN DOTS-1257
+2854 ; [*0B65.0020.0002.2854] # BRAILLE PATTERN DOTS-357
+2855 ; [*0B66.0020.0002.2855] # BRAILLE PATTERN DOTS-1357
+2856 ; [*0B67.0020.0002.2856] # BRAILLE PATTERN DOTS-2357
+2857 ; [*0B68.0020.0002.2857] # BRAILLE PATTERN DOTS-12357
+2858 ; [*0B69.0020.0002.2858] # BRAILLE PATTERN DOTS-457
+2859 ; [*0B6A.0020.0002.2859] # BRAILLE PATTERN DOTS-1457
+285A ; [*0B6B.0020.0002.285A] # BRAILLE PATTERN DOTS-2457
+285B ; [*0B6C.0020.0002.285B] # BRAILLE PATTERN DOTS-12457
+285C ; [*0B6D.0020.0002.285C] # BRAILLE PATTERN DOTS-3457
+285D ; [*0B6E.0020.0002.285D] # BRAILLE PATTERN DOTS-13457
+285E ; [*0B6F.0020.0002.285E] # BRAILLE PATTERN DOTS-23457
+285F ; [*0B70.0020.0002.285F] # BRAILLE PATTERN DOTS-123457
+2860 ; [*0B71.0020.0002.2860] # BRAILLE PATTERN DOTS-67
+2861 ; [*0B72.0020.0002.2861] # BRAILLE PATTERN DOTS-167
+2862 ; [*0B73.0020.0002.2862] # BRAILLE PATTERN DOTS-267
+2863 ; [*0B74.0020.0002.2863] # BRAILLE PATTERN DOTS-1267
+2864 ; [*0B75.0020.0002.2864] # BRAILLE PATTERN DOTS-367
+2865 ; [*0B76.0020.0002.2865] # BRAILLE PATTERN DOTS-1367
+2866 ; [*0B77.0020.0002.2866] # BRAILLE PATTERN DOTS-2367
+2867 ; [*0B78.0020.0002.2867] # BRAILLE PATTERN DOTS-12367
+2868 ; [*0B79.0020.0002.2868] # BRAILLE PATTERN DOTS-467
+2869 ; [*0B7A.0020.0002.2869] # BRAILLE PATTERN DOTS-1467
+286A ; [*0B7B.0020.0002.286A] # BRAILLE PATTERN DOTS-2467
+286B ; [*0B7C.0020.0002.286B] # BRAILLE PATTERN DOTS-12467
+286C ; [*0B7D.0020.0002.286C] # BRAILLE PATTERN DOTS-3467
+286D ; [*0B7E.0020.0002.286D] # BRAILLE PATTERN DOTS-13467
+286E ; [*0B7F.0020.0002.286E] # BRAILLE PATTERN DOTS-23467
+286F ; [*0B80.0020.0002.286F] # BRAILLE PATTERN DOTS-123467
+2870 ; [*0B81.0020.0002.2870] # BRAILLE PATTERN DOTS-567
+2871 ; [*0B82.0020.0002.2871] # BRAILLE PATTERN DOTS-1567
+2872 ; [*0B83.0020.0002.2872] # BRAILLE PATTERN DOTS-2567
+2873 ; [*0B84.0020.0002.2873] # BRAILLE PATTERN DOTS-12567
+2874 ; [*0B85.0020.0002.2874] # BRAILLE PATTERN DOTS-3567
+2875 ; [*0B86.0020.0002.2875] # BRAILLE PATTERN DOTS-13567
+2876 ; [*0B87.0020.0002.2876] # BRAILLE PATTERN DOTS-23567
+2877 ; [*0B88.0020.0002.2877] # BRAILLE PATTERN DOTS-123567
+2878 ; [*0B89.0020.0002.2878] # BRAILLE PATTERN DOTS-4567
+2879 ; [*0B8A.0020.0002.2879] # BRAILLE PATTERN DOTS-14567
+287A ; [*0B8B.0020.0002.287A] # BRAILLE PATTERN DOTS-24567
+287B ; [*0B8C.0020.0002.287B] # BRAILLE PATTERN DOTS-124567
+287C ; [*0B8D.0020.0002.287C] # BRAILLE PATTERN DOTS-34567
+287D ; [*0B8E.0020.0002.287D] # BRAILLE PATTERN DOTS-134567
+287E ; [*0B8F.0020.0002.287E] # BRAILLE PATTERN DOTS-234567
+287F ; [*0B90.0020.0002.287F] # BRAILLE PATTERN DOTS-1234567
+2880 ; [*0B91.0020.0002.2880] # BRAILLE PATTERN DOTS-8
+2881 ; [*0B92.0020.0002.2881] # BRAILLE PATTERN DOTS-18
+2882 ; [*0B93.0020.0002.2882] # BRAILLE PATTERN DOTS-28
+2883 ; [*0B94.0020.0002.2883] # BRAILLE PATTERN DOTS-128
+2884 ; [*0B95.0020.0002.2884] # BRAILLE PATTERN DOTS-38
+2885 ; [*0B96.0020.0002.2885] # BRAILLE PATTERN DOTS-138
+2886 ; [*0B97.0020.0002.2886] # BRAILLE PATTERN DOTS-238
+2887 ; [*0B98.0020.0002.2887] # BRAILLE PATTERN DOTS-1238
+2888 ; [*0B99.0020.0002.2888] # BRAILLE PATTERN DOTS-48
+2889 ; [*0B9A.0020.0002.2889] # BRAILLE PATTERN DOTS-148
+288A ; [*0B9B.0020.0002.288A] # BRAILLE PATTERN DOTS-248
+288B ; [*0B9C.0020.0002.288B] # BRAILLE PATTERN DOTS-1248
+288C ; [*0B9D.0020.0002.288C] # BRAILLE PATTERN DOTS-348
+288D ; [*0B9E.0020.0002.288D] # BRAILLE PATTERN DOTS-1348
+288E ; [*0B9F.0020.0002.288E] # BRAILLE PATTERN DOTS-2348
+288F ; [*0BA0.0020.0002.288F] # BRAILLE PATTERN DOTS-12348
+2890 ; [*0BA1.0020.0002.2890] # BRAILLE PATTERN DOTS-58
+2891 ; [*0BA2.0020.0002.2891] # BRAILLE PATTERN DOTS-158
+2892 ; [*0BA3.0020.0002.2892] # BRAILLE PATTERN DOTS-258
+2893 ; [*0BA4.0020.0002.2893] # BRAILLE PATTERN DOTS-1258
+2894 ; [*0BA5.0020.0002.2894] # BRAILLE PATTERN DOTS-358
+2895 ; [*0BA6.0020.0002.2895] # BRAILLE PATTERN DOTS-1358
+2896 ; [*0BA7.0020.0002.2896] # BRAILLE PATTERN DOTS-2358
+2897 ; [*0BA8.0020.0002.2897] # BRAILLE PATTERN DOTS-12358
+2898 ; [*0BA9.0020.0002.2898] # BRAILLE PATTERN DOTS-458
+2899 ; [*0BAA.0020.0002.2899] # BRAILLE PATTERN DOTS-1458
+289A ; [*0BAB.0020.0002.289A] # BRAILLE PATTERN DOTS-2458
+289B ; [*0BAC.0020.0002.289B] # BRAILLE PATTERN DOTS-12458
+289C ; [*0BAD.0020.0002.289C] # BRAILLE PATTERN DOTS-3458
+289D ; [*0BAE.0020.0002.289D] # BRAILLE PATTERN DOTS-13458
+289E ; [*0BAF.0020.0002.289E] # BRAILLE PATTERN DOTS-23458
+289F ; [*0BB0.0020.0002.289F] # BRAILLE PATTERN DOTS-123458
+28A0 ; [*0BB1.0020.0002.28A0] # BRAILLE PATTERN DOTS-68
+28A1 ; [*0BB2.0020.0002.28A1] # BRAILLE PATTERN DOTS-168
+28A2 ; [*0BB3.0020.0002.28A2] # BRAILLE PATTERN DOTS-268
+28A3 ; [*0BB4.0020.0002.28A3] # BRAILLE PATTERN DOTS-1268
+28A4 ; [*0BB5.0020.0002.28A4] # BRAILLE PATTERN DOTS-368
+28A5 ; [*0BB6.0020.0002.28A5] # BRAILLE PATTERN DOTS-1368
+28A6 ; [*0BB7.0020.0002.28A6] # BRAILLE PATTERN DOTS-2368
+28A7 ; [*0BB8.0020.0002.28A7] # BRAILLE PATTERN DOTS-12368
+28A8 ; [*0BB9.0020.0002.28A8] # BRAILLE PATTERN DOTS-468
+28A9 ; [*0BBA.0020.0002.28A9] # BRAILLE PATTERN DOTS-1468
+28AA ; [*0BBB.0020.0002.28AA] # BRAILLE PATTERN DOTS-2468
+28AB ; [*0BBC.0020.0002.28AB] # BRAILLE PATTERN DOTS-12468
+28AC ; [*0BBD.0020.0002.28AC] # BRAILLE PATTERN DOTS-3468
+28AD ; [*0BBE.0020.0002.28AD] # BRAILLE PATTERN DOTS-13468
+28AE ; [*0BBF.0020.0002.28AE] # BRAILLE PATTERN DOTS-23468
+28AF ; [*0BC0.0020.0002.28AF] # BRAILLE PATTERN DOTS-123468
+28B0 ; [*0BC1.0020.0002.28B0] # BRAILLE PATTERN DOTS-568
+28B1 ; [*0BC2.0020.0002.28B1] # BRAILLE PATTERN DOTS-1568
+28B2 ; [*0BC3.0020.0002.28B2] # BRAILLE PATTERN DOTS-2568
+28B3 ; [*0BC4.0020.0002.28B3] # BRAILLE PATTERN DOTS-12568
+28B4 ; [*0BC5.0020.0002.28B4] # BRAILLE PATTERN DOTS-3568
+28B5 ; [*0BC6.0020.0002.28B5] # BRAILLE PATTERN DOTS-13568
+28B6 ; [*0BC7.0020.0002.28B6] # BRAILLE PATTERN DOTS-23568
+28B7 ; [*0BC8.0020.0002.28B7] # BRAILLE PATTERN DOTS-123568
+28B8 ; [*0BC9.0020.0002.28B8] # BRAILLE PATTERN DOTS-4568
+28B9 ; [*0BCA.0020.0002.28B9] # BRAILLE PATTERN DOTS-14568
+28BA ; [*0BCB.0020.0002.28BA] # BRAILLE PATTERN DOTS-24568
+28BB ; [*0BCC.0020.0002.28BB] # BRAILLE PATTERN DOTS-124568
+28BC ; [*0BCD.0020.0002.28BC] # BRAILLE PATTERN DOTS-34568
+28BD ; [*0BCE.0020.0002.28BD] # BRAILLE PATTERN DOTS-134568
+28BE ; [*0BCF.0020.0002.28BE] # BRAILLE PATTERN DOTS-234568
+28BF ; [*0BD0.0020.0002.28BF] # BRAILLE PATTERN DOTS-1234568
+28C0 ; [*0BD1.0020.0002.28C0] # BRAILLE PATTERN DOTS-78
+28C1 ; [*0BD2.0020.0002.28C1] # BRAILLE PATTERN DOTS-178
+28C2 ; [*0BD3.0020.0002.28C2] # BRAILLE PATTERN DOTS-278
+28C3 ; [*0BD4.0020.0002.28C3] # BRAILLE PATTERN DOTS-1278
+28C4 ; [*0BD5.0020.0002.28C4] # BRAILLE PATTERN DOTS-378
+28C5 ; [*0BD6.0020.0002.28C5] # BRAILLE PATTERN DOTS-1378
+28C6 ; [*0BD7.0020.0002.28C6] # BRAILLE PATTERN DOTS-2378
+28C7 ; [*0BD8.0020.0002.28C7] # BRAILLE PATTERN DOTS-12378
+28C8 ; [*0BD9.0020.0002.28C8] # BRAILLE PATTERN DOTS-478
+28C9 ; [*0BDA.0020.0002.28C9] # BRAILLE PATTERN DOTS-1478
+28CA ; [*0BDB.0020.0002.28CA] # BRAILLE PATTERN DOTS-2478
+28CB ; [*0BDC.0020.0002.28CB] # BRAILLE PATTERN DOTS-12478
+28CC ; [*0BDD.0020.0002.28CC] # BRAILLE PATTERN DOTS-3478
+28CD ; [*0BDE.0020.0002.28CD] # BRAILLE PATTERN DOTS-13478
+28CE ; [*0BDF.0020.0002.28CE] # BRAILLE PATTERN DOTS-23478
+28CF ; [*0BE0.0020.0002.28CF] # BRAILLE PATTERN DOTS-123478
+28D0 ; [*0BE1.0020.0002.28D0] # BRAILLE PATTERN DOTS-578
+28D1 ; [*0BE2.0020.0002.28D1] # BRAILLE PATTERN DOTS-1578
+28D2 ; [*0BE3.0020.0002.28D2] # BRAILLE PATTERN DOTS-2578
+28D3 ; [*0BE4.0020.0002.28D3] # BRAILLE PATTERN DOTS-12578
+28D4 ; [*0BE5.0020.0002.28D4] # BRAILLE PATTERN DOTS-3578
+28D5 ; [*0BE6.0020.0002.28D5] # BRAILLE PATTERN DOTS-13578
+28D6 ; [*0BE7.0020.0002.28D6] # BRAILLE PATTERN DOTS-23578
+28D7 ; [*0BE8.0020.0002.28D7] # BRAILLE PATTERN DOTS-123578
+28D8 ; [*0BE9.0020.0002.28D8] # BRAILLE PATTERN DOTS-4578
+28D9 ; [*0BEA.0020.0002.28D9] # BRAILLE PATTERN DOTS-14578
+28DA ; [*0BEB.0020.0002.28DA] # BRAILLE PATTERN DOTS-24578
+28DB ; [*0BEC.0020.0002.28DB] # BRAILLE PATTERN DOTS-124578
+28DC ; [*0BED.0020.0002.28DC] # BRAILLE PATTERN DOTS-34578
+28DD ; [*0BEE.0020.0002.28DD] # BRAILLE PATTERN DOTS-134578
+28DE ; [*0BEF.0020.0002.28DE] # BRAILLE PATTERN DOTS-234578
+28DF ; [*0BF0.0020.0002.28DF] # BRAILLE PATTERN DOTS-1234578
+28E0 ; [*0BF1.0020.0002.28E0] # BRAILLE PATTERN DOTS-678
+28E1 ; [*0BF2.0020.0002.28E1] # BRAILLE PATTERN DOTS-1678
+28E2 ; [*0BF3.0020.0002.28E2] # BRAILLE PATTERN DOTS-2678
+28E3 ; [*0BF4.0020.0002.28E3] # BRAILLE PATTERN DOTS-12678
+28E4 ; [*0BF5.0020.0002.28E4] # BRAILLE PATTERN DOTS-3678
+28E5 ; [*0BF6.0020.0002.28E5] # BRAILLE PATTERN DOTS-13678
+28E6 ; [*0BF7.0020.0002.28E6] # BRAILLE PATTERN DOTS-23678
+28E7 ; [*0BF8.0020.0002.28E7] # BRAILLE PATTERN DOTS-123678
+28E8 ; [*0BF9.0020.0002.28E8] # BRAILLE PATTERN DOTS-4678
+28E9 ; [*0BFA.0020.0002.28E9] # BRAILLE PATTERN DOTS-14678
+28EA ; [*0BFB.0020.0002.28EA] # BRAILLE PATTERN DOTS-24678
+28EB ; [*0BFC.0020.0002.28EB] # BRAILLE PATTERN DOTS-124678
+28EC ; [*0BFD.0020.0002.28EC] # BRAILLE PATTERN DOTS-34678
+28ED ; [*0BFE.0020.0002.28ED] # BRAILLE PATTERN DOTS-134678
+28EE ; [*0BFF.0020.0002.28EE] # BRAILLE PATTERN DOTS-234678
+28EF ; [*0C00.0020.0002.28EF] # BRAILLE PATTERN DOTS-1234678
+28F0 ; [*0C01.0020.0002.28F0] # BRAILLE PATTERN DOTS-5678
+28F1 ; [*0C02.0020.0002.28F1] # BRAILLE PATTERN DOTS-15678
+28F2 ; [*0C03.0020.0002.28F2] # BRAILLE PATTERN DOTS-25678
+28F3 ; [*0C04.0020.0002.28F3] # BRAILLE PATTERN DOTS-125678
+28F4 ; [*0C05.0020.0002.28F4] # BRAILLE PATTERN DOTS-35678
+28F5 ; [*0C06.0020.0002.28F5] # BRAILLE PATTERN DOTS-135678
+28F6 ; [*0C07.0020.0002.28F6] # BRAILLE PATTERN DOTS-235678
+28F7 ; [*0C08.0020.0002.28F7] # BRAILLE PATTERN DOTS-1235678
+28F8 ; [*0C09.0020.0002.28F8] # BRAILLE PATTERN DOTS-45678
+28F9 ; [*0C0A.0020.0002.28F9] # BRAILLE PATTERN DOTS-145678
+28FA ; [*0C0B.0020.0002.28FA] # BRAILLE PATTERN DOTS-245678
+28FB ; [*0C0C.0020.0002.28FB] # BRAILLE PATTERN DOTS-1245678
+28FC ; [*0C0D.0020.0002.28FC] # BRAILLE PATTERN DOTS-345678
+28FD ; [*0C0E.0020.0002.28FD] # BRAILLE PATTERN DOTS-1345678
+28FE ; [*0C0F.0020.0002.28FE] # BRAILLE PATTERN DOTS-2345678
+28FF ; [*0C10.0020.0002.28FF] # BRAILLE PATTERN DOTS-12345678
+2900 ; [*0909.0020.0002.2900] # RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE
+2901 ; [*090A.0020.0002.2901] # RIGHTWARDS TWO-HEADED ARROW WITH DOUBLE VERTICAL STROKE
+2902 ; [*090B.0020.0002.2902] # LEFTWARDS DOUBLE ARROW WITH VERTICAL STROKE
+2903 ; [*090C.0020.0002.2903] # RIGHTWARDS DOUBLE ARROW WITH VERTICAL STROKE
+2904 ; [*090D.0020.0002.2904] # LEFT RIGHT DOUBLE ARROW WITH VERTICAL STROKE
+2905 ; [*090E.0020.0002.2905] # RIGHTWARDS TWO-HEADED ARROW FROM BAR
+2906 ; [*090F.0020.0002.2906] # LEFTWARDS DOUBLE ARROW FROM BAR
+2907 ; [*0910.0020.0002.2907] # RIGHTWARDS DOUBLE ARROW FROM BAR
+2908 ; [*0911.0020.0002.2908] # DOWNWARDS ARROW WITH HORIZONTAL STROKE
+2909 ; [*0912.0020.0002.2909] # UPWARDS ARROW WITH HORIZONTAL STROKE
+290A ; [*0913.0020.0002.290A] # UPWARDS TRIPLE ARROW
+290B ; [*0914.0020.0002.290B] # DOWNWARDS TRIPLE ARROW
+290C ; [*0915.0020.0002.290C] # LEFTWARDS DOUBLE DASH ARROW
+290D ; [*0916.0020.0002.290D] # RIGHTWARDS DOUBLE DASH ARROW
+290E ; [*0917.0020.0002.290E] # LEFTWARDS TRIPLE DASH ARROW
+290F ; [*0918.0020.0002.290F] # RIGHTWARDS TRIPLE DASH ARROW
+2910 ; [*0919.0020.0002.2910] # RIGHTWARDS TWO-HEADED TRIPLE DASH ARROW
+2911 ; [*091A.0020.0002.2911] # RIGHTWARDS ARROW WITH DOTTED STEM
+2912 ; [*091B.0020.0002.2912] # UPWARDS ARROW TO BAR
+2913 ; [*091C.0020.0002.2913] # DOWNWARDS ARROW TO BAR
+2914 ; [*091D.0020.0002.2914] # RIGHTWARDS ARROW WITH TAIL WITH VERTICAL STROKE
+2915 ; [*091E.0020.0002.2915] # RIGHTWARDS ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE
+2916 ; [*091F.0020.0002.2916] # RIGHTWARDS TWO-HEADED ARROW WITH TAIL
+2917 ; [*0920.0020.0002.2917] # RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH VERTICAL STROKE
+2918 ; [*0921.0020.0002.2918] # RIGHTWARDS TWO-HEADED ARROW WITH TAIL WITH DOUBLE VERTICAL STROKE
+2919 ; [*0922.0020.0002.2919] # LEFTWARDS ARROW-TAIL
+291A ; [*0923.0020.0002.291A] # RIGHTWARDS ARROW-TAIL
+291B ; [*0924.0020.0002.291B] # LEFTWARDS DOUBLE ARROW-TAIL
+291C ; [*0925.0020.0002.291C] # RIGHTWARDS DOUBLE ARROW-TAIL
+291D ; [*0926.0020.0002.291D] # LEFTWARDS ARROW TO BLACK DIAMOND
+291E ; [*0927.0020.0002.291E] # RIGHTWARDS ARROW TO BLACK DIAMOND
+291F ; [*0928.0020.0002.291F] # LEFTWARDS ARROW FROM BAR TO BLACK DIAMOND
+2920 ; [*0929.0020.0002.2920] # RIGHTWARDS ARROW FROM BAR TO BLACK DIAMOND
+2921 ; [*092A.0020.0002.2921] # NORTH WEST AND SOUTH EAST ARROW
+2922 ; [*092B.0020.0002.2922] # NORTH EAST AND SOUTH WEST ARROW
+2923 ; [*092C.0020.0002.2923] # NORTH WEST ARROW WITH HOOK
+2924 ; [*092D.0020.0002.2924] # NORTH EAST ARROW WITH HOOK
+2925 ; [*092E.0020.0002.2925] # SOUTH EAST ARROW WITH HOOK
+2926 ; [*092F.0020.0002.2926] # SOUTH WEST ARROW WITH HOOK
+2927 ; [*0930.0020.0002.2927] # NORTH WEST ARROW AND NORTH EAST ARROW
+2928 ; [*0931.0020.0002.2928] # NORTH EAST ARROW AND SOUTH EAST ARROW
+2929 ; [*0932.0020.0002.2929] # SOUTH EAST ARROW AND SOUTH WEST ARROW
+292A ; [*0933.0020.0002.292A] # SOUTH WEST ARROW AND NORTH WEST ARROW
+292B ; [*0934.0020.0002.292B] # RISING DIAGONAL CROSSING FALLING DIAGONAL
+292C ; [*0935.0020.0002.292C] # FALLING DIAGONAL CROSSING RISING DIAGONAL
+292D ; [*0936.0020.0002.292D] # SOUTH EAST ARROW CROSSING NORTH EAST ARROW
+292E ; [*0937.0020.0002.292E] # NORTH EAST ARROW CROSSING SOUTH EAST ARROW
+292F ; [*0938.0020.0002.292F] # FALLING DIAGONAL CROSSING NORTH EAST ARROW
+2930 ; [*0939.0020.0002.2930] # RISING DIAGONAL CROSSING SOUTH EAST ARROW
+2931 ; [*093A.0020.0002.2931] # NORTH EAST ARROW CROSSING NORTH WEST ARROW
+2932 ; [*093B.0020.0002.2932] # NORTH WEST ARROW CROSSING NORTH EAST ARROW
+2933 ; [*093C.0020.0002.2933] # WAVE ARROW POINTING DIRECTLY RIGHT
+2934 ; [*093D.0020.0002.2934] # ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS
+2935 ; [*093E.0020.0002.2935] # ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS
+2936 ; [*093F.0020.0002.2936] # ARROW POINTING DOWNWARDS THEN CURVING LEFTWARDS
+2937 ; [*0940.0020.0002.2937] # ARROW POINTING DOWNWARDS THEN CURVING RIGHTWARDS
+2938 ; [*0941.0020.0002.2938] # RIGHT-SIDE ARC CLOCKWISE ARROW
+2939 ; [*0942.0020.0002.2939] # LEFT-SIDE ARC ANTICLOCKWISE ARROW
+293A ; [*0943.0020.0002.293A] # TOP ARC ANTICLOCKWISE ARROW
+293B ; [*0944.0020.0002.293B] # BOTTOM ARC ANTICLOCKWISE ARROW
+293C ; [*0945.0020.0002.293C] # TOP ARC CLOCKWISE ARROW WITH MINUS
+293D ; [*0946.0020.0002.293D] # TOP ARC ANTICLOCKWISE ARROW WITH PLUS
+293E ; [*0947.0020.0002.293E] # LOWER RIGHT SEMICIRCULAR CLOCKWISE ARROW
+293F ; [*0948.0020.0002.293F] # LOWER LEFT SEMICIRCULAR ANTICLOCKWISE ARROW
+2940 ; [*0949.0020.0002.2940] # ANTICLOCKWISE CLOSED CIRCLE ARROW
+2941 ; [*094A.0020.0002.2941] # CLOCKWISE CLOSED CIRCLE ARROW
+2942 ; [*094B.0020.0002.2942] # RIGHTWARDS ARROW ABOVE SHORT LEFTWARDS ARROW
+2943 ; [*094C.0020.0002.2943] # LEFTWARDS ARROW ABOVE SHORT RIGHTWARDS ARROW
+2944 ; [*094D.0020.0002.2944] # SHORT RIGHTWARDS ARROW ABOVE LEFTWARDS ARROW
+2945 ; [*094E.0020.0002.2945] # RIGHTWARDS ARROW WITH PLUS BELOW
+2946 ; [*094F.0020.0002.2946] # LEFTWARDS ARROW WITH PLUS BELOW
+2947 ; [*0950.0020.0002.2947] # RIGHTWARDS ARROW THROUGH X
+2948 ; [*0951.0020.0002.2948] # LEFT RIGHT ARROW THROUGH SMALL CIRCLE
+2949 ; [*0952.0020.0002.2949] # UPWARDS TWO-HEADED ARROW FROM SMALL CIRCLE
+294A ; [*0953.0020.0002.294A] # LEFT BARB UP RIGHT BARB DOWN HARPOON
+294B ; [*0954.0020.0002.294B] # LEFT BARB DOWN RIGHT BARB UP HARPOON
+294C ; [*0955.0020.0002.294C] # UP BARB RIGHT DOWN BARB LEFT HARPOON
+294D ; [*0956.0020.0002.294D] # UP BARB LEFT DOWN BARB RIGHT HARPOON
+294E ; [*0957.0020.0002.294E] # LEFT BARB UP RIGHT BARB UP HARPOON
+294F ; [*0958.0020.0002.294F] # UP BARB RIGHT DOWN BARB RIGHT HARPOON
+2950 ; [*0959.0020.0002.2950] # LEFT BARB DOWN RIGHT BARB DOWN HARPOON
+2951 ; [*095A.0020.0002.2951] # UP BARB LEFT DOWN BARB LEFT HARPOON
+2952 ; [*095B.0020.0002.2952] # LEFTWARDS HARPOON WITH BARB UP TO BAR
+2953 ; [*095C.0020.0002.2953] # RIGHTWARDS HARPOON WITH BARB UP TO BAR
+2954 ; [*095D.0020.0002.2954] # UPWARDS HARPOON WITH BARB RIGHT TO BAR
+2955 ; [*095E.0020.0002.2955] # DOWNWARDS HARPOON WITH BARB RIGHT TO BAR
+2956 ; [*095F.0020.0002.2956] # LEFTWARDS HARPOON WITH BARB DOWN TO BAR
+2957 ; [*0960.0020.0002.2957] # RIGHTWARDS HARPOON WITH BARB DOWN TO BAR
+2958 ; [*0961.0020.0002.2958] # UPWARDS HARPOON WITH BARB LEFT TO BAR
+2959 ; [*0962.0020.0002.2959] # DOWNWARDS HARPOON WITH BARB LEFT TO BAR
+295A ; [*0963.0020.0002.295A] # LEFTWARDS HARPOON WITH BARB UP FROM BAR
+295B ; [*0964.0020.0002.295B] # RIGHTWARDS HARPOON WITH BARB UP FROM BAR
+295C ; [*0965.0020.0002.295C] # UPWARDS HARPOON WITH BARB RIGHT FROM BAR
+295D ; [*0966.0020.0002.295D] # DOWNWARDS HARPOON WITH BARB RIGHT FROM BAR
+295E ; [*0967.0020.0002.295E] # LEFTWARDS HARPOON WITH BARB DOWN FROM BAR
+295F ; [*0968.0020.0002.295F] # RIGHTWARDS HARPOON WITH BARB DOWN FROM BAR
+2960 ; [*0969.0020.0002.2960] # UPWARDS HARPOON WITH BARB LEFT FROM BAR
+2961 ; [*096A.0020.0002.2961] # DOWNWARDS HARPOON WITH BARB LEFT FROM BAR
+2962 ; [*096B.0020.0002.2962] # LEFTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB DOWN
+2963 ; [*096C.0020.0002.2963] # UPWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT
+2964 ; [*096D.0020.0002.2964] # RIGHTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB DOWN
+2965 ; [*096E.0020.0002.2965] # DOWNWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT
+2966 ; [*096F.0020.0002.2966] # LEFTWARDS HARPOON WITH BARB UP ABOVE RIGHTWARDS HARPOON WITH BARB UP
+2967 ; [*0970.0020.0002.2967] # LEFTWARDS HARPOON WITH BARB DOWN ABOVE RIGHTWARDS HARPOON WITH BARB DOWN
+2968 ; [*0971.0020.0002.2968] # RIGHTWARDS HARPOON WITH BARB UP ABOVE LEFTWARDS HARPOON WITH BARB UP
+2969 ; [*0972.0020.0002.2969] # RIGHTWARDS HARPOON WITH BARB DOWN ABOVE LEFTWARDS HARPOON WITH BARB DOWN
+296A ; [*0973.0020.0002.296A] # LEFTWARDS HARPOON WITH BARB UP ABOVE LONG DASH
+296B ; [*0974.0020.0002.296B] # LEFTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH
+296C ; [*0975.0020.0002.296C] # RIGHTWARDS HARPOON WITH BARB UP ABOVE LONG DASH
+296D ; [*0976.0020.0002.296D] # RIGHTWARDS HARPOON WITH BARB DOWN BELOW LONG DASH
+296E ; [*0977.0020.0002.296E] # UPWARDS HARPOON WITH BARB LEFT BESIDE DOWNWARDS HARPOON WITH BARB RIGHT
+296F ; [*0978.0020.0002.296F] # DOWNWARDS HARPOON WITH BARB LEFT BESIDE UPWARDS HARPOON WITH BARB RIGHT
+2970 ; [*0979.0020.0002.2970] # RIGHT DOUBLE ARROW WITH ROUNDED HEAD
+2971 ; [*097A.0020.0002.2971] # EQUALS SIGN ABOVE RIGHTWARDS ARROW
+2972 ; [*097B.0020.0002.2972] # TILDE OPERATOR ABOVE RIGHTWARDS ARROW
+2973 ; [*097C.0020.0002.2973] # LEFTWARDS ARROW ABOVE TILDE OPERATOR
+2974 ; [*097D.0020.0002.2974] # RIGHTWARDS ARROW ABOVE TILDE OPERATOR
+2975 ; [*097E.0020.0002.2975] # RIGHTWARDS ARROW ABOVE ALMOST EQUAL TO
+2976 ; [*097F.0020.0002.2976] # LESS-THAN ABOVE LEFTWARDS ARROW
+2977 ; [*0980.0020.0002.2977] # LEFTWARDS ARROW THROUGH LESS-THAN
+2978 ; [*0981.0020.0002.2978] # GREATER-THAN ABOVE RIGHTWARDS ARROW
+2979 ; [*0982.0020.0002.2979] # SUBSET ABOVE RIGHTWARDS ARROW
+297A ; [*0983.0020.0002.297A] # LEFTWARDS ARROW THROUGH SUBSET
+297B ; [*0984.0020.0002.297B] # SUPERSET ABOVE LEFTWARDS ARROW
+297C ; [*0985.0020.0002.297C] # LEFT FISH TAIL
+297D ; [*0986.0020.0002.297D] # RIGHT FISH TAIL
+297E ; [*0987.0020.0002.297E] # UP FISH TAIL
+297F ; [*0988.0020.0002.297F] # DOWN FISH TAIL
+2980 ; [*0989.0020.0002.2980] # TRIPLE VERTICAL BAR DELIMITER
+2981 ; [*098A.0020.0002.2981] # Z NOTATION SPOT
+2982 ; [*098B.0020.0002.2982] # Z NOTATION TYPE COLON
+2983 ; [*02C1.0020.0002.2983] # LEFT WHITE CURLY BRACKET
+2984 ; [*02C2.0020.0002.2984] # RIGHT WHITE CURLY BRACKET
+2985 ; [*02C3.0020.0002.2985] # LEFT WHITE PARENTHESIS
+2986 ; [*02C4.0020.0002.2986] # RIGHT WHITE PARENTHESIS
+2987 ; [*02C5.0020.0002.2987] # Z NOTATION LEFT IMAGE BRACKET
+2988 ; [*02C6.0020.0002.2988] # Z NOTATION RIGHT IMAGE BRACKET
+2989 ; [*02C7.0020.0002.2989] # Z NOTATION LEFT BINDING BRACKET
+298A ; [*02C8.0020.0002.298A] # Z NOTATION RIGHT BINDING BRACKET
+298B ; [*02C9.0020.0002.298B] # LEFT SQUARE BRACKET WITH UNDERBAR
+298C ; [*02CA.0020.0002.298C] # RIGHT SQUARE BRACKET WITH UNDERBAR
+298D ; [*02CB.0020.0002.298D] # LEFT SQUARE BRACKET WITH TICK IN TOP CORNER
+298E ; [*02CC.0020.0002.298E] # RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
+298F ; [*02CD.0020.0002.298F] # LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
+2990 ; [*02CE.0020.0002.2990] # RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER
+2991 ; [*02CF.0020.0002.2991] # LEFT ANGLE BRACKET WITH DOT
+2992 ; [*02D0.0020.0002.2992] # RIGHT ANGLE BRACKET WITH DOT
+2993 ; [*02D1.0020.0002.2993] # LEFT ARC LESS-THAN BRACKET
+2994 ; [*02D2.0020.0002.2994] # RIGHT ARC GREATER-THAN BRACKET
+2995 ; [*02D3.0020.0002.2995] # DOUBLE LEFT ARC GREATER-THAN BRACKET
+2996 ; [*02D4.0020.0002.2996] # DOUBLE RIGHT ARC LESS-THAN BRACKET
+2997 ; [*02D5.0020.0002.2997] # LEFT BLACK TORTOISE SHELL BRACKET
+2998 ; [*02D6.0020.0002.2998] # RIGHT BLACK TORTOISE SHELL BRACKET
+2999 ; [*098C.0020.0002.2999] # DOTTED FENCE
+299A ; [*098D.0020.0002.299A] # VERTICAL ZIGZAG LINE
+299B ; [*098E.0020.0002.299B] # MEASURED ANGLE OPENING LEFT
+299C ; [*098F.0020.0002.299C] # RIGHT ANGLE VARIANT WITH SQUARE
+299D ; [*0990.0020.0002.299D] # MEASURED RIGHT ANGLE WITH DOT
+299E ; [*0991.0020.0002.299E] # ANGLE WITH S INSIDE
+299F ; [*0992.0020.0002.299F] # ACUTE ANGLE
+29A0 ; [*0993.0020.0002.29A0] # SPHERICAL ANGLE OPENING LEFT
+29A1 ; [*0994.0020.0002.29A1] # SPHERICAL ANGLE OPENING UP
+29A2 ; [*0995.0020.0002.29A2] # TURNED ANGLE
+29A3 ; [*0996.0020.0002.29A3] # REVERSED ANGLE
+29A4 ; [*0997.0020.0002.29A4] # ANGLE WITH UNDERBAR
+29A5 ; [*0998.0020.0002.29A5] # REVERSED ANGLE WITH UNDERBAR
+29A6 ; [*0999.0020.0002.29A6] # OBLIQUE ANGLE OPENING UP
+29A7 ; [*099A.0020.0002.29A7] # OBLIQUE ANGLE OPENING DOWN
+29A8 ; [*099B.0020.0002.29A8] # MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND RIGHT
+29A9 ; [*099C.0020.0002.29A9] # MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING UP AND LEFT
+29AA ; [*099D.0020.0002.29AA] # MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND RIGHT
+29AB ; [*099E.0020.0002.29AB] # MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING DOWN AND LEFT
+29AC ; [*099F.0020.0002.29AC] # MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND UP
+29AD ; [*09A0.0020.0002.29AD] # MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND UP
+29AE ; [*09A1.0020.0002.29AE] # MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING RIGHT AND DOWN
+29AF ; [*09A2.0020.0002.29AF] # MEASURED ANGLE WITH OPEN ARM ENDING IN ARROW POINTING LEFT AND DOWN
+29B0 ; [*09A3.0020.0002.29B0] # REVERSED EMPTY SET
+29B1 ; [*09A4.0020.0002.29B1] # EMPTY SET WITH OVERBAR
+29B2 ; [*09A5.0020.0002.29B2] # EMPTY SET WITH SMALL CIRCLE ABOVE
+29B3 ; [*09A6.0020.0002.29B3] # EMPTY SET WITH RIGHT ARROW ABOVE
+29B4 ; [*09A7.0020.0002.29B4] # EMPTY SET WITH LEFT ARROW ABOVE
+29B5 ; [*09A8.0020.0002.29B5] # CIRCLE WITH HORIZONTAL BAR
+29B6 ; [*09A9.0020.0002.29B6] # CIRCLED VERTICAL BAR
+29B7 ; [*09AA.0020.0002.29B7] # CIRCLED PARALLEL
+29B8 ; [*09AB.0020.0002.29B8] # CIRCLED REVERSE SOLIDUS
+29B9 ; [*09AC.0020.0002.29B9] # CIRCLED PERPENDICULAR
+29BA ; [*09AD.0020.0002.29BA] # CIRCLE DIVIDED BY HORIZONTAL BAR AND TOP HALF DIVIDED BY VERTICAL BAR
+29BB ; [*09AE.0020.0002.29BB] # CIRCLE WITH SUPERIMPOSED X
+29BC ; [*09AF.0020.0002.29BC] # CIRCLED ANTICLOCKWISE-ROTATED DIVISION SIGN
+29BD ; [*09B0.0020.0002.29BD] # UP ARROW THROUGH CIRCLE
+29BE ; [*09B1.0020.0002.29BE] # CIRCLED WHITE BULLET
+29BF ; [*09B2.0020.0002.29BF] # CIRCLED BULLET
+29C0 ; [*09B3.0020.0002.29C0] # CIRCLED LESS-THAN
+29C1 ; [*09B4.0020.0002.29C1] # CIRCLED GREATER-THAN
+29C2 ; [*09B5.0020.0002.29C2] # CIRCLE WITH SMALL CIRCLE TO THE RIGHT
+29C3 ; [*09B6.0020.0002.29C3] # CIRCLE WITH TWO HORIZONTAL STROKES TO THE RIGHT
+29C4 ; [*09B7.0020.0002.29C4] # SQUARED RISING DIAGONAL SLASH
+29C5 ; [*09B8.0020.0002.29C5] # SQUARED FALLING DIAGONAL SLASH
+29C6 ; [*09B9.0020.0002.29C6] # SQUARED ASTERISK
+29C7 ; [*09BA.0020.0002.29C7] # SQUARED SMALL CIRCLE
+29C8 ; [*09BB.0020.0002.29C8] # SQUARED SQUARE
+29C9 ; [*09BC.0020.0002.29C9] # TWO JOINED SQUARES
+29CA ; [*09BD.0020.0002.29CA] # TRIANGLE WITH DOT ABOVE
+29CB ; [*09BE.0020.0002.29CB] # TRIANGLE WITH UNDERBAR
+29CC ; [*09BF.0020.0002.29CC] # S IN TRIANGLE
+29CD ; [*09C0.0020.0002.29CD] # TRIANGLE WITH SERIFS AT BOTTOM
+29CE ; [*09C1.0020.0002.29CE] # RIGHT TRIANGLE ABOVE LEFT TRIANGLE
+29CF ; [*09C2.0020.0002.29CF] # LEFT TRIANGLE BESIDE VERTICAL BAR
+29D0 ; [*09C3.0020.0002.29D0] # VERTICAL BAR BESIDE RIGHT TRIANGLE
+29D1 ; [*09C4.0020.0002.29D1] # BOWTIE WITH LEFT HALF BLACK
+29D2 ; [*09C5.0020.0002.29D2] # BOWTIE WITH RIGHT HALF BLACK
+29D3 ; [*09C6.0020.0002.29D3] # BLACK BOWTIE
+29D4 ; [*09C7.0020.0002.29D4] # TIMES WITH LEFT HALF BLACK
+29D5 ; [*09C8.0020.0002.29D5] # TIMES WITH RIGHT HALF BLACK
+29D6 ; [*09C9.0020.0002.29D6] # WHITE HOURGLASS
+29D7 ; [*09CA.0020.0002.29D7] # BLACK HOURGLASS
+29D8 ; [*09CB.0020.0002.29D8] # LEFT WIGGLY FENCE
+29D9 ; [*09CC.0020.0002.29D9] # RIGHT WIGGLY FENCE
+29DA ; [*09CD.0020.0002.29DA] # LEFT DOUBLE WIGGLY FENCE
+29DB ; [*09CE.0020.0002.29DB] # RIGHT DOUBLE WIGGLY FENCE
+29DC ; [*09CF.0020.0002.29DC] # INCOMPLETE INFINITY
+29DD ; [*09D0.0020.0002.29DD] # TIE OVER INFINITY
+29DE ; [*09D1.0020.0002.29DE] # INFINITY NEGATED WITH VERTICAL BAR
+29DF ; [*09D2.0020.0002.29DF] # DOUBLE-ENDED MULTIMAP
+29E0 ; [*09D3.0020.0002.29E0] # SQUARE WITH CONTOURED OUTLINE
+29E1 ; [*09D4.0020.0002.29E1] # INCREASES AS
+29E2 ; [*09D5.0020.0002.29E2] # SHUFFLE PRODUCT
+29E3 ; [*09D6.0020.0002.29E3] # EQUALS SIGN AND SLANTED PARALLEL
+29E4 ; [*09D7.0020.0002.29E4] # EQUALS SIGN AND SLANTED PARALLEL WITH TILDE ABOVE
+29E5 ; [*09D8.0020.0002.29E5] # IDENTICAL TO AND SLANTED PARALLEL
+29E6 ; [*09D9.0020.0002.29E6] # GLEICH STARK
+29E7 ; [*09DA.0020.0002.29E7] # THERMODYNAMIC
+29E8 ; [*09DB.0020.0002.29E8] # DOWN-POINTING TRIANGLE WITH LEFT HALF BLACK
+29E9 ; [*09DC.0020.0002.29E9] # DOWN-POINTING TRIANGLE WITH RIGHT HALF BLACK
+29EA ; [*09DD.0020.0002.29EA] # BLACK DIAMOND WITH DOWN ARROW
+29EB ; [*09DE.0020.0002.29EB] # BLACK LOZENGE
+29EC ; [*09DF.0020.0002.29EC] # WHITE CIRCLE WITH DOWN ARROW
+29ED ; [*09E0.0020.0002.29ED] # BLACK CIRCLE WITH DOWN ARROW
+29EE ; [*09E1.0020.0002.29EE] # ERROR-BARRED WHITE SQUARE
+29EF ; [*09E2.0020.0002.29EF] # ERROR-BARRED BLACK SQUARE
+29F0 ; [*09E3.0020.0002.29F0] # ERROR-BARRED WHITE DIAMOND
+29F1 ; [*09E4.0020.0002.29F1] # ERROR-BARRED BLACK DIAMOND
+29F2 ; [*09E5.0020.0002.29F2] # ERROR-BARRED WHITE CIRCLE
+29F3 ; [*09E6.0020.0002.29F3] # ERROR-BARRED BLACK CIRCLE
+29F4 ; [*09E7.0020.0002.29F4] # RULE-DELAYED
+29F5 ; [*09E8.0020.0002.29F5] # REVERSE SOLIDUS OPERATOR
+29F6 ; [*09E9.0020.0002.29F6] # SOLIDUS WITH OVERBAR
+29F7 ; [*09EA.0020.0002.29F7] # REVERSE SOLIDUS WITH HORIZONTAL STROKE
+29F8 ; [*09EB.0020.0002.29F8] # BIG SOLIDUS
+29F9 ; [*09EC.0020.0002.29F9] # BIG REVERSE SOLIDUS
+29FA ; [*09ED.0020.0002.29FA] # DOUBLE PLUS
+29FB ; [*09EE.0020.0002.29FB] # TRIPLE PLUS
+29FC ; [*02BF.0020.0002.29FC] # LEFT-POINTING CURVED ANGLE BRACKET
+29FD ; [*02C0.0020.0002.29FD] # RIGHT-POINTING CURVED ANGLE BRACKET
+29FE ; [*09EF.0020.0002.29FE] # TINY
+29FF ; [*09F0.0020.0002.29FF] # MINY
+2A00 ; [*09F1.0020.0002.2A00] # N-ARY CIRCLED DOT OPERATOR
+2A01 ; [*09F2.0020.0002.2A01] # N-ARY CIRCLED PLUS OPERATOR
+2A02 ; [*09F3.0020.0002.2A02] # N-ARY CIRCLED TIMES OPERATOR
+2A03 ; [*09F4.0020.0002.2A03] # N-ARY UNION OPERATOR WITH DOT
+2A04 ; [*09F5.0020.0002.2A04] # N-ARY UNION OPERATOR WITH PLUS
+2A05 ; [*09F6.0020.0002.2A05] # N-ARY SQUARE INTERSECTION OPERATOR
+2A06 ; [*09F7.0020.0002.2A06] # N-ARY SQUARE UNION OPERATOR
+2A07 ; [*09F8.0020.0002.2A07] # TWO LOGICAL AND OPERATOR
+2A08 ; [*09F9.0020.0002.2A08] # TWO LOGICAL OR OPERATOR
+2A09 ; [*09FA.0020.0002.2A09] # N-ARY TIMES OPERATOR
+2A0A ; [*09FB.0020.0002.2A0A] # MODULO TWO SUM
+2A0B ; [*09FC.0020.0002.2A0B] # SUMMATION WITH INTEGRAL
+2A0C ; [*04DB.0020.0004.2A0C][*04DB.0020.0004.2A0C][*04DB.0020.001F.2A0C][*04DB.0020.001F.2A0C] # QUADRUPLE INTEGRAL OPERATOR; QQKN
+2A0D ; [*09FD.0020.0002.2A0D] # FINITE PART INTEGRAL
+2A0E ; [*09FE.0020.0002.2A0E] # INTEGRAL WITH DOUBLE STROKE
+2A0F ; [*09FF.0020.0002.2A0F] # INTEGRAL AVERAGE WITH SLASH
+2A10 ; [*0A00.0020.0002.2A10] # CIRCULATION FUNCTION
+2A11 ; [*0A01.0020.0002.2A11] # ANTICLOCKWISE INTEGRATION
+2A12 ; [*0A02.0020.0002.2A12] # LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE
+2A13 ; [*0A03.0020.0002.2A13] # LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE
+2A14 ; [*0A04.0020.0002.2A14] # LINE INTEGRATION NOT INCLUDING THE POLE
+2A15 ; [*0A05.0020.0002.2A15] # INTEGRAL AROUND A POINT OPERATOR
+2A16 ; [*0A06.0020.0002.2A16] # QUATERNION INTEGRAL OPERATOR
+2A17 ; [*0A07.0020.0002.2A17] # INTEGRAL WITH LEFTWARDS ARROW WITH HOOK
+2A18 ; [*0A08.0020.0002.2A18] # INTEGRAL WITH TIMES SIGN
+2A19 ; [*0A09.0020.0002.2A19] # INTEGRAL WITH INTERSECTION
+2A1A ; [*0A0A.0020.0002.2A1A] # INTEGRAL WITH UNION
+2A1B ; [*0A0B.0020.0002.2A1B] # INTEGRAL WITH OVERBAR
+2A1C ; [*0A0C.0020.0002.2A1C] # INTEGRAL WITH UNDERBAR
+2A1D ; [*0A0D.0020.0002.2A1D] # JOIN
+2A1E ; [*0A0E.0020.0002.2A1E] # LARGE LEFT TRIANGLE OPERATOR
+2A1F ; [*0A0F.0020.0002.2A1F] # Z NOTATION SCHEMA COMPOSITION
+2A20 ; [*0A10.0020.0002.2A20] # Z NOTATION SCHEMA PIPING
+2A21 ; [*0A11.0020.0002.2A21] # Z NOTATION SCHEMA PROJECTION
+2A22 ; [*0A12.0020.0002.2A22] # PLUS SIGN WITH SMALL CIRCLE ABOVE
+2A23 ; [*0A13.0020.0002.2A23] # PLUS SIGN WITH CIRCUMFLEX ACCENT ABOVE
+2A24 ; [*0A14.0020.0002.2A24] # PLUS SIGN WITH TILDE ABOVE
+2A25 ; [*0A15.0020.0002.2A25] # PLUS SIGN WITH DOT BELOW
+2A26 ; [*0A16.0020.0002.2A26] # PLUS SIGN WITH TILDE BELOW
+2A27 ; [*0A17.0020.0002.2A27] # PLUS SIGN WITH SUBSCRIPT TWO
+2A28 ; [*0A18.0020.0002.2A28] # PLUS SIGN WITH BLACK TRIANGLE
+2A29 ; [*0A19.0020.0002.2A29] # MINUS SIGN WITH COMMA ABOVE
+2A2A ; [*0A1A.0020.0002.2A2A] # MINUS SIGN WITH DOT BELOW
+2A2B ; [*0A1B.0020.0002.2A2B] # MINUS SIGN WITH FALLING DOTS
+2A2C ; [*0A1C.0020.0002.2A2C] # MINUS SIGN WITH RISING DOTS
+2A2D ; [*0A1D.0020.0002.2A2D] # PLUS SIGN IN LEFT HALF CIRCLE
+2A2E ; [*0A1E.0020.0002.2A2E] # PLUS SIGN IN RIGHT HALF CIRCLE
+2A2F ; [*0A1F.0020.0002.2A2F] # VECTOR OR CROSS PRODUCT
+2A30 ; [*0A20.0020.0002.2A30] # MULTIPLICATION SIGN WITH DOT ABOVE
+2A31 ; [*0A21.0020.0002.2A31] # MULTIPLICATION SIGN WITH UNDERBAR
+2A32 ; [*0A22.0020.0002.2A32] # SEMIDIRECT PRODUCT WITH BOTTOM CLOSED
+2A33 ; [*0A23.0020.0002.2A33] # SMASH PRODUCT
+2A34 ; [*0A24.0020.0002.2A34] # MULTIPLICATION SIGN IN LEFT HALF CIRCLE
+2A35 ; [*0A25.0020.0002.2A35] # MULTIPLICATION SIGN IN RIGHT HALF CIRCLE
+2A36 ; [*0A26.0020.0002.2A36] # CIRCLED MULTIPLICATION SIGN WITH CIRCUMFLEX ACCENT
+2A37 ; [*0A27.0020.0002.2A37] # MULTIPLICATION SIGN IN DOUBLE CIRCLE
+2A38 ; [*0A28.0020.0002.2A38] # CIRCLED DIVISION SIGN
+2A39 ; [*0A29.0020.0002.2A39] # PLUS SIGN IN TRIANGLE
+2A3A ; [*0A2A.0020.0002.2A3A] # MINUS SIGN IN TRIANGLE
+2A3B ; [*0A2B.0020.0002.2A3B] # MULTIPLICATION SIGN IN TRIANGLE
+2A3C ; [*0A2C.0020.0002.2A3C] # INTERIOR PRODUCT
+2A3D ; [*0A2D.0020.0002.2A3D] # RIGHTHAND INTERIOR PRODUCT
+2A3E ; [*0A2E.0020.0002.2A3E] # Z NOTATION RELATIONAL COMPOSITION
+2A3F ; [*0A2F.0020.0002.2A3F] # AMALGAMATION OR COPRODUCT
+2A40 ; [*0A30.0020.0002.2A40] # INTERSECTION WITH DOT
+2A41 ; [*0A31.0020.0002.2A41] # UNION WITH MINUS SIGN
+2A42 ; [*0A32.0020.0002.2A42] # UNION WITH OVERBAR
+2A43 ; [*0A33.0020.0002.2A43] # INTERSECTION WITH OVERBAR
+2A44 ; [*0A34.0020.0002.2A44] # INTERSECTION WITH LOGICAL AND
+2A45 ; [*0A35.0020.0002.2A45] # UNION WITH LOGICAL OR
+2A46 ; [*0A36.0020.0002.2A46] # UNION ABOVE INTERSECTION
+2A47 ; [*0A37.0020.0002.2A47] # INTERSECTION ABOVE UNION
+2A48 ; [*0A38.0020.0002.2A48] # UNION ABOVE BAR ABOVE INTERSECTION
+2A49 ; [*0A39.0020.0002.2A49] # INTERSECTION ABOVE BAR ABOVE UNION
+2A4A ; [*0A3A.0020.0002.2A4A] # UNION BESIDE AND JOINED WITH UNION
+2A4B ; [*0A3B.0020.0002.2A4B] # INTERSECTION BESIDE AND JOINED WITH INTERSECTION
+2A4C ; [*0A3C.0020.0002.2A4C] # CLOSED UNION WITH SERIFS
+2A4D ; [*0A3D.0020.0002.2A4D] # CLOSED INTERSECTION WITH SERIFS
+2A4E ; [*0A3E.0020.0002.2A4E] # DOUBLE SQUARE INTERSECTION
+2A4F ; [*0A3F.0020.0002.2A4F] # DOUBLE SQUARE UNION
+2A50 ; [*0A40.0020.0002.2A50] # CLOSED UNION WITH SERIFS AND SMASH PRODUCT
+2A51 ; [*0A41.0020.0002.2A51] # LOGICAL AND WITH DOT ABOVE
+2A52 ; [*0A42.0020.0002.2A52] # LOGICAL OR WITH DOT ABOVE
+2A53 ; [*0A43.0020.0002.2A53] # DOUBLE LOGICAL AND
+2A54 ; [*0A44.0020.0002.2A54] # DOUBLE LOGICAL OR
+2A55 ; [*0A45.0020.0002.2A55] # TWO INTERSECTING LOGICAL AND
+2A56 ; [*0A46.0020.0002.2A56] # TWO INTERSECTING LOGICAL OR
+2A57 ; [*0A47.0020.0002.2A57] # SLOPING LARGE OR
+2A58 ; [*0A48.0020.0002.2A58] # SLOPING LARGE AND
+2A59 ; [*0A49.0020.0002.2A59] # LOGICAL OR OVERLAPPING LOGICAL AND
+2A5A ; [*0A4A.0020.0002.2A5A] # LOGICAL AND WITH MIDDLE STEM
+2A5B ; [*0A4B.0020.0002.2A5B] # LOGICAL OR WITH MIDDLE STEM
+2A5C ; [*0A4C.0020.0002.2A5C] # LOGICAL AND WITH HORIZONTAL DASH
+2A5D ; [*0A4D.0020.0002.2A5D] # LOGICAL OR WITH HORIZONTAL DASH
+2A5E ; [*0A4E.0020.0002.2A5E] # LOGICAL AND WITH DOUBLE OVERBAR
+2A5F ; [*0A4F.0020.0002.2A5F] # LOGICAL AND WITH UNDERBAR
+2A60 ; [*0A50.0020.0002.2A60] # LOGICAL AND WITH DOUBLE UNDERBAR
+2A61 ; [*0A51.0020.0002.2A61] # SMALL VEE WITH UNDERBAR
+2A62 ; [*0A52.0020.0002.2A62] # LOGICAL OR WITH DOUBLE OVERBAR
+2A63 ; [*0A53.0020.0002.2A63] # LOGICAL OR WITH DOUBLE UNDERBAR
+2A64 ; [*0A54.0020.0002.2A64] # Z NOTATION DOMAIN ANTIRESTRICTION
+2A65 ; [*0A55.0020.0002.2A65] # Z NOTATION RANGE ANTIRESTRICTION
+2A66 ; [*0A56.0020.0002.2A66] # EQUALS SIGN WITH DOT BELOW
+2A67 ; [*0A57.0020.0002.2A67] # IDENTICAL WITH DOT ABOVE
+2A68 ; [*0A58.0020.0002.2A68] # TRIPLE HORIZONTAL BAR WITH DOUBLE VERTICAL STROKE
+2A69 ; [*0A59.0020.0002.2A69] # TRIPLE HORIZONTAL BAR WITH TRIPLE VERTICAL STROKE
+2A6A ; [*0A5A.0020.0002.2A6A] # TILDE OPERATOR WITH DOT ABOVE
+2A6B ; [*0A5B.0020.0002.2A6B] # TILDE OPERATOR WITH RISING DOTS
+2A6C ; [*0A5C.0020.0002.2A6C] # SIMILAR MINUS SIMILAR
+2A6D ; [*0A5D.0020.0002.2A6D] # CONGRUENT WITH DOT ABOVE
+2A6E ; [*0A5E.0020.0002.2A6E] # EQUALS WITH ASTERISK
+2A6F ; [*0A5F.0020.0002.2A6F] # ALMOST EQUAL TO WITH CIRCUMFLEX ACCENT
+2A70 ; [*0A60.0020.0002.2A70] # APPROXIMATELY EQUAL OR EQUAL TO
+2A71 ; [*0A61.0020.0002.2A71] # EQUALS SIGN ABOVE PLUS SIGN
+2A72 ; [*0A62.0020.0002.2A72] # PLUS SIGN ABOVE EQUALS SIGN
+2A73 ; [*0A63.0020.0002.2A73] # EQUALS SIGN ABOVE TILDE OPERATOR
+2A74 ; [*0241.0020.0004.2A74][*0241.0020.0004.2A74][*04BD.0020.001F.2A74] # DOUBLE COLON EQUAL; QQKN
+2A75 ; [*04BD.0020.0004.2A75][*04BD.0020.0004.2A75] # TWO CONSECUTIVE EQUALS SIGNS; QQKN
+2A76 ; [*04BD.0020.0004.2A76][*04BD.0020.0004.2A76][*04BD.0020.001F.2A76] # THREE CONSECUTIVE EQUALS SIGNS; QQKN
+2A77 ; [*0A64.0020.0002.2A77] # EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW
+2A78 ; [*0A65.0020.0002.2A78] # EQUIVALENT WITH FOUR DOTS ABOVE
+2A79 ; [*0A66.0020.0002.2A79] # LESS-THAN WITH CIRCLE INSIDE
+2A7A ; [*0A67.0020.0002.2A7A] # GREATER-THAN WITH CIRCLE INSIDE
+2A7B ; [*0A68.0020.0002.2A7B] # LESS-THAN WITH QUESTION MARK ABOVE
+2A7C ; [*0A69.0020.0002.2A7C] # GREATER-THAN WITH QUESTION MARK ABOVE
+2A7D ; [*0A6A.0020.0002.2A7D] # LESS-THAN OR SLANTED EQUAL TO
+2A7E ; [*0A6B.0020.0002.2A7E] # GREATER-THAN OR SLANTED EQUAL TO
+2A7F ; [*0A6C.0020.0002.2A7F] # LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE
+2A80 ; [*0A6D.0020.0002.2A80] # GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE
+2A81 ; [*0A6E.0020.0002.2A81] # LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE
+2A82 ; [*0A6F.0020.0002.2A82] # GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE
+2A83 ; [*0A70.0020.0002.2A83] # LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT
+2A84 ; [*0A71.0020.0002.2A84] # GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT
+2A85 ; [*0A72.0020.0002.2A85] # LESS-THAN OR APPROXIMATE
+2A86 ; [*0A73.0020.0002.2A86] # GREATER-THAN OR APPROXIMATE
+2A87 ; [*0A74.0020.0002.2A87] # LESS-THAN AND SINGLE-LINE NOT EQUAL TO
+2A88 ; [*0A75.0020.0002.2A88] # GREATER-THAN AND SINGLE-LINE NOT EQUAL TO
+2A89 ; [*0A76.0020.0002.2A89] # LESS-THAN AND NOT APPROXIMATE
+2A8A ; [*0A77.0020.0002.2A8A] # GREATER-THAN AND NOT APPROXIMATE
+2A8B ; [*0A78.0020.0002.2A8B] # LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN
+2A8C ; [*0A79.0020.0002.2A8C] # GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN
+2A8D ; [*0A7A.0020.0002.2A8D] # LESS-THAN ABOVE SIMILAR OR EQUAL
+2A8E ; [*0A7B.0020.0002.2A8E] # GREATER-THAN ABOVE SIMILAR OR EQUAL
+2A8F ; [*0A7C.0020.0002.2A8F] # LESS-THAN ABOVE SIMILAR ABOVE GREATER-THAN
+2A90 ; [*0A7D.0020.0002.2A90] # GREATER-THAN ABOVE SIMILAR ABOVE LESS-THAN
+2A91 ; [*0A7E.0020.0002.2A91] # LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL
+2A92 ; [*0A7F.0020.0002.2A92] # GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL
+2A93 ; [*0A80.0020.0002.2A93] # LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL
+2A94 ; [*0A81.0020.0002.2A94] # GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL
+2A95 ; [*0A82.0020.0002.2A95] # SLANTED EQUAL TO OR LESS-THAN
+2A96 ; [*0A83.0020.0002.2A96] # SLANTED EQUAL TO OR GREATER-THAN
+2A97 ; [*0A84.0020.0002.2A97] # SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE
+2A98 ; [*0A85.0020.0002.2A98] # SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE
+2A99 ; [*0A86.0020.0002.2A99] # DOUBLE-LINE EQUAL TO OR LESS-THAN
+2A9A ; [*0A87.0020.0002.2A9A] # DOUBLE-LINE EQUAL TO OR GREATER-THAN
+2A9B ; [*0A88.0020.0002.2A9B] # DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN
+2A9C ; [*0A89.0020.0002.2A9C] # DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN
+2A9D ; [*0A8A.0020.0002.2A9D] # SIMILAR OR LESS-THAN
+2A9E ; [*0A8B.0020.0002.2A9E] # SIMILAR OR GREATER-THAN
+2A9F ; [*0A8C.0020.0002.2A9F] # SIMILAR ABOVE LESS-THAN ABOVE EQUALS SIGN
+2AA0 ; [*0A8D.0020.0002.2AA0] # SIMILAR ABOVE GREATER-THAN ABOVE EQUALS SIGN
+2AA1 ; [*0A8E.0020.0002.2AA1] # DOUBLE NESTED LESS-THAN
+2AA2 ; [*0A8F.0020.0002.2AA2] # DOUBLE NESTED GREATER-THAN
+2AA3 ; [*0A90.0020.0002.2AA3] # DOUBLE NESTED LESS-THAN WITH UNDERBAR
+2AA4 ; [*0A91.0020.0002.2AA4] # GREATER-THAN OVERLAPPING LESS-THAN
+2AA5 ; [*0A92.0020.0002.2AA5] # GREATER-THAN BESIDE LESS-THAN
+2AA6 ; [*0A93.0020.0002.2AA6] # LESS-THAN CLOSED BY CURVE
+2AA7 ; [*0A94.0020.0002.2AA7] # GREATER-THAN CLOSED BY CURVE
+2AA8 ; [*0A95.0020.0002.2AA8] # LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL
+2AA9 ; [*0A96.0020.0002.2AA9] # GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL
+2AAA ; [*0A97.0020.0002.2AAA] # SMALLER THAN
+2AAB ; [*0A98.0020.0002.2AAB] # LARGER THAN
+2AAC ; [*0A99.0020.0002.2AAC] # SMALLER THAN OR EQUAL TO
+2AAD ; [*0A9A.0020.0002.2AAD] # LARGER THAN OR EQUAL TO
+2AAE ; [*0A9B.0020.0002.2AAE] # EQUALS SIGN WITH BUMPY ABOVE
+2AAF ; [*0A9C.0020.0002.2AAF] # PRECEDES ABOVE SINGLE-LINE EQUALS SIGN
+2AB0 ; [*0A9D.0020.0002.2AB0] # SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN
+2AB1 ; [*0A9E.0020.0002.2AB1] # PRECEDES ABOVE SINGLE-LINE NOT EQUAL TO
+2AB2 ; [*0A9F.0020.0002.2AB2] # SUCCEEDS ABOVE SINGLE-LINE NOT EQUAL TO
+2AB3 ; [*0AA0.0020.0002.2AB3] # PRECEDES ABOVE EQUALS SIGN
+2AB4 ; [*0AA1.0020.0002.2AB4] # SUCCEEDS ABOVE EQUALS SIGN
+2AB5 ; [*0AA2.0020.0002.2AB5] # PRECEDES ABOVE NOT EQUAL TO
+2AB6 ; [*0AA3.0020.0002.2AB6] # SUCCEEDS ABOVE NOT EQUAL TO
+2AB7 ; [*0AA4.0020.0002.2AB7] # PRECEDES ABOVE ALMOST EQUAL TO
+2AB8 ; [*0AA5.0020.0002.2AB8] # SUCCEEDS ABOVE ALMOST EQUAL TO
+2AB9 ; [*0AA6.0020.0002.2AB9] # PRECEDES ABOVE NOT ALMOST EQUAL TO
+2ABA ; [*0AA7.0020.0002.2ABA] # SUCCEEDS ABOVE NOT ALMOST EQUAL TO
+2ABB ; [*0AA8.0020.0002.2ABB] # DOUBLE PRECEDES
+2ABC ; [*0AA9.0020.0002.2ABC] # DOUBLE SUCCEEDS
+2ABD ; [*0AAA.0020.0002.2ABD] # SUBSET WITH DOT
+2ABE ; [*0AAB.0020.0002.2ABE] # SUPERSET WITH DOT
+2ABF ; [*0AAC.0020.0002.2ABF] # SUBSET WITH PLUS SIGN BELOW
+2AC0 ; [*0AAD.0020.0002.2AC0] # SUPERSET WITH PLUS SIGN BELOW
+2AC1 ; [*0AAE.0020.0002.2AC1] # SUBSET WITH MULTIPLICATION SIGN BELOW
+2AC2 ; [*0AAF.0020.0002.2AC2] # SUPERSET WITH MULTIPLICATION SIGN BELOW
+2AC3 ; [*0AB0.0020.0002.2AC3] # SUBSET OF OR EQUAL TO WITH DOT ABOVE
+2AC4 ; [*0AB1.0020.0002.2AC4] # SUPERSET OF OR EQUAL TO WITH DOT ABOVE
+2AC5 ; [*0AB2.0020.0002.2AC5] # SUBSET OF ABOVE EQUALS SIGN
+2AC6 ; [*0AB3.0020.0002.2AC6] # SUPERSET OF ABOVE EQUALS SIGN
+2AC7 ; [*0AB4.0020.0002.2AC7] # SUBSET OF ABOVE TILDE OPERATOR
+2AC8 ; [*0AB5.0020.0002.2AC8] # SUPERSET OF ABOVE TILDE OPERATOR
+2AC9 ; [*0AB6.0020.0002.2AC9] # SUBSET OF ABOVE ALMOST EQUAL TO
+2ACA ; [*0AB7.0020.0002.2ACA] # SUPERSET OF ABOVE ALMOST EQUAL TO
+2ACB ; [*0AB8.0020.0002.2ACB] # SUBSET OF ABOVE NOT EQUAL TO
+2ACC ; [*0AB9.0020.0002.2ACC] # SUPERSET OF ABOVE NOT EQUAL TO
+2ACD ; [*0ABA.0020.0002.2ACD] # SQUARE LEFT OPEN BOX OPERATOR
+2ACE ; [*0ABB.0020.0002.2ACE] # SQUARE RIGHT OPEN BOX OPERATOR
+2ACF ; [*0ABC.0020.0002.2ACF] # CLOSED SUBSET
+2AD0 ; [*0ABD.0020.0002.2AD0] # CLOSED SUPERSET
+2AD1 ; [*0ABE.0020.0002.2AD1] # CLOSED SUBSET OR EQUAL TO
+2AD2 ; [*0ABF.0020.0002.2AD2] # CLOSED SUPERSET OR EQUAL TO
+2AD3 ; [*0AC0.0020.0002.2AD3] # SUBSET ABOVE SUPERSET
+2AD4 ; [*0AC1.0020.0002.2AD4] # SUPERSET ABOVE SUBSET
+2AD5 ; [*0AC2.0020.0002.2AD5] # SUBSET ABOVE SUBSET
+2AD6 ; [*0AC3.0020.0002.2AD6] # SUPERSET ABOVE SUPERSET
+2AD7 ; [*0AC4.0020.0002.2AD7] # SUPERSET BESIDE SUBSET
+2AD8 ; [*0AC5.0020.0002.2AD8] # SUPERSET BESIDE AND JOINED BY DASH WITH SUBSET
+2AD9 ; [*0AC6.0020.0002.2AD9] # ELEMENT OF OPENING DOWNWARDS
+2ADA ; [*0AC7.0020.0002.2ADA] # PITCHFORK WITH TEE TOP
+2ADB ; [*0AC8.0020.0002.2ADB] # TRANSVERSAL INTERSECTION
+2ADC ; [*0AC9.0020.0002.2ADD][.0000.0054.0002.0338] # FORKING; QQCM
+2ADD ; [*0AC9.0020.0002.2ADD] # NONFORKING
+2ADE ; [*0ACA.0020.0002.2ADE] # SHORT LEFT TACK
+2ADF ; [*0ACB.0020.0002.2ADF] # SHORT DOWN TACK
+2AE0 ; [*0ACC.0020.0002.2AE0] # SHORT UP TACK
+2AE1 ; [*0ACD.0020.0002.2AE1] # PERPENDICULAR WITH S
+2AE2 ; [*0ACE.0020.0002.2AE2] # VERTICAL BAR TRIPLE RIGHT TURNSTILE
+2AE3 ; [*0ACF.0020.0002.2AE3] # DOUBLE VERTICAL BAR LEFT TURNSTILE
+2AE4 ; [*0AD0.0020.0002.2AE4] # VERTICAL BAR DOUBLE LEFT TURNSTILE
+2AE5 ; [*0AD1.0020.0002.2AE5] # DOUBLE VERTICAL BAR DOUBLE LEFT TURNSTILE
+2AE6 ; [*0AD2.0020.0002.2AE6] # LONG DASH FROM LEFT MEMBER OF DOUBLE VERTICAL
+2AE7 ; [*0AD3.0020.0002.2AE7] # SHORT DOWN TACK WITH OVERBAR
+2AE8 ; [*0AD4.0020.0002.2AE8] # SHORT UP TACK WITH UNDERBAR
+2AE9 ; [*0AD5.0020.0002.2AE9] # SHORT UP TACK ABOVE SHORT DOWN TACK
+2AEA ; [*0AD6.0020.0002.2AEA] # DOUBLE DOWN TACK
+2AEB ; [*0AD7.0020.0002.2AEB] # DOUBLE UP TACK
+2AEC ; [*0AD8.0020.0002.2AEC] # DOUBLE STROKE NOT SIGN
+2AED ; [*0AD9.0020.0002.2AED] # REVERSED DOUBLE STROKE NOT SIGN
+2AEE ; [*0ADA.0020.0002.2AEE] # DOES NOT DIVIDE WITH REVERSED NEGATION SLASH
+2AEF ; [*0ADB.0020.0002.2AEF] # VERTICAL LINE WITH CIRCLE ABOVE
+2AF0 ; [*0ADC.0020.0002.2AF0] # VERTICAL LINE WITH CIRCLE BELOW
+2AF1 ; [*0ADD.0020.0002.2AF1] # DOWN TACK WITH CIRCLE BELOW
+2AF2 ; [*0ADE.0020.0002.2AF2] # PARALLEL WITH HORIZONTAL STROKE
+2AF3 ; [*0ADF.0020.0002.2AF3] # PARALLEL WITH TILDE OPERATOR
+2AF4 ; [*0AE0.0020.0002.2AF4] # TRIPLE VERTICAL BAR BINARY RELATION
+2AF5 ; [*0AE1.0020.0002.2AF5] # TRIPLE VERTICAL BAR WITH HORIZONTAL STROKE
+2AF6 ; [*0AE2.0020.0002.2AF6] # TRIPLE COLON OPERATOR
+2AF7 ; [*0AE3.0020.0002.2AF7] # TRIPLE NESTED LESS-THAN
+2AF8 ; [*0AE4.0020.0002.2AF8] # TRIPLE NESTED GREATER-THAN
+2AF9 ; [*0AE5.0020.0002.2AF9] # DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO
+2AFA ; [*0AE6.0020.0002.2AFA] # DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO
+2AFB ; [*0AE7.0020.0002.2AFB] # TRIPLE SOLIDUS BINARY RELATION
+2AFC ; [*0AE8.0020.0002.2AFC] # LARGE TRIPLE VERTICAL BAR OPERATOR
+2AFD ; [*0AE9.0020.0002.2AFD] # DOUBLE SOLIDUS OPERATOR
+2AFE ; [*0AEA.0020.0002.2AFE] # WHITE VERTICAL BAR
+2AFF ; [*0AEB.0020.0002.2AFF] # N-ARY WHITE VERTICAL BAR
+2B00 ; [*0AEC.0020.0002.2B00] # NORTH EAST WHITE ARROW
+2B01 ; [*0AED.0020.0002.2B01] # NORTH WEST WHITE ARROW
+2B02 ; [*0AEE.0020.0002.2B02] # SOUTH EAST WHITE ARROW
+2B03 ; [*0AEF.0020.0002.2B03] # SOUTH WEST WHITE ARROW
+2B04 ; [*0AF0.0020.0002.2B04] # LEFT RIGHT WHITE ARROW
+2B05 ; [*0AF1.0020.0002.2B05] # LEFTWARDS BLACK ARROW
+2B06 ; [*0AF2.0020.0002.2B06] # UPWARDS BLACK ARROW
+2B07 ; [*0AF3.0020.0002.2B07] # DOWNWARDS BLACK ARROW
+2B08 ; [*0AF4.0020.0002.2B08] # NORTH EAST BLACK ARROW
+2B09 ; [*0AF5.0020.0002.2B09] # NORTH WEST BLACK ARROW
+2B0A ; [*0AF6.0020.0002.2B0A] # SOUTH EAST BLACK ARROW
+2B0B ; [*0AF7.0020.0002.2B0B] # SOUTH WEST BLACK ARROW
+2B0C ; [*0AF8.0020.0002.2B0C] # LEFT RIGHT BLACK ARROW
+2B0D ; [*0AF9.0020.0002.2B0D] # UP DOWN BLACK ARROW
+2B0E ; [*0AFA.0020.0002.2B0E] # RIGHTWARDS ARROW WITH TIP DOWNWARDS
+2B0F ; [*0AFB.0020.0002.2B0F] # RIGHTWARDS ARROW WITH TIP UPWARDS
+2B10 ; [*0AFC.0020.0002.2B10] # LEFTWARDS ARROW WITH TIP DOWNWARDS
+2B11 ; [*0AFD.0020.0002.2B11] # LEFTWARDS ARROW WITH TIP UPWARDS
+2B12 ; [*0AFE.0020.0002.2B12] # SQUARE WITH TOP HALF BLACK
+2B13 ; [*0AFF.0020.0002.2B13] # SQUARE WITH BOTTOM HALF BLACK
+2B14 ; [*0B00.0020.0002.2B14] # SQUARE WITH UPPER RIGHT DIAGONAL HALF BLACK
+2B15 ; [*0B01.0020.0002.2B15] # SQUARE WITH LOWER LEFT DIAGONAL HALF BLACK
+2B16 ; [*0B02.0020.0002.2B16] # DIAMOND WITH LEFT HALF BLACK
+2B17 ; [*0B03.0020.0002.2B17] # DIAMOND WITH RIGHT HALF BLACK
+2B18 ; [*0B04.0020.0002.2B18] # DIAMOND WITH TOP HALF BLACK
+2B19 ; [*0B05.0020.0002.2B19] # DIAMOND WITH BOTTOM HALF BLACK
+2B1A ; [*0B06.0020.0002.2B1A] # DOTTED SQUARE
+2B20 ; [*0B07.0020.0002.2B20] # WHITE PENTAGON
+2B21 ; [*0B08.0020.0002.2B21] # WHITE HEXAGON
+2B22 ; [*0B09.0020.0002.2B22] # BLACK HEXAGON
+2B23 ; [*0B0A.0020.0002.2B23] # HORIZONTAL BLACK HEXAGON
+2CE5 ; [*0B0B.0020.0002.2CE5] # COPTIC SYMBOL MI RO
+2CE6 ; [*0B0C.0020.0002.2CE6] # COPTIC SYMBOL PI RO
+2CE7 ; [*0B0D.0020.0002.2CE7] # COPTIC SYMBOL STAUROS
+2CE8 ; [*0B0E.0020.0002.2CE8] # COPTIC SYMBOL TAU RO
+2CE9 ; [*0B0F.0020.0002.2CE9] # COPTIC SYMBOL KHI RO
+2CEA ; [*0B10.0020.0002.2CEA] # COPTIC SYMBOL SHIMA SIMA
+2CF9 ; [*0270.0020.0002.2CF9] # COPTIC OLD NUBIAN FULL STOP
+2CFA ; [*0263.0020.0002.2CFA] # COPTIC OLD NUBIAN DIRECT QUESTION MARK
+2CFB ; [*0264.0020.0002.2CFB] # COPTIC OLD NUBIAN INDIRECT QUESTION MARK
+2CFC ; [*0294.0020.0002.2CFC] # COPTIC OLD NUBIAN VERSE DIVIDER
+2CFD ; [*0F26.0020.0002.2CFD] # COPTIC FRACTION ONE HALF
+2CFE ; [*0271.0020.0002.2CFE] # COPTIC FULL STOP
+2CFF ; [*0295.0020.0002.2CFF] # COPTIC MORPHOLOGICAL DIVIDER
+2E00 ; [*031F.0020.0002.2E00] # RIGHT ANGLE SUBSTITUTION MARKER
+2E01 ; [*0320.0020.0002.2E01] # RIGHT ANGLE DOTTED SUBSTITUTION MARKER
+2E02 ; [*02D7.0020.0002.2E02] # LEFT SUBSTITUTION BRACKET
+2E03 ; [*02D8.0020.0002.2E03] # RIGHT SUBSTITUTION BRACKET
+2E04 ; [*02D9.0020.0002.2E04] # LEFT DOTTED SUBSTITUTION BRACKET
+2E05 ; [*02DA.0020.0002.2E05] # RIGHT DOTTED SUBSTITUTION BRACKET
+2E06 ; [*0321.0020.0002.2E06] # RAISED INTERPOLATION MARKER
+2E07 ; [*0322.0020.0002.2E07] # RAISED DOTTED INTERPOLATION MARKER
+2E08 ; [*0323.0020.0002.2E08] # DOTTED TRANSPOSITION MARKER
+2E09 ; [*02DB.0020.0002.2E09] # LEFT TRANSPOSITION BRACKET
+2E0A ; [*02DC.0020.0002.2E0A] # RIGHT TRANSPOSITION BRACKET
+2E0B ; [*0324.0020.0002.2E0B] # RAISED SQUARE
+2E0C ; [*02DD.0020.0002.2E0C] # LEFT RAISED OMISSION BRACKET
+2E0D ; [*02DE.0020.0002.2E0D] # RIGHT RAISED OMISSION BRACKET
+2E0E ; [*0325.0020.0002.2E0E] # EDITORIAL CORONIS
+2E0F ; [*0326.0020.0002.2E0F] # PARAGRAPHOS
+2E10 ; [*0327.0020.0002.2E10] # FORKED PARAGRAPHOS
+2E11 ; [*0328.0020.0002.2E11] # REVERSED FORKED PARAGRAPHOS
+2E12 ; [*0329.0020.0002.2E12] # HYPODIASTOLE
+2E13 ; [*032A.0020.0002.2E13] # DOTTED OBELOS
+2E14 ; [*032B.0020.0002.2E14] # DOWNWARDS ANCORA
+2E15 ; [*032C.0020.0002.2E15] # UPWARDS ANCORA
+2E16 ; [*032D.0020.0002.2E16] # DOTTED RIGHT-POINTING ANGLE
+2E17 ; [*022D.0020.0002.2E17] # DOUBLE OBLIQUE HYPHEN
+2E1C ; [*02DF.0020.0002.2E1C] # LEFT LOW PARAPHRASE BRACKET
+2E1D ; [*02E0.0020.0002.2E1D] # RIGHT LOW PARAPHRASE BRACKET
+2FF0 ; [*0EEB.0020.0002.2FF0] # IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT
+2FF1 ; [*0EEC.0020.0002.2FF1] # IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO BELOW
+2FF2 ; [*0EED.0020.0002.2FF2] # IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO MIDDLE AND RIGHT
+2FF3 ; [*0EEE.0020.0002.2FF3] # IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO MIDDLE AND BELOW
+2FF4 ; [*0EEF.0020.0002.2FF4] # IDEOGRAPHIC DESCRIPTION CHARACTER FULL SURROUND
+2FF5 ; [*0EF0.0020.0002.2FF5] # IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM ABOVE
+2FF6 ; [*0EF1.0020.0002.2FF6] # IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM BELOW
+2FF7 ; [*0EF2.0020.0002.2FF7] # IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LEFT
+2FF8 ; [*0EF3.0020.0002.2FF8] # IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER LEFT
+2FF9 ; [*0EF4.0020.0002.2FF9] # IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER RIGHT
+2FFA ; [*0EF5.0020.0002.2FFA] # IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER LEFT
+2FFB ; [*0EF6.0020.0002.2FFB] # IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID
+3000 ; [*0209.0020.0003.3000] # IDEOGRAPHIC SPACE; QQK
+3001 ; [*023B.0020.0002.3001] # IDEOGRAPHIC COMMA
+3002 ; [*0272.0020.0002.3002] # IDEOGRAPHIC FULL STOP
+3003 ; [*0315.0020.0002.3003] # DITTO MARK
+3004 ; [*0F07.0020.0002.3004] # JAPANESE INDUSTRIAL STANDARD SYMBOL
+3008 ; [*02E1.0020.0002.3008] # LEFT ANGLE BRACKET
+3009 ; [*02E2.0020.0002.3009] # RIGHT ANGLE BRACKET
+300A ; [*02E3.0020.0002.300A] # LEFT DOUBLE ANGLE BRACKET
+300B ; [*02E4.0020.0002.300B] # RIGHT DOUBLE ANGLE BRACKET
+300C ; [*02E5.0020.0002.300C] # LEFT CORNER BRACKET
+300D ; [*02E6.0020.0002.300D] # RIGHT CORNER BRACKET
+300E ; [*02E7.0020.0002.300E] # LEFT WHITE CORNER BRACKET
+300F ; [*02E8.0020.0002.300F] # RIGHT WHITE CORNER BRACKET
+3010 ; [*02E9.0020.0002.3010] # LEFT BLACK LENTICULAR BRACKET
+3011 ; [*02EA.0020.0002.3011] # RIGHT BLACK LENTICULAR BRACKET
+3012 ; [*0F08.0020.0002.3012] # POSTAL MARK
+3013 ; [*0F09.0020.0002.3013] # GETA MARK
+3014 ; [*02EB.0020.0002.3014] # LEFT TORTOISE SHELL BRACKET
+3015 ; [*02EC.0020.0002.3015] # RIGHT TORTOISE SHELL BRACKET
+3016 ; [*02ED.0020.0002.3016] # LEFT WHITE LENTICULAR BRACKET
+3017 ; [*02EE.0020.0002.3017] # RIGHT WHITE LENTICULAR BRACKET
+3018 ; [*02EF.0020.0002.3018] # LEFT WHITE TORTOISE SHELL BRACKET
+3019 ; [*02F0.0020.0002.3019] # RIGHT WHITE TORTOISE SHELL BRACKET
+301A ; [*02F1.0020.0002.301A] # LEFT WHITE SQUARE BRACKET
+301B ; [*02F2.0020.0002.301B] # RIGHT WHITE SQUARE BRACKET
+301C ; [*022E.0020.0002.301C] # WAVE DASH
+301D ; [*02AC.0020.0002.301D] # REVERSED DOUBLE PRIME QUOTATION MARK
+301E ; [*02AD.0020.0002.301E] # DOUBLE PRIME QUOTATION MARK
+301F ; [*02AE.0020.0002.301F] # LOW DOUBLE PRIME QUOTATION MARK
+3020 ; [*0F0A.0020.0002.3020] # POSTAL MARK FACE
+3030 ; [*022F.0020.0002.3030] # WAVY DASH
+3036 ; [*0F08.0020.0004.3036] # CIRCLED POSTAL MARK; QQK
+3037 ; [*0F0B.0020.0002.3037] # IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL
+303D ; [*0316.0020.0002.303D] # PART ALTERNATION MARK
+303E ; [*0F0C.0020.0002.303E] # IDEOGRAPHIC VARIATION INDICATOR
+303F ; [*0F0D.0020.0002.303F] # IDEOGRAPHIC HALF FILL SPACE
+309B ; [*021F.0020.0002.309B] # KATAKANA-HIRAGANA VOICED SOUND MARK
+309C ; [*0220.0020.0002.309C] # KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+30A0 ; [*0230.0020.0002.30A0] # KATAKANA-HIRAGANA DOUBLE HYPHEN
+30FB ; [*0231.0020.0002.30FB] # KATAKANA MIDDLE DOT
+3190 ; [*0F0E.0020.0002.3190] # IDEOGRAPHIC ANNOTATION LINKING MARK
+3191 ; [*0F0F.0020.0002.3191] # IDEOGRAPHIC ANNOTATION REVERSE MARK
+31C0 ; [*0EF7.0020.0002.31C0] # CJK STROKE T
+31C1 ; [*0EF8.0020.0002.31C1] # CJK STROKE WG
+31C2 ; [*0EF9.0020.0002.31C2] # CJK STROKE XG
+31C3 ; [*0EFA.0020.0002.31C3] # CJK STROKE BXG
+31C4 ; [*0EFB.0020.0002.31C4] # CJK STROKE SW
+31C5 ; [*0EFC.0020.0002.31C5] # CJK STROKE HZZ
+31C6 ; [*0EFD.0020.0002.31C6] # CJK STROKE HZG
+31C7 ; [*0EFE.0020.0002.31C7] # CJK STROKE HP
+31C8 ; [*0EFF.0020.0002.31C8] # CJK STROKE HZWG
+31C9 ; [*0F00.0020.0002.31C9] # CJK STROKE SZWG
+31CA ; [*0F01.0020.0002.31CA] # CJK STROKE HZT
+31CB ; [*0F02.0020.0002.31CB] # CJK STROKE HZZP
+31CC ; [*0F03.0020.0002.31CC] # CJK STROKE HPWG
+31CD ; [*0F04.0020.0002.31CD] # CJK STROKE HZW
+31CE ; [*0F05.0020.0002.31CE] # CJK STROKE HZZZ
+31CF ; [*0F06.0020.0002.31CF] # CJK STROKE N
+327F ; [*0F10.0020.0002.327F] # KOREAN STANDARD SYMBOL
+4DC0 ; [*0C1F.0020.0002.4DC0] # HEXAGRAM FOR THE CREATIVE HEAVEN
+4DC1 ; [*0C20.0020.0002.4DC1] # HEXAGRAM FOR THE RECEPTIVE EARTH
+4DC2 ; [*0C21.0020.0002.4DC2] # HEXAGRAM FOR DIFFICULTY AT THE BEGINNING
+4DC3 ; [*0C22.0020.0002.4DC3] # HEXAGRAM FOR YOUTHFUL FOLLY
+4DC4 ; [*0C23.0020.0002.4DC4] # HEXAGRAM FOR WAITING
+4DC5 ; [*0C24.0020.0002.4DC5] # HEXAGRAM FOR CONFLICT
+4DC6 ; [*0C25.0020.0002.4DC6] # HEXAGRAM FOR THE ARMY
+4DC7 ; [*0C26.0020.0002.4DC7] # HEXAGRAM FOR HOLDING TOGETHER
+4DC8 ; [*0C27.0020.0002.4DC8] # HEXAGRAM FOR SMALL TAMING
+4DC9 ; [*0C28.0020.0002.4DC9] # HEXAGRAM FOR TREADING
+4DCA ; [*0C29.0020.0002.4DCA] # HEXAGRAM FOR PEACE
+4DCB ; [*0C2A.0020.0002.4DCB] # HEXAGRAM FOR STANDSTILL
+4DCC ; [*0C2B.0020.0002.4DCC] # HEXAGRAM FOR FELLOWSHIP
+4DCD ; [*0C2C.0020.0002.4DCD] # HEXAGRAM FOR GREAT POSSESSION
+4DCE ; [*0C2D.0020.0002.4DCE] # HEXAGRAM FOR MODESTY
+4DCF ; [*0C2E.0020.0002.4DCF] # HEXAGRAM FOR ENTHUSIASM
+4DD0 ; [*0C2F.0020.0002.4DD0] # HEXAGRAM FOR FOLLOWING
+4DD1 ; [*0C30.0020.0002.4DD1] # HEXAGRAM FOR WORK ON THE DECAYED
+4DD2 ; [*0C31.0020.0002.4DD2] # HEXAGRAM FOR APPROACH
+4DD3 ; [*0C32.0020.0002.4DD3] # HEXAGRAM FOR CONTEMPLATION
+4DD4 ; [*0C33.0020.0002.4DD4] # HEXAGRAM FOR BITING THROUGH
+4DD5 ; [*0C34.0020.0002.4DD5] # HEXAGRAM FOR GRACE
+4DD6 ; [*0C35.0020.0002.4DD6] # HEXAGRAM FOR SPLITTING APART
+4DD7 ; [*0C36.0020.0002.4DD7] # HEXAGRAM FOR RETURN
+4DD8 ; [*0C37.0020.0002.4DD8] # HEXAGRAM FOR INNOCENCE
+4DD9 ; [*0C38.0020.0002.4DD9] # HEXAGRAM FOR GREAT TAMING
+4DDA ; [*0C39.0020.0002.4DDA] # HEXAGRAM FOR MOUTH CORNERS
+4DDB ; [*0C3A.0020.0002.4DDB] # HEXAGRAM FOR GREAT PREPONDERANCE
+4DDC ; [*0C3B.0020.0002.4DDC] # HEXAGRAM FOR THE ABYSMAL WATER
+4DDD ; [*0C3C.0020.0002.4DDD] # HEXAGRAM FOR THE CLINGING FIRE
+4DDE ; [*0C3D.0020.0002.4DDE] # HEXAGRAM FOR INFLUENCE
+4DDF ; [*0C3E.0020.0002.4DDF] # HEXAGRAM FOR DURATION
+4DE0 ; [*0C3F.0020.0002.4DE0] # HEXAGRAM FOR RETREAT
+4DE1 ; [*0C40.0020.0002.4DE1] # HEXAGRAM FOR GREAT POWER
+4DE2 ; [*0C41.0020.0002.4DE2] # HEXAGRAM FOR PROGRESS
+4DE3 ; [*0C42.0020.0002.4DE3] # HEXAGRAM FOR DARKENING OF THE LIGHT
+4DE4 ; [*0C43.0020.0002.4DE4] # HEXAGRAM FOR THE FAMILY
+4DE5 ; [*0C44.0020.0002.4DE5] # HEXAGRAM FOR OPPOSITION
+4DE6 ; [*0C45.0020.0002.4DE6] # HEXAGRAM FOR OBSTRUCTION
+4DE7 ; [*0C46.0020.0002.4DE7] # HEXAGRAM FOR DELIVERANCE
+4DE8 ; [*0C47.0020.0002.4DE8] # HEXAGRAM FOR DECREASE
+4DE9 ; [*0C48.0020.0002.4DE9] # HEXAGRAM FOR INCREASE
+4DEA ; [*0C49.0020.0002.4DEA] # HEXAGRAM FOR BREAKTHROUGH
+4DEB ; [*0C4A.0020.0002.4DEB] # HEXAGRAM FOR COMING TO MEET
+4DEC ; [*0C4B.0020.0002.4DEC] # HEXAGRAM FOR GATHERING TOGETHER
+4DED ; [*0C4C.0020.0002.4DED] # HEXAGRAM FOR PUSHING UPWARD
+4DEE ; [*0C4D.0020.0002.4DEE] # HEXAGRAM FOR OPPRESSION
+4DEF ; [*0C4E.0020.0002.4DEF] # HEXAGRAM FOR THE WELL
+4DF0 ; [*0C4F.0020.0002.4DF0] # HEXAGRAM FOR REVOLUTION
+4DF1 ; [*0C50.0020.0002.4DF1] # HEXAGRAM FOR THE CAULDRON
+4DF2 ; [*0C51.0020.0002.4DF2] # HEXAGRAM FOR THE AROUSING THUNDER
+4DF3 ; [*0C52.0020.0002.4DF3] # HEXAGRAM FOR THE KEEPING STILL MOUNTAIN
+4DF4 ; [*0C53.0020.0002.4DF4] # HEXAGRAM FOR DEVELOPMENT
+4DF5 ; [*0C54.0020.0002.4DF5] # HEXAGRAM FOR THE MARRYING MAIDEN
+4DF6 ; [*0C55.0020.0002.4DF6] # HEXAGRAM FOR ABUNDANCE
+4DF7 ; [*0C56.0020.0002.4DF7] # HEXAGRAM FOR THE WANDERER
+4DF8 ; [*0C57.0020.0002.4DF8] # HEXAGRAM FOR THE GENTLE WIND
+4DF9 ; [*0C58.0020.0002.4DF9] # HEXAGRAM FOR THE JOYOUS LAKE
+4DFA ; [*0C59.0020.0002.4DFA] # HEXAGRAM FOR DISPERSION
+4DFB ; [*0C5A.0020.0002.4DFB] # HEXAGRAM FOR LIMITATION
+4DFC ; [*0C5B.0020.0002.4DFC] # HEXAGRAM FOR INNER TRUTH
+4DFD ; [*0C5C.0020.0002.4DFD] # HEXAGRAM FOR SMALL PREPONDERANCE
+4DFE ; [*0C5D.0020.0002.4DFE] # HEXAGRAM FOR AFTER COMPLETION
+4DFF ; [*0C5E.0020.0002.4DFF] # HEXAGRAM FOR BEFORE COMPLETION
+A490 ; [*0CB6.0020.0002.A490] # YI RADICAL QOT
+A491 ; [*0CB7.0020.0002.A491] # YI RADICAL LI
+A492 ; [*0CB8.0020.0002.A492] # YI RADICAL KIT
+A493 ; [*0CB9.0020.0002.A493] # YI RADICAL NYIP
+A494 ; [*0CBA.0020.0002.A494] # YI RADICAL CYP
+A495 ; [*0CBB.0020.0002.A495] # YI RADICAL SSI
+A496 ; [*0CBC.0020.0002.A496] # YI RADICAL GGOP
+A497 ; [*0CBD.0020.0002.A497] # YI RADICAL GEP
+A498 ; [*0CBE.0020.0002.A498] # YI RADICAL MI
+A499 ; [*0CBF.0020.0002.A499] # YI RADICAL HXIT
+A49A ; [*0CC0.0020.0002.A49A] # YI RADICAL LYR
+A49B ; [*0CC1.0020.0002.A49B] # YI RADICAL BBUT
+A49C ; [*0CC2.0020.0002.A49C] # YI RADICAL MOP
+A49D ; [*0CC3.0020.0002.A49D] # YI RADICAL YO
+A49E ; [*0CC4.0020.0002.A49E] # YI RADICAL PUT
+A49F ; [*0CC5.0020.0002.A49F] # YI RADICAL HXUO
+A4A0 ; [*0CC6.0020.0002.A4A0] # YI RADICAL TAT
+A4A1 ; [*0CC7.0020.0002.A4A1] # YI RADICAL GA
+A4A2 ; [*0CC8.0020.0002.A4A2] # YI RADICAL ZUP
+A4A3 ; [*0CC9.0020.0002.A4A3] # YI RADICAL CYT
+A4A4 ; [*0CCA.0020.0002.A4A4] # YI RADICAL DDUR
+A4A5 ; [*0CCB.0020.0002.A4A5] # YI RADICAL BUR
+A4A6 ; [*0CCC.0020.0002.A4A6] # YI RADICAL GGUO
+A4A7 ; [*0CCD.0020.0002.A4A7] # YI RADICAL NYOP
+A4A8 ; [*0CCE.0020.0002.A4A8] # YI RADICAL TU
+A4A9 ; [*0CCF.0020.0002.A4A9] # YI RADICAL OP
+A4AA ; [*0CD0.0020.0002.A4AA] # YI RADICAL JJUT
+A4AB ; [*0CD1.0020.0002.A4AB] # YI RADICAL ZOT
+A4AC ; [*0CD2.0020.0002.A4AC] # YI RADICAL PYT
+A4AD ; [*0CD3.0020.0002.A4AD] # YI RADICAL HMO
+A4AE ; [*0CD4.0020.0002.A4AE] # YI RADICAL YIT
+A4AF ; [*0CD5.0020.0002.A4AF] # YI RADICAL VUR
+A4B0 ; [*0CD6.0020.0002.A4B0] # YI RADICAL SHY
+A4B1 ; [*0CD7.0020.0002.A4B1] # YI RADICAL VEP
+A4B2 ; [*0CD8.0020.0002.A4B2] # YI RADICAL ZA
+A4B3 ; [*0CD9.0020.0002.A4B3] # YI RADICAL JO
+A4B4 ; [*0CDA.0020.0002.A4B4] # YI RADICAL NZUP
+A4B5 ; [*0CDB.0020.0002.A4B5] # YI RADICAL JJY
+A4B6 ; [*0CDC.0020.0002.A4B6] # YI RADICAL GOT
+A4B7 ; [*0CDD.0020.0002.A4B7] # YI RADICAL JJIE
+A4B8 ; [*0CDE.0020.0002.A4B8] # YI RADICAL WO
+A4B9 ; [*0CDF.0020.0002.A4B9] # YI RADICAL DU
+A4BA ; [*0CE0.0020.0002.A4BA] # YI RADICAL SHUR
+A4BB ; [*0CE1.0020.0002.A4BB] # YI RADICAL LIE
+A4BC ; [*0CE2.0020.0002.A4BC] # YI RADICAL CY
+A4BD ; [*0CE3.0020.0002.A4BD] # YI RADICAL CUOP
+A4BE ; [*0CE4.0020.0002.A4BE] # YI RADICAL CIP
+A4BF ; [*0CE5.0020.0002.A4BF] # YI RADICAL HXOP
+A4C0 ; [*0CE6.0020.0002.A4C0] # YI RADICAL SHAT
+A4C1 ; [*0CE7.0020.0002.A4C1] # YI RADICAL ZUR
+A4C2 ; [*0CE8.0020.0002.A4C2] # YI RADICAL SHOP
+A4C3 ; [*0CE9.0020.0002.A4C3] # YI RADICAL CHE
+A4C4 ; [*0CEA.0020.0002.A4C4] # YI RADICAL ZZIET
+A4C5 ; [*0CEB.0020.0002.A4C5] # YI RADICAL NBIE
+A4C6 ; [*0CEC.0020.0002.A4C6] # YI RADICAL KE
+A700 ; [*03A2.0020.0002.A700] # MODIFIER LETTER CHINESE TONE YIN PING
+A701 ; [*03A3.0020.0002.A701] # MODIFIER LETTER CHINESE TONE YANG PING
+A702 ; [*03A4.0020.0002.A702] # MODIFIER LETTER CHINESE TONE YIN SHANG
+A703 ; [*03A5.0020.0002.A703] # MODIFIER LETTER CHINESE TONE YANG SHANG
+A704 ; [*03A6.0020.0002.A704] # MODIFIER LETTER CHINESE TONE YIN QU
+A705 ; [*03A7.0020.0002.A705] # MODIFIER LETTER CHINESE TONE YANG QU
+A706 ; [*03A8.0020.0002.A706] # MODIFIER LETTER CHINESE TONE YIN RU
+A707 ; [*03A9.0020.0002.A707] # MODIFIER LETTER CHINESE TONE YANG RU
+A708 ; [*03AA.0020.0002.A708] # MODIFIER LETTER EXTRA-HIGH DOTTED TONE BAR
+A709 ; [*03AB.0020.0002.A709] # MODIFIER LETTER HIGH DOTTED TONE BAR
+A70A ; [*03AC.0020.0002.A70A] # MODIFIER LETTER MID DOTTED TONE BAR
+A70B ; [*03AD.0020.0002.A70B] # MODIFIER LETTER LOW DOTTED TONE BAR
+A70C ; [*03AE.0020.0002.A70C] # MODIFIER LETTER EXTRA-LOW DOTTED TONE BAR
+A70D ; [*03AF.0020.0002.A70D] # MODIFIER LETTER EXTRA-HIGH DOTTED LEFT-STEM TONE BAR
+A70E ; [*03B0.0020.0002.A70E] # MODIFIER LETTER HIGH DOTTED LEFT-STEM TONE BAR
+A70F ; [*03B1.0020.0002.A70F] # MODIFIER LETTER MID DOTTED LEFT-STEM TONE BAR
+A710 ; [*03B2.0020.0002.A710] # MODIFIER LETTER LOW DOTTED LEFT-STEM TONE BAR
+A711 ; [*03B3.0020.0002.A711] # MODIFIER LETTER EXTRA-LOW DOTTED LEFT-STEM TONE BAR
+A712 ; [*03B4.0020.0002.A712] # MODIFIER LETTER EXTRA-HIGH LEFT-STEM TONE BAR
+A713 ; [*03B5.0020.0002.A713] # MODIFIER LETTER HIGH LEFT-STEM TONE BAR
+A714 ; [*03B6.0020.0002.A714] # MODIFIER LETTER MID LEFT-STEM TONE BAR
+A715 ; [*03B7.0020.0002.A715] # MODIFIER LETTER LOW LEFT-STEM TONE BAR
+A716 ; [*03B8.0020.0002.A716] # MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR
+A717 ; [*03B9.0020.0002.A717] # MODIFIER LETTER DOT VERTICAL BAR
+A718 ; [*03BA.0020.0002.A718] # MODIFIER LETTER DOT SLASH
+A719 ; [*03BB.0020.0002.A719] # MODIFIER LETTER DOT HORIZONTAL BAR
+A71A ; [*03BC.0020.0002.A71A] # MODIFIER LETTER LOWER RIGHT CORNER ANGLE
+A720 ; [*03BD.0020.0002.A720] # MODIFIER LETTER STRESS AND HIGH TONE
+A721 ; [*03BE.0020.0002.A721] # MODIFIER LETTER STRESS AND LOW TONE
+A828 ; [*03D1.0020.0002.A828] # SYLOTI NAGRI POETRY MARK-1
+A829 ; [*03D2.0020.0002.A829] # SYLOTI NAGRI POETRY MARK-2
+A82A ; [*03D3.0020.0002.A82A] # SYLOTI NAGRI POETRY MARK-3
+A82B ; [*03D4.0020.0002.A82B] # SYLOTI NAGRI POETRY MARK-4
+A874 ; [*035C.0020.0002.A874] # PHAGS-PA SINGLE HEAD MARK
+A875 ; [*035D.0020.0002.A875] # PHAGS-PA DOUBLE HEAD MARK
+A876 ; [*0276.0020.0002.A876] # PHAGS-PA MARK SHAD
+A877 ; [*0277.0020.0002.A877] # PHAGS-PA MARK DOUBLE SHAD
+FB29 ; [*04B8.0020.0005.FB29] # HEBREW LETTER ALTERNATIVE PLUS SIGN; QQK
+FD3E ; [*02F3.0020.0002.FD3E] # ORNATE LEFT PARENTHESIS
+FD3F ; [*02F4.0020.0002.FD3F] # ORNATE RIGHT PARENTHESIS
+FDFD ; [*03C4.0020.0002.FDFD] # ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM
+FE10 ; [*0232.0020.0016.FE10] # PRESENTATION FORM FOR VERTICAL COMMA; QQK
+FE11 ; [*023B.0020.0016.FE11] # PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC COMMA; QQK
+FE12 ; [*0272.0020.0016.FE12] # PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC FULL STOP; QQK
+FE13 ; [*0241.0020.0016.FE13] # PRESENTATION FORM FOR VERTICAL COLON; QQK
+FE14 ; [*023E.0020.0016.FE14] # PRESENTATION FORM FOR VERTICAL SEMICOLON; QQK
+FE15 ; [*0257.0020.0016.FE15] # PRESENTATION FORM FOR VERTICAL EXCLAMATION MARK; QQK
+FE16 ; [*025C.0020.0016.FE16] # PRESENTATION FORM FOR VERTICAL QUESTION MARK; QQK
+FE17 ; [*02ED.0020.0016.FE17] # PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET; QQK
+FE18 ; [*02EE.0020.0016.FE18] # PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET; QQK
+FE19 ; [*0266.0020.0016.FE19][*0266.0020.0016.FE19][*0266.0020.001F.FE19] # PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS; QQKN
+FE21 ; [.0000.0000.0000.FE21] # COMBINING LIGATURE RIGHT HALF
+FE23 ; [.0000.0000.0000.FE23] # COMBINING DOUBLE TILDE RIGHT HALF
+FE30 ; [*0266.0020.0016.FE30][*0266.0020.0016.FE30] # PRESENTATION FORM FOR VERTICAL TWO DOT LEADER; QQKN
+FE31 ; [*022A.0020.0016.FE31] # PRESENTATION FORM FOR VERTICAL EM DASH; QQK
+FE32 ; [*0229.0020.0016.FE32] # PRESENTATION FORM FOR VERTICAL EN DASH; QQK
+FE33 ; [*021C.0020.0016.FE33] # PRESENTATION FORM FOR VERTICAL LOW LINE; QQK
+FE34 ; [*021C.0020.0016.FE34] # PRESENTATION FORM FOR VERTICAL WAVY LOW LINE; QQK
+FE35 ; [*02B1.0020.0016.FE35] # PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS; QQK
+FE36 ; [*02B2.0020.0016.FE36] # PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS; QQK
+FE37 ; [*02B5.0020.0016.FE37] # PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET; QQK
+FE38 ; [*02B6.0020.0016.FE38] # PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET; QQK
+FE39 ; [*02EB.0020.0016.FE39] # PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET; QQK
+FE3A ; [*02EC.0020.0016.FE3A] # PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET; QQK
+FE3B ; [*02E9.0020.0016.FE3B] # PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET; QQK
+FE3C ; [*02EA.0020.0016.FE3C] # PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET; QQK
+FE3D ; [*02E3.0020.0016.FE3D] # PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET; QQK
+FE3E ; [*02E4.0020.0016.FE3E] # PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET; QQK
+FE3F ; [*02E1.0020.0016.FE3F] # PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET; QQK
+FE40 ; [*02E2.0020.0016.FE40] # PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET; QQK
+FE41 ; [*02E5.0020.0016.FE41] # PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET; QQK
+FE42 ; [*02E6.0020.0016.FE42] # PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET; QQK
+FE43 ; [*02E7.0020.0016.FE43] # PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET; QQK
+FE44 ; [*02E8.0020.0016.FE44] # PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET; QQK
+FE45 ; [*023C.0020.0002.FE45] # SESAME DOT
+FE46 ; [*023D.0020.0002.FE46] # WHITE SESAME DOT
+FE47 ; [*02B3.0020.0016.FE47] # PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET; QQK
+FE48 ; [*02B4.0020.0016.FE48] # PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET; QQK
+FE49 ; [*0212.0020.0004.FE49] # DASHED OVERLINE; QQK
+FE4A ; [*0212.0020.0004.FE4A] # CENTRELINE OVERLINE; QQK
+FE4B ; [*0212.0020.0004.FE4B] # WAVY OVERLINE; QQK
+FE4C ; [*0212.0020.0004.FE4C] # DOUBLE WAVY OVERLINE; QQK
+FE4D ; [*021C.0020.0004.FE4D] # DASHED LOW LINE; QQK
+FE4E ; [*021C.0020.0004.FE4E] # CENTRELINE LOW LINE; QQK
+FE4F ; [*021C.0020.0004.FE4F] # WAVY LOW LINE; QQK
+FE50 ; [*0232.0020.000F.FE50] # SMALL COMMA; QQK
+FE51 ; [*023B.0020.000F.FE51] # SMALL IDEOGRAPHIC COMMA; QQK
+FE52 ; [*0266.0020.000F.FE52] # SMALL FULL STOP; QQK
+FE54 ; [*023E.0020.000F.FE54] # SMALL SEMICOLON; QQK
+FE55 ; [*0241.0020.000F.FE55] # SMALL COLON; QQK
+FE56 ; [*025C.0020.000F.FE56] # SMALL QUESTION MARK; QQK
+FE57 ; [*0257.0020.000F.FE57] # SMALL EXCLAMATION MARK; QQK
+FE58 ; [*022A.0020.000F.FE58] # SMALL EM DASH; QQK
+FE59 ; [*02B1.0020.000F.FE59] # SMALL LEFT PARENTHESIS; QQK
+FE5A ; [*02B2.0020.000F.FE5A] # SMALL RIGHT PARENTHESIS; QQK
+FE5B ; [*02B5.0020.000F.FE5B] # SMALL LEFT CURLY BRACKET; QQK
+FE5C ; [*02B6.0020.000F.FE5C] # SMALL RIGHT CURLY BRACKET; QQK
+FE5D ; [*02EB.0020.000F.FE5D] # SMALL LEFT TORTOISE SHELL BRACKET; QQK
+FE5E ; [*02EC.0020.000F.FE5E] # SMALL RIGHT TORTOISE SHELL BRACKET; QQK
+FE5F ; [*0305.0020.000F.FE5F] # SMALL NUMBER SIGN; QQK
+FE60 ; [*0302.0020.000F.FE60] # SMALL AMPERSAND; QQK
+FE61 ; [*02FB.0020.000F.FE61] # SMALL ASTERISK; QQK
+FE62 ; [*04B8.0020.000F.FE62] # SMALL PLUS SIGN; QQK
+FE63 ; [*0222.0020.000F.FE63] # SMALL HYPHEN-MINUS; QQK
+FE64 ; [*04BC.0020.000F.FE64] # SMALL LESS-THAN SIGN; QQK
+FE65 ; [*04BE.0020.000F.FE65] # SMALL GREATER-THAN SIGN; QQK
+FE66 ; [*04BD.0020.000F.FE66] # SMALL EQUALS SIGN; QQK
+FE68 ; [*0301.0020.000F.FE68] # SMALL REVERSE SOLIDUS; QQK
+FE6A ; [*0306.0020.000F.FE6A] # SMALL PERCENT SIGN; QQK
+FE6B ; [*02FA.0020.000F.FE6B] # SMALL COMMERCIAL AT; QQK
+FE73 ; [.0000.0000.0000.FE73] # ARABIC TAIL FRAGMENT
+FF01 ; [*0257.0020.0003.FF01] # FULLWIDTH EXCLAMATION MARK; QQK
+FF02 ; [*02A7.0020.0003.FF02] # FULLWIDTH QUOTATION MARK; QQK
+FF03 ; [*0305.0020.0003.FF03] # FULLWIDTH NUMBER SIGN; QQK
+FF05 ; [*0306.0020.0003.FF05] # FULLWIDTH PERCENT SIGN; QQK
+FF06 ; [*0302.0020.0003.FF06] # FULLWIDTH AMPERSAND; QQK
+FF07 ; [*02A0.0020.0003.FF07] # FULLWIDTH APOSTROPHE; QQK
+FF08 ; [*02B1.0020.0003.FF08] # FULLWIDTH LEFT PARENTHESIS; QQK
+FF09 ; [*02B2.0020.0003.FF09] # FULLWIDTH RIGHT PARENTHESIS; QQK
+FF0A ; [*02FB.0020.0003.FF0A] # FULLWIDTH ASTERISK; QQK
+FF0B ; [*04B8.0020.0003.FF0B] # FULLWIDTH PLUS SIGN; QQK
+FF0C ; [*0232.0020.0003.FF0C] # FULLWIDTH COMMA; QQK
+FF0D ; [*0222.0020.0003.FF0D] # FULLWIDTH HYPHEN-MINUS; QQK
+FF0E ; [*0266.0020.0003.FF0E] # FULLWIDTH FULL STOP; QQK
+FF0F ; [*02FF.0020.0003.FF0F] # FULLWIDTH SOLIDUS; QQK
+FF1A ; [*0241.0020.0003.FF1A] # FULLWIDTH COLON; QQK
+FF1B ; [*023E.0020.0003.FF1B] # FULLWIDTH SEMICOLON; QQK
+FF1C ; [*04BC.0020.0003.FF1C] # FULLWIDTH LESS-THAN SIGN; QQK
+FF1D ; [*04BD.0020.0003.FF1D] # FULLWIDTH EQUALS SIGN; QQK
+FF1E ; [*04BE.0020.0003.FF1E] # FULLWIDTH GREATER-THAN SIGN; QQK
+FF1F ; [*025C.0020.0003.FF1F] # FULLWIDTH QUESTION MARK; QQK
+FF20 ; [*02FA.0020.0003.FF20] # FULLWIDTH COMMERCIAL AT; QQK
+FF3B ; [*02B3.0020.0003.FF3B] # FULLWIDTH LEFT SQUARE BRACKET; QQK
+FF3C ; [*0301.0020.0003.FF3C] # FULLWIDTH REVERSE SOLIDUS; QQK
+FF3D ; [*02B4.0020.0003.FF3D] # FULLWIDTH RIGHT SQUARE BRACKET; QQK
+FF3E ; [*0210.0020.0003.FF3E] # FULLWIDTH CIRCUMFLEX ACCENT; QQK
+FF3F ; [*021C.0020.0003.FF3F] # FULLWIDTH LOW LINE; QQK
+FF40 ; [*020D.0020.0003.FF40] # FULLWIDTH GRAVE ACCENT; QQK
+FF5B ; [*02B5.0020.0003.FF5B] # FULLWIDTH LEFT CURLY BRACKET; QQK
+FF5C ; [*04C0.0020.0003.FF5C] # FULLWIDTH VERTICAL LINE; QQK
+FF5D ; [*02B6.0020.0003.FF5D] # FULLWIDTH RIGHT CURLY BRACKET; QQK
+FF5E ; [*04C3.0020.0003.FF5E] # FULLWIDTH TILDE; QQK
+FF5F ; [*02C3.0020.0003.FF5F] # FULLWIDTH LEFT WHITE PARENTHESIS; QQK
+FF60 ; [*02C4.0020.0003.FF60] # FULLWIDTH RIGHT WHITE PARENTHESIS; QQK
+FF61 ; [*0272.0020.0012.FF61] # HALFWIDTH IDEOGRAPHIC FULL STOP; QQK
+FF62 ; [*02E5.0020.0012.FF62] # HALFWIDTH LEFT CORNER BRACKET; QQK
+FF63 ; [*02E6.0020.0012.FF63] # HALFWIDTH RIGHT CORNER BRACKET; QQK
+FF64 ; [*023B.0020.0012.FF64] # HALFWIDTH IDEOGRAPHIC COMMA; QQK
+FF65 ; [*0231.0020.0012.FF65] # HALFWIDTH KATAKANA MIDDLE DOT; QQK
+FFE2 ; [*04BF.0020.0003.FFE2] # FULLWIDTH NOT SIGN; QQK
+FFE3 ; [*0211.0020.0003.FFE3] # FULLWIDTH MACRON; QQK
+FFE4 ; [*04C1.0020.0003.FFE4] # FULLWIDTH BROKEN BAR; QQK
+FFE8 ; [*06A5.0020.0012.FFE8] # HALFWIDTH FORMS LIGHT VERTICAL; QQK
+FFE9 ; [*043E.0020.0012.FFE9] # HALFWIDTH LEFTWARDS ARROW; QQK
+FFEA ; [*0440.0020.0012.FFEA] # HALFWIDTH UPWARDS ARROW; QQK
+FFEB ; [*043F.0020.0012.FFEB] # HALFWIDTH RIGHTWARDS ARROW; QQK
+FFEC ; [*0441.0020.0012.FFEC] # HALFWIDTH DOWNWARDS ARROW; QQK
+FFED ; [*0743.0020.0012.FFED] # HALFWIDTH BLACK SQUARE; QQK
+FFEE ; [*076E.0020.0012.FFEE] # HALFWIDTH WHITE CIRCLE; QQK
+FFFC ; [*0F11.0020.0002.FFFC] # OBJECT REPLACEMENT CHARACTER
+FFFD ; [*0F12.0020.0002.FFFD] # REPLACEMENT CHARACTER
+10100 ; [*0296.0020.0002.10100] # AEGEAN WORD SEPARATOR LINE
+10101 ; [*0297.0020.0002.10101] # AEGEAN WORD SEPARATOR DOT
+10102 ; [*0298.0020.0002.10102] # AEGEAN CHECK MARK
+10110 ; [*0F29.0020.0002.10110] # AEGEAN NUMBER TEN
+10111 ; [*0F2A.0020.0002.10111] # AEGEAN NUMBER TWENTY
+10112 ; [*0F2B.0020.0002.10112] # AEGEAN NUMBER THIRTY
+10113 ; [*0F2C.0020.0002.10113] # AEGEAN NUMBER FORTY
+10114 ; [*0F2D.0020.0002.10114] # AEGEAN NUMBER FIFTY
+10115 ; [*0F2E.0020.0002.10115] # AEGEAN NUMBER SIXTY
+10116 ; [*0F2F.0020.0002.10116] # AEGEAN NUMBER SEVENTY
+10117 ; [*0F30.0020.0002.10117] # AEGEAN NUMBER EIGHTY
+10118 ; [*0F31.0020.0002.10118] # AEGEAN NUMBER NINETY
+10119 ; [*0F32.0020.0002.10119] # AEGEAN NUMBER ONE HUNDRED
+1011A ; [*0F33.0020.0002.1011A] # AEGEAN NUMBER TWO HUNDRED
+1011B ; [*0F34.0020.0002.1011B] # AEGEAN NUMBER THREE HUNDRED
+1011C ; [*0F35.0020.0002.1011C] # AEGEAN NUMBER FOUR HUNDRED
+1011D ; [*0F36.0020.0002.1011D] # AEGEAN NUMBER FIVE HUNDRED
+1011E ; [*0F37.0020.0002.1011E] # AEGEAN NUMBER SIX HUNDRED
+1011F ; [*0F38.0020.0002.1011F] # AEGEAN NUMBER SEVEN HUNDRED
+10120 ; [*0F39.0020.0002.10120] # AEGEAN NUMBER EIGHT HUNDRED
+10121 ; [*0F3A.0020.0002.10121] # AEGEAN NUMBER NINE HUNDRED
+10122 ; [*0F3B.0020.0002.10122] # AEGEAN NUMBER ONE THOUSAND
+10123 ; [*0F3C.0020.0002.10123] # AEGEAN NUMBER TWO THOUSAND
+10124 ; [*0F3D.0020.0002.10124] # AEGEAN NUMBER THREE THOUSAND
+10125 ; [*0F3E.0020.0002.10125] # AEGEAN NUMBER FOUR THOUSAND
+10126 ; [*0F3F.0020.0002.10126] # AEGEAN NUMBER FIVE THOUSAND
+10127 ; [*0F40.0020.0002.10127] # AEGEAN NUMBER SIX THOUSAND
+10128 ; [*0F41.0020.0002.10128] # AEGEAN NUMBER SEVEN THOUSAND
+10129 ; [*0F42.0020.0002.10129] # AEGEAN NUMBER EIGHT THOUSAND
+1012A ; [*0F43.0020.0002.1012A] # AEGEAN NUMBER NINE THOUSAND
+1012B ; [*0F44.0020.0002.1012B] # AEGEAN NUMBER TEN THOUSAND
+1012C ; [*0F45.0020.0002.1012C] # AEGEAN NUMBER TWENTY THOUSAND
+1012D ; [*0F46.0020.0002.1012D] # AEGEAN NUMBER THIRTY THOUSAND
+1012E ; [*0F47.0020.0002.1012E] # AEGEAN NUMBER FORTY THOUSAND
+1012F ; [*0F48.0020.0002.1012F] # AEGEAN NUMBER FIFTY THOUSAND
+10130 ; [*0F49.0020.0002.10130] # AEGEAN NUMBER SIXTY THOUSAND
+10131 ; [*0F4A.0020.0002.10131] # AEGEAN NUMBER SEVENTY THOUSAND
+10132 ; [*0F4B.0020.0002.10132] # AEGEAN NUMBER EIGHTY THOUSAND
+10133 ; [*0F4C.0020.0002.10133] # AEGEAN NUMBER NINETY THOUSAND
+10137 ; [*0CED.0020.0002.10137] # AEGEAN WEIGHT BASE UNIT
+10138 ; [*0CEE.0020.0002.10138] # AEGEAN WEIGHT FIRST SUBUNIT
+10139 ; [*0CEF.0020.0002.10139] # AEGEAN WEIGHT SECOND SUBUNIT
+1013A ; [*0CF0.0020.0002.1013A] # AEGEAN WEIGHT THIRD SUBUNIT
+1013B ; [*0CF1.0020.0002.1013B] # AEGEAN WEIGHT FOURTH SUBUNIT
+1013C ; [*0CF2.0020.0002.1013C] # AEGEAN DRY MEASURE FIRST SUBUNIT
+1013D ; [*0CF3.0020.0002.1013D] # AEGEAN LIQUID MEASURE FIRST SUBUNIT
+1013E ; [*0CF4.0020.0002.1013E] # AEGEAN MEASURE SECOND SUBUNIT
+1013F ; [*0CF5.0020.0002.1013F] # AEGEAN MEASURE THIRD SUBUNIT
+10140 ; [*0F4D.0020.0002.10140] # GREEK ACROPHONIC ATTIC ONE QUARTER
+10141 ; [*0F4E.0020.0002.10141] # GREEK ACROPHONIC ATTIC ONE HALF
+10144 ; [*0F4F.0020.0002.10144] # GREEK ACROPHONIC ATTIC FIFTY
+10145 ; [*0F50.0020.0002.10145] # GREEK ACROPHONIC ATTIC FIVE HUNDRED
+10146 ; [*0F51.0020.0002.10146] # GREEK ACROPHONIC ATTIC FIVE THOUSAND
+10147 ; [*0F52.0020.0002.10147] # GREEK ACROPHONIC ATTIC FIFTY THOUSAND
+10149 ; [*0F53.0020.0002.10149] # GREEK ACROPHONIC ATTIC TEN TALENTS
+1014A ; [*0F54.0020.0002.1014A] # GREEK ACROPHONIC ATTIC FIFTY TALENTS
+1014B ; [*0F55.0020.0002.1014B] # GREEK ACROPHONIC ATTIC ONE HUNDRED TALENTS
+1014C ; [*0F56.0020.0002.1014C] # GREEK ACROPHONIC ATTIC FIVE HUNDRED TALENTS
+1014D ; [*0F57.0020.0002.1014D] # GREEK ACROPHONIC ATTIC ONE THOUSAND TALENTS
+1014E ; [*0F58.0020.0002.1014E] # GREEK ACROPHONIC ATTIC FIVE THOUSAND TALENTS
+10150 ; [*0F59.0020.0002.10150] # GREEK ACROPHONIC ATTIC TEN STATERS
+10151 ; [*0F5A.0020.0002.10151] # GREEK ACROPHONIC ATTIC FIFTY STATERS
+10152 ; [*0F5B.0020.0002.10152] # GREEK ACROPHONIC ATTIC ONE HUNDRED STATERS
+10153 ; [*0F5C.0020.0002.10153] # GREEK ACROPHONIC ATTIC FIVE HUNDRED STATERS
+10154 ; [*0F5D.0020.0002.10154] # GREEK ACROPHONIC ATTIC ONE THOUSAND STATERS
+10155 ; [*0F5E.0020.0002.10155] # GREEK ACROPHONIC ATTIC TEN THOUSAND STATERS
+10156 ; [*0F5F.0020.0002.10156] # GREEK ACROPHONIC ATTIC FIFTY THOUSAND STATERS
+10157 ; [*0F60.0020.0002.10157] # GREEK ACROPHONIC ATTIC TEN MNAS
+10160 ; [*0F61.0020.0002.10160] # GREEK ACROPHONIC TROEZENIAN TEN
+10161 ; [*0F62.0020.0002.10161] # GREEK ACROPHONIC TROEZENIAN TEN ALTERNATE FORM
+10162 ; [*0F63.0020.0002.10162] # GREEK ACROPHONIC HERMIONIAN TEN
+10163 ; [*0F64.0020.0002.10163] # GREEK ACROPHONIC MESSENIAN TEN
+10164 ; [*0F65.0020.0002.10164] # GREEK ACROPHONIC THESPIAN TEN
+10165 ; [*0F66.0020.0002.10165] # GREEK ACROPHONIC THESPIAN THIRTY
+10166 ; [*0F67.0020.0002.10166] # GREEK ACROPHONIC TROEZENIAN FIFTY
+10167 ; [*0F68.0020.0002.10167] # GREEK ACROPHONIC TROEZENIAN FIFTY ALTERNATE FORM
+10168 ; [*0F69.0020.0002.10168] # GREEK ACROPHONIC HERMIONIAN FIFTY
+10169 ; [*0F6A.0020.0002.10169] # GREEK ACROPHONIC THESPIAN FIFTY
+1016A ; [*0F6B.0020.0002.1016A] # GREEK ACROPHONIC THESPIAN ONE HUNDRED
+1016B ; [*0F6C.0020.0002.1016B] # GREEK ACROPHONIC THESPIAN THREE HUNDRED
+1016C ; [*0F6D.0020.0002.1016C] # GREEK ACROPHONIC EPIDAUREAN FIVE HUNDRED
+1016D ; [*0F6E.0020.0002.1016D] # GREEK ACROPHONIC TROEZENIAN FIVE HUNDRED
+1016E ; [*0F6F.0020.0002.1016E] # GREEK ACROPHONIC THESPIAN FIVE HUNDRED
+1016F ; [*0F70.0020.0002.1016F] # GREEK ACROPHONIC CARYSTIAN FIVE HUNDRED
+10170 ; [*0F71.0020.0002.10170] # GREEK ACROPHONIC NAXIAN FIVE HUNDRED
+10171 ; [*0F72.0020.0002.10171] # GREEK ACROPHONIC THESPIAN ONE THOUSAND
+10172 ; [*0F73.0020.0002.10172] # GREEK ACROPHONIC THESPIAN FIVE THOUSAND
+10174 ; [*0F74.0020.0002.10174] # GREEK ACROPHONIC STRATIAN FIFTY MNAS
+10175 ; [*0F75.0020.0002.10175] # GREEK ONE HALF SIGN
+10176 ; [*0F76.0020.0002.10176] # GREEK ONE HALF SIGN ALTERNATE FORM
+10177 ; [*0F77.0020.0002.10177] # GREEK TWO THIRDS SIGN
+10178 ; [*0F78.0020.0002.10178] # GREEK THREE QUARTERS SIGN
+10179 ; [*0CF6.0020.0002.10179] # GREEK YEAR SIGN
+1017A ; [*0CF7.0020.0002.1017A] # GREEK TALENT SIGN
+1017B ; [*0CF8.0020.0002.1017B] # GREEK DRACHMA SIGN
+1017C ; [*0CF9.0020.0002.1017C] # GREEK OBOL SIGN
+1017D ; [*0CFA.0020.0002.1017D] # GREEK TWO OBOLS SIGN
+1017E ; [*0CFB.0020.0002.1017E] # GREEK THREE OBOLS SIGN
+1017F ; [*0CFC.0020.0002.1017F] # GREEK FOUR OBOLS SIGN
+10180 ; [*0CFD.0020.0002.10180] # GREEK FIVE OBOLS SIGN
+10181 ; [*0CFE.0020.0002.10181] # GREEK METRETES SIGN
+10182 ; [*0CFF.0020.0002.10182] # GREEK KYATHOS BASE SIGN
+10183 ; [*0D00.0020.0002.10183] # GREEK LITRA SIGN
+10184 ; [*0D01.0020.0002.10184] # GREEK OUNKIA SIGN
+10185 ; [*0D02.0020.0002.10185] # GREEK XESTES SIGN
+10186 ; [*0D03.0020.0002.10186] # GREEK ARTABE SIGN
+10187 ; [*0D04.0020.0002.10187] # GREEK AROURA SIGN
+10188 ; [*0D05.0020.0002.10188] # GREEK GRAMMA SIGN
+10189 ; [*0D06.0020.0002.10189] # GREEK TRYBLION BASE SIGN
+10322 ; [*0F27.0020.0002.10322] # OLD ITALIC NUMERAL TEN
+10323 ; [*0F28.0020.0002.10323] # OLD ITALIC NUMERAL FIFTY
+1039F ; [*0299.0020.0002.1039F] # UGARITIC WORD DIVIDER
+103D0 ; [*029A.0020.0002.103D0] # OLD PERSIAN WORD DIVIDER
+103D3 ; [*0F79.0020.0002.103D3] # OLD PERSIAN NUMBER TEN
+103D4 ; [*0F7A.0020.0002.103D4] # OLD PERSIAN NUMBER TWENTY
+103D5 ; [*0F7B.0020.0002.103D5] # OLD PERSIAN NUMBER HUNDRED
+10917 ; [*0F7C.0020.0002.10917] # PHOENICIAN NUMBER TEN
+10918 ; [*0F7D.0020.0002.10918] # PHOENICIAN NUMBER TWENTY
+10919 ; [*0F7E.0020.0002.10919] # PHOENICIAN NUMBER ONE HUNDRED
+1091F ; [*029B.0020.0002.1091F] # PHOENICIAN WORD SEPARATOR
+10A44 ; [*0F7F.0020.0002.10A44] # KHAROSHTHI NUMBER TEN
+10A45 ; [*0F80.0020.0002.10A45] # KHAROSHTHI NUMBER TWENTY
+10A46 ; [*0F81.0020.0002.10A46] # KHAROSHTHI NUMBER ONE HUNDRED
+10A47 ; [*0F82.0020.0002.10A47] # KHAROSHTHI NUMBER ONE THOUSAND
+10A50 ; [*035E.0020.0002.10A50] # KHAROSHTHI PUNCTUATION DOT
+10A51 ; [*035F.0020.0002.10A51] # KHAROSHTHI PUNCTUATION SMALL CIRCLE
+10A52 ; [*0360.0020.0002.10A52] # KHAROSHTHI PUNCTUATION CIRCLE
+10A53 ; [*0361.0020.0002.10A53] # KHAROSHTHI PUNCTUATION CRESCENT BAR
+10A54 ; [*0362.0020.0002.10A54] # KHAROSHTHI PUNCTUATION MANGALAM
+10A55 ; [*0363.0020.0002.10A55] # KHAROSHTHI PUNCTUATION LOTUS
+10A56 ; [*0280.0020.0002.10A56] # KHAROSHTHI PUNCTUATION DANDA
+10A57 ; [*0281.0020.0002.10A57] # KHAROSHTHI PUNCTUATION DOUBLE DANDA
+10A58 ; [*0364.0020.0002.10A58] # KHAROSHTHI PUNCTUATION LINES
+12432 ; [*0F83.0020.0002.12432] # CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS DISH
+12433 ; [*0F84.0020.0002.12433] # CUNEIFORM NUMERIC SIGN SHAR2 TIMES GAL PLUS MIN
+12456 ; [*0F85.0020.0002.12456] # CUNEIFORM NUMERIC SIGN NIGIDAMIN
+12457 ; [*0F86.0020.0002.12457] # CUNEIFORM NUMERIC SIGN NIGIDAESH
+1245A ; [*0F87.0020.0002.1245A] # CUNEIFORM NUMERIC SIGN ONE THIRD DISH
+1245B ; [*0F88.0020.0002.1245B] # CUNEIFORM NUMERIC SIGN TWO THIRDS DISH
+1245C ; [*0F89.0020.0002.1245C] # CUNEIFORM NUMERIC SIGN FIVE SIXTHS DISH
+1245D ; [*0F8A.0020.0002.1245D] # CUNEIFORM NUMERIC SIGN ONE THIRD VARIANT FORM A
+1245E ; [*0F8B.0020.0002.1245E] # CUNEIFORM NUMERIC SIGN TWO THIRDS VARIANT FORM A
+1245F ; [*0F8C.0020.0002.1245F] # CUNEIFORM NUMERIC SIGN ONE EIGHTH ASH
+12460 ; [*0F8D.0020.0002.12460] # CUNEIFORM NUMERIC SIGN ONE QUARTER ASH
+12461 ; [*0F8E.0020.0002.12461] # CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE SIXTH
+12462 ; [*0F8F.0020.0002.12462] # CUNEIFORM NUMERIC SIGN OLD ASSYRIAN ONE QUARTER
+12470 ; [*029C.0020.0002.12470] # CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER
+12471 ; [*029D.0020.0002.12471] # CUNEIFORM PUNCTUATION SIGN VERTICAL COLON
+12472 ; [*029E.0020.0002.12472] # CUNEIFORM PUNCTUATION SIGN DIAGONAL COLON
+12473 ; [*029F.0020.0002.12473] # CUNEIFORM PUNCTUATION SIGN DIAGONAL TRICOLON
+1D000 ; [*0D07.0020.0002.1D000] # BYZANTINE MUSICAL SYMBOL PSILI
+1D001 ; [*0D08.0020.0002.1D001] # BYZANTINE MUSICAL SYMBOL DASEIA
+1D002 ; [*0D09.0020.0002.1D002] # BYZANTINE MUSICAL SYMBOL PERISPOMENI
+1D003 ; [*0D0A.0020.0002.1D003] # BYZANTINE MUSICAL SYMBOL OXEIA EKFONITIKON
+1D004 ; [*0D0B.0020.0002.1D004] # BYZANTINE MUSICAL SYMBOL OXEIA DIPLI
+1D005 ; [*0D0C.0020.0002.1D005] # BYZANTINE MUSICAL SYMBOL VAREIA EKFONITIKON
+1D006 ; [*0D0D.0020.0002.1D006] # BYZANTINE MUSICAL SYMBOL VAREIA DIPLI
+1D007 ; [*0D0E.0020.0002.1D007] # BYZANTINE MUSICAL SYMBOL KATHISTI
+1D008 ; [*0D0F.0020.0002.1D008] # BYZANTINE MUSICAL SYMBOL SYRMATIKI
+1D009 ; [*0D10.0020.0002.1D009] # BYZANTINE MUSICAL SYMBOL PARAKLITIKI
+1D00A ; [*0D11.0020.0002.1D00A] # BYZANTINE MUSICAL SYMBOL YPOKRISIS
+1D00B ; [*0D12.0020.0002.1D00B] # BYZANTINE MUSICAL SYMBOL YPOKRISIS DIPLI
+1D00C ; [*0D13.0020.0002.1D00C] # BYZANTINE MUSICAL SYMBOL KREMASTI
+1D00D ; [*0D14.0020.0002.1D00D] # BYZANTINE MUSICAL SYMBOL APESO EKFONITIKON
+1D00E ; [*0D15.0020.0002.1D00E] # BYZANTINE MUSICAL SYMBOL EXO EKFONITIKON
+1D00F ; [*0D16.0020.0002.1D00F] # BYZANTINE MUSICAL SYMBOL TELEIA
+1D010 ; [*0D17.0020.0002.1D010] # BYZANTINE MUSICAL SYMBOL KENTIMATA
+1D011 ; [*0D18.0020.0002.1D011] # BYZANTINE MUSICAL SYMBOL APOSTROFOS
+1D012 ; [*0D19.0020.0002.1D012] # BYZANTINE MUSICAL SYMBOL APOSTROFOS DIPLI
+1D013 ; [*0D1A.0020.0002.1D013] # BYZANTINE MUSICAL SYMBOL SYNEVMA
+1D014 ; [*0D1B.0020.0002.1D014] # BYZANTINE MUSICAL SYMBOL THITA
+1D015 ; [*0D1C.0020.0002.1D015] # BYZANTINE MUSICAL SYMBOL OLIGON ARCHAION
+1D016 ; [*0D1D.0020.0002.1D016] # BYZANTINE MUSICAL SYMBOL GORGON ARCHAION
+1D017 ; [*0D1E.0020.0002.1D017] # BYZANTINE MUSICAL SYMBOL PSILON
+1D018 ; [*0D1F.0020.0002.1D018] # BYZANTINE MUSICAL SYMBOL CHAMILON
+1D019 ; [*0D20.0020.0002.1D019] # BYZANTINE MUSICAL SYMBOL VATHY
+1D01A ; [*0D21.0020.0002.1D01A] # BYZANTINE MUSICAL SYMBOL ISON ARCHAION
+1D01B ; [*0D22.0020.0002.1D01B] # BYZANTINE MUSICAL SYMBOL KENTIMA ARCHAION
+1D01C ; [*0D23.0020.0002.1D01C] # BYZANTINE MUSICAL SYMBOL KENTIMATA ARCHAION
+1D01D ; [*0D24.0020.0002.1D01D] # BYZANTINE MUSICAL SYMBOL SAXIMATA
+1D01E ; [*0D25.0020.0002.1D01E] # BYZANTINE MUSICAL SYMBOL PARICHON
+1D01F ; [*0D26.0020.0002.1D01F] # BYZANTINE MUSICAL SYMBOL STAVROS APODEXIA
+1D020 ; [*0D27.0020.0002.1D020] # BYZANTINE MUSICAL SYMBOL OXEIAI ARCHAION
+1D021 ; [*0D28.0020.0002.1D021] # BYZANTINE MUSICAL SYMBOL VAREIAI ARCHAION
+1D022 ; [*0D29.0020.0002.1D022] # BYZANTINE MUSICAL SYMBOL APODERMA ARCHAION
+1D023 ; [*0D2A.0020.0002.1D023] # BYZANTINE MUSICAL SYMBOL APOTHEMA
+1D024 ; [*0D2B.0020.0002.1D024] # BYZANTINE MUSICAL SYMBOL KLASMA
+1D025 ; [*0D2C.0020.0002.1D025] # BYZANTINE MUSICAL SYMBOL REVMA
+1D026 ; [*0D2D.0020.0002.1D026] # BYZANTINE MUSICAL SYMBOL PIASMA ARCHAION
+1D027 ; [*0D2E.0020.0002.1D027] # BYZANTINE MUSICAL SYMBOL TINAGMA
+1D028 ; [*0D2F.0020.0002.1D028] # BYZANTINE MUSICAL SYMBOL ANATRICHISMA
+1D029 ; [*0D30.0020.0002.1D029] # BYZANTINE MUSICAL SYMBOL SEISMA
+1D02A ; [*0D31.0020.0002.1D02A] # BYZANTINE MUSICAL SYMBOL SYNAGMA ARCHAION
+1D02B ; [*0D32.0020.0002.1D02B] # BYZANTINE MUSICAL SYMBOL SYNAGMA META STAVROU
+1D02C ; [*0D33.0020.0002.1D02C] # BYZANTINE MUSICAL SYMBOL OYRANISMA ARCHAION
+1D02D ; [*0D34.0020.0002.1D02D] # BYZANTINE MUSICAL SYMBOL THEMA
+1D02E ; [*0D35.0020.0002.1D02E] # BYZANTINE MUSICAL SYMBOL LEMOI
+1D02F ; [*0D36.0020.0002.1D02F] # BYZANTINE MUSICAL SYMBOL DYO
+1D030 ; [*0D37.0020.0002.1D030] # BYZANTINE MUSICAL SYMBOL TRIA
+1D031 ; [*0D38.0020.0002.1D031] # BYZANTINE MUSICAL SYMBOL TESSERA
+1D032 ; [*0D39.0020.0002.1D032] # BYZANTINE MUSICAL SYMBOL KRATIMATA
+1D033 ; [*0D3A.0020.0002.1D033] # BYZANTINE MUSICAL SYMBOL APESO EXO NEO
+1D034 ; [*0D3B.0020.0002.1D034] # BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION
+1D035 ; [*0D3C.0020.0002.1D035] # BYZANTINE MUSICAL SYMBOL IMIFTHORA
+1D036 ; [*0D3D.0020.0002.1D036] # BYZANTINE MUSICAL SYMBOL TROMIKON ARCHAION
+1D037 ; [*0D3E.0020.0002.1D037] # BYZANTINE MUSICAL SYMBOL KATAVA TROMIKON
+1D038 ; [*0D3F.0020.0002.1D038] # BYZANTINE MUSICAL SYMBOL PELASTON
+1D039 ; [*0D40.0020.0002.1D039] # BYZANTINE MUSICAL SYMBOL PSIFISTON
+1D03A ; [*0D41.0020.0002.1D03A] # BYZANTINE MUSICAL SYMBOL KONTEVMA
+1D03B ; [*0D42.0020.0002.1D03B] # BYZANTINE MUSICAL SYMBOL CHOREVMA ARCHAION
+1D03C ; [*0D43.0020.0002.1D03C] # BYZANTINE MUSICAL SYMBOL RAPISMA
+1D03D ; [*0D44.0020.0002.1D03D] # BYZANTINE MUSICAL SYMBOL PARAKALESMA ARCHAION
+1D03E ; [*0D45.0020.0002.1D03E] # BYZANTINE MUSICAL SYMBOL PARAKLITIKI ARCHAION
+1D03F ; [*0D46.0020.0002.1D03F] # BYZANTINE MUSICAL SYMBOL ICHADIN
+1D040 ; [*0D47.0020.0002.1D040] # BYZANTINE MUSICAL SYMBOL NANA
+1D041 ; [*0D48.0020.0002.1D041] # BYZANTINE MUSICAL SYMBOL PETASMA
+1D042 ; [*0D49.0020.0002.1D042] # BYZANTINE MUSICAL SYMBOL KONTEVMA ALLO
+1D043 ; [*0D4A.0020.0002.1D043] # BYZANTINE MUSICAL SYMBOL TROMIKON ALLO
+1D044 ; [*0D4B.0020.0002.1D044] # BYZANTINE MUSICAL SYMBOL STRAGGISMATA
+1D045 ; [*0D4C.0020.0002.1D045] # BYZANTINE MUSICAL SYMBOL GRONTHISMATA
+1D046 ; [*0D4D.0020.0002.1D046] # BYZANTINE MUSICAL SYMBOL ISON NEO
+1D047 ; [*0D4E.0020.0002.1D047] # BYZANTINE MUSICAL SYMBOL OLIGON NEO
+1D048 ; [*0D4F.0020.0002.1D048] # BYZANTINE MUSICAL SYMBOL OXEIA NEO
+1D049 ; [*0D50.0020.0002.1D049] # BYZANTINE MUSICAL SYMBOL PETASTI
+1D04A ; [*0D51.0020.0002.1D04A] # BYZANTINE MUSICAL SYMBOL KOUFISMA
+1D04B ; [*0D52.0020.0002.1D04B] # BYZANTINE MUSICAL SYMBOL PETASTOKOUFISMA
+1D04C ; [*0D53.0020.0002.1D04C] # BYZANTINE MUSICAL SYMBOL KRATIMOKOUFISMA
+1D04D ; [*0D54.0020.0002.1D04D] # BYZANTINE MUSICAL SYMBOL PELASTON NEO
+1D04E ; [*0D55.0020.0002.1D04E] # BYZANTINE MUSICAL SYMBOL KENTIMATA NEO ANO
+1D04F ; [*0D56.0020.0002.1D04F] # BYZANTINE MUSICAL SYMBOL KENTIMA NEO ANO
+1D050 ; [*0D57.0020.0002.1D050] # BYZANTINE MUSICAL SYMBOL YPSILI
+1D051 ; [*0D58.0020.0002.1D051] # BYZANTINE MUSICAL SYMBOL APOSTROFOS NEO
+1D052 ; [*0D59.0020.0002.1D052] # BYZANTINE MUSICAL SYMBOL APOSTROFOI SYNDESMOS NEO
+1D053 ; [*0D5A.0020.0002.1D053] # BYZANTINE MUSICAL SYMBOL YPORROI
+1D054 ; [*0D5B.0020.0002.1D054] # BYZANTINE MUSICAL SYMBOL KRATIMOYPORROON
+1D055 ; [*0D5C.0020.0002.1D055] # BYZANTINE MUSICAL SYMBOL ELAFRON
+1D056 ; [*0D5D.0020.0002.1D056] # BYZANTINE MUSICAL SYMBOL CHAMILI
+1D057 ; [*0D5E.0020.0002.1D057] # BYZANTINE MUSICAL SYMBOL MIKRON ISON
+1D058 ; [*0D5F.0020.0002.1D058] # BYZANTINE MUSICAL SYMBOL VAREIA NEO
+1D059 ; [*0D60.0020.0002.1D059] # BYZANTINE MUSICAL SYMBOL PIASMA NEO
+1D05A ; [*0D61.0020.0002.1D05A] # BYZANTINE MUSICAL SYMBOL PSIFISTON NEO
+1D05B ; [*0D62.0020.0002.1D05B] # BYZANTINE MUSICAL SYMBOL OMALON
+1D05C ; [*0D63.0020.0002.1D05C] # BYZANTINE MUSICAL SYMBOL ANTIKENOMA
+1D05D ; [*0D64.0020.0002.1D05D] # BYZANTINE MUSICAL SYMBOL LYGISMA
+1D05E ; [*0D65.0020.0002.1D05E] # BYZANTINE MUSICAL SYMBOL PARAKLITIKI NEO
+1D05F ; [*0D66.0020.0002.1D05F] # BYZANTINE MUSICAL SYMBOL PARAKALESMA NEO
+1D060 ; [*0D67.0020.0002.1D060] # BYZANTINE MUSICAL SYMBOL ETERON PARAKALESMA
+1D061 ; [*0D68.0020.0002.1D061] # BYZANTINE MUSICAL SYMBOL KYLISMA
+1D062 ; [*0D69.0020.0002.1D062] # BYZANTINE MUSICAL SYMBOL ANTIKENOKYLISMA
+1D063 ; [*0D6A.0020.0002.1D063] # BYZANTINE MUSICAL SYMBOL TROMIKON NEO
+1D064 ; [*0D6B.0020.0002.1D064] # BYZANTINE MUSICAL SYMBOL EKSTREPTON
+1D065 ; [*0D6C.0020.0002.1D065] # BYZANTINE MUSICAL SYMBOL SYNAGMA NEO
+1D066 ; [*0D6D.0020.0002.1D066] # BYZANTINE MUSICAL SYMBOL SYRMA
+1D067 ; [*0D6E.0020.0002.1D067] # BYZANTINE MUSICAL SYMBOL CHOREVMA NEO
+1D068 ; [*0D6F.0020.0002.1D068] # BYZANTINE MUSICAL SYMBOL EPEGERMA
+1D069 ; [*0D70.0020.0002.1D069] # BYZANTINE MUSICAL SYMBOL SEISMA NEO
+1D06A ; [*0D71.0020.0002.1D06A] # BYZANTINE MUSICAL SYMBOL XIRON KLASMA
+1D06B ; [*0D72.0020.0002.1D06B] # BYZANTINE MUSICAL SYMBOL TROMIKOPSIFISTON
+1D06C ; [*0D73.0020.0002.1D06C] # BYZANTINE MUSICAL SYMBOL PSIFISTOLYGISMA
+1D06D ; [*0D74.0020.0002.1D06D] # BYZANTINE MUSICAL SYMBOL TROMIKOLYGISMA
+1D06E ; [*0D75.0020.0002.1D06E] # BYZANTINE MUSICAL SYMBOL TROMIKOPARAKALESMA
+1D06F ; [*0D76.0020.0002.1D06F] # BYZANTINE MUSICAL SYMBOL PSIFISTOPARAKALESMA
+1D070 ; [*0D77.0020.0002.1D070] # BYZANTINE MUSICAL SYMBOL TROMIKOSYNAGMA
+1D071 ; [*0D78.0020.0002.1D071] # BYZANTINE MUSICAL SYMBOL PSIFISTOSYNAGMA
+1D072 ; [*0D79.0020.0002.1D072] # BYZANTINE MUSICAL SYMBOL GORGOSYNTHETON
+1D073 ; [*0D7A.0020.0002.1D073] # BYZANTINE MUSICAL SYMBOL ARGOSYNTHETON
+1D074 ; [*0D7B.0020.0002.1D074] # BYZANTINE MUSICAL SYMBOL ETERON ARGOSYNTHETON
+1D075 ; [*0D7C.0020.0002.1D075] # BYZANTINE MUSICAL SYMBOL OYRANISMA NEO
+1D076 ; [*0D7D.0020.0002.1D076] # BYZANTINE MUSICAL SYMBOL THEMATISMOS ESO
+1D077 ; [*0D7E.0020.0002.1D077] # BYZANTINE MUSICAL SYMBOL THEMATISMOS EXO
+1D078 ; [*0D7F.0020.0002.1D078] # BYZANTINE MUSICAL SYMBOL THEMA APLOUN
+1D079 ; [*0D80.0020.0002.1D079] # BYZANTINE MUSICAL SYMBOL THES KAI APOTHES
+1D07A ; [*0D81.0020.0002.1D07A] # BYZANTINE MUSICAL SYMBOL KATAVASMA
+1D07B ; [*0D82.0020.0002.1D07B] # BYZANTINE MUSICAL SYMBOL ENDOFONON
+1D07C ; [*0D83.0020.0002.1D07C] # BYZANTINE MUSICAL SYMBOL YFEN KATO
+1D07D ; [*0D84.0020.0002.1D07D] # BYZANTINE MUSICAL SYMBOL YFEN ANO
+1D07E ; [*0D85.0020.0002.1D07E] # BYZANTINE MUSICAL SYMBOL STAVROS
+1D07F ; [*0D86.0020.0002.1D07F] # BYZANTINE MUSICAL SYMBOL KLASMA ANO
+1D080 ; [*0D87.0020.0002.1D080] # BYZANTINE MUSICAL SYMBOL DIPLI ARCHAION
+1D081 ; [*0D88.0020.0002.1D081] # BYZANTINE MUSICAL SYMBOL KRATIMA ARCHAION
+1D082 ; [*0D89.0020.0002.1D082] # BYZANTINE MUSICAL SYMBOL KRATIMA ALLO
+1D083 ; [*0D8A.0020.0002.1D083] # BYZANTINE MUSICAL SYMBOL KRATIMA NEO
+1D084 ; [*0D8B.0020.0002.1D084] # BYZANTINE MUSICAL SYMBOL APODERMA NEO
+1D085 ; [*0D8C.0020.0002.1D085] # BYZANTINE MUSICAL SYMBOL APLI
+1D086 ; [*0D8D.0020.0002.1D086] # BYZANTINE MUSICAL SYMBOL DIPLI
+1D087 ; [*0D8E.0020.0002.1D087] # BYZANTINE MUSICAL SYMBOL TRIPLI
+1D088 ; [*0D8F.0020.0002.1D088] # BYZANTINE MUSICAL SYMBOL TETRAPLI
+1D089 ; [*0D90.0020.0002.1D089] # BYZANTINE MUSICAL SYMBOL KORONIS
+1D08A ; [*0D91.0020.0002.1D08A] # BYZANTINE MUSICAL SYMBOL LEIMMA ENOS CHRONOU
+1D08B ; [*0D92.0020.0002.1D08B] # BYZANTINE MUSICAL SYMBOL LEIMMA DYO CHRONON
+1D08C ; [*0D93.0020.0002.1D08C] # BYZANTINE MUSICAL SYMBOL LEIMMA TRION CHRONON
+1D08D ; [*0D94.0020.0002.1D08D] # BYZANTINE MUSICAL SYMBOL LEIMMA TESSARON CHRONON
+1D08E ; [*0D95.0020.0002.1D08E] # BYZANTINE MUSICAL SYMBOL LEIMMA IMISEOS CHRONOU
+1D08F ; [*0D96.0020.0002.1D08F] # BYZANTINE MUSICAL SYMBOL GORGON NEO ANO
+1D090 ; [*0D97.0020.0002.1D090] # BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON ARISTERA
+1D091 ; [*0D98.0020.0002.1D091] # BYZANTINE MUSICAL SYMBOL GORGON PARESTIGMENON DEXIA
+1D092 ; [*0D99.0020.0002.1D092] # BYZANTINE MUSICAL SYMBOL DIGORGON
+1D093 ; [*0D9A.0020.0002.1D093] # BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA KATO
+1D094 ; [*0D9B.0020.0002.1D094] # BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON ARISTERA ANO
+1D095 ; [*0D9C.0020.0002.1D095] # BYZANTINE MUSICAL SYMBOL DIGORGON PARESTIGMENON DEXIA
+1D096 ; [*0D9D.0020.0002.1D096] # BYZANTINE MUSICAL SYMBOL TRIGORGON
+1D097 ; [*0D9E.0020.0002.1D097] # BYZANTINE MUSICAL SYMBOL ARGON
+1D098 ; [*0D9F.0020.0002.1D098] # BYZANTINE MUSICAL SYMBOL IMIDIARGON
+1D099 ; [*0DA0.0020.0002.1D099] # BYZANTINE MUSICAL SYMBOL DIARGON
+1D09A ; [*0DA1.0020.0002.1D09A] # BYZANTINE MUSICAL SYMBOL AGOGI POLI ARGI
+1D09B ; [*0DA2.0020.0002.1D09B] # BYZANTINE MUSICAL SYMBOL AGOGI ARGOTERI
+1D09C ; [*0DA3.0020.0002.1D09C] # BYZANTINE MUSICAL SYMBOL AGOGI ARGI
+1D09D ; [*0DA4.0020.0002.1D09D] # BYZANTINE MUSICAL SYMBOL AGOGI METRIA
+1D09E ; [*0DA5.0020.0002.1D09E] # BYZANTINE MUSICAL SYMBOL AGOGI MESI
+1D09F ; [*0DA6.0020.0002.1D09F] # BYZANTINE MUSICAL SYMBOL AGOGI GORGI
+1D0A0 ; [*0DA7.0020.0002.1D0A0] # BYZANTINE MUSICAL SYMBOL AGOGI GORGOTERI
+1D0A1 ; [*0DA8.0020.0002.1D0A1] # BYZANTINE MUSICAL SYMBOL AGOGI POLI GORGI
+1D0A2 ; [*0DA9.0020.0002.1D0A2] # BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOS ICHOS
+1D0A3 ; [*0DAA.0020.0002.1D0A3] # BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI PROTOS ICHOS
+1D0A4 ; [*0DAB.0020.0002.1D0A4] # BYZANTINE MUSICAL SYMBOL MARTYRIA DEYTEROS ICHOS
+1D0A5 ; [*0DAC.0020.0002.1D0A5] # BYZANTINE MUSICAL SYMBOL MARTYRIA ALLI DEYTEROS ICHOS
+1D0A6 ; [*0DAD.0020.0002.1D0A6] # BYZANTINE MUSICAL SYMBOL MARTYRIA TRITOS ICHOS
+1D0A7 ; [*0DAE.0020.0002.1D0A7] # BYZANTINE MUSICAL SYMBOL MARTYRIA TRIFONIAS
+1D0A8 ; [*0DAF.0020.0002.1D0A8] # BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS ICHOS
+1D0A9 ; [*0DB0.0020.0002.1D0A9] # BYZANTINE MUSICAL SYMBOL MARTYRIA TETARTOS LEGETOS ICHOS
+1D0AA ; [*0DB1.0020.0002.1D0AA] # BYZANTINE MUSICAL SYMBOL MARTYRIA LEGETOS ICHOS
+1D0AB ; [*0DB2.0020.0002.1D0AB] # BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS ICHOS
+1D0AC ; [*0DB3.0020.0002.1D0AC] # BYZANTINE MUSICAL SYMBOL ISAKIA TELOUS ICHIMATOS
+1D0AD ; [*0DB4.0020.0002.1D0AD] # BYZANTINE MUSICAL SYMBOL APOSTROFOI TELOUS ICHIMATOS
+1D0AE ; [*0DB5.0020.0002.1D0AE] # BYZANTINE MUSICAL SYMBOL FANEROSIS TETRAFONIAS
+1D0AF ; [*0DB6.0020.0002.1D0AF] # BYZANTINE MUSICAL SYMBOL FANEROSIS MONOFONIAS
+1D0B0 ; [*0DB7.0020.0002.1D0B0] # BYZANTINE MUSICAL SYMBOL FANEROSIS DIFONIAS
+1D0B1 ; [*0DB8.0020.0002.1D0B1] # BYZANTINE MUSICAL SYMBOL MARTYRIA VARYS ICHOS
+1D0B2 ; [*0DB9.0020.0002.1D0B2] # BYZANTINE MUSICAL SYMBOL MARTYRIA PROTOVARYS ICHOS
+1D0B3 ; [*0DBA.0020.0002.1D0B3] # BYZANTINE MUSICAL SYMBOL MARTYRIA PLAGIOS TETARTOS ICHOS
+1D0B4 ; [*0DBB.0020.0002.1D0B4] # BYZANTINE MUSICAL SYMBOL GORTHMIKON N APLOUN
+1D0B5 ; [*0DBC.0020.0002.1D0B5] # BYZANTINE MUSICAL SYMBOL GORTHMIKON N DIPLOUN
+1D0B6 ; [*0DBD.0020.0002.1D0B6] # BYZANTINE MUSICAL SYMBOL ENARXIS KAI FTHORA VOU
+1D0B7 ; [*0DBE.0020.0002.1D0B7] # BYZANTINE MUSICAL SYMBOL IMIFONON
+1D0B8 ; [*0DBF.0020.0002.1D0B8] # BYZANTINE MUSICAL SYMBOL IMIFTHORON
+1D0B9 ; [*0DC0.0020.0002.1D0B9] # BYZANTINE MUSICAL SYMBOL FTHORA ARCHAION DEYTEROU ICHOU
+1D0BA ; [*0DC1.0020.0002.1D0BA] # BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI PA
+1D0BB ; [*0DC2.0020.0002.1D0BB] # BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NANA
+1D0BC ; [*0DC3.0020.0002.1D0BC] # BYZANTINE MUSICAL SYMBOL FTHORA NAOS ICHOS
+1D0BD ; [*0DC4.0020.0002.1D0BD] # BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI DI
+1D0BE ; [*0DC5.0020.0002.1D0BE] # BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON DIATONON DI
+1D0BF ; [*0DC6.0020.0002.1D0BF] # BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI KE
+1D0C0 ; [*0DC7.0020.0002.1D0C0] # BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI ZO
+1D0C1 ; [*0DC8.0020.0002.1D0C1] # BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI KATO
+1D0C2 ; [*0DC9.0020.0002.1D0C2] # BYZANTINE MUSICAL SYMBOL FTHORA DIATONIKI NI ANO
+1D0C3 ; [*0DCA.0020.0002.1D0C3] # BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA DIFONIAS
+1D0C4 ; [*0DCB.0020.0002.1D0C4] # BYZANTINE MUSICAL SYMBOL FTHORA MALAKON CHROMA MONOFONIAS
+1D0C5 ; [*0DCC.0020.0002.1D0C5] # BYZANTINE MUSICAL SYMBOL FHTORA SKLIRON CHROMA VASIS
+1D0C6 ; [*0DCD.0020.0002.1D0C6] # BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON CHROMA SYNAFI
+1D0C7 ; [*0DCE.0020.0002.1D0C7] # BYZANTINE MUSICAL SYMBOL FTHORA NENANO
+1D0C8 ; [*0DCF.0020.0002.1D0C8] # BYZANTINE MUSICAL SYMBOL CHROA ZYGOS
+1D0C9 ; [*0DD0.0020.0002.1D0C9] # BYZANTINE MUSICAL SYMBOL CHROA KLITON
+1D0CA ; [*0DD1.0020.0002.1D0CA] # BYZANTINE MUSICAL SYMBOL CHROA SPATHI
+1D0CB ; [*0DD2.0020.0002.1D0CB] # BYZANTINE MUSICAL SYMBOL FTHORA I YFESIS TETARTIMORION
+1D0CC ; [*0DD3.0020.0002.1D0CC] # BYZANTINE MUSICAL SYMBOL FTHORA ENARMONIOS ANTIFONIA
+1D0CD ; [*0DD4.0020.0002.1D0CD] # BYZANTINE MUSICAL SYMBOL YFESIS TRITIMORION
+1D0CE ; [*0DD5.0020.0002.1D0CE] # BYZANTINE MUSICAL SYMBOL DIESIS TRITIMORION
+1D0CF ; [*0DD6.0020.0002.1D0CF] # BYZANTINE MUSICAL SYMBOL DIESIS TETARTIMORION
+1D0D0 ; [*0DD7.0020.0002.1D0D0] # BYZANTINE MUSICAL SYMBOL DIESIS APLI DYO DODEKATA
+1D0D1 ; [*0DD8.0020.0002.1D0D1] # BYZANTINE MUSICAL SYMBOL DIESIS MONOGRAMMOS TESSERA DODEKATA
+1D0D2 ; [*0DD9.0020.0002.1D0D2] # BYZANTINE MUSICAL SYMBOL DIESIS DIGRAMMOS EX DODEKATA
+1D0D3 ; [*0DDA.0020.0002.1D0D3] # BYZANTINE MUSICAL SYMBOL DIESIS TRIGRAMMOS OKTO DODEKATA
+1D0D4 ; [*0DDB.0020.0002.1D0D4] # BYZANTINE MUSICAL SYMBOL YFESIS APLI DYO DODEKATA
+1D0D5 ; [*0DDC.0020.0002.1D0D5] # BYZANTINE MUSICAL SYMBOL YFESIS MONOGRAMMOS TESSERA DODEKATA
+1D0D6 ; [*0DDD.0020.0002.1D0D6] # BYZANTINE MUSICAL SYMBOL YFESIS DIGRAMMOS EX DODEKATA
+1D0D7 ; [*0DDE.0020.0002.1D0D7] # BYZANTINE MUSICAL SYMBOL YFESIS TRIGRAMMOS OKTO DODEKATA
+1D0D8 ; [*0DDF.0020.0002.1D0D8] # BYZANTINE MUSICAL SYMBOL GENIKI DIESIS
+1D0D9 ; [*0DE0.0020.0002.1D0D9] # BYZANTINE MUSICAL SYMBOL GENIKI YFESIS
+1D0DA ; [*0DE1.0020.0002.1D0DA] # BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MIKRI
+1D0DB ; [*0DE2.0020.0002.1D0DB] # BYZANTINE MUSICAL SYMBOL DIASTOLI APLI MEGALI
+1D0DC ; [*0DE3.0020.0002.1D0DC] # BYZANTINE MUSICAL SYMBOL DIASTOLI DIPLI
+1D0DD ; [*0DE4.0020.0002.1D0DD] # BYZANTINE MUSICAL SYMBOL DIASTOLI THESEOS
+1D0DE ; [*0DE5.0020.0002.1D0DE] # BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS
+1D0DF ; [*0DE6.0020.0002.1D0DF] # BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS DISIMOU
+1D0E0 ; [*0DE7.0020.0002.1D0E0] # BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TRISIMOU
+1D0E1 ; [*0DE8.0020.0002.1D0E1] # BYZANTINE MUSICAL SYMBOL SIMANSIS THESEOS TETRASIMOU
+1D0E2 ; [*0DE9.0020.0002.1D0E2] # BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS
+1D0E3 ; [*0DEA.0020.0002.1D0E3] # BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS DISIMOU
+1D0E4 ; [*0DEB.0020.0002.1D0E4] # BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TRISIMOU
+1D0E5 ; [*0DEC.0020.0002.1D0E5] # BYZANTINE MUSICAL SYMBOL SIMANSIS ARSEOS TETRASIMOU
+1D0E6 ; [*0DED.0020.0002.1D0E6] # BYZANTINE MUSICAL SYMBOL DIGRAMMA GG
+1D0E7 ; [*0DEE.0020.0002.1D0E7] # BYZANTINE MUSICAL SYMBOL DIFTOGGOS OU
+1D0E8 ; [*0DEF.0020.0002.1D0E8] # BYZANTINE MUSICAL SYMBOL STIGMA
+1D0E9 ; [*0DF0.0020.0002.1D0E9] # BYZANTINE MUSICAL SYMBOL ARKTIKO PA
+1D0EA ; [*0DF1.0020.0002.1D0EA] # BYZANTINE MUSICAL SYMBOL ARKTIKO VOU
+1D0EB ; [*0DF2.0020.0002.1D0EB] # BYZANTINE MUSICAL SYMBOL ARKTIKO GA
+1D0EC ; [*0DF3.0020.0002.1D0EC] # BYZANTINE MUSICAL SYMBOL ARKTIKO DI
+1D0ED ; [*0DF4.0020.0002.1D0ED] # BYZANTINE MUSICAL SYMBOL ARKTIKO KE
+1D0EE ; [*0DF5.0020.0002.1D0EE] # BYZANTINE MUSICAL SYMBOL ARKTIKO ZO
+1D0EF ; [*0DF6.0020.0002.1D0EF] # BYZANTINE MUSICAL SYMBOL ARKTIKO NI
+1D0F0 ; [*0DF7.0020.0002.1D0F0] # BYZANTINE MUSICAL SYMBOL KENTIMATA NEO MESO
+1D0F1 ; [*0DF8.0020.0002.1D0F1] # BYZANTINE MUSICAL SYMBOL KENTIMA NEO MESO
+1D0F2 ; [*0DF9.0020.0002.1D0F2] # BYZANTINE MUSICAL SYMBOL KENTIMATA NEO KATO
+1D0F3 ; [*0DFA.0020.0002.1D0F3] # BYZANTINE MUSICAL SYMBOL KENTIMA NEO KATO
+1D0F4 ; [*0DFB.0020.0002.1D0F4] # BYZANTINE MUSICAL SYMBOL KLASMA KATO
+1D0F5 ; [*0DFC.0020.0002.1D0F5] # BYZANTINE MUSICAL SYMBOL GORGON NEO KATO
+1D100 ; [*0DFD.0020.0002.1D100] # MUSICAL SYMBOL SINGLE BARLINE
+1D101 ; [*0DFE.0020.0002.1D101] # MUSICAL SYMBOL DOUBLE BARLINE
+1D102 ; [*0DFF.0020.0002.1D102] # MUSICAL SYMBOL FINAL BARLINE
+1D103 ; [*0E00.0020.0002.1D103] # MUSICAL SYMBOL REVERSE FINAL BARLINE
+1D104 ; [*0E01.0020.0002.1D104] # MUSICAL SYMBOL DASHED BARLINE
+1D105 ; [*0E02.0020.0002.1D105] # MUSICAL SYMBOL SHORT BARLINE
+1D106 ; [*0E03.0020.0002.1D106] # MUSICAL SYMBOL LEFT REPEAT SIGN
+1D107 ; [*0E04.0020.0002.1D107] # MUSICAL SYMBOL RIGHT REPEAT SIGN
+1D108 ; [*0E05.0020.0002.1D108] # MUSICAL SYMBOL REPEAT DOTS
+1D109 ; [*0E06.0020.0002.1D109] # MUSICAL SYMBOL DAL SEGNO
+1D10A ; [*0E07.0020.0002.1D10A] # MUSICAL SYMBOL DA CAPO
+1D10B ; [*0E08.0020.0002.1D10B] # MUSICAL SYMBOL SEGNO
+1D10C ; [*0E09.0020.0002.1D10C] # MUSICAL SYMBOL CODA
+1D10D ; [*0E0A.0020.0002.1D10D] # MUSICAL SYMBOL REPEATED FIGURE-1
+1D10E ; [*0E0B.0020.0002.1D10E] # MUSICAL SYMBOL REPEATED FIGURE-2
+1D10F ; [*0E0C.0020.0002.1D10F] # MUSICAL SYMBOL REPEATED FIGURE-3
+1D110 ; [*0E0D.0020.0002.1D110] # MUSICAL SYMBOL FERMATA
+1D111 ; [*0E0E.0020.0002.1D111] # MUSICAL SYMBOL FERMATA BELOW
+1D112 ; [*0E0F.0020.0002.1D112] # MUSICAL SYMBOL BREATH MARK
+1D113 ; [*0E10.0020.0002.1D113] # MUSICAL SYMBOL CAESURA
+1D114 ; [*0E11.0020.0002.1D114] # MUSICAL SYMBOL BRACE
+1D115 ; [*0E12.0020.0002.1D115] # MUSICAL SYMBOL BRACKET
+1D116 ; [*0E13.0020.0002.1D116] # MUSICAL SYMBOL ONE-LINE STAFF
+1D117 ; [*0E14.0020.0002.1D117] # MUSICAL SYMBOL TWO-LINE STAFF
+1D118 ; [*0E15.0020.0002.1D118] # MUSICAL SYMBOL THREE-LINE STAFF
+1D119 ; [*0E16.0020.0002.1D119] # MUSICAL SYMBOL FOUR-LINE STAFF
+1D11A ; [*0E17.0020.0002.1D11A] # MUSICAL SYMBOL FIVE-LINE STAFF
+1D11B ; [*0E18.0020.0002.1D11B] # MUSICAL SYMBOL SIX-LINE STAFF
+1D11C ; [*0E19.0020.0002.1D11C] # MUSICAL SYMBOL SIX-STRING FRETBOARD
+1D11D ; [*0E1A.0020.0002.1D11D] # MUSICAL SYMBOL FOUR-STRING FRETBOARD
+1D11E ; [*0E1B.0020.0002.1D11E] # MUSICAL SYMBOL G CLEF
+1D11F ; [*0E1C.0020.0002.1D11F] # MUSICAL SYMBOL G CLEF OTTAVA ALTA
+1D120 ; [*0E1D.0020.0002.1D120] # MUSICAL SYMBOL G CLEF OTTAVA BASSA
+1D121 ; [*0E1E.0020.0002.1D121] # MUSICAL SYMBOL C CLEF
+1D122 ; [*0E1F.0020.0002.1D122] # MUSICAL SYMBOL F CLEF
+1D123 ; [*0E20.0020.0002.1D123] # MUSICAL SYMBOL F CLEF OTTAVA ALTA
+1D124 ; [*0E21.0020.0002.1D124] # MUSICAL SYMBOL F CLEF OTTAVA BASSA
+1D125 ; [*0E22.0020.0002.1D125] # MUSICAL SYMBOL DRUM CLEF-1
+1D126 ; [*0E23.0020.0002.1D126] # MUSICAL SYMBOL DRUM CLEF-2
+1D12A ; [*0E27.0020.0002.1D12A] # MUSICAL SYMBOL DOUBLE SHARP
+1D12B ; [*0E28.0020.0002.1D12B] # MUSICAL SYMBOL DOUBLE FLAT
+1D12C ; [*0E29.0020.0002.1D12C] # MUSICAL SYMBOL FLAT UP
+1D12D ; [*0E2A.0020.0002.1D12D] # MUSICAL SYMBOL FLAT DOWN
+1D12E ; [*0E2B.0020.0002.1D12E] # MUSICAL SYMBOL NATURAL UP
+1D12F ; [*0E2C.0020.0002.1D12F] # MUSICAL SYMBOL NATURAL DOWN
+1D130 ; [*0E2D.0020.0002.1D130] # MUSICAL SYMBOL SHARP UP
+1D131 ; [*0E2E.0020.0002.1D131] # MUSICAL SYMBOL SHARP DOWN
+1D132 ; [*0E2F.0020.0002.1D132] # MUSICAL SYMBOL QUARTER TONE SHARP
+1D133 ; [*0E30.0020.0002.1D133] # MUSICAL SYMBOL QUARTER TONE FLAT
+1D134 ; [*0E31.0020.0002.1D134] # MUSICAL SYMBOL COMMON TIME
+1D135 ; [*0E32.0020.0002.1D135] # MUSICAL SYMBOL CUT TIME
+1D136 ; [*0E33.0020.0002.1D136] # MUSICAL SYMBOL OTTAVA ALTA
+1D137 ; [*0E34.0020.0002.1D137] # MUSICAL SYMBOL OTTAVA BASSA
+1D138 ; [*0E35.0020.0002.1D138] # MUSICAL SYMBOL QUINDICESIMA ALTA
+1D139 ; [*0E36.0020.0002.1D139] # MUSICAL SYMBOL QUINDICESIMA BASSA
+1D13A ; [*0E37.0020.0002.1D13A] # MUSICAL SYMBOL MULTI REST
+1D13B ; [*0E38.0020.0002.1D13B] # MUSICAL SYMBOL WHOLE REST
+1D13C ; [*0E39.0020.0002.1D13C] # MUSICAL SYMBOL HALF REST
+1D13D ; [*0E3A.0020.0002.1D13D] # MUSICAL SYMBOL QUARTER REST
+1D13E ; [*0E3B.0020.0002.1D13E] # MUSICAL SYMBOL EIGHTH REST
+1D13F ; [*0E3C.0020.0002.1D13F] # MUSICAL SYMBOL SIXTEENTH REST
+1D140 ; [*0E3D.0020.0002.1D140] # MUSICAL SYMBOL THIRTY-SECOND REST
+1D141 ; [*0E3E.0020.0002.1D141] # MUSICAL SYMBOL SIXTY-FOURTH REST
+1D142 ; [*0E3F.0020.0002.1D142] # MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH REST
+1D143 ; [*0E40.0020.0002.1D143] # MUSICAL SYMBOL X NOTEHEAD
+1D144 ; [*0E41.0020.0002.1D144] # MUSICAL SYMBOL PLUS NOTEHEAD
+1D145 ; [*0E42.0020.0002.1D145] # MUSICAL SYMBOL CIRCLE X NOTEHEAD
+1D146 ; [*0E43.0020.0002.1D146] # MUSICAL SYMBOL SQUARE NOTEHEAD WHITE
+1D147 ; [*0E44.0020.0002.1D147] # MUSICAL SYMBOL SQUARE NOTEHEAD BLACK
+1D148 ; [*0E45.0020.0002.1D148] # MUSICAL SYMBOL TRIANGLE NOTEHEAD UP WHITE
+1D149 ; [*0E46.0020.0002.1D149] # MUSICAL SYMBOL TRIANGLE NOTEHEAD UP BLACK
+1D14A ; [*0E47.0020.0002.1D14A] # MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT WHITE
+1D14B ; [*0E48.0020.0002.1D14B] # MUSICAL SYMBOL TRIANGLE NOTEHEAD LEFT BLACK
+1D14C ; [*0E49.0020.0002.1D14C] # MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT WHITE
+1D14D ; [*0E4A.0020.0002.1D14D] # MUSICAL SYMBOL TRIANGLE NOTEHEAD RIGHT BLACK
+1D14E ; [*0E4B.0020.0002.1D14E] # MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN WHITE
+1D14F ; [*0E4C.0020.0002.1D14F] # MUSICAL SYMBOL TRIANGLE NOTEHEAD DOWN BLACK
+1D150 ; [*0E4D.0020.0002.1D150] # MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT WHITE
+1D151 ; [*0E4E.0020.0002.1D151] # MUSICAL SYMBOL TRIANGLE NOTEHEAD UP RIGHT BLACK
+1D152 ; [*0E4F.0020.0002.1D152] # MUSICAL SYMBOL MOON NOTEHEAD WHITE
+1D153 ; [*0E50.0020.0002.1D153] # MUSICAL SYMBOL MOON NOTEHEAD BLACK
+1D154 ; [*0E51.0020.0002.1D154] # MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN WHITE
+1D155 ; [*0E52.0020.0002.1D155] # MUSICAL SYMBOL TRIANGLE-ROUND NOTEHEAD DOWN BLACK
+1D156 ; [*0E53.0020.0002.1D156] # MUSICAL SYMBOL PARENTHESIS NOTEHEAD
+1D157 ; [*0E54.0020.0002.1D157] # MUSICAL SYMBOL VOID NOTEHEAD
+1D158 ; [*0E55.0020.0002.1D158] # MUSICAL SYMBOL NOTEHEAD BLACK
+1D159 ; [*0E56.0020.0002.1D159] # MUSICAL SYMBOL NULL NOTEHEAD
+1D15A ; [*0E57.0020.0002.1D15A] # MUSICAL SYMBOL CLUSTER NOTEHEAD WHITE
+1D15B ; [*0E58.0020.0002.1D15B] # MUSICAL SYMBOL CLUSTER NOTEHEAD BLACK
+1D15C ; [*0E59.0020.0002.1D15C] # MUSICAL SYMBOL BREVE
+1D15D ; [*0E5A.0020.0002.1D15D] # MUSICAL SYMBOL WHOLE NOTE
+1D15E ; [*0E54.0020.0002.1D157][.0000.0000.0000.1D165] # MUSICAL SYMBOL HALF NOTE; QQCN
+1D15F ; [*0E55.0020.0002.1D158][.0000.0000.0000.1D165] # MUSICAL SYMBOL QUARTER NOTE; QQCN
+1D160 ; [*0E55.0020.0002.1D158][.0000.0000.0000.1D165][.0000.0000.0000.1D16E] # MUSICAL SYMBOL EIGHTH NOTE; QQCN
+1D161 ; [*0E55.0020.0002.1D158][.0000.0000.0000.1D165][.0000.0000.0000.1D16F] # MUSICAL SYMBOL SIXTEENTH NOTE; QQCN
+1D162 ; [*0E55.0020.0002.1D158][.0000.0000.0000.1D165][.0000.0000.0000.1D170] # MUSICAL SYMBOL THIRTY-SECOND NOTE; QQCN
+1D163 ; [*0E55.0020.0002.1D158][.0000.0000.0000.1D165][.0000.0000.0000.1D171] # MUSICAL SYMBOL SIXTY-FOURTH NOTE; QQCN
+1D164 ; [*0E55.0020.0002.1D158][.0000.0000.0000.1D165][.0000.0000.0000.1D172] # MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE; QQCN
+1D165 ; [.0000.0000.0000.1D165] # MUSICAL SYMBOL COMBINING STEM
+1D166 ; [.0000.0000.0000.1D166] # MUSICAL SYMBOL COMBINING SPRECHGESANG STEM
+1D167 ; [.0000.0000.0000.1D167] # MUSICAL SYMBOL COMBINING TREMOLO-1
+1D168 ; [.0000.0000.0000.1D168] # MUSICAL SYMBOL COMBINING TREMOLO-2
+1D169 ; [.0000.0000.0000.1D169] # MUSICAL SYMBOL COMBINING TREMOLO-3
+1D16A ; [*0E5B.0020.0002.1D16A] # MUSICAL SYMBOL FINGERED TREMOLO-1
+1D16B ; [*0E5C.0020.0002.1D16B] # MUSICAL SYMBOL FINGERED TREMOLO-2
+1D16C ; [*0E5D.0020.0002.1D16C] # MUSICAL SYMBOL FINGERED TREMOLO-3
+1D16D ; [.0000.0000.0000.1D16D] # MUSICAL SYMBOL COMBINING AUGMENTATION DOT
+1D16E ; [.0000.0000.0000.1D16E] # MUSICAL SYMBOL COMBINING FLAG-1
+1D16F ; [.0000.0000.0000.1D16F] # MUSICAL SYMBOL COMBINING FLAG-2
+1D170 ; [.0000.0000.0000.1D170] # MUSICAL SYMBOL COMBINING FLAG-3
+1D171 ; [.0000.0000.0000.1D171] # MUSICAL SYMBOL COMBINING FLAG-4
+1D172 ; [.0000.0000.0000.1D172] # MUSICAL SYMBOL COMBINING FLAG-5
+1D17B ; [.0000.0000.0000.1D17B] # MUSICAL SYMBOL COMBINING ACCENT
+1D17C ; [.0000.0000.0000.1D17C] # MUSICAL SYMBOL COMBINING STACCATO
+1D17D ; [.0000.0000.0000.1D17D] # MUSICAL SYMBOL COMBINING TENUTO
+1D17E ; [.0000.0000.0000.1D17E] # MUSICAL SYMBOL COMBINING STACCATISSIMO
+1D17F ; [.0000.0000.0000.1D17F] # MUSICAL SYMBOL COMBINING MARCATO
+1D180 ; [.0000.0000.0000.1D180] # MUSICAL SYMBOL COMBINING MARCATO-STACCATO
+1D181 ; [.0000.0000.0000.1D181] # MUSICAL SYMBOL COMBINING ACCENT-STACCATO
+1D182 ; [.0000.0000.0000.1D182] # MUSICAL SYMBOL COMBINING LOURE
+1D183 ; [*0E5E.0020.0002.1D183] # MUSICAL SYMBOL ARPEGGIATO UP
+1D184 ; [*0E5F.0020.0002.1D184] # MUSICAL SYMBOL ARPEGGIATO DOWN
+1D185 ; [.0000.0000.0000.1D185] # MUSICAL SYMBOL COMBINING DOIT
+1D186 ; [.0000.0000.0000.1D186] # MUSICAL SYMBOL COMBINING RIP
+1D187 ; [.0000.0000.0000.1D187] # MUSICAL SYMBOL COMBINING FLIP
+1D188 ; [.0000.0000.0000.1D188] # MUSICAL SYMBOL COMBINING SMEAR
+1D189 ; [.0000.0000.0000.1D189] # MUSICAL SYMBOL COMBINING BEND
+1D18A ; [.0000.0000.0000.1D18A] # MUSICAL SYMBOL COMBINING DOUBLE TONGUE
+1D18B ; [.0000.0000.0000.1D18B] # MUSICAL SYMBOL COMBINING TRIPLE TONGUE
+1D18C ; [*0E60.0020.0002.1D18C] # MUSICAL SYMBOL RINFORZANDO
+1D18D ; [*0E61.0020.0002.1D18D] # MUSICAL SYMBOL SUBITO
+1D18E ; [*0E62.0020.0002.1D18E] # MUSICAL SYMBOL Z
+1D18F ; [*0E63.0020.0002.1D18F] # MUSICAL SYMBOL PIANO
+1D190 ; [*0E64.0020.0002.1D190] # MUSICAL SYMBOL MEZZO
+1D191 ; [*0E65.0020.0002.1D191] # MUSICAL SYMBOL FORTE
+1D192 ; [*0E66.0020.0002.1D192] # MUSICAL SYMBOL CRESCENDO
+1D193 ; [*0E67.0020.0002.1D193] # MUSICAL SYMBOL DECRESCENDO
+1D194 ; [*0E68.0020.0002.1D194] # MUSICAL SYMBOL GRACE NOTE SLASH
+1D195 ; [*0E69.0020.0002.1D195] # MUSICAL SYMBOL GRACE NOTE NO SLASH
+1D196 ; [*0E6A.0020.0002.1D196] # MUSICAL SYMBOL TR
+1D197 ; [*0E6B.0020.0002.1D197] # MUSICAL SYMBOL TURN
+1D198 ; [*0E6C.0020.0002.1D198] # MUSICAL SYMBOL INVERTED TURN
+1D199 ; [*0E6D.0020.0002.1D199] # MUSICAL SYMBOL TURN SLASH
+1D19A ; [*0E6E.0020.0002.1D19A] # MUSICAL SYMBOL TURN UP
+1D19B ; [*0E6F.0020.0002.1D19B] # MUSICAL SYMBOL ORNAMENT STROKE-1
+1D19C ; [*0E70.0020.0002.1D19C] # MUSICAL SYMBOL ORNAMENT STROKE-2
+1D19D ; [*0E71.0020.0002.1D19D] # MUSICAL SYMBOL ORNAMENT STROKE-3
+1D19E ; [*0E72.0020.0002.1D19E] # MUSICAL SYMBOL ORNAMENT STROKE-4
+1D19F ; [*0E73.0020.0002.1D19F] # MUSICAL SYMBOL ORNAMENT STROKE-5
+1D1A0 ; [*0E74.0020.0002.1D1A0] # MUSICAL SYMBOL ORNAMENT STROKE-6
+1D1A1 ; [*0E75.0020.0002.1D1A1] # MUSICAL SYMBOL ORNAMENT STROKE-7
+1D1A2 ; [*0E76.0020.0002.1D1A2] # MUSICAL SYMBOL ORNAMENT STROKE-8
+1D1A3 ; [*0E77.0020.0002.1D1A3] # MUSICAL SYMBOL ORNAMENT STROKE-9
+1D1A4 ; [*0E78.0020.0002.1D1A4] # MUSICAL SYMBOL ORNAMENT STROKE-10
+1D1A5 ; [*0E79.0020.0002.1D1A5] # MUSICAL SYMBOL ORNAMENT STROKE-11
+1D1A6 ; [*0E7A.0020.0002.1D1A6] # MUSICAL SYMBOL HAUPTSTIMME
+1D1A7 ; [*0E7B.0020.0002.1D1A7] # MUSICAL SYMBOL NEBENSTIMME
+1D1A8 ; [*0E7C.0020.0002.1D1A8] # MUSICAL SYMBOL END OF STIMME
+1D1A9 ; [*0E7D.0020.0002.1D1A9] # MUSICAL SYMBOL DEGREE SLASH
+1D1AA ; [.0000.0000.0000.1D1AA] # MUSICAL SYMBOL COMBINING DOWN BOW
+1D1AB ; [.0000.0000.0000.1D1AB] # MUSICAL SYMBOL COMBINING UP BOW
+1D1AC ; [.0000.0000.0000.1D1AC] # MUSICAL SYMBOL COMBINING HARMONIC
+1D1AD ; [.0000.0000.0000.1D1AD] # MUSICAL SYMBOL COMBINING SNAP PIZZICATO
+1D1AE ; [*0E7E.0020.0002.1D1AE] # MUSICAL SYMBOL PEDAL MARK
+1D1AF ; [*0E7F.0020.0002.1D1AF] # MUSICAL SYMBOL PEDAL UP MARK
+1D1B0 ; [*0E80.0020.0002.1D1B0] # MUSICAL SYMBOL HALF PEDAL MARK
+1D1B1 ; [*0E81.0020.0002.1D1B1] # MUSICAL SYMBOL GLISSANDO UP
+1D1B2 ; [*0E82.0020.0002.1D1B2] # MUSICAL SYMBOL GLISSANDO DOWN
+1D1B3 ; [*0E83.0020.0002.1D1B3] # MUSICAL SYMBOL WITH FINGERNAILS
+1D1B4 ; [*0E84.0020.0002.1D1B4] # MUSICAL SYMBOL DAMP
+1D1B5 ; [*0E85.0020.0002.1D1B5] # MUSICAL SYMBOL DAMP ALL
+1D1B6 ; [*0E86.0020.0002.1D1B6] # MUSICAL SYMBOL MAXIMA
+1D1B7 ; [*0E87.0020.0002.1D1B7] # MUSICAL SYMBOL LONGA
+1D1B8 ; [*0E88.0020.0002.1D1B8] # MUSICAL SYMBOL BREVIS
+1D1B9 ; [*0E89.0020.0002.1D1B9] # MUSICAL SYMBOL SEMIBREVIS WHITE
+1D1BA ; [*0E8A.0020.0002.1D1BA] # MUSICAL SYMBOL SEMIBREVIS BLACK
+1D1BB ; [*0E89.0020.0002.1D1B9][.0000.0000.0000.1D165] # MUSICAL SYMBOL MINIMA; QQCN
+1D1BC ; [*0E8A.0020.0002.1D1BA][.0000.0000.0000.1D165] # MUSICAL SYMBOL MINIMA BLACK; QQCN
+1D1BD ; [*0E89.0020.0002.1D1B9][.0000.0000.0000.1D165][.0000.0000.0000.1D16E] # MUSICAL SYMBOL SEMIMINIMA WHITE; QQCN
+1D1BE ; [*0E8A.0020.0002.1D1BA][.0000.0000.0000.1D165][.0000.0000.0000.1D16E] # MUSICAL SYMBOL SEMIMINIMA BLACK; QQCN
+1D1BF ; [*0E89.0020.0002.1D1B9][.0000.0000.0000.1D165][.0000.0000.0000.1D16F] # MUSICAL SYMBOL FUSA WHITE; QQCN
+1D1C0 ; [*0E8A.0020.0002.1D1BA][.0000.0000.0000.1D165][.0000.0000.0000.1D16F] # MUSICAL SYMBOL FUSA BLACK; QQCN
+1D1C1 ; [*0E8B.0020.0002.1D1C1] # MUSICAL SYMBOL LONGA PERFECTA REST
+1D1C2 ; [*0E8C.0020.0002.1D1C2] # MUSICAL SYMBOL LONGA IMPERFECTA REST
+1D1C3 ; [*0E8D.0020.0002.1D1C3] # MUSICAL SYMBOL BREVIS REST
+1D1C4 ; [*0E8E.0020.0002.1D1C4] # MUSICAL SYMBOL SEMIBREVIS REST
+1D1C5 ; [*0E8F.0020.0002.1D1C5] # MUSICAL SYMBOL MINIMA REST
+1D1C6 ; [*0E90.0020.0002.1D1C6] # MUSICAL SYMBOL SEMIMINIMA REST
+1D1C7 ; [*0E91.0020.0002.1D1C7] # MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA
+1D1C8 ; [*0E92.0020.0002.1D1C8] # MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE IMPERFECTA
+1D1C9 ; [*0E93.0020.0002.1D1C9] # MUSICAL SYMBOL TEMPUS PERFECTUM CUM PROLATIONE PERFECTA DIMINUTION-1
+1D1CA ; [*0E94.0020.0002.1D1CA] # MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE PERFECTA
+1D1CB ; [*0E95.0020.0002.1D1CB] # MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA
+1D1CC ; [*0E96.0020.0002.1D1CC] # MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-1
+1D1CD ; [*0E97.0020.0002.1D1CD] # MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-2
+1D1CE ; [*0E98.0020.0002.1D1CE] # MUSICAL SYMBOL TEMPUS IMPERFECTUM CUM PROLATIONE IMPERFECTA DIMINUTION-3
+1D1CF ; [*0E99.0020.0002.1D1CF] # MUSICAL SYMBOL CROIX
+1D1D0 ; [*0E9A.0020.0002.1D1D0] # MUSICAL SYMBOL GREGORIAN C CLEF
+1D1D1 ; [*0E9B.0020.0002.1D1D1] # MUSICAL SYMBOL GREGORIAN F CLEF
+1D1D2 ; [*0E9C.0020.0002.1D1D2] # MUSICAL SYMBOL SQUARE B
+1D1D3 ; [*0E9D.0020.0002.1D1D3] # MUSICAL SYMBOL VIRGA
+1D1D4 ; [*0E9E.0020.0002.1D1D4] # MUSICAL SYMBOL PODATUS
+1D1D5 ; [*0E9F.0020.0002.1D1D5] # MUSICAL SYMBOL CLIVIS
+1D1D6 ; [*0EA0.0020.0002.1D1D6] # MUSICAL SYMBOL SCANDICUS
+1D1D7 ; [*0EA1.0020.0002.1D1D7] # MUSICAL SYMBOL CLIMACUS
+1D1D8 ; [*0EA2.0020.0002.1D1D8] # MUSICAL SYMBOL TORCULUS
+1D1D9 ; [*0EA3.0020.0002.1D1D9] # MUSICAL SYMBOL PORRECTUS
+1D1DA ; [*0EA4.0020.0002.1D1DA] # MUSICAL SYMBOL PORRECTUS FLEXUS
+1D1DB ; [*0EA5.0020.0002.1D1DB] # MUSICAL SYMBOL SCANDICUS FLEXUS
+1D1DC ; [*0EA6.0020.0002.1D1DC] # MUSICAL SYMBOL TORCULUS RESUPINUS
+1D1DD ; [*0EA7.0020.0002.1D1DD] # MUSICAL SYMBOL PES SUBPUNCTIS
+1D200 ; [*0EA8.0020.0002.1D200] # GREEK VOCAL NOTATION SYMBOL-1
+1D201 ; [*0EA9.0020.0002.1D201] # GREEK VOCAL NOTATION SYMBOL-2
+1D202 ; [*0EAA.0020.0002.1D202] # GREEK VOCAL NOTATION SYMBOL-3
+1D203 ; [*0EAB.0020.0002.1D203] # GREEK VOCAL NOTATION SYMBOL-4
+1D204 ; [*0EAC.0020.0002.1D204] # GREEK VOCAL NOTATION SYMBOL-5
+1D205 ; [*0EAD.0020.0002.1D205] # GREEK VOCAL NOTATION SYMBOL-6
+1D206 ; [*0EAE.0020.0002.1D206] # GREEK VOCAL NOTATION SYMBOL-7
+1D207 ; [*0EAF.0020.0002.1D207] # GREEK VOCAL NOTATION SYMBOL-8
+1D208 ; [*0EB0.0020.0002.1D208] # GREEK VOCAL NOTATION SYMBOL-9
+1D209 ; [*0EB1.0020.0002.1D209] # GREEK VOCAL NOTATION SYMBOL-10
+1D20A ; [*0EB2.0020.0002.1D20A] # GREEK VOCAL NOTATION SYMBOL-11
+1D20B ; [*0EB3.0020.0002.1D20B] # GREEK VOCAL NOTATION SYMBOL-12
+1D20C ; [*0EB4.0020.0002.1D20C] # GREEK VOCAL NOTATION SYMBOL-13
+1D20D ; [*0EB5.0020.0002.1D20D] # GREEK VOCAL NOTATION SYMBOL-14
+1D20E ; [*0EB6.0020.0002.1D20E] # GREEK VOCAL NOTATION SYMBOL-15
+1D20F ; [*0EB7.0020.0002.1D20F] # GREEK VOCAL NOTATION SYMBOL-16
+1D210 ; [*0EB8.0020.0002.1D210] # GREEK VOCAL NOTATION SYMBOL-17
+1D211 ; [*0EB9.0020.0002.1D211] # GREEK VOCAL NOTATION SYMBOL-18
+1D212 ; [*0EBA.0020.0002.1D212] # GREEK VOCAL NOTATION SYMBOL-19
+1D213 ; [*0EBB.0020.0002.1D213] # GREEK VOCAL NOTATION SYMBOL-20
+1D214 ; [*0EBC.0020.0002.1D214] # GREEK VOCAL NOTATION SYMBOL-21
+1D215 ; [*0EBD.0020.0002.1D215] # GREEK VOCAL NOTATION SYMBOL-22
+1D216 ; [*0EBE.0020.0002.1D216] # GREEK VOCAL NOTATION SYMBOL-23
+1D217 ; [*0EBF.0020.0002.1D217] # GREEK VOCAL NOTATION SYMBOL-24
+1D218 ; [*0EC0.0020.0002.1D218] # GREEK VOCAL NOTATION SYMBOL-50
+1D219 ; [*0EC1.0020.0002.1D219] # GREEK VOCAL NOTATION SYMBOL-51
+1D21A ; [*0EC2.0020.0002.1D21A] # GREEK VOCAL NOTATION SYMBOL-52
+1D21B ; [*0EC3.0020.0002.1D21B] # GREEK VOCAL NOTATION SYMBOL-53
+1D21C ; [*0EC4.0020.0002.1D21C] # GREEK VOCAL NOTATION SYMBOL-54
+1D21D ; [*0EC5.0020.0002.1D21D] # GREEK INSTRUMENTAL NOTATION SYMBOL-1
+1D21E ; [*0EC6.0020.0002.1D21E] # GREEK INSTRUMENTAL NOTATION SYMBOL-2
+1D21F ; [*0EC7.0020.0002.1D21F] # GREEK INSTRUMENTAL NOTATION SYMBOL-4
+1D220 ; [*0EC8.0020.0002.1D220] # GREEK INSTRUMENTAL NOTATION SYMBOL-5
+1D221 ; [*0EC9.0020.0002.1D221] # GREEK INSTRUMENTAL NOTATION SYMBOL-7
+1D222 ; [*0ECA.0020.0002.1D222] # GREEK INSTRUMENTAL NOTATION SYMBOL-8
+1D223 ; [*0ECB.0020.0002.1D223] # GREEK INSTRUMENTAL NOTATION SYMBOL-11
+1D224 ; [*0ECC.0020.0002.1D224] # GREEK INSTRUMENTAL NOTATION SYMBOL-12
+1D225 ; [*0ECD.0020.0002.1D225] # GREEK INSTRUMENTAL NOTATION SYMBOL-13
+1D226 ; [*0ECE.0020.0002.1D226] # GREEK INSTRUMENTAL NOTATION SYMBOL-14
+1D227 ; [*0ECF.0020.0002.1D227] # GREEK INSTRUMENTAL NOTATION SYMBOL-17
+1D228 ; [*0ED0.0020.0002.1D228] # GREEK INSTRUMENTAL NOTATION SYMBOL-18
+1D229 ; [*0ED1.0020.0002.1D229] # GREEK INSTRUMENTAL NOTATION SYMBOL-19
+1D22A ; [*0ED2.0020.0002.1D22A] # GREEK INSTRUMENTAL NOTATION SYMBOL-23
+1D22B ; [*0ED3.0020.0002.1D22B] # GREEK INSTRUMENTAL NOTATION SYMBOL-24
+1D22C ; [*0ED4.0020.0002.1D22C] # GREEK INSTRUMENTAL NOTATION SYMBOL-25
+1D22D ; [*0ED5.0020.0002.1D22D] # GREEK INSTRUMENTAL NOTATION SYMBOL-26
+1D22E ; [*0ED6.0020.0002.1D22E] # GREEK INSTRUMENTAL NOTATION SYMBOL-27
+1D22F ; [*0ED7.0020.0002.1D22F] # GREEK INSTRUMENTAL NOTATION SYMBOL-29
+1D230 ; [*0ED8.0020.0002.1D230] # GREEK INSTRUMENTAL NOTATION SYMBOL-30
+1D231 ; [*0ED9.0020.0002.1D231] # GREEK INSTRUMENTAL NOTATION SYMBOL-32
+1D232 ; [*0EDA.0020.0002.1D232] # GREEK INSTRUMENTAL NOTATION SYMBOL-36
+1D233 ; [*0EDB.0020.0002.1D233] # GREEK INSTRUMENTAL NOTATION SYMBOL-37
+1D234 ; [*0EDC.0020.0002.1D234] # GREEK INSTRUMENTAL NOTATION SYMBOL-38
+1D235 ; [*0EDD.0020.0002.1D235] # GREEK INSTRUMENTAL NOTATION SYMBOL-39
+1D236 ; [*0EDE.0020.0002.1D236] # GREEK INSTRUMENTAL NOTATION SYMBOL-40
+1D237 ; [*0EDF.0020.0002.1D237] # GREEK INSTRUMENTAL NOTATION SYMBOL-42
+1D238 ; [*0EE0.0020.0002.1D238] # GREEK INSTRUMENTAL NOTATION SYMBOL-43
+1D239 ; [*0EE1.0020.0002.1D239] # GREEK INSTRUMENTAL NOTATION SYMBOL-45
+1D23A ; [*0EE2.0020.0002.1D23A] # GREEK INSTRUMENTAL NOTATION SYMBOL-47
+1D23B ; [*0EE3.0020.0002.1D23B] # GREEK INSTRUMENTAL NOTATION SYMBOL-48
+1D23C ; [*0EE4.0020.0002.1D23C] # GREEK INSTRUMENTAL NOTATION SYMBOL-49
+1D23D ; [*0EE5.0020.0002.1D23D] # GREEK INSTRUMENTAL NOTATION SYMBOL-50
+1D23E ; [*0EE6.0020.0002.1D23E] # GREEK INSTRUMENTAL NOTATION SYMBOL-51
+1D23F ; [*0EE7.0020.0002.1D23F] # GREEK INSTRUMENTAL NOTATION SYMBOL-52
+1D240 ; [*0EE8.0020.0002.1D240] # GREEK INSTRUMENTAL NOTATION SYMBOL-53
+1D241 ; [*0EE9.0020.0002.1D241] # GREEK INSTRUMENTAL NOTATION SYMBOL-54
+1D242 ; [.0000.0000.0000.1D242] # COMBINING GREEK MUSICAL TRISEME
+1D243 ; [.0000.0000.0000.1D243] # COMBINING GREEK MUSICAL TETRASEME
+1D244 ; [.0000.0000.0000.1D244] # COMBINING GREEK MUSICAL PENTASEME
+1D245 ; [*0EEA.0020.0002.1D245] # GREEK MUSICAL LEIMMA
+1D300 ; [*0C5F.0020.0002.1D300] # MONOGRAM FOR EARTH
+1D301 ; [*0C60.0020.0002.1D301] # DIGRAM FOR HEAVENLY EARTH
+1D302 ; [*0C61.0020.0002.1D302] # DIGRAM FOR HUMAN EARTH
+1D303 ; [*0C62.0020.0002.1D303] # DIGRAM FOR EARTHLY HEAVEN
+1D304 ; [*0C63.0020.0002.1D304] # DIGRAM FOR EARTHLY HUMAN
+1D305 ; [*0C64.0020.0002.1D305] # DIGRAM FOR EARTH
+1D306 ; [*0C65.0020.0002.1D306] # TETRAGRAM FOR CENTRE
+1D307 ; [*0C66.0020.0002.1D307] # TETRAGRAM FOR FULL CIRCLE
+1D308 ; [*0C67.0020.0002.1D308] # TETRAGRAM FOR MIRED
+1D309 ; [*0C68.0020.0002.1D309] # TETRAGRAM FOR BARRIER
+1D30A ; [*0C69.0020.0002.1D30A] # TETRAGRAM FOR KEEPING SMALL
+1D30B ; [*0C6A.0020.0002.1D30B] # TETRAGRAM FOR CONTRARIETY
+1D30C ; [*0C6B.0020.0002.1D30C] # TETRAGRAM FOR ASCENT
+1D30D ; [*0C6C.0020.0002.1D30D] # TETRAGRAM FOR OPPOSITION
+1D30E ; [*0C6D.0020.0002.1D30E] # TETRAGRAM FOR BRANCHING OUT
+1D30F ; [*0C6E.0020.0002.1D30F] # TETRAGRAM FOR DEFECTIVENESS OR DISTORTION
+1D310 ; [*0C6F.0020.0002.1D310] # TETRAGRAM FOR DIVERGENCE
+1D311 ; [*0C70.0020.0002.1D311] # TETRAGRAM FOR YOUTHFULNESS
+1D312 ; [*0C71.0020.0002.1D312] # TETRAGRAM FOR INCREASE
+1D313 ; [*0C72.0020.0002.1D313] # TETRAGRAM FOR PENETRATION
+1D314 ; [*0C73.0020.0002.1D314] # TETRAGRAM FOR REACH
+1D315 ; [*0C74.0020.0002.1D315] # TETRAGRAM FOR CONTACT
+1D316 ; [*0C75.0020.0002.1D316] # TETRAGRAM FOR HOLDING BACK
+1D317 ; [*0C76.0020.0002.1D317] # TETRAGRAM FOR WAITING
+1D318 ; [*0C77.0020.0002.1D318] # TETRAGRAM FOR FOLLOWING
+1D319 ; [*0C78.0020.0002.1D319] # TETRAGRAM FOR ADVANCE
+1D31A ; [*0C79.0020.0002.1D31A] # TETRAGRAM FOR RELEASE
+1D31B ; [*0C7A.0020.0002.1D31B] # TETRAGRAM FOR RESISTANCE
+1D31C ; [*0C7B.0020.0002.1D31C] # TETRAGRAM FOR EASE
+1D31D ; [*0C7C.0020.0002.1D31D] # TETRAGRAM FOR JOY
+1D31E ; [*0C7D.0020.0002.1D31E] # TETRAGRAM FOR CONTENTION
+1D31F ; [*0C7E.0020.0002.1D31F] # TETRAGRAM FOR ENDEAVOUR
+1D320 ; [*0C7F.0020.0002.1D320] # TETRAGRAM FOR DUTIES
+1D321 ; [*0C80.0020.0002.1D321] # TETRAGRAM FOR CHANGE
+1D322 ; [*0C81.0020.0002.1D322] # TETRAGRAM FOR DECISIVENESS
+1D323 ; [*0C82.0020.0002.1D323] # TETRAGRAM FOR BOLD RESOLUTION
+1D324 ; [*0C83.0020.0002.1D324] # TETRAGRAM FOR PACKING
+1D325 ; [*0C84.0020.0002.1D325] # TETRAGRAM FOR LEGION
+1D326 ; [*0C85.0020.0002.1D326] # TETRAGRAM FOR CLOSENESS
+1D327 ; [*0C86.0020.0002.1D327] # TETRAGRAM FOR KINSHIP
+1D328 ; [*0C87.0020.0002.1D328] # TETRAGRAM FOR GATHERING
+1D329 ; [*0C88.0020.0002.1D329] # TETRAGRAM FOR STRENGTH
+1D32A ; [*0C89.0020.0002.1D32A] # TETRAGRAM FOR PURITY
+1D32B ; [*0C8A.0020.0002.1D32B] # TETRAGRAM FOR FULLNESS
+1D32C ; [*0C8B.0020.0002.1D32C] # TETRAGRAM FOR RESIDENCE
+1D32D ; [*0C8C.0020.0002.1D32D] # TETRAGRAM FOR LAW OR MODEL
+1D32E ; [*0C8D.0020.0002.1D32E] # TETRAGRAM FOR RESPONSE
+1D32F ; [*0C8E.0020.0002.1D32F] # TETRAGRAM FOR GOING TO MEET
+1D330 ; [*0C8F.0020.0002.1D330] # TETRAGRAM FOR ENCOUNTERS
+1D331 ; [*0C90.0020.0002.1D331] # TETRAGRAM FOR STOVE
+1D332 ; [*0C91.0020.0002.1D332] # TETRAGRAM FOR GREATNESS
+1D333 ; [*0C92.0020.0002.1D333] # TETRAGRAM FOR ENLARGEMENT
+1D334 ; [*0C93.0020.0002.1D334] # TETRAGRAM FOR PATTERN
+1D335 ; [*0C94.0020.0002.1D335] # TETRAGRAM FOR RITUAL
+1D336 ; [*0C95.0020.0002.1D336] # TETRAGRAM FOR FLIGHT
+1D337 ; [*0C96.0020.0002.1D337] # TETRAGRAM FOR VASTNESS OR WASTING
+1D338 ; [*0C97.0020.0002.1D338] # TETRAGRAM FOR CONSTANCY
+1D339 ; [*0C98.0020.0002.1D339] # TETRAGRAM FOR MEASURE
+1D33A ; [*0C99.0020.0002.1D33A] # TETRAGRAM FOR ETERNITY
+1D33B ; [*0C9A.0020.0002.1D33B] # TETRAGRAM FOR UNITY
+1D33C ; [*0C9B.0020.0002.1D33C] # TETRAGRAM FOR DIMINISHMENT
+1D33D ; [*0C9C.0020.0002.1D33D] # TETRAGRAM FOR CLOSED MOUTH
+1D33E ; [*0C9D.0020.0002.1D33E] # TETRAGRAM FOR GUARDEDNESS
+1D33F ; [*0C9E.0020.0002.1D33F] # TETRAGRAM FOR GATHERING IN
+1D340 ; [*0C9F.0020.0002.1D340] # TETRAGRAM FOR MASSING
+1D341 ; [*0CA0.0020.0002.1D341] # TETRAGRAM FOR ACCUMULATION
+1D342 ; [*0CA1.0020.0002.1D342] # TETRAGRAM FOR EMBELLISHMENT
+1D343 ; [*0CA2.0020.0002.1D343] # TETRAGRAM FOR DOUBT
+1D344 ; [*0CA3.0020.0002.1D344] # TETRAGRAM FOR WATCH
+1D345 ; [*0CA4.0020.0002.1D345] # TETRAGRAM FOR SINKING
+1D346 ; [*0CA5.0020.0002.1D346] # TETRAGRAM FOR INNER
+1D347 ; [*0CA6.0020.0002.1D347] # TETRAGRAM FOR DEPARTURE
+1D348 ; [*0CA7.0020.0002.1D348] # TETRAGRAM FOR DARKENING
+1D349 ; [*0CA8.0020.0002.1D349] # TETRAGRAM FOR DIMMING
+1D34A ; [*0CA9.0020.0002.1D34A] # TETRAGRAM FOR EXHAUSTION
+1D34B ; [*0CAA.0020.0002.1D34B] # TETRAGRAM FOR SEVERANCE
+1D34C ; [*0CAB.0020.0002.1D34C] # TETRAGRAM FOR STOPPAGE
+1D34D ; [*0CAC.0020.0002.1D34D] # TETRAGRAM FOR HARDNESS
+1D34E ; [*0CAD.0020.0002.1D34E] # TETRAGRAM FOR COMPLETION
+1D34F ; [*0CAE.0020.0002.1D34F] # TETRAGRAM FOR CLOSURE
+1D350 ; [*0CAF.0020.0002.1D350] # TETRAGRAM FOR FAILURE
+1D351 ; [*0CB0.0020.0002.1D351] # TETRAGRAM FOR AGGRAVATION
+1D352 ; [*0CB1.0020.0002.1D352] # TETRAGRAM FOR COMPLIANCE
+1D353 ; [*0CB2.0020.0002.1D353] # TETRAGRAM FOR ON THE VERGE
+1D354 ; [*0CB3.0020.0002.1D354] # TETRAGRAM FOR DIFFICULTIES
+1D355 ; [*0CB4.0020.0002.1D355] # TETRAGRAM FOR LABOURING
+1D356 ; [*0CB5.0020.0002.1D356] # TETRAGRAM FOR FOSTERING
+1D369 ; [*0F90.0020.0002.1D369] # COUNTING ROD TENS DIGIT ONE
+1D36A ; [*0F91.0020.0002.1D36A] # COUNTING ROD TENS DIGIT TWO
+1D36B ; [*0F92.0020.0002.1D36B] # COUNTING ROD TENS DIGIT THREE
+1D36C ; [*0F93.0020.0002.1D36C] # COUNTING ROD TENS DIGIT FOUR
+1D36D ; [*0F94.0020.0002.1D36D] # COUNTING ROD TENS DIGIT FIVE
+1D36E ; [*0F95.0020.0002.1D36E] # COUNTING ROD TENS DIGIT SIX
+1D36F ; [*0F96.0020.0002.1D36F] # COUNTING ROD TENS DIGIT SEVEN
+1D370 ; [*0F97.0020.0002.1D370] # COUNTING ROD TENS DIGIT EIGHT
+1D371 ; [*0F98.0020.0002.1D371] # COUNTING ROD TENS DIGIT NINE
+1D6C1 ; [*04AE.0020.0005.1D6C1] # MATHEMATICAL BOLD NABLA; QQK
+1D6DB ; [*04AA.0020.0005.1D6DB] # MATHEMATICAL BOLD PARTIAL DIFFERENTIAL; QQK
+1D6FB ; [*04AE.0020.0005.1D6FB] # MATHEMATICAL ITALIC NABLA; QQK
+1D715 ; [*04AA.0020.0005.1D715] # MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL; QQK
+1D735 ; [*04AE.0020.0005.1D735] # MATHEMATICAL BOLD ITALIC NABLA; QQK
+1D74F ; [*04AA.0020.0005.1D74F] # MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL; QQK
+1D76F ; [*04AE.0020.0005.1D76F] # MATHEMATICAL SANS-SERIF BOLD NABLA; QQK
+1D789 ; [*04AA.0020.0005.1D789] # MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL; QQK
+1D7A9 ; [*04AE.0020.0005.1D7A9] # MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA; QQK
+1D7C3 ; [*04AA.0020.0005.1D7C3] # MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL; QQK
+0332 ; [.0000.0021.0002.0332] # COMBINING LOW LINE
+0313 ; [.0000.0022.0002.0313] # COMBINING COMMA ABOVE
+0343 ; [.0000.0022.0002.0343] # COMBINING GREEK KORONIS; QQC
+0314 ; [.0000.002A.0002.0314] # COMBINING REVERSED COMMA ABOVE
+0301 ; [.0000.0032.0002.0301] # COMBINING ACUTE ACCENT
+0341 ; [.0000.0032.0002.0341] # COMBINING ACUTE TONE MARK; QQC
+0300 ; [.0000.0035.0002.0300] # COMBINING GRAVE ACCENT
+0340 ; [.0000.0035.0002.0340] # COMBINING GRAVE TONE MARK; QQC
+0306 ; [.0000.0037.0002.0306] # COMBINING BREVE
+0302 ; [.0000.003C.0002.0302] # COMBINING CIRCUMFLEX ACCENT
+030C ; [.0000.0041.0002.030C] # COMBINING CARON
+030A ; [.0000.0043.0002.030A] # COMBINING RING ABOVE
+0342 ; [.0000.0045.0002.0342] # COMBINING GREEK PERISPOMENI
+0308 ; [.0000.0047.0002.0308] # COMBINING DIAERESIS
+0344 ; [.0000.0047.0002.0308][.0000.0032.0002.0301] # COMBINING GREEK DIALYTIKA TONOS; QQCM
+030B ; [.0000.004D.0002.030B] # COMBINING DOUBLE ACUTE ACCENT
+0303 ; [.0000.004E.0002.0303] # COMBINING TILDE
+0307 ; [.0000.0052.0002.0307] # COMBINING DOT ABOVE
+0338 ; [.0000.0054.0002.0338] # COMBINING LONG SOLIDUS OVERLAY
+0327 ; [.0000.0056.0002.0327] # COMBINING CEDILLA
+0328 ; [.0000.0059.0002.0328] # COMBINING OGONEK
+0304 ; [.0000.005B.0002.0304] # COMBINING MACRON
+0305 ; [.0000.005F.0002.0305] # COMBINING OVERLINE
+0309 ; [.0000.0060.0002.0309] # COMBINING HOOK ABOVE
+030D ; [.0000.0061.0002.030D] # COMBINING VERTICAL LINE ABOVE
+030E ; [.0000.0062.0002.030E] # COMBINING DOUBLE VERTICAL LINE ABOVE
+030F ; [.0000.0063.0002.030F] # COMBINING DOUBLE GRAVE ACCENT
+0310 ; [.0000.0064.0002.0310] # COMBINING CANDRABINDU
+0311 ; [.0000.0065.0002.0311] # COMBINING INVERTED BREVE
+0312 ; [.0000.0066.0002.0312] # COMBINING TURNED COMMA ABOVE
+0315 ; [.0000.0067.0002.0315] # COMBINING COMMA ABOVE RIGHT
+0316 ; [.0000.0068.0002.0316] # COMBINING GRAVE ACCENT BELOW
+0317 ; [.0000.0069.0002.0317] # COMBINING ACUTE ACCENT BELOW
+0318 ; [.0000.006A.0002.0318] # COMBINING LEFT TACK BELOW
+0319 ; [.0000.006B.0002.0319] # COMBINING RIGHT TACK BELOW
+031A ; [.0000.006C.0002.031A] # COMBINING LEFT ANGLE ABOVE
+031B ; [.0000.006D.0002.031B] # COMBINING HORN
+031C ; [.0000.0073.0002.031C] # COMBINING LEFT HALF RING BELOW
+031D ; [.0000.0074.0002.031D] # COMBINING UP TACK BELOW
+031E ; [.0000.0075.0002.031E] # COMBINING DOWN TACK BELOW
+031F ; [.0000.0076.0002.031F] # COMBINING PLUS SIGN BELOW
+0320 ; [.0000.0077.0002.0320] # COMBINING MINUS SIGN BELOW
+0321 ; [.0000.0078.0002.0321] # COMBINING PALATALIZED HOOK BELOW
+0322 ; [.0000.0079.0002.0322] # COMBINING RETROFLEX HOOK BELOW
+0323 ; [.0000.007A.0002.0323] # COMBINING DOT BELOW
+0324 ; [.0000.007F.0002.0324] # COMBINING DIAERESIS BELOW
+0325 ; [.0000.0080.0002.0325] # COMBINING RING BELOW
+0326 ; [.0000.0081.0002.0326] # COMBINING COMMA BELOW
+0329 ; [.0000.0082.0002.0329] # COMBINING VERTICAL LINE BELOW
+032A ; [.0000.0083.0002.032A] # COMBINING BRIDGE BELOW
+032B ; [.0000.0084.0002.032B] # COMBINING INVERTED DOUBLE ARCH BELOW
+032C ; [.0000.0085.0002.032C] # COMBINING CARON BELOW
+032D ; [.0000.0086.0002.032D] # COMBINING CIRCUMFLEX ACCENT BELOW
+032E ; [.0000.0087.0002.032E] # COMBINING BREVE BELOW
+032F ; [.0000.0088.0002.032F] # COMBINING INVERTED BREVE BELOW
+0330 ; [.0000.0089.0002.0330] # COMBINING TILDE BELOW
+0331 ; [.0000.008A.0002.0331] # COMBINING MACRON BELOW
+0333 ; [.0000.008B.0002.0333] # COMBINING DOUBLE LOW LINE
+0334 ; [.0000.008C.0002.0334] # COMBINING TILDE OVERLAY
+0335 ; [.0000.008D.0002.0335] # COMBINING SHORT STROKE OVERLAY
+0336 ; [.0000.008E.0002.0336] # COMBINING LONG STROKE OVERLAY
+0337 ; [.0000.008F.0002.0337] # COMBINING SHORT SOLIDUS OVERLAY
+0339 ; [.0000.0090.0002.0339] # COMBINING RIGHT HALF RING BELOW
+033A ; [.0000.0091.0002.033A] # COMBINING INVERTED BRIDGE BELOW
+033B ; [.0000.0092.0002.033B] # COMBINING SQUARE BELOW
+033C ; [.0000.0093.0002.033C] # COMBINING SEAGULL BELOW
+033D ; [.0000.0094.0002.033D] # COMBINING X ABOVE
+033E ; [.0000.0095.0002.033E] # COMBINING VERTICAL TILDE
+033F ; [.0000.0096.0002.033F] # COMBINING DOUBLE OVERLINE
+0345 ; [.0000.0097.0002.0345] # COMBINING GREEK YPOGEGRAMMENI
+0346 ; [.0000.0098.0002.0346] # COMBINING BRIDGE ABOVE
+0347 ; [.0000.0099.0002.0347] # COMBINING EQUALS SIGN BELOW
+0348 ; [.0000.009A.0002.0348] # COMBINING DOUBLE VERTICAL LINE BELOW
+0349 ; [.0000.009B.0002.0349] # COMBINING LEFT ANGLE BELOW
+034A ; [.0000.009C.0002.034A] # COMBINING NOT TILDE ABOVE
+034B ; [.0000.009D.0002.034B] # COMBINING HOMOTHETIC ABOVE
+034C ; [.0000.009E.0002.034C] # COMBINING ALMOST EQUAL TO ABOVE
+034D ; [.0000.009F.0002.034D] # COMBINING LEFT RIGHT ARROW BELOW
+034E ; [.0000.00A0.0002.034E] # COMBINING UPWARDS ARROW BELOW
+0350 ; [.0000.00A1.0002.0350] # COMBINING RIGHT ARROWHEAD ABOVE
+0351 ; [.0000.00A2.0002.0351] # COMBINING LEFT HALF RING ABOVE
+0352 ; [.0000.00A3.0002.0352] # COMBINING FERMATA
+0353 ; [.0000.00A4.0002.0353] # COMBINING X BELOW
+0354 ; [.0000.00A5.0002.0354] # COMBINING LEFT ARROWHEAD BELOW
+0355 ; [.0000.00A6.0002.0355] # COMBINING RIGHT ARROWHEAD BELOW
+0356 ; [.0000.00A7.0002.0356] # COMBINING RIGHT ARROWHEAD AND UP ARROWHEAD BELOW
+0357 ; [.0000.00A8.0002.0357] # COMBINING RIGHT HALF RING ABOVE
+0358 ; [.0000.00A9.0002.0358] # COMBINING DOT ABOVE RIGHT
+0359 ; [.0000.00AA.0002.0359] # COMBINING ASTERISK BELOW
+035A ; [.0000.00AB.0002.035A] # COMBINING DOUBLE RING BELOW
+035B ; [.0000.00AC.0002.035B] # COMBINING ZIGZAG ABOVE
+035C ; [.0000.00AD.0002.035C] # COMBINING DOUBLE BREVE BELOW
+035D ; [.0000.00AE.0002.035D] # COMBINING DOUBLE BREVE
+035E ; [.0000.00AF.0002.035E] # COMBINING DOUBLE MACRON
+035F ; [.0000.00B0.0002.035F] # COMBINING DOUBLE MACRON BELOW
+0360 ; [.0000.00B1.0002.0360] # COMBINING DOUBLE TILDE
+FE22 ; [.0000.00B1.0002.FE22] # COMBINING DOUBLE TILDE LEFT HALF; QQC
+0361 ; [.0000.00B2.0002.0361] # COMBINING DOUBLE INVERTED BREVE
+FE20 ; [.0000.00B2.0002.FE20] # COMBINING LIGATURE LEFT HALF; QQC
+0362 ; [.0000.00B3.0002.0362] # COMBINING DOUBLE RIGHTWARDS ARROW BELOW
+1DC0 ; [.0000.00B4.0002.1DC0] # COMBINING DOTTED GRAVE ACCENT
+1DC1 ; [.0000.00B5.0002.1DC1] # COMBINING DOTTED ACUTE ACCENT
+1DC2 ; [.0000.00B6.0002.1DC2] # COMBINING SNAKE BELOW
+1DC3 ; [.0000.00B7.0002.1DC3] # COMBINING SUSPENSION MARK
+1DC4 ; [.0000.00B8.0002.1DC4] # COMBINING MACRON-ACUTE
+1DC5 ; [.0000.00B9.0002.1DC5] # COMBINING GRAVE-MACRON
+1DC6 ; [.0000.00BA.0002.1DC6] # COMBINING MACRON-GRAVE
+1DC7 ; [.0000.00BB.0002.1DC7] # COMBINING ACUTE-MACRON
+1DC8 ; [.0000.00BC.0002.1DC8] # COMBINING GRAVE-ACUTE-GRAVE
+1DC9 ; [.0000.00BD.0002.1DC9] # COMBINING ACUTE-GRAVE-ACUTE
+1DCA ; [.0000.00BE.0002.1DCA] # COMBINING LATIN SMALL LETTER R BELOW
+1DFE ; [.0000.00BF.0002.1DFE] # COMBINING LEFT ARROWHEAD ABOVE
+1DFF ; [.0000.00C0.0002.1DFF] # COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW
+0483 ; [.0000.00C1.0002.0483] # COMBINING CYRILLIC TITLO
+0484 ; [.0000.00C2.0002.0484] # COMBINING CYRILLIC PALATALIZATION
+0485 ; [.0000.00C3.0002.0485] # COMBINING CYRILLIC DASIA PNEUMATA
+0486 ; [.0000.00C4.0002.0486] # COMBINING CYRILLIC PSILI PNEUMATA
+05B0 ; [.0000.00C5.0002.05B0] # HEBREW POINT SHEVA
+05B1 ; [.0000.00C6.0002.05B1] # HEBREW POINT HATAF SEGOL
+05B2 ; [.0000.00C7.0002.05B2] # HEBREW POINT HATAF PATAH
+05B3 ; [.0000.00C8.0002.05B3] # HEBREW POINT HATAF QAMATS
+05B4 ; [.0000.00C9.0002.05B4] # HEBREW POINT HIRIQ
+05B5 ; [.0000.00CA.0002.05B5] # HEBREW POINT TSERE
+05B6 ; [.0000.00CB.0002.05B6] # HEBREW POINT SEGOL
+05B7 ; [.0000.00CC.0002.05B7] # HEBREW POINT PATAH
+05B8 ; [.0000.00CD.0002.05B8] # HEBREW POINT QAMATS
+05C7 ; [.0000.00CE.0002.05C7] # HEBREW POINT QAMATS QATAN
+05B9 ; [.0000.00CF.0002.05B9] # HEBREW POINT HOLAM
+05BA ; [.0000.00D0.0002.05BA] # HEBREW POINT HOLAM HASER FOR VAV
+05BB ; [.0000.00D1.0002.05BB] # HEBREW POINT QUBUTS
+05C2 ; [.0000.00D2.0002.05C2] # HEBREW POINT SIN DOT
+05C1 ; [.0000.00D3.0002.05C1] # HEBREW POINT SHIN DOT
+05BC ; [.0000.00D4.0002.05BC] # HEBREW POINT DAGESH OR MAPIQ
+05BF ; [.0000.00D7.0002.05BF] # HEBREW POINT RAFE
+FB1E ; [.0000.00D8.0002.FB1E] # HEBREW POINT JUDEO-SPANISH VARIKA
+064B ; [.0000.00D9.0002.064B] # ARABIC FATHATAN
+FE71 ; [.0000.00D9.0018.FE71] # ARABIC TATWEEL WITH FATHATAN ABOVE; QQK
+FE70 ; [.0000.00D9.001A.FE70] # ARABIC FATHATAN ISOLATED FORM; QQK
+064C ; [.0000.00DA.0002.064C] # ARABIC DAMMATAN
+FE72 ; [.0000.00DA.001A.FE72] # ARABIC DAMMATAN ISOLATED FORM; QQK
+064D ; [.0000.00DC.0002.064D] # ARABIC KASRATAN
+FE74 ; [.0000.00DC.001A.FE74] # ARABIC KASRATAN ISOLATED FORM; QQK
+064E ; [.0000.00DE.0002.064E] # ARABIC FATHA
+FE77 ; [.0000.00DE.0018.FE77] # ARABIC FATHA MEDIAL FORM; QQK
+FE76 ; [.0000.00DE.001A.FE76] # ARABIC FATHA ISOLATED FORM; QQK
+064F ; [.0000.00E0.0002.064F] # ARABIC DAMMA
+FE79 ; [.0000.00E0.0018.FE79] # ARABIC DAMMA MEDIAL FORM; QQK
+FE78 ; [.0000.00E0.001A.FE78] # ARABIC DAMMA ISOLATED FORM; QQK
+0650 ; [.0000.00E2.0002.0650] # ARABIC KASRA
+FE7B ; [.0000.00E2.0018.FE7B] # ARABIC KASRA MEDIAL FORM; QQK
+FE7A ; [.0000.00E2.001A.FE7A] # ARABIC KASRA ISOLATED FORM; QQK
+0651 ; [.0000.00E4.0002.0651] # ARABIC SHADDA
+FCF2 ; [.0000.00E4.0018.FCF2] # ARABIC LIGATURE SHADDA WITH FATHA MEDIAL FORM; QQKM
+FCF3 ; [.0000.00E4.0018.FCF3] # ARABIC LIGATURE SHADDA WITH DAMMA MEDIAL FORM; QQKM
+FCF4 ; [.0000.00E4.0018.FCF4] # ARABIC LIGATURE SHADDA WITH KASRA MEDIAL FORM; QQKM
+FE7D ; [.0000.00E4.0018.FE7D] # ARABIC SHADDA MEDIAL FORM; QQK
+FC5E ; [.0000.00E4.001A.FC5E] # ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM; QQKM
+FC5F ; [.0000.00E4.001A.FC5F] # ARABIC LIGATURE SHADDA WITH KASRATAN ISOLATED FORM; QQKM
+FC60 ; [.0000.00E4.001A.FC60] # ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM; QQKM
+FC61 ; [.0000.00E4.001A.FC61] # ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM; QQKM
+FC62 ; [.0000.00E4.001A.FC62] # ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM; QQKM
+FE7C ; [.0000.00E4.001A.FE7C] # ARABIC SHADDA ISOLATED FORM; QQK
+FC63 ; [.0000.00E4.001A.FC63][.0000.00F3.001A.FC63] # ARABIC LIGATURE SHADDA WITH SUPERSCRIPT ALEF ISOLATED FORM; QQKN
+0652 ; [.0000.00E6.0002.0652] # ARABIC SUKUN
+FE7F ; [.0000.00E6.0018.FE7F] # ARABIC SUKUN MEDIAL FORM; QQK
+FE7E ; [.0000.00E6.001A.FE7E] # ARABIC SUKUN ISOLATED FORM; QQK
+0653 ; [.0000.00E7.0002.0653] # ARABIC MADDAH ABOVE
+0654 ; [.0000.00E8.0002.0654] # ARABIC HAMZA ABOVE
+0655 ; [.0000.00E9.0002.0655] # ARABIC HAMZA BELOW
+0656 ; [.0000.00EA.0002.0656] # ARABIC SUBSCRIPT ALEF
+0657 ; [.0000.00EB.0002.0657] # ARABIC INVERTED DAMMA
+0658 ; [.0000.00EC.0002.0658] # ARABIC MARK NOON GHUNNA
+0659 ; [.0000.00ED.0002.0659] # ARABIC ZWARAKAY
+065A ; [.0000.00EE.0002.065A] # ARABIC VOWEL SIGN SMALL V ABOVE
+065B ; [.0000.00EF.0002.065B] # ARABIC VOWEL SIGN INVERTED SMALL V ABOVE
+065C ; [.0000.00F0.0002.065C] # ARABIC VOWEL SIGN DOT BELOW
+065D ; [.0000.00F1.0002.065D] # ARABIC REVERSED DAMMA
+065E ; [.0000.00F2.0002.065E] # ARABIC FATHA WITH TWO DOTS
+0670 ; [.0000.00F3.0002.0670] # ARABIC LETTER SUPERSCRIPT ALEF
+0711 ; [.0000.00F4.0002.0711] # SYRIAC LETTER SUPERSCRIPT ALAPH
+0730 ; [.0000.00F5.0002.0730] # SYRIAC PTHAHA ABOVE
+0731 ; [.0000.00F6.0002.0731] # SYRIAC PTHAHA BELOW
+0732 ; [.0000.00F7.0002.0732] # SYRIAC PTHAHA DOTTED
+0733 ; [.0000.00F8.0002.0733] # SYRIAC ZQAPHA ABOVE
+0734 ; [.0000.00F9.0002.0734] # SYRIAC ZQAPHA BELOW
+0735 ; [.0000.00FA.0002.0735] # SYRIAC ZQAPHA DOTTED
+0736 ; [.0000.00FB.0002.0736] # SYRIAC RBASA ABOVE
+0737 ; [.0000.00FC.0002.0737] # SYRIAC RBASA BELOW
+0738 ; [.0000.00FD.0002.0738] # SYRIAC DOTTED ZLAMA HORIZONTAL
+0739 ; [.0000.00FE.0002.0739] # SYRIAC DOTTED ZLAMA ANGULAR
+073A ; [.0000.00FF.0002.073A] # SYRIAC HBASA ABOVE
+073B ; [.0000.0100.0002.073B] # SYRIAC HBASA BELOW
+073C ; [.0000.0101.0002.073C] # SYRIAC HBASA-ESASA DOTTED
+073D ; [.0000.0102.0002.073D] # SYRIAC ESASA ABOVE
+073E ; [.0000.0103.0002.073E] # SYRIAC ESASA BELOW
+073F ; [.0000.0104.0002.073F] # SYRIAC RWAHA
+0740 ; [.0000.0105.0002.0740] # SYRIAC FEMININE DOT
+0741 ; [.0000.0106.0002.0741] # SYRIAC QUSHSHAYA
+0742 ; [.0000.0107.0002.0742] # SYRIAC RUKKAKHA
+0743 ; [.0000.0108.0002.0743] # SYRIAC TWO VERTICAL DOTS ABOVE
+0744 ; [.0000.0109.0002.0744] # SYRIAC TWO VERTICAL DOTS BELOW
+0745 ; [.0000.010A.0002.0745] # SYRIAC THREE DOTS ABOVE
+0746 ; [.0000.010B.0002.0746] # SYRIAC THREE DOTS BELOW
+0747 ; [.0000.010C.0002.0747] # SYRIAC OBLIQUE LINE ABOVE
+0748 ; [.0000.010D.0002.0748] # SYRIAC OBLIQUE LINE BELOW
+0749 ; [.0000.010E.0002.0749] # SYRIAC MUSIC
+074A ; [.0000.010F.0002.074A] # SYRIAC BARREKH
+07EB ; [.0000.0110.0002.07EB] # NKO COMBINING SHORT HIGH TONE
+07EC ; [.0000.0111.0002.07EC] # NKO COMBINING SHORT LOW TONE
+07ED ; [.0000.0112.0002.07ED] # NKO COMBINING SHORT RISING TONE
+07EE ; [.0000.0113.0002.07EE] # NKO COMBINING LONG DESCENDING TONE
+07EF ; [.0000.0114.0002.07EF] # NKO COMBINING LONG HIGH TONE
+07F0 ; [.0000.0115.0002.07F0] # NKO COMBINING LONG LOW TONE
+07F1 ; [.0000.0116.0002.07F1] # NKO COMBINING LONG RISING TONE
+07F2 ; [.0000.0117.0002.07F2] # NKO COMBINING NASALIZATION MARK
+07F3 ; [.0000.0118.0002.07F3] # NKO COMBINING DOUBLE DOT ABOVE
+093C ; [.0000.0119.0002.093C] # DEVANAGARI SIGN NUKTA
+0901 ; [.0000.011A.0002.0901] # DEVANAGARI SIGN CANDRABINDU
+0902 ; [.0000.011B.0002.0902] # DEVANAGARI SIGN ANUSVARA
+0903 ; [.0000.011C.0002.0903] # DEVANAGARI SIGN VISARGA
+0951 ; [.0000.011D.0002.0951] # DEVANAGARI STRESS SIGN UDATTA
+0952 ; [.0000.011E.0002.0952] # DEVANAGARI STRESS SIGN ANUDATTA
+0953 ; [.0000.011F.0002.0953] # DEVANAGARI GRAVE ACCENT
+0954 ; [.0000.0120.0002.0954] # DEVANAGARI ACUTE ACCENT
+09BC ; [.0000.0121.0002.09BC] # BENGALI SIGN NUKTA
+0981 ; [.0000.0122.0002.0981] # BENGALI SIGN CANDRABINDU
+0982 ; [.0000.0123.0002.0982] # BENGALI SIGN ANUSVARA
+0983 ; [.0000.0124.0002.0983] # BENGALI SIGN VISARGA
+0A3C ; [.0000.0125.0002.0A3C] # GURMUKHI SIGN NUKTA
+0A01 ; [.0000.0126.0002.0A01] # GURMUKHI SIGN ADAK BINDI
+0A02 ; [.0000.0127.0002.0A02] # GURMUKHI SIGN BINDI
+0A03 ; [.0000.0128.0002.0A03] # GURMUKHI SIGN VISARGA
+0A70 ; [.0000.0129.0002.0A70] # GURMUKHI TIPPI
+0A71 ; [.0000.012A.0002.0A71] # GURMUKHI ADDAK
+0ABC ; [.0000.012B.0002.0ABC] # GUJARATI SIGN NUKTA
+0A81 ; [.0000.012C.0002.0A81] # GUJARATI SIGN CANDRABINDU
+0A82 ; [.0000.012D.0002.0A82] # GUJARATI SIGN ANUSVARA
+0A83 ; [.0000.012E.0002.0A83] # GUJARATI SIGN VISARGA
+0B3C ; [.0000.012F.0002.0B3C] # ORIYA SIGN NUKTA
+0B01 ; [.0000.0130.0002.0B01] # ORIYA SIGN CANDRABINDU
+0B02 ; [.0000.0131.0002.0B02] # ORIYA SIGN ANUSVARA
+0B03 ; [.0000.0132.0002.0B03] # ORIYA SIGN VISARGA
+0B82 ; [.0000.0133.0002.0B82] # TAMIL SIGN ANUSVARA
+0C01 ; [.0000.0134.0002.0C01] # TELUGU SIGN CANDRABINDU
+0C02 ; [.0000.0135.0002.0C02] # TELUGU SIGN ANUSVARA
+0C03 ; [.0000.0136.0002.0C03] # TELUGU SIGN VISARGA
+0CBC ; [.0000.0137.0002.0CBC] # KANNADA SIGN NUKTA
+0C82 ; [.0000.0138.0002.0C82] # KANNADA SIGN ANUSVARA
+0C83 ; [.0000.0139.0002.0C83] # KANNADA SIGN VISARGA
+0D02 ; [.0000.013A.0002.0D02] # MALAYALAM SIGN ANUSVARA
+0D03 ; [.0000.013B.0002.0D03] # MALAYALAM SIGN VISARGA
+0D82 ; [.0000.013C.0002.0D82] # SINHALA SIGN ANUSVARAYA
+0D83 ; [.0000.013D.0002.0D83] # SINHALA SIGN VISARGAYA
+1B34 ; [.0000.013E.0002.1B34] # BALINESE SIGN REREKAN
+1B00 ; [.0000.013F.0002.1B00] # BALINESE SIGN ULU RICEM
+1B01 ; [.0000.0140.0002.1B01] # BALINESE SIGN ULU CANDRA
+1B02 ; [.0000.0141.0002.1B02] # BALINESE SIGN CECEK
+1B03 ; [.0000.0142.0002.1B03] # BALINESE SIGN SURANG
+1B04 ; [.0000.0143.0002.1B04] # BALINESE SIGN BISAH
+A80B ; [.0000.0144.0002.A80B] # SYLOTI NAGRI SIGN ANUSVARA
+10A0D ; [.0000.0145.0002.10A0D] # KHAROSHTHI SIGN DOUBLE RING BELOW
+10A0E ; [.0000.0146.0002.10A0E] # KHAROSHTHI SIGN ANUSVARA
+10A0F ; [.0000.0147.0002.10A0F] # KHAROSHTHI SIGN VISARGA
+10A38 ; [.0000.0148.0002.10A38] # KHAROSHTHI SIGN BAR ABOVE
+10A39 ; [.0000.0149.0002.10A39] # KHAROSHTHI SIGN CAUDA
+10A3A ; [.0000.014A.0002.10A3A] # KHAROSHTHI SIGN DOT BELOW
+0E4E ; [.0000.014B.0002.0E4E] # THAI CHARACTER YAMAKKAN
+0E47 ; [.0000.014C.0002.0E47] # THAI CHARACTER MAITAIKHU
+0E48 ; [.0000.014D.0002.0E48] # THAI CHARACTER MAI EK
+0E49 ; [.0000.014E.0002.0E49] # THAI CHARACTER MAI THO
+0E4A ; [.0000.014F.0002.0E4A] # THAI CHARACTER MAI TRI
+0E4B ; [.0000.0150.0002.0E4B] # THAI CHARACTER MAI CHATTAWA
+0E4C ; [.0000.0151.0002.0E4C] # THAI CHARACTER THANTHAKHAT
+0E4D ; [.0000.0152.0002.0E4D] # THAI CHARACTER NIKHAHIT
+0EC8 ; [.0000.0153.0002.0EC8] # LAO TONE MAI EK
+0EC9 ; [.0000.0154.0002.0EC9] # LAO TONE MAI THO
+0ECA ; [.0000.0155.0002.0ECA] # LAO TONE MAI TI
+0ECB ; [.0000.0156.0002.0ECB] # LAO TONE MAI CATAWA
+0ECC ; [.0000.0157.0002.0ECC] # LAO CANCELLATION MARK
+0ECD ; [.0000.0158.0002.0ECD] # LAO NIGGAHITA
+0F39 ; [.0000.0159.0002.0F39] # TIBETAN MARK TSA -PHRU
+0F7E ; [.0000.015A.0002.0F7E] # TIBETAN SIGN RJES SU NGA RO
+0F7F ; [.0000.015B.0002.0F7F] # TIBETAN SIGN RNAM BCAD
+1036 ; [.0000.015C.0002.1036] # MYANMAR SIGN ANUSVARA
+1037 ; [.0000.015D.0002.1037] # MYANMAR SIGN DOT BELOW
+1038 ; [.0000.015E.0002.1038] # MYANMAR SIGN VISARGA
+135F ; [.0000.015F.0002.135F] # ETHIOPIC COMBINING GEMINATION MARK
+17C6 ; [.0000.0160.0002.17C6] # KHMER SIGN NIKAHIT
+17C7 ; [.0000.0161.0002.17C7] # KHMER SIGN REAHMUK
+17C8 ; [.0000.0162.0002.17C8] # KHMER SIGN YUUKALEAPINTU
+17C9 ; [.0000.0163.0002.17C9] # KHMER SIGN MUUSIKATOAN
+17CA ; [.0000.0164.0002.17CA] # KHMER SIGN TRIISAP
+17CB ; [.0000.0165.0002.17CB] # KHMER SIGN BANTOC
+17CC ; [.0000.0166.0002.17CC] # KHMER SIGN ROBAT
+17CD ; [.0000.0167.0002.17CD] # KHMER SIGN TOANDAKHIAT
+17CE ; [.0000.0168.0002.17CE] # KHMER SIGN KAKABAT
+17CF ; [.0000.0169.0002.17CF] # KHMER SIGN AHSDA
+17D0 ; [.0000.016A.0002.17D0] # KHMER SIGN SAMYOK SANNYA
+17D1 ; [.0000.016B.0002.17D1] # KHMER SIGN VIRIAM
+17D3 ; [.0000.016C.0002.17D3] # KHMER SIGN BATHAMASAT
+17DD ; [.0000.016D.0002.17DD] # KHMER SIGN ATTHACAN
+1939 ; [.0000.016E.0002.1939] # LIMBU SIGN MUKPHRENG
+193A ; [.0000.016F.0002.193A] # LIMBU SIGN KEMPHRENG
+193B ; [.0000.0170.0002.193B] # LIMBU SIGN SA-I
+302A ; [.0000.0171.0002.302A] # IDEOGRAPHIC LEVEL TONE MARK
+302B ; [.0000.0172.0002.302B] # IDEOGRAPHIC RISING TONE MARK
+302C ; [.0000.0173.0002.302C] # IDEOGRAPHIC DEPARTING TONE MARK
+302D ; [.0000.0174.0002.302D] # IDEOGRAPHIC ENTERING TONE MARK
+302E ; [.0000.0175.0002.302E] # HANGUL SINGLE DOT TONE MARK
+302F ; [.0000.0176.0002.302F] # HANGUL DOUBLE DOT TONE MARK
+3099 ; [.0000.0177.0002.3099] # COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+FF9E ; [.0000.0177.0012.FF9E] # HALFWIDTH KATAKANA VOICED SOUND MARK; QQK
+309A ; [.0000.0178.0002.309A] # COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+FF9F ; [.0000.0178.0012.FF9F] # HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK; QQK
+20D0 ; [.0000.0179.0002.20D0] # COMBINING LEFT HARPOON ABOVE
+20D1 ; [.0000.017A.0002.20D1] # COMBINING RIGHT HARPOON ABOVE
+20D2 ; [.0000.017B.0002.20D2] # COMBINING LONG VERTICAL LINE OVERLAY
+20D3 ; [.0000.017C.0002.20D3] # COMBINING SHORT VERTICAL LINE OVERLAY
+20D4 ; [.0000.017D.0002.20D4] # COMBINING ANTICLOCKWISE ARROW ABOVE
+20D5 ; [.0000.017E.0002.20D5] # COMBINING CLOCKWISE ARROW ABOVE
+20D6 ; [.0000.017F.0002.20D6] # COMBINING LEFT ARROW ABOVE
+20D7 ; [.0000.0180.0002.20D7] # COMBINING RIGHT ARROW ABOVE
+20D8 ; [.0000.0181.0002.20D8] # COMBINING RING OVERLAY
+20D9 ; [.0000.0182.0002.20D9] # COMBINING CLOCKWISE RING OVERLAY
+20DA ; [.0000.0183.0002.20DA] # COMBINING ANTICLOCKWISE RING OVERLAY
+20DB ; [.0000.0184.0002.20DB] # COMBINING THREE DOTS ABOVE
+20DC ; [.0000.0185.0002.20DC] # COMBINING FOUR DOTS ABOVE
+20DD ; [.0000.0186.0002.20DD] # COMBINING ENCLOSING CIRCLE
+20DE ; [.0000.0187.0002.20DE] # COMBINING ENCLOSING SQUARE
+20DF ; [.0000.0188.0002.20DF] # COMBINING ENCLOSING DIAMOND
+20E0 ; [.0000.0189.0002.20E0] # COMBINING ENCLOSING CIRCLE BACKSLASH
+20E1 ; [.0000.018A.0002.20E1] # COMBINING LEFT RIGHT ARROW ABOVE
+20E2 ; [.0000.018B.0002.20E2] # COMBINING ENCLOSING SCREEN
+20E3 ; [.0000.018C.0002.20E3] # COMBINING ENCLOSING KEYCAP
+20E4 ; [.0000.018D.0002.20E4] # COMBINING ENCLOSING UPWARD POINTING TRIANGLE
+20E5 ; [.0000.018E.0002.20E5] # COMBINING REVERSE SOLIDUS OVERLAY
+20E6 ; [.0000.018F.0002.20E6] # COMBINING DOUBLE VERTICAL STROKE OVERLAY
+20E7 ; [.0000.0190.0002.20E7] # COMBINING ANNUITY SYMBOL
+20E8 ; [.0000.0191.0002.20E8] # COMBINING TRIPLE UNDERDOT
+20E9 ; [.0000.0192.0002.20E9] # COMBINING WIDE BRIDGE ABOVE
+20EA ; [.0000.0193.0002.20EA] # COMBINING LEFTWARDS ARROW OVERLAY
+20EB ; [.0000.0194.0002.20EB] # COMBINING LONG DOUBLE SOLIDUS OVERLAY
+20EC ; [.0000.0195.0002.20EC] # COMBINING RIGHTWARDS HARPOON WITH BARB DOWNWARDS
+20ED ; [.0000.0196.0002.20ED] # COMBINING LEFTWARDS HARPOON WITH BARB DOWNWARDS
+20EE ; [.0000.0197.0002.20EE] # COMBINING LEFT ARROW BELOW
+20EF ; [.0000.0198.0002.20EF] # COMBINING RIGHT ARROW BELOW
+02D0 ; [.0F99.0020.0002.02D0] # MODIFIER LETTER TRIANGULAR COLON
+02D1 ; [.0F9A.0020.0002.02D1] # MODIFIER LETTER HALF TRIANGULAR COLON
+0E46 ; [.0F9B.0020.0002.0E46] # THAI CHARACTER MAIYAMOK
+0EC6 ; [.0F9C.0020.0002.0EC6] # LAO KO LA
+3005 ; [.0F9D.0020.0002.3005] # IDEOGRAPHIC ITERATION MARK
+303B ; [.0F9E.0020.0002.303B] # VERTICAL IDEOGRAPHIC ITERATION MARK
+3031 ; [.0F9F.0020.0002.3031] # VERTICAL KANA REPEAT MARK
+3032 ; [.0F9F.0020.0002.3031][.0000.0177.0002.3099] # VERTICAL KANA REPEAT WITH VOICED SOUND MARK; QQCM
+3033 ; [.0FA0.0020.0002.3033] # VERTICAL KANA REPEAT MARK UPPER HALF
+3034 ; [.0FA0.0020.0002.3033][.0000.0177.0002.3099] # VERTICAL KANA REPEAT WITH VOICED SOUND MARK UPPER HALF; QQCM
+3035 ; [.0FA1.0020.0002.3035] # VERTICAL KANA REPEAT MARK LOWER HALF
+309D ; [.0FA2.0020.0002.309D] # HIRAGANA ITERATION MARK
+309E ; [.0FA2.0020.0002.309D][.0000.0177.0002.3099] # HIRAGANA VOICED ITERATION MARK; QQCM
+30FC ; [.0FA3.0020.0002.30FC] # KATAKANA-HIRAGANA PROLONGED SOUND MARK
+FF70 ; [.0FA3.0020.0012.FF70] # HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK; QQK
+30FD ; [.0FA4.0020.0002.30FD] # KATAKANA ITERATION MARK
+30FE ; [.0FA4.0020.0002.30FD][.0000.0177.0002.3099] # KATAKANA VOICED ITERATION MARK; QQCM
+00A4 ; [.0FA5.0020.0002.00A4] # CURRENCY SIGN
+00A2 ; [.0FA6.0020.0002.00A2] # CENT SIGN
+FFE0 ; [.0FA6.0020.0003.FFE0] # FULLWIDTH CENT SIGN; QQK
+0024 ; [.0FA7.0020.0002.0024] # DOLLAR SIGN
+FF04 ; [.0FA7.0020.0003.FF04] # FULLWIDTH DOLLAR SIGN; QQK
+FE69 ; [.0FA7.0020.000F.FE69] # SMALL DOLLAR SIGN; QQK
+00A3 ; [.0FA8.0020.0002.00A3] # POUND SIGN
+FFE1 ; [.0FA8.0020.0003.FFE1] # FULLWIDTH POUND SIGN; QQK
+00A5 ; [.0FA9.0020.0002.00A5] # YEN SIGN
+FFE5 ; [.0FA9.0020.0003.FFE5] # FULLWIDTH YEN SIGN; QQK
+060B ; [.0FAA.0020.0002.060B] # AFGHANI SIGN
+09F2 ; [.0FAB.0020.0002.09F2] # BENGALI RUPEE MARK
+09F3 ; [.0FAC.0020.0002.09F3] # BENGALI RUPEE SIGN
+0AF1 ; [.0FAD.0020.0002.0AF1] # GUJARATI RUPEE SIGN
+0BF9 ; [.0FAE.0020.0002.0BF9] # TAMIL RUPEE SIGN
+0E3F ; [.0FAF.0020.0002.0E3F] # THAI CURRENCY SYMBOL BAHT
+17DB ; [.0FB0.0020.0002.17DB] # KHMER CURRENCY SYMBOL RIEL
+20A0 ; [.0FB1.0020.0002.20A0] # EURO-CURRENCY SIGN
+20A1 ; [.0FB2.0020.0002.20A1] # COLON SIGN
+20A2 ; [.0FB3.0020.0002.20A2] # CRUZEIRO SIGN
+20A3 ; [.0FB4.0020.0002.20A3] # FRENCH FRANC SIGN
+20A4 ; [.0FB5.0020.0002.20A4] # LIRA SIGN
+20A5 ; [.0FB6.0020.0002.20A5] # MILL SIGN
+20A6 ; [.0FB7.0020.0002.20A6] # NAIRA SIGN
+20A7 ; [.0FB8.0020.0002.20A7] # PESETA SIGN
+20A9 ; [.0FB9.0020.0002.20A9] # WON SIGN
+FFE6 ; [.0FB9.0020.0003.FFE6] # FULLWIDTH WON SIGN; QQK
+20AA ; [.0FBA.0020.0002.20AA] # NEW SHEQEL SIGN
+20AB ; [.0FBB.0020.0002.20AB] # DONG SIGN
+20AC ; [.0FBC.0020.0002.20AC] # EURO SIGN
+20AD ; [.0FBD.0020.0002.20AD] # KIP SIGN
+20AE ; [.0FBE.0020.0002.20AE] # TUGRIK SIGN
+20AF ; [.0FBF.0020.0002.20AF] # DRACHMA SIGN
+20B0 ; [.0FC0.0020.0002.20B0] # GERMAN PENNY SIGN
+20B1 ; [.0FC1.0020.0002.20B1] # PESO SIGN
+20B2 ; [.0FC2.0020.0002.20B2] # GUARANI SIGN
+20B3 ; [.0FC3.0020.0002.20B3] # AUSTRAL SIGN
+20B4 ; [.0FC4.0020.0002.20B4] # HRYVNIA SIGN
+20B5 ; [.0FC5.0020.0002.20B5] # CEDI SIGN
+0030 ; [.0FC6.0020.0002.0030] # DIGIT ZERO
+FF10 ; [.0FC6.0020.0003.FF10] # FULLWIDTH DIGIT ZERO; QQK
+1D7CE ; [.0FC6.0020.0005.1D7CE] # MATHEMATICAL BOLD DIGIT ZERO; QQK
+1D7D8 ; [.0FC6.0020.0005.1D7D8] # MATHEMATICAL DOUBLE-STRUCK DIGIT ZERO; QQK
+1D7E2 ; [.0FC6.0020.0005.1D7E2] # MATHEMATICAL SANS-SERIF DIGIT ZERO; QQK
+1D7EC ; [.0FC6.0020.0005.1D7EC] # MATHEMATICAL SANS-SERIF BOLD DIGIT ZERO; QQK
+1D7F6 ; [.0FC6.0020.0005.1D7F6] # MATHEMATICAL MONOSPACE DIGIT ZERO; QQK
+24EA ; [.0FC6.0020.0006.24EA] # CIRCLED DIGIT ZERO; QQK
+24FF ; [.0FC6.0020.0006.24FF] # NEGATIVE CIRCLED DIGIT ZERO; QQK
+2070 ; [.0FC6.0020.0014.2070] # SUPERSCRIPT ZERO; QQK
+2080 ; [.0FC6.0020.0015.2080] # SUBSCRIPT ZERO; QQK
+0660 ; [.0FC6.0020.0002.0660][.0000.019F.0002.0660] # ARABIC-INDIC DIGIT ZERO
+06F0 ; [.0FC6.0020.0002.06F0][.0000.01A0.0002.06F0] # EXTENDED ARABIC-INDIC DIGIT ZERO
+07C0 ; [.0FC6.0020.0002.07C0][.0000.01A1.0002.07C0] # NKO DIGIT ZERO
+104A0 ; [.0FC6.0020.0002.104A0][.0000.01A3.0002.104A0] # OSMANYA DIGIT ZERO
+0966 ; [.0FC6.0020.0002.0966][.0000.01A4.0002.0966] # DEVANAGARI DIGIT ZERO
+09E6 ; [.0FC6.0020.0002.09E6][.0000.01A5.0002.09E6] # BENGALI DIGIT ZERO
+0A66 ; [.0FC6.0020.0002.0A66][.0000.01A6.0002.0A66] # GURMUKHI DIGIT ZERO
+0AE6 ; [.0FC6.0020.0002.0AE6][.0000.01A7.0002.0AE6] # GUJARATI DIGIT ZERO
+0B66 ; [.0FC6.0020.0002.0B66][.0000.01A8.0002.0B66] # ORIYA DIGIT ZERO
+0BE6 ; [.0FC6.0020.0002.0BE6][.0000.01A9.0002.0BE6] # TAMIL DIGIT ZERO
+0C66 ; [.0FC6.0020.0002.0C66][.0000.01AA.0002.0C66] # TELUGU DIGIT ZERO
+0CE6 ; [.0FC6.0020.0002.0CE6][.0000.01AB.0002.0CE6] # KANNADA DIGIT ZERO
+0D66 ; [.0FC6.0020.0002.0D66][.0000.01AC.0002.0D66] # MALAYALAM DIGIT ZERO
+1946 ; [.0FC6.0020.0002.1946][.0000.01AD.0002.1946] # LIMBU DIGIT ZERO
+19D0 ; [.0FC6.0020.0002.19D0][.0000.01AE.0002.19D0] # NEW TAI LUE DIGIT ZERO
+0E50 ; [.0FC6.0020.0002.0E50][.0000.01AF.0002.0E50] # THAI DIGIT ZERO
+0ED0 ; [.0FC6.0020.0002.0ED0][.0000.01B0.0002.0ED0] # LAO DIGIT ZERO
+0F20 ; [.0FC6.0020.0002.0F20][.0000.01B1.0002.0F20] # TIBETAN DIGIT ZERO
+0F33 ; [.0FC6.0020.0004.0F33][.0000.01B1.0004.0F33] # TIBETAN DIGIT HALF ZERO; QQK
+1040 ; [.0FC6.0020.0002.1040][.0000.01B2.0002.1040] # MYANMAR DIGIT ZERO
+17E0 ; [.0FC6.0020.0002.17E0][.0000.01B3.0002.17E0] # KHMER DIGIT ZERO
+17F0 ; [.0FC6.0020.0002.17F0][.0000.01B4.0002.17F0] # KHMER SYMBOL LEK ATTAK SON
+1B50 ; [.0FC6.0020.0002.1B50][.0000.01B5.0002.1B50] # BALINESE DIGIT ZERO
+1810 ; [.0FC6.0020.0002.1810][.0000.01B6.0002.1810] # MONGOLIAN DIGIT ZERO
+3007 ; [.0FC6.0020.0002.3007][.0000.01B7.0002.3007] # IDEOGRAPHIC NUMBER ZERO
+1018A ; [.0FC6.0020.0002.1018A][.0000.01B9.0002.1018A] # GREEK ZERO SIGN
+3358 ; [.0FC6.0020.0004.3358][.FB40.0020.0004.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ZERO; QQKN
+0031 ; [.0FC7.0020.0002.0031] # DIGIT ONE
+FF11 ; [.0FC7.0020.0003.FF11] # FULLWIDTH DIGIT ONE; QQK
+2474 ; [*02B1.0020.0004.2474][.0FC7.0020.0004.2474][*02B2.0020.001F.2474] # PARENTHESIZED DIGIT ONE; QQKN
+2488 ; [.0FC7.0020.0004.2488][*0266.0020.0004.2488] # DIGIT ONE FULL STOP; QQKN
+1D7CF ; [.0FC7.0020.0005.1D7CF] # MATHEMATICAL BOLD DIGIT ONE; QQK
+1D7D9 ; [.0FC7.0020.0005.1D7D9] # MATHEMATICAL DOUBLE-STRUCK DIGIT ONE; QQK
+1D7E3 ; [.0FC7.0020.0005.1D7E3] # MATHEMATICAL SANS-SERIF DIGIT ONE; QQK
+1D7ED ; [.0FC7.0020.0005.1D7ED] # MATHEMATICAL SANS-SERIF BOLD DIGIT ONE; QQK
+1D7F7 ; [.0FC7.0020.0005.1D7F7] # MATHEMATICAL MONOSPACE DIGIT ONE; QQK
+2460 ; [.0FC7.0020.0006.2460] # CIRCLED DIGIT ONE; QQK
+24F5 ; [.0FC7.0020.0006.24F5] # DOUBLE CIRCLED DIGIT ONE; QQK
+2776 ; [.0FC7.0020.0006.2776] # DINGBAT NEGATIVE CIRCLED DIGIT ONE; QQK
+2780 ; [.0FC7.0020.0006.2780] # DINGBAT CIRCLED SANS-SERIF DIGIT ONE; QQK
+278A ; [.0FC7.0020.0006.278A] # DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE; QQK
+00B9 ; [.0FC7.0020.0014.00B9] # SUPERSCRIPT ONE; QQK
+2081 ; [.0FC7.0020.0015.2081] # SUBSCRIPT ONE; QQK
+215F ; [.0FC7.0020.001E.215F][*0300.0020.001E.215F] # FRACTION NUMERATOR ONE; QQKN
+0661 ; [.0FC7.0020.0002.0661][.0000.019F.0002.0661] # ARABIC-INDIC DIGIT ONE
+06F1 ; [.0FC7.0020.0002.06F1][.0000.01A0.0002.06F1] # EXTENDED ARABIC-INDIC DIGIT ONE
+07C1 ; [.0FC7.0020.0002.07C1][.0000.01A1.0002.07C1] # NKO DIGIT ONE
+1369 ; [.0FC7.0020.0002.1369][.0000.01A2.0002.1369] # ETHIOPIC DIGIT ONE
+104A1 ; [.0FC7.0020.0002.104A1][.0000.01A3.0002.104A1] # OSMANYA DIGIT ONE
+0967 ; [.0FC7.0020.0002.0967][.0000.01A4.0002.0967] # DEVANAGARI DIGIT ONE
+09E7 ; [.0FC7.0020.0002.09E7][.0000.01A5.0002.09E7] # BENGALI DIGIT ONE
+09F4 ; [.0FC7.0020.0002.09F4][.0000.01A5.0002.09F4] # BENGALI CURRENCY NUMERATOR ONE
+0A67 ; [.0FC7.0020.0002.0A67][.0000.01A6.0002.0A67] # GURMUKHI DIGIT ONE
+0AE7 ; [.0FC7.0020.0002.0AE7][.0000.01A7.0002.0AE7] # GUJARATI DIGIT ONE
+0B67 ; [.0FC7.0020.0002.0B67][.0000.01A8.0002.0B67] # ORIYA DIGIT ONE
+0BE7 ; [.0FC7.0020.0002.0BE7][.0000.01A9.0002.0BE7] # TAMIL DIGIT ONE
+0C67 ; [.0FC7.0020.0002.0C67][.0000.01AA.0002.0C67] # TELUGU DIGIT ONE
+0CE7 ; [.0FC7.0020.0002.0CE7][.0000.01AB.0002.0CE7] # KANNADA DIGIT ONE
+0D67 ; [.0FC7.0020.0002.0D67][.0000.01AC.0002.0D67] # MALAYALAM DIGIT ONE
+1947 ; [.0FC7.0020.0002.1947][.0000.01AD.0002.1947] # LIMBU DIGIT ONE
+19D1 ; [.0FC7.0020.0002.19D1][.0000.01AE.0002.19D1] # NEW TAI LUE DIGIT ONE
+0E51 ; [.0FC7.0020.0002.0E51][.0000.01AF.0002.0E51] # THAI DIGIT ONE
+0ED1 ; [.0FC7.0020.0002.0ED1][.0000.01B0.0002.0ED1] # LAO DIGIT ONE
+0F21 ; [.0FC7.0020.0002.0F21][.0000.01B1.0002.0F21] # TIBETAN DIGIT ONE
+0F2A ; [.0FC7.0020.0004.0F2A][.0000.01B1.0004.0F2A] # TIBETAN DIGIT HALF ONE; QQK
+1041 ; [.0FC7.0020.0002.1041][.0000.01B2.0002.1041] # MYANMAR DIGIT ONE
+17E1 ; [.0FC7.0020.0002.17E1][.0000.01B3.0002.17E1] # KHMER DIGIT ONE
+17F1 ; [.0FC7.0020.0002.17F1][.0000.01B4.0002.17F1] # KHMER SYMBOL LEK ATTAK MUOY
+1B51 ; [.0FC7.0020.0002.1B51][.0000.01B5.0002.1B51] # BALINESE DIGIT ONE
+1811 ; [.0FC7.0020.0002.1811][.0000.01B6.0002.1811] # MONGOLIAN DIGIT ONE
+3021 ; [.0FC7.0020.0002.3021][.0000.01B7.0002.3021] # HANGZHOU NUMERAL ONE
+10107 ; [.0FC7.0020.0002.10107][.0000.01B8.0002.10107] # AEGEAN NUMBER ONE
+10142 ; [.0FC7.0020.0002.10142][.0000.01B9.0002.10142] # GREEK ACROPHONIC ATTIC ONE DRACHMA
+10158 ; [.0FC7.0020.0002.10158][.0000.01B9.0002.10158] # GREEK ACROPHONIC HERAEUM ONE PLETHRON
+10159 ; [.0FC7.0020.0002.10159][.0000.01B9.0002.10159] # GREEK ACROPHONIC THESPIAN ONE
+1015A ; [.0FC7.0020.0002.1015A][.0000.01B9.0002.1015A] # GREEK ACROPHONIC HERMIONIAN ONE
+10320 ; [.0FC7.0020.0002.10320][.0000.01BA.0002.10320] # OLD ITALIC NUMERAL ONE
+103D1 ; [.0FC7.0020.0002.103D1][.0000.01BB.0002.103D1] # OLD PERSIAN NUMBER ONE
+12415 ; [.0FC7.0020.0002.12415][.0000.01BC.0002.12415] # CUNEIFORM NUMERIC SIGN ONE GESH2
+1241E ; [.0FC7.0020.0002.1241E][.0000.01BC.0002.1241E] # CUNEIFORM NUMERIC SIGN ONE GESHU
+1242C ; [.0FC7.0020.0002.1242C][.0000.01BC.0002.1242C] # CUNEIFORM NUMERIC SIGN ONE SHARU
+12434 ; [.0FC7.0020.0002.12434][.0000.01BC.0002.12434] # CUNEIFORM NUMERIC SIGN ONE BURU
+1244F ; [.0FC7.0020.0002.1244F][.0000.01BC.0002.1244F] # CUNEIFORM NUMERIC SIGN ONE BAN2
+12458 ; [.0FC7.0020.0002.12458][.0000.01BC.0002.12458] # CUNEIFORM NUMERIC SIGN ONE ESHE3
+10916 ; [.0FC7.0020.0002.10916][.0000.01BD.0002.10916] # PHOENICIAN NUMBER ONE
+10A40 ; [.0FC7.0020.0002.10A40][.0000.01BE.0002.10A40] # KHAROSHTHI DIGIT ONE
+1D360 ; [.0FC7.0020.0002.1D360][.0000.01BF.0002.1D360] # COUNTING ROD UNIT DIGIT ONE
+2491 ; [.0FC7.0020.0004.2491][.0FC6.0020.0004.2491][*0266.0020.001F.2491] # NUMBER TEN FULL STOP; QQKN
+247D ; [*02B1.0020.0004.247D][.0FC7.0020.0004.247D][.0FC6.0020.001F.247D][*02B2.0020.001F.247D] # PARENTHESIZED NUMBER TEN; QQKN
+2469 ; [.0FC7.0020.0006.2469][.0FC6.0020.0006.2469] # CIRCLED NUMBER TEN; QQKN
+24FE ; [.0FC7.0020.0006.24FE][.0FC6.0020.0006.24FE] # DOUBLE CIRCLED NUMBER TEN; QQKN
+277F ; [.0FC7.0020.0006.277F][.0FC6.0020.0006.277F] # DINGBAT NEGATIVE CIRCLED NUMBER TEN; QQKN
+2789 ; [.0FC7.0020.0006.2789][.0FC6.0020.0006.2789] # DINGBAT CIRCLED SANS-SERIF NUMBER TEN; QQKN
+2793 ; [.0FC7.0020.0006.2793][.0FC6.0020.0006.2793] # DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN; QQKN
+33E9 ; [.0FC7.0020.0004.33E9][.0FC6.0020.0004.33E9][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TEN; QQKN
+32C9 ; [.0FC7.0020.0004.32C9][.0FC6.0020.0004.32C9][.FB40.0020.001F.6708][.E708.0000.0000.6708] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR OCTOBER; QQKN
+3362 ; [.0FC7.0020.0004.3362][.0FC6.0020.0004.3362][.FB40.0020.001F.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TEN; QQKN
+2492 ; [.0FC7.0020.0004.2492][.0FC7.0020.0004.2492][*0266.0020.001F.2492] # NUMBER ELEVEN FULL STOP; QQKN
+247E ; [*02B1.0020.0004.247E][.0FC7.0020.0004.247E][.0FC7.0020.001F.247E][*02B2.0020.001F.247E] # PARENTHESIZED NUMBER ELEVEN; QQKN
+246A ; [.0FC7.0020.0006.246A][.0FC7.0020.0006.246A] # CIRCLED NUMBER ELEVEN; QQKN
+24EB ; [.0FC7.0020.0006.24EB][.0FC7.0020.0006.24EB] # NEGATIVE CIRCLED NUMBER ELEVEN; QQKN
+33EA ; [.0FC7.0020.0004.33EA][.0FC7.0020.0004.33EA][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ELEVEN; QQKN
+32CA ; [.0FC7.0020.0004.32CA][.0FC7.0020.0004.32CA][.FB40.0020.001F.6708][.E708.0000.0000.6708] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR NOVEMBER; QQKN
+3363 ; [.0FC7.0020.0004.3363][.0FC7.0020.0004.3363][.FB40.0020.001F.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ELEVEN; QQKN
+2493 ; [.0FC7.0020.0004.2493][.0FC8.0020.0004.2493][*0266.0020.001F.2493] # NUMBER TWELVE FULL STOP; QQKN
+247F ; [*02B1.0020.0004.247F][.0FC7.0020.0004.247F][.0FC8.0020.001F.247F][*02B2.0020.001F.247F] # PARENTHESIZED NUMBER TWELVE; QQKN
+246B ; [.0FC7.0020.0006.246B][.0FC8.0020.0006.246B] # CIRCLED NUMBER TWELVE; QQKN
+24EC ; [.0FC7.0020.0006.24EC][.0FC8.0020.0006.24EC] # NEGATIVE CIRCLED NUMBER TWELVE; QQKN
+00BD ; [.0FC7.0020.001E.00BD][*0300.0020.001E.00BD][.0FC8.0020.001F.00BD] # VULGAR FRACTION ONE HALF; QQKN
+33EB ; [.0FC7.0020.0004.33EB][.0FC8.0020.0004.33EB][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWELVE; QQKN
+32CB ; [.0FC7.0020.0004.32CB][.0FC8.0020.0004.32CB][.FB40.0020.001F.6708][.E708.0000.0000.6708] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DECEMBER; QQKN
+3364 ; [.0FC7.0020.0004.3364][.0FC8.0020.0004.3364][.FB40.0020.001F.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWELVE; QQKN
+2494 ; [.0FC7.0020.0004.2494][.0FC9.0020.0004.2494][*0266.0020.001F.2494] # NUMBER THIRTEEN FULL STOP; QQKN
+2480 ; [*02B1.0020.0004.2480][.0FC7.0020.0004.2480][.0FC9.0020.001F.2480][*02B2.0020.001F.2480] # PARENTHESIZED NUMBER THIRTEEN; QQKN
+246C ; [.0FC7.0020.0006.246C][.0FC9.0020.0006.246C] # CIRCLED NUMBER THIRTEEN; QQKN
+24ED ; [.0FC7.0020.0006.24ED][.0FC9.0020.0006.24ED] # NEGATIVE CIRCLED NUMBER THIRTEEN; QQKN
+2153 ; [.0FC7.0020.001E.2153][*0300.0020.001E.2153][.0FC9.0020.001F.2153] # VULGAR FRACTION ONE THIRD; QQKN
+33EC ; [.0FC7.0020.0004.33EC][.0FC9.0020.0004.33EC][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTEEN; QQKN
+3365 ; [.0FC7.0020.0004.3365][.0FC9.0020.0004.3365][.FB40.0020.001F.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THIRTEEN; QQKN
+2495 ; [.0FC7.0020.0004.2495][.0FCA.0020.0004.2495][*0266.0020.001F.2495] # NUMBER FOURTEEN FULL STOP; QQKN
+2481 ; [*02B1.0020.0004.2481][.0FC7.0020.0004.2481][.0FCA.0020.001F.2481][*02B2.0020.001F.2481] # PARENTHESIZED NUMBER FOURTEEN; QQKN
+246D ; [.0FC7.0020.0006.246D][.0FCA.0020.0006.246D] # CIRCLED NUMBER FOURTEEN; QQKN
+24EE ; [.0FC7.0020.0006.24EE][.0FCA.0020.0006.24EE] # NEGATIVE CIRCLED NUMBER FOURTEEN; QQKN
+00BC ; [.0FC7.0020.001E.00BC][*0300.0020.001E.00BC][.0FCA.0020.001F.00BC] # VULGAR FRACTION ONE QUARTER; QQKN
+33ED ; [.0FC7.0020.0004.33ED][.0FCA.0020.0004.33ED][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOURTEEN; QQKN
+3366 ; [.0FC7.0020.0004.3366][.0FCA.0020.0004.3366][.FB40.0020.001F.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOURTEEN; QQKN
+2496 ; [.0FC7.0020.0004.2496][.0FCB.0020.0004.2496][*0266.0020.001F.2496] # NUMBER FIFTEEN FULL STOP; QQKN
+2482 ; [*02B1.0020.0004.2482][.0FC7.0020.0004.2482][.0FCB.0020.001F.2482][*02B2.0020.001F.2482] # PARENTHESIZED NUMBER FIFTEEN; QQKN
+246E ; [.0FC7.0020.0006.246E][.0FCB.0020.0006.246E] # CIRCLED NUMBER FIFTEEN; QQKN
+24EF ; [.0FC7.0020.0006.24EF][.0FCB.0020.0006.24EF] # NEGATIVE CIRCLED NUMBER FIFTEEN; QQKN
+2155 ; [.0FC7.0020.001E.2155][*0300.0020.001E.2155][.0FCB.0020.001F.2155] # VULGAR FRACTION ONE FIFTH; QQKN
+33EE ; [.0FC7.0020.0004.33EE][.0FCB.0020.0004.33EE][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIFTEEN; QQKN
+3367 ; [.0FC7.0020.0004.3367][.0FCB.0020.0004.3367][.FB40.0020.001F.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIFTEEN; QQKN
+2497 ; [.0FC7.0020.0004.2497][.0FCC.0020.0004.2497][*0266.0020.001F.2497] # NUMBER SIXTEEN FULL STOP; QQKN
+2483 ; [*02B1.0020.0004.2483][.0FC7.0020.0004.2483][.0FCC.0020.001F.2483][*02B2.0020.001F.2483] # PARENTHESIZED NUMBER SIXTEEN; QQKN
+246F ; [.0FC7.0020.0006.246F][.0FCC.0020.0006.246F] # CIRCLED NUMBER SIXTEEN; QQKN
+24F0 ; [.0FC7.0020.0006.24F0][.0FCC.0020.0006.24F0] # NEGATIVE CIRCLED NUMBER SIXTEEN; QQKN
+2159 ; [.0FC7.0020.001E.2159][*0300.0020.001E.2159][.0FCC.0020.001F.2159] # VULGAR FRACTION ONE SIXTH; QQKN
+33EF ; [.0FC7.0020.0004.33EF][.0FCC.0020.0004.33EF][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIXTEEN; QQKN
+3368 ; [.0FC7.0020.0004.3368][.0FCC.0020.0004.3368][.FB40.0020.001F.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIXTEEN; QQKN
+2498 ; [.0FC7.0020.0004.2498][.0FCD.0020.0004.2498][*0266.0020.001F.2498] # NUMBER SEVENTEEN FULL STOP; QQKN
+2484 ; [*02B1.0020.0004.2484][.0FC7.0020.0004.2484][.0FCD.0020.001F.2484][*02B2.0020.001F.2484] # PARENTHESIZED NUMBER SEVENTEEN; QQKN
+2470 ; [.0FC7.0020.0006.2470][.0FCD.0020.0006.2470] # CIRCLED NUMBER SEVENTEEN; QQKN
+24F1 ; [.0FC7.0020.0006.24F1][.0FCD.0020.0006.24F1] # NEGATIVE CIRCLED NUMBER SEVENTEEN; QQKN
+33F0 ; [.0FC7.0020.0004.33F0][.0FCD.0020.0004.33F0][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVENTEEN; QQKN
+3369 ; [.0FC7.0020.0004.3369][.0FCD.0020.0004.3369][.FB40.0020.001F.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVENTEEN; QQKN
+2499 ; [.0FC7.0020.0004.2499][.0FCE.0020.0004.2499][*0266.0020.001F.2499] # NUMBER EIGHTEEN FULL STOP; QQKN
+2485 ; [*02B1.0020.0004.2485][.0FC7.0020.0004.2485][.0FCE.0020.001F.2485][*02B2.0020.001F.2485] # PARENTHESIZED NUMBER EIGHTEEN; QQKN
+2471 ; [.0FC7.0020.0006.2471][.0FCE.0020.0006.2471] # CIRCLED NUMBER EIGHTEEN; QQKN
+24F2 ; [.0FC7.0020.0006.24F2][.0FCE.0020.0006.24F2] # NEGATIVE CIRCLED NUMBER EIGHTEEN; QQKN
+215B ; [.0FC7.0020.001E.215B][*0300.0020.001E.215B][.0FCE.0020.001F.215B] # VULGAR FRACTION ONE EIGHTH; QQKN
+33F1 ; [.0FC7.0020.0004.33F1][.0FCE.0020.0004.33F1][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHTEEN; QQKN
+336A ; [.0FC7.0020.0004.336A][.0FCE.0020.0004.336A][.FB40.0020.001F.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHTEEN; QQKN
+249A ; [.0FC7.0020.0004.249A][.0FCF.0020.0004.249A][*0266.0020.001F.249A] # NUMBER NINETEEN FULL STOP; QQKN
+2486 ; [*02B1.0020.0004.2486][.0FC7.0020.0004.2486][.0FCF.0020.001F.2486][*02B2.0020.001F.2486] # PARENTHESIZED NUMBER NINETEEN; QQKN
+2472 ; [.0FC7.0020.0006.2472][.0FCF.0020.0006.2472] # CIRCLED NUMBER NINETEEN; QQKN
+24F3 ; [.0FC7.0020.0006.24F3][.0FCF.0020.0006.24F3] # NEGATIVE CIRCLED NUMBER NINETEEN; QQKN
+33F2 ; [.0FC7.0020.0004.33F2][.0FCF.0020.0004.33F2][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINETEEN; QQKN
+336B ; [.0FC7.0020.0004.336B][.0FCF.0020.0004.336B][.FB40.0020.001F.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINETEEN; QQKN
+33E0 ; [.0FC7.0020.0004.33E0][.FB40.0020.0004.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ONE; QQKN
+32C0 ; [.0FC7.0020.0004.32C0][.FB40.0020.0004.6708][.E708.0000.0000.6708] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY; QQKN
+3359 ; [.0FC7.0020.0004.3359][.FB40.0020.0004.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR ONE; QQKN
+0032 ; [.0FC8.0020.0002.0032] # DIGIT TWO
+FF12 ; [.0FC8.0020.0003.FF12] # FULLWIDTH DIGIT TWO; QQK
+2475 ; [*02B1.0020.0004.2475][.0FC8.0020.0004.2475][*02B2.0020.001F.2475] # PARENTHESIZED DIGIT TWO; QQKN
+2489 ; [.0FC8.0020.0004.2489][*0266.0020.0004.2489] # DIGIT TWO FULL STOP; QQKN
+1D7D0 ; [.0FC8.0020.0005.1D7D0] # MATHEMATICAL BOLD DIGIT TWO; QQK
+1D7DA ; [.0FC8.0020.0005.1D7DA] # MATHEMATICAL DOUBLE-STRUCK DIGIT TWO; QQK
+1D7E4 ; [.0FC8.0020.0005.1D7E4] # MATHEMATICAL SANS-SERIF DIGIT TWO; QQK
+1D7EE ; [.0FC8.0020.0005.1D7EE] # MATHEMATICAL SANS-SERIF BOLD DIGIT TWO; QQK
+1D7F8 ; [.0FC8.0020.0005.1D7F8] # MATHEMATICAL MONOSPACE DIGIT TWO; QQK
+2461 ; [.0FC8.0020.0006.2461] # CIRCLED DIGIT TWO; QQK
+24F6 ; [.0FC8.0020.0006.24F6] # DOUBLE CIRCLED DIGIT TWO; QQK
+2777 ; [.0FC8.0020.0006.2777] # DINGBAT NEGATIVE CIRCLED DIGIT TWO; QQK
+2781 ; [.0FC8.0020.0006.2781] # DINGBAT CIRCLED SANS-SERIF DIGIT TWO; QQK
+278B ; [.0FC8.0020.0006.278B] # DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO; QQK
+00B2 ; [.0FC8.0020.0014.00B2] # SUPERSCRIPT TWO; QQK
+2082 ; [.0FC8.0020.0015.2082] # SUBSCRIPT TWO; QQK
+0662 ; [.0FC8.0020.0002.0662][.0000.019F.0002.0662] # ARABIC-INDIC DIGIT TWO
+06F2 ; [.0FC8.0020.0002.06F2][.0000.01A0.0002.06F2] # EXTENDED ARABIC-INDIC DIGIT TWO
+07C2 ; [.0FC8.0020.0002.07C2][.0000.01A1.0002.07C2] # NKO DIGIT TWO
+136A ; [.0FC8.0020.0002.136A][.0000.01A2.0002.136A] # ETHIOPIC DIGIT TWO
+104A2 ; [.0FC8.0020.0002.104A2][.0000.01A3.0002.104A2] # OSMANYA DIGIT TWO
+0968 ; [.0FC8.0020.0002.0968][.0000.01A4.0002.0968] # DEVANAGARI DIGIT TWO
+09E8 ; [.0FC8.0020.0002.09E8][.0000.01A5.0002.09E8] # BENGALI DIGIT TWO
+09F5 ; [.0FC8.0020.0002.09F5][.0000.01A5.0002.09F5] # BENGALI CURRENCY NUMERATOR TWO
+0A68 ; [.0FC8.0020.0002.0A68][.0000.01A6.0002.0A68] # GURMUKHI DIGIT TWO
+0AE8 ; [.0FC8.0020.0002.0AE8][.0000.01A7.0002.0AE8] # GUJARATI DIGIT TWO
+0B68 ; [.0FC8.0020.0002.0B68][.0000.01A8.0002.0B68] # ORIYA DIGIT TWO
+0BE8 ; [.0FC8.0020.0002.0BE8][.0000.01A9.0002.0BE8] # TAMIL DIGIT TWO
+0C68 ; [.0FC8.0020.0002.0C68][.0000.01AA.0002.0C68] # TELUGU DIGIT TWO
+0CE8 ; [.0FC8.0020.0002.0CE8][.0000.01AB.0002.0CE8] # KANNADA DIGIT TWO
+0D68 ; [.0FC8.0020.0002.0D68][.0000.01AC.0002.0D68] # MALAYALAM DIGIT TWO
+1948 ; [.0FC8.0020.0002.1948][.0000.01AD.0002.1948] # LIMBU DIGIT TWO
+19D2 ; [.0FC8.0020.0002.19D2][.0000.01AE.0002.19D2] # NEW TAI LUE DIGIT TWO
+0E52 ; [.0FC8.0020.0002.0E52][.0000.01AF.0002.0E52] # THAI DIGIT TWO
+0ED2 ; [.0FC8.0020.0002.0ED2][.0000.01B0.0002.0ED2] # LAO DIGIT TWO
+0F22 ; [.0FC8.0020.0002.0F22][.0000.01B1.0002.0F22] # TIBETAN DIGIT TWO
+0F2B ; [.0FC8.0020.0004.0F2B][.0000.01B1.0004.0F2B] # TIBETAN DIGIT HALF TWO; QQK
+1042 ; [.0FC8.0020.0002.1042][.0000.01B2.0002.1042] # MYANMAR DIGIT TWO
+17E2 ; [.0FC8.0020.0002.17E2][.0000.01B3.0002.17E2] # KHMER DIGIT TWO
+17F2 ; [.0FC8.0020.0002.17F2][.0000.01B4.0002.17F2] # KHMER SYMBOL LEK ATTAK PII
+1B52 ; [.0FC8.0020.0002.1B52][.0000.01B5.0002.1B52] # BALINESE DIGIT TWO
+1812 ; [.0FC8.0020.0002.1812][.0000.01B6.0002.1812] # MONGOLIAN DIGIT TWO
+3022 ; [.0FC8.0020.0002.3022][.0000.01B7.0002.3022] # HANGZHOU NUMERAL TWO
+10108 ; [.0FC8.0020.0002.10108][.0000.01B8.0002.10108] # AEGEAN NUMBER TWO
+1015B ; [.0FC8.0020.0002.1015B][.0000.01B9.0002.1015B] # GREEK ACROPHONIC EPIDAUREAN TWO
+1015C ; [.0FC8.0020.0002.1015C][.0000.01B9.0002.1015C] # GREEK ACROPHONIC THESPIAN TWO
+1015D ; [.0FC8.0020.0002.1015D][.0000.01B9.0002.1015D] # GREEK ACROPHONIC CYRENAIC TWO DRACHMAS
+1015E ; [.0FC8.0020.0002.1015E][.0000.01B9.0002.1015E] # GREEK ACROPHONIC EPIDAUREAN TWO DRACHMAS
+103D2 ; [.0FC8.0020.0002.103D2][.0000.01BB.0002.103D2] # OLD PERSIAN NUMBER TWO
+12400 ; [.0FC8.0020.0002.12400][.0000.01BC.0002.12400] # CUNEIFORM NUMERIC SIGN TWO ASH
+12416 ; [.0FC8.0020.0002.12416][.0000.01BC.0002.12416] # CUNEIFORM NUMERIC SIGN TWO GESH2
+1241F ; [.0FC8.0020.0002.1241F][.0000.01BC.0002.1241F] # CUNEIFORM NUMERIC SIGN TWO GESHU
+12423 ; [.0FC8.0020.0002.12423][.0000.01BC.0002.12423] # CUNEIFORM NUMERIC SIGN TWO SHAR2
+1242D ; [.0FC8.0020.0002.1242D][.0000.01BC.0002.1242D] # CUNEIFORM NUMERIC SIGN TWO SHARU
+12435 ; [.0FC8.0020.0002.12435][.0000.01BC.0002.12435] # CUNEIFORM NUMERIC SIGN TWO BURU
+1244A ; [.0FC8.0020.0002.1244A][.0000.01BC.0002.1244A] # CUNEIFORM NUMERIC SIGN TWO ASH TENU
+12450 ; [.0FC8.0020.0002.12450][.0000.01BC.0002.12450] # CUNEIFORM NUMERIC SIGN TWO BAN2
+12459 ; [.0FC8.0020.0002.12459][.0000.01BC.0002.12459] # CUNEIFORM NUMERIC SIGN TWO ESHE3
+10A41 ; [.0FC8.0020.0002.10A41][.0000.01BE.0002.10A41] # KHAROSHTHI DIGIT TWO
+1D361 ; [.0FC8.0020.0002.1D361][.0000.01BF.0002.1D361] # COUNTING ROD UNIT DIGIT TWO
+249B ; [.0FC8.0020.0004.249B][.0FC6.0020.0004.249B][*0266.0020.001F.249B] # NUMBER TWENTY FULL STOP; QQKN
+2487 ; [*02B1.0020.0004.2487][.0FC8.0020.0004.2487][.0FC6.0020.001F.2487][*02B2.0020.001F.2487] # PARENTHESIZED NUMBER TWENTY; QQKN
+2473 ; [.0FC8.0020.0006.2473][.0FC6.0020.0006.2473] # CIRCLED NUMBER TWENTY; QQKN
+24F4 ; [.0FC8.0020.0006.24F4][.0FC6.0020.0006.24F4] # NEGATIVE CIRCLED NUMBER TWENTY; QQKN
+33F3 ; [.0FC8.0020.0004.33F3][.0FC6.0020.0004.33F3][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY; QQKN
+336C ; [.0FC8.0020.0004.336C][.0FC6.0020.0004.336C][.FB40.0020.001F.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY; QQKN
+3251 ; [.0FC8.0020.0006.3251][.0FC7.0020.0006.3251] # CIRCLED NUMBER TWENTY ONE; QQKN
+33F4 ; [.0FC8.0020.0004.33F4][.0FC7.0020.0004.33F4][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-ONE; QQKN
+336D ; [.0FC8.0020.0004.336D][.0FC7.0020.0004.336D][.FB40.0020.001F.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-ONE; QQKN
+3252 ; [.0FC8.0020.0006.3252][.0FC8.0020.0006.3252] # CIRCLED NUMBER TWENTY TWO; QQKN
+33F5 ; [.0FC8.0020.0004.33F5][.0FC8.0020.0004.33F5][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-TWO; QQKN
+336E ; [.0FC8.0020.0004.336E][.0FC8.0020.0004.336E][.FB40.0020.001F.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-TWO; QQKN
+3253 ; [.0FC8.0020.0006.3253][.0FC9.0020.0006.3253] # CIRCLED NUMBER TWENTY THREE; QQKN
+2154 ; [.0FC8.0020.001E.2154][*0300.0020.001E.2154][.0FC9.0020.001F.2154] # VULGAR FRACTION TWO THIRDS; QQKN
+33F6 ; [.0FC8.0020.0004.33F6][.0FC9.0020.0004.33F6][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-THREE; QQKN
+336F ; [.0FC8.0020.0004.336F][.0FC9.0020.0004.336F][.FB40.0020.001F.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-THREE; QQKN
+3254 ; [.0FC8.0020.0006.3254][.0FCA.0020.0006.3254] # CIRCLED NUMBER TWENTY FOUR; QQKN
+33F7 ; [.0FC8.0020.0004.33F7][.0FCA.0020.0004.33F7][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FOUR; QQKN
+3370 ; [.0FC8.0020.0004.3370][.0FCA.0020.0004.3370][.FB40.0020.001F.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWENTY-FOUR; QQKN
+3255 ; [.0FC8.0020.0006.3255][.0FCB.0020.0006.3255] # CIRCLED NUMBER TWENTY FIVE; QQKN
+2156 ; [.0FC8.0020.001E.2156][*0300.0020.001E.2156][.0FCB.0020.001F.2156] # VULGAR FRACTION TWO FIFTHS; QQKN
+33F8 ; [.0FC8.0020.0004.33F8][.0FCB.0020.0004.33F8][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-FIVE; QQKN
+3256 ; [.0FC8.0020.0006.3256][.0FCC.0020.0006.3256] # CIRCLED NUMBER TWENTY SIX; QQKN
+33F9 ; [.0FC8.0020.0004.33F9][.0FCC.0020.0004.33F9][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SIX; QQKN
+3257 ; [.0FC8.0020.0006.3257][.0FCD.0020.0006.3257] # CIRCLED NUMBER TWENTY SEVEN; QQKN
+33FA ; [.0FC8.0020.0004.33FA][.0FCD.0020.0004.33FA][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-SEVEN; QQKN
+3258 ; [.0FC8.0020.0006.3258][.0FCE.0020.0006.3258] # CIRCLED NUMBER TWENTY EIGHT; QQKN
+33FB ; [.0FC8.0020.0004.33FB][.0FCE.0020.0004.33FB][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-EIGHT; QQKN
+3259 ; [.0FC8.0020.0006.3259][.0FCF.0020.0006.3259] # CIRCLED NUMBER TWENTY NINE; QQKN
+33FC ; [.0FC8.0020.0004.33FC][.0FCF.0020.0004.33FC][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-NINE; QQKN
+33E1 ; [.0FC8.0020.0004.33E1][.FB40.0020.0004.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWO; QQKN
+32C1 ; [.0FC8.0020.0004.32C1][.FB40.0020.0004.6708][.E708.0000.0000.6708] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR FEBRUARY; QQKN
+335A ; [.0FC8.0020.0004.335A][.FB40.0020.0004.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR TWO; QQKN
+0033 ; [.0FC9.0020.0002.0033] # DIGIT THREE
+FF13 ; [.0FC9.0020.0003.FF13] # FULLWIDTH DIGIT THREE; QQK
+2476 ; [*02B1.0020.0004.2476][.0FC9.0020.0004.2476][*02B2.0020.001F.2476] # PARENTHESIZED DIGIT THREE; QQKN
+248A ; [.0FC9.0020.0004.248A][*0266.0020.0004.248A] # DIGIT THREE FULL STOP; QQKN
+1D7D1 ; [.0FC9.0020.0005.1D7D1] # MATHEMATICAL BOLD DIGIT THREE; QQK
+1D7DB ; [.0FC9.0020.0005.1D7DB] # MATHEMATICAL DOUBLE-STRUCK DIGIT THREE; QQK
+1D7E5 ; [.0FC9.0020.0005.1D7E5] # MATHEMATICAL SANS-SERIF DIGIT THREE; QQK
+1D7EF ; [.0FC9.0020.0005.1D7EF] # MATHEMATICAL SANS-SERIF BOLD DIGIT THREE; QQK
+1D7F9 ; [.0FC9.0020.0005.1D7F9] # MATHEMATICAL MONOSPACE DIGIT THREE; QQK
+2462 ; [.0FC9.0020.0006.2462] # CIRCLED DIGIT THREE; QQK
+24F7 ; [.0FC9.0020.0006.24F7] # DOUBLE CIRCLED DIGIT THREE; QQK
+2778 ; [.0FC9.0020.0006.2778] # DINGBAT NEGATIVE CIRCLED DIGIT THREE; QQK
+2782 ; [.0FC9.0020.0006.2782] # DINGBAT CIRCLED SANS-SERIF DIGIT THREE; QQK
+278C ; [.0FC9.0020.0006.278C] # DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE; QQK
+00B3 ; [.0FC9.0020.0014.00B3] # SUPERSCRIPT THREE; QQK
+2083 ; [.0FC9.0020.0015.2083] # SUBSCRIPT THREE; QQK
+0663 ; [.0FC9.0020.0002.0663][.0000.019F.0002.0663] # ARABIC-INDIC DIGIT THREE
+06F3 ; [.0FC9.0020.0002.06F3][.0000.01A0.0002.06F3] # EXTENDED ARABIC-INDIC DIGIT THREE
+07C3 ; [.0FC9.0020.0002.07C3][.0000.01A1.0002.07C3] # NKO DIGIT THREE
+136B ; [.0FC9.0020.0002.136B][.0000.01A2.0002.136B] # ETHIOPIC DIGIT THREE
+104A3 ; [.0FC9.0020.0002.104A3][.0000.01A3.0002.104A3] # OSMANYA DIGIT THREE
+0969 ; [.0FC9.0020.0002.0969][.0000.01A4.0002.0969] # DEVANAGARI DIGIT THREE
+09E9 ; [.0FC9.0020.0002.09E9][.0000.01A5.0002.09E9] # BENGALI DIGIT THREE
+09F6 ; [.0FC9.0020.0002.09F6][.0000.01A5.0002.09F6] # BENGALI CURRENCY NUMERATOR THREE
+0A69 ; [.0FC9.0020.0002.0A69][.0000.01A6.0002.0A69] # GURMUKHI DIGIT THREE
+0AE9 ; [.0FC9.0020.0002.0AE9][.0000.01A7.0002.0AE9] # GUJARATI DIGIT THREE
+0B69 ; [.0FC9.0020.0002.0B69][.0000.01A8.0002.0B69] # ORIYA DIGIT THREE
+0BE9 ; [.0FC9.0020.0002.0BE9][.0000.01A9.0002.0BE9] # TAMIL DIGIT THREE
+0C69 ; [.0FC9.0020.0002.0C69][.0000.01AA.0002.0C69] # TELUGU DIGIT THREE
+0CE9 ; [.0FC9.0020.0002.0CE9][.0000.01AB.0002.0CE9] # KANNADA DIGIT THREE
+0D69 ; [.0FC9.0020.0002.0D69][.0000.01AC.0002.0D69] # MALAYALAM DIGIT THREE
+1949 ; [.0FC9.0020.0002.1949][.0000.01AD.0002.1949] # LIMBU DIGIT THREE
+19D3 ; [.0FC9.0020.0002.19D3][.0000.01AE.0002.19D3] # NEW TAI LUE DIGIT THREE
+0E53 ; [.0FC9.0020.0002.0E53][.0000.01AF.0002.0E53] # THAI DIGIT THREE
+0ED3 ; [.0FC9.0020.0002.0ED3][.0000.01B0.0002.0ED3] # LAO DIGIT THREE
+0F23 ; [.0FC9.0020.0002.0F23][.0000.01B1.0002.0F23] # TIBETAN DIGIT THREE
+0F2C ; [.0FC9.0020.0004.0F2C][.0000.01B1.0004.0F2C] # TIBETAN DIGIT HALF THREE; QQK
+1043 ; [.0FC9.0020.0002.1043][.0000.01B2.0002.1043] # MYANMAR DIGIT THREE
+17E3 ; [.0FC9.0020.0002.17E3][.0000.01B3.0002.17E3] # KHMER DIGIT THREE
+17F3 ; [.0FC9.0020.0002.17F3][.0000.01B4.0002.17F3] # KHMER SYMBOL LEK ATTAK BEI
+1B53 ; [.0FC9.0020.0002.1B53][.0000.01B5.0002.1B53] # BALINESE DIGIT THREE
+1813 ; [.0FC9.0020.0002.1813][.0000.01B6.0002.1813] # MONGOLIAN DIGIT THREE
+3023 ; [.0FC9.0020.0002.3023][.0000.01B7.0002.3023] # HANGZHOU NUMERAL THREE
+10109 ; [.0FC9.0020.0002.10109][.0000.01B8.0002.10109] # AEGEAN NUMBER THREE
+12401 ; [.0FC9.0020.0002.12401][.0000.01BC.0002.12401] # CUNEIFORM NUMERIC SIGN THREE ASH
+12408 ; [.0FC9.0020.0002.12408][.0000.01BC.0002.12408] # CUNEIFORM NUMERIC SIGN THREE DISH
+12417 ; [.0FC9.0020.0002.12417][.0000.01BC.0002.12417] # CUNEIFORM NUMERIC SIGN THREE GESH2
+12420 ; [.0FC9.0020.0002.12420][.0000.01BC.0002.12420] # CUNEIFORM NUMERIC SIGN THREE GESHU
+12424 ; [.0FC9.0020.0002.12424][.0000.01BC.0002.12424] # CUNEIFORM NUMERIC SIGN THREE SHAR2
+12425 ; [.0FC9.0020.0002.12425][.0000.01BC.0002.12425] # CUNEIFORM NUMERIC SIGN THREE SHAR2 VARIANT FORM
+1242E ; [.0FC9.0020.0002.1242E][.0000.01BC.0002.1242E] # CUNEIFORM NUMERIC SIGN THREE SHARU
+1242F ; [.0FC9.0020.0002.1242F][.0000.01BC.0002.1242F] # CUNEIFORM NUMERIC SIGN THREE SHARU VARIANT FORM
+12436 ; [.0FC9.0020.0002.12436][.0000.01BC.0002.12436] # CUNEIFORM NUMERIC SIGN THREE BURU
+12437 ; [.0FC9.0020.0002.12437][.0000.01BC.0002.12437] # CUNEIFORM NUMERIC SIGN THREE BURU VARIANT FORM
+1243A ; [.0FC9.0020.0002.1243A][.0000.01BC.0002.1243A] # CUNEIFORM NUMERIC SIGN THREE VARIANT FORM ESH16
+1243B ; [.0FC9.0020.0002.1243B][.0000.01BC.0002.1243B] # CUNEIFORM NUMERIC SIGN THREE VARIANT FORM ESH21
+1244B ; [.0FC9.0020.0002.1244B][.0000.01BC.0002.1244B] # CUNEIFORM NUMERIC SIGN THREE ASH TENU
+12451 ; [.0FC9.0020.0002.12451][.0000.01BC.0002.12451] # CUNEIFORM NUMERIC SIGN THREE BAN2
+10A42 ; [.0FC9.0020.0002.10A42][.0000.01BE.0002.10A42] # KHAROSHTHI DIGIT THREE
+1D362 ; [.0FC9.0020.0002.1D362][.0000.01BF.0002.1D362] # COUNTING ROD UNIT DIGIT THREE
+325A ; [.0FC9.0020.0006.325A][.0FC6.0020.0006.325A] # CIRCLED NUMBER THIRTY; QQKN
+33FD ; [.0FC9.0020.0004.33FD][.0FC6.0020.0004.33FD][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY; QQKN
+325B ; [.0FC9.0020.0006.325B][.0FC7.0020.0006.325B] # CIRCLED NUMBER THIRTY ONE; QQKN
+33FE ; [.0FC9.0020.0004.33FE][.0FC7.0020.0004.33FE][.FB40.0020.001F.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY-ONE; QQKN
+325C ; [.0FC9.0020.0006.325C][.0FC8.0020.0006.325C] # CIRCLED NUMBER THIRTY TWO; QQKN
+325D ; [.0FC9.0020.0006.325D][.0FC9.0020.0006.325D] # CIRCLED NUMBER THIRTY THREE; QQKN
+325E ; [.0FC9.0020.0006.325E][.0FCA.0020.0006.325E] # CIRCLED NUMBER THIRTY FOUR; QQKN
+00BE ; [.0FC9.0020.001E.00BE][*0300.0020.001E.00BE][.0FCA.0020.001F.00BE] # VULGAR FRACTION THREE QUARTERS; QQKN
+325F ; [.0FC9.0020.0006.325F][.0FCB.0020.0006.325F] # CIRCLED NUMBER THIRTY FIVE; QQKN
+2157 ; [.0FC9.0020.001E.2157][*0300.0020.001E.2157][.0FCB.0020.001F.2157] # VULGAR FRACTION THREE FIFTHS; QQKN
+32B1 ; [.0FC9.0020.0006.32B1][.0FCC.0020.0006.32B1] # CIRCLED NUMBER THIRTY SIX; QQKN
+32B2 ; [.0FC9.0020.0006.32B2][.0FCD.0020.0006.32B2] # CIRCLED NUMBER THIRTY SEVEN; QQKN
+32B3 ; [.0FC9.0020.0006.32B3][.0FCE.0020.0006.32B3] # CIRCLED NUMBER THIRTY EIGHT; QQKN
+215C ; [.0FC9.0020.001E.215C][*0300.0020.001E.215C][.0FCE.0020.001F.215C] # VULGAR FRACTION THREE EIGHTHS; QQKN
+32B4 ; [.0FC9.0020.0006.32B4][.0FCF.0020.0006.32B4] # CIRCLED NUMBER THIRTY NINE; QQKN
+33E2 ; [.0FC9.0020.0004.33E2][.FB40.0020.0004.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THREE; QQKN
+32C2 ; [.0FC9.0020.0004.32C2][.FB40.0020.0004.6708][.E708.0000.0000.6708] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR MARCH; QQKN
+335B ; [.0FC9.0020.0004.335B][.FB40.0020.0004.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR THREE; QQKN
+0034 ; [.0FCA.0020.0002.0034] # DIGIT FOUR
+FF14 ; [.0FCA.0020.0003.FF14] # FULLWIDTH DIGIT FOUR; QQK
+2477 ; [*02B1.0020.0004.2477][.0FCA.0020.0004.2477][*02B2.0020.001F.2477] # PARENTHESIZED DIGIT FOUR; QQKN
+248B ; [.0FCA.0020.0004.248B][*0266.0020.0004.248B] # DIGIT FOUR FULL STOP; QQKN
+1D7D2 ; [.0FCA.0020.0005.1D7D2] # MATHEMATICAL BOLD DIGIT FOUR; QQK
+1D7DC ; [.0FCA.0020.0005.1D7DC] # MATHEMATICAL DOUBLE-STRUCK DIGIT FOUR; QQK
+1D7E6 ; [.0FCA.0020.0005.1D7E6] # MATHEMATICAL SANS-SERIF DIGIT FOUR; QQK
+1D7F0 ; [.0FCA.0020.0005.1D7F0] # MATHEMATICAL SANS-SERIF BOLD DIGIT FOUR; QQK
+1D7FA ; [.0FCA.0020.0005.1D7FA] # MATHEMATICAL MONOSPACE DIGIT FOUR; QQK
+2463 ; [.0FCA.0020.0006.2463] # CIRCLED DIGIT FOUR; QQK
+24F8 ; [.0FCA.0020.0006.24F8] # DOUBLE CIRCLED DIGIT FOUR; QQK
+2779 ; [.0FCA.0020.0006.2779] # DINGBAT NEGATIVE CIRCLED DIGIT FOUR; QQK
+2783 ; [.0FCA.0020.0006.2783] # DINGBAT CIRCLED SANS-SERIF DIGIT FOUR; QQK
+278D ; [.0FCA.0020.0006.278D] # DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR; QQK
+2074 ; [.0FCA.0020.0014.2074] # SUPERSCRIPT FOUR; QQK
+2084 ; [.0FCA.0020.0015.2084] # SUBSCRIPT FOUR; QQK
+0664 ; [.0FCA.0020.0002.0664][.0000.019F.0002.0664] # ARABIC-INDIC DIGIT FOUR
+06F4 ; [.0FCA.0020.0002.06F4][.0000.01A0.0002.06F4] # EXTENDED ARABIC-INDIC DIGIT FOUR
+07C4 ; [.0FCA.0020.0002.07C4][.0000.01A1.0002.07C4] # NKO DIGIT FOUR
+136C ; [.0FCA.0020.0002.136C][.0000.01A2.0002.136C] # ETHIOPIC DIGIT FOUR
+104A4 ; [.0FCA.0020.0002.104A4][.0000.01A3.0002.104A4] # OSMANYA DIGIT FOUR
+096A ; [.0FCA.0020.0002.096A][.0000.01A4.0002.096A] # DEVANAGARI DIGIT FOUR
+09EA ; [.0FCA.0020.0002.09EA][.0000.01A5.0002.09EA] # BENGALI DIGIT FOUR
+09F7 ; [.0FCA.0020.0002.09F7][.0000.01A5.0002.09F7] # BENGALI CURRENCY NUMERATOR FOUR
+0A6A ; [.0FCA.0020.0002.0A6A][.0000.01A6.0002.0A6A] # GURMUKHI DIGIT FOUR
+0AEA ; [.0FCA.0020.0002.0AEA][.0000.01A7.0002.0AEA] # GUJARATI DIGIT FOUR
+0B6A ; [.0FCA.0020.0002.0B6A][.0000.01A8.0002.0B6A] # ORIYA DIGIT FOUR
+0BEA ; [.0FCA.0020.0002.0BEA][.0000.01A9.0002.0BEA] # TAMIL DIGIT FOUR
+0C6A ; [.0FCA.0020.0002.0C6A][.0000.01AA.0002.0C6A] # TELUGU DIGIT FOUR
+0CEA ; [.0FCA.0020.0002.0CEA][.0000.01AB.0002.0CEA] # KANNADA DIGIT FOUR
+0D6A ; [.0FCA.0020.0002.0D6A][.0000.01AC.0002.0D6A] # MALAYALAM DIGIT FOUR
+194A ; [.0FCA.0020.0002.194A][.0000.01AD.0002.194A] # LIMBU DIGIT FOUR
+19D4 ; [.0FCA.0020.0002.19D4][.0000.01AE.0002.19D4] # NEW TAI LUE DIGIT FOUR
+0E54 ; [.0FCA.0020.0002.0E54][.0000.01AF.0002.0E54] # THAI DIGIT FOUR
+0ED4 ; [.0FCA.0020.0002.0ED4][.0000.01B0.0002.0ED4] # LAO DIGIT FOUR
+0F24 ; [.0FCA.0020.0002.0F24][.0000.01B1.0002.0F24] # TIBETAN DIGIT FOUR
+0F2D ; [.0FCA.0020.0004.0F2D][.0000.01B1.0004.0F2D] # TIBETAN DIGIT HALF FOUR; QQK
+1044 ; [.0FCA.0020.0002.1044][.0000.01B2.0002.1044] # MYANMAR DIGIT FOUR
+17E4 ; [.0FCA.0020.0002.17E4][.0000.01B3.0002.17E4] # KHMER DIGIT FOUR
+17F4 ; [.0FCA.0020.0002.17F4][.0000.01B4.0002.17F4] # KHMER SYMBOL LEK ATTAK BUON
+1B54 ; [.0FCA.0020.0002.1B54][.0000.01B5.0002.1B54] # BALINESE DIGIT FOUR
+1814 ; [.0FCA.0020.0002.1814][.0000.01B6.0002.1814] # MONGOLIAN DIGIT FOUR
+3024 ; [.0FCA.0020.0002.3024][.0000.01B7.0002.3024] # HANGZHOU NUMERAL FOUR
+1010A ; [.0FCA.0020.0002.1010A][.0000.01B8.0002.1010A] # AEGEAN NUMBER FOUR
+12402 ; [.0FCA.0020.0002.12402][.0000.01BC.0002.12402] # CUNEIFORM NUMERIC SIGN FOUR ASH
+12409 ; [.0FCA.0020.0002.12409][.0000.01BC.0002.12409] # CUNEIFORM NUMERIC SIGN FOUR DISH
+1240F ; [.0FCA.0020.0002.1240F][.0000.01BC.0002.1240F] # CUNEIFORM NUMERIC SIGN FOUR U
+12418 ; [.0FCA.0020.0002.12418][.0000.01BC.0002.12418] # CUNEIFORM NUMERIC SIGN FOUR GESH2
+12421 ; [.0FCA.0020.0002.12421][.0000.01BC.0002.12421] # CUNEIFORM NUMERIC SIGN FOUR GESHU
+12426 ; [.0FCA.0020.0002.12426][.0000.01BC.0002.12426] # CUNEIFORM NUMERIC SIGN FOUR SHAR2
+12430 ; [.0FCA.0020.0002.12430][.0000.01BC.0002.12430] # CUNEIFORM NUMERIC SIGN FOUR SHARU
+12438 ; [.0FCA.0020.0002.12438][.0000.01BC.0002.12438] # CUNEIFORM NUMERIC SIGN FOUR BURU
+1243C ; [.0FCA.0020.0002.1243C][.0000.01BC.0002.1243C] # CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU
+1243D ; [.0FCA.0020.0002.1243D][.0000.01BC.0002.1243D] # CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU4
+1243E ; [.0FCA.0020.0002.1243E][.0000.01BC.0002.1243E] # CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU A
+1243F ; [.0FCA.0020.0002.1243F][.0000.01BC.0002.1243F] # CUNEIFORM NUMERIC SIGN FOUR VARIANT FORM LIMMU B
+1244C ; [.0FCA.0020.0002.1244C][.0000.01BC.0002.1244C] # CUNEIFORM NUMERIC SIGN FOUR ASH TENU
+12452 ; [.0FCA.0020.0002.12452][.0000.01BC.0002.12452] # CUNEIFORM NUMERIC SIGN FOUR BAN2
+12453 ; [.0FCA.0020.0002.12453][.0000.01BC.0002.12453] # CUNEIFORM NUMERIC SIGN FOUR BAN2 VARIANT FORM
+10A43 ; [.0FCA.0020.0002.10A43][.0000.01BE.0002.10A43] # KHAROSHTHI DIGIT FOUR
+1D363 ; [.0FCA.0020.0002.1D363][.0000.01BF.0002.1D363] # COUNTING ROD UNIT DIGIT FOUR
+32B5 ; [.0FCA.0020.0006.32B5][.0FC6.0020.0006.32B5] # CIRCLED NUMBER FORTY; QQKN
+32B6 ; [.0FCA.0020.0006.32B6][.0FC7.0020.0006.32B6] # CIRCLED NUMBER FORTY ONE; QQKN
+32B7 ; [.0FCA.0020.0006.32B7][.0FC8.0020.0006.32B7] # CIRCLED NUMBER FORTY TWO; QQKN
+32B8 ; [.0FCA.0020.0006.32B8][.0FC9.0020.0006.32B8] # CIRCLED NUMBER FORTY THREE; QQKN
+32B9 ; [.0FCA.0020.0006.32B9][.0FCA.0020.0006.32B9] # CIRCLED NUMBER FORTY FOUR; QQKN
+32BA ; [.0FCA.0020.0006.32BA][.0FCB.0020.0006.32BA] # CIRCLED NUMBER FORTY FIVE; QQKN
+2158 ; [.0FCA.0020.001E.2158][*0300.0020.001E.2158][.0FCB.0020.001F.2158] # VULGAR FRACTION FOUR FIFTHS; QQKN
+32BB ; [.0FCA.0020.0006.32BB][.0FCC.0020.0006.32BB] # CIRCLED NUMBER FORTY SIX; QQKN
+32BC ; [.0FCA.0020.0006.32BC][.0FCD.0020.0006.32BC] # CIRCLED NUMBER FORTY SEVEN; QQKN
+32BD ; [.0FCA.0020.0006.32BD][.0FCE.0020.0006.32BD] # CIRCLED NUMBER FORTY EIGHT; QQKN
+32BE ; [.0FCA.0020.0006.32BE][.0FCF.0020.0006.32BE] # CIRCLED NUMBER FORTY NINE; QQKN
+33E3 ; [.0FCA.0020.0004.33E3][.FB40.0020.0004.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FOUR; QQKN
+32C3 ; [.0FCA.0020.0004.32C3][.FB40.0020.0004.6708][.E708.0000.0000.6708] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR APRIL; QQKN
+335C ; [.0FCA.0020.0004.335C][.FB40.0020.0004.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FOUR; QQKN
+0035 ; [.0FCB.0020.0002.0035] # DIGIT FIVE
+FF15 ; [.0FCB.0020.0003.FF15] # FULLWIDTH DIGIT FIVE; QQK
+2478 ; [*02B1.0020.0004.2478][.0FCB.0020.0004.2478][*02B2.0020.001F.2478] # PARENTHESIZED DIGIT FIVE; QQKN
+248C ; [.0FCB.0020.0004.248C][*0266.0020.0004.248C] # DIGIT FIVE FULL STOP; QQKN
+1D7D3 ; [.0FCB.0020.0005.1D7D3] # MATHEMATICAL BOLD DIGIT FIVE; QQK
+1D7DD ; [.0FCB.0020.0005.1D7DD] # MATHEMATICAL DOUBLE-STRUCK DIGIT FIVE; QQK
+1D7E7 ; [.0FCB.0020.0005.1D7E7] # MATHEMATICAL SANS-SERIF DIGIT FIVE; QQK
+1D7F1 ; [.0FCB.0020.0005.1D7F1] # MATHEMATICAL SANS-SERIF BOLD DIGIT FIVE; QQK
+1D7FB ; [.0FCB.0020.0005.1D7FB] # MATHEMATICAL MONOSPACE DIGIT FIVE; QQK
+2464 ; [.0FCB.0020.0006.2464] # CIRCLED DIGIT FIVE; QQK
+24F9 ; [.0FCB.0020.0006.24F9] # DOUBLE CIRCLED DIGIT FIVE; QQK
+277A ; [.0FCB.0020.0006.277A] # DINGBAT NEGATIVE CIRCLED DIGIT FIVE; QQK
+2784 ; [.0FCB.0020.0006.2784] # DINGBAT CIRCLED SANS-SERIF DIGIT FIVE; QQK
+278E ; [.0FCB.0020.0006.278E] # DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE; QQK
+2075 ; [.0FCB.0020.0014.2075] # SUPERSCRIPT FIVE; QQK
+2085 ; [.0FCB.0020.0015.2085] # SUBSCRIPT FIVE; QQK
+0665 ; [.0FCB.0020.0002.0665][.0000.019F.0002.0665] # ARABIC-INDIC DIGIT FIVE
+06F5 ; [.0FCB.0020.0002.06F5][.0000.01A0.0002.06F5] # EXTENDED ARABIC-INDIC DIGIT FIVE
+07C5 ; [.0FCB.0020.0002.07C5][.0000.01A1.0002.07C5] # NKO DIGIT FIVE
+136D ; [.0FCB.0020.0002.136D][.0000.01A2.0002.136D] # ETHIOPIC DIGIT FIVE
+104A5 ; [.0FCB.0020.0002.104A5][.0000.01A3.0002.104A5] # OSMANYA DIGIT FIVE
+096B ; [.0FCB.0020.0002.096B][.0000.01A4.0002.096B] # DEVANAGARI DIGIT FIVE
+09EB ; [.0FCB.0020.0002.09EB][.0000.01A5.0002.09EB] # BENGALI DIGIT FIVE
+0A6B ; [.0FCB.0020.0002.0A6B][.0000.01A6.0002.0A6B] # GURMUKHI DIGIT FIVE
+0AEB ; [.0FCB.0020.0002.0AEB][.0000.01A7.0002.0AEB] # GUJARATI DIGIT FIVE
+0B6B ; [.0FCB.0020.0002.0B6B][.0000.01A8.0002.0B6B] # ORIYA DIGIT FIVE
+0BEB ; [.0FCB.0020.0002.0BEB][.0000.01A9.0002.0BEB] # TAMIL DIGIT FIVE
+0C6B ; [.0FCB.0020.0002.0C6B][.0000.01AA.0002.0C6B] # TELUGU DIGIT FIVE
+0CEB ; [.0FCB.0020.0002.0CEB][.0000.01AB.0002.0CEB] # KANNADA DIGIT FIVE
+0D6B ; [.0FCB.0020.0002.0D6B][.0000.01AC.0002.0D6B] # MALAYALAM DIGIT FIVE
+194B ; [.0FCB.0020.0002.194B][.0000.01AD.0002.194B] # LIMBU DIGIT FIVE
+19D5 ; [.0FCB.0020.0002.19D5][.0000.01AE.0002.19D5] # NEW TAI LUE DIGIT FIVE
+0E55 ; [.0FCB.0020.0002.0E55][.0000.01AF.0002.0E55] # THAI DIGIT FIVE
+0ED5 ; [.0FCB.0020.0002.0ED5][.0000.01B0.0002.0ED5] # LAO DIGIT FIVE
+0F25 ; [.0FCB.0020.0002.0F25][.0000.01B1.0002.0F25] # TIBETAN DIGIT FIVE
+0F2E ; [.0FCB.0020.0004.0F2E][.0000.01B1.0004.0F2E] # TIBETAN DIGIT HALF FIVE; QQK
+1045 ; [.0FCB.0020.0002.1045][.0000.01B2.0002.1045] # MYANMAR DIGIT FIVE
+17E5 ; [.0FCB.0020.0002.17E5][.0000.01B3.0002.17E5] # KHMER DIGIT FIVE
+17F5 ; [.0FCB.0020.0002.17F5][.0000.01B4.0002.17F5] # KHMER SYMBOL LEK ATTAK PRAM
+1B55 ; [.0FCB.0020.0002.1B55][.0000.01B5.0002.1B55] # BALINESE DIGIT FIVE
+1815 ; [.0FCB.0020.0002.1815][.0000.01B6.0002.1815] # MONGOLIAN DIGIT FIVE
+3025 ; [.0FCB.0020.0002.3025][.0000.01B7.0002.3025] # HANGZHOU NUMERAL FIVE
+1010B ; [.0FCB.0020.0002.1010B][.0000.01B8.0002.1010B] # AEGEAN NUMBER FIVE
+10143 ; [.0FCB.0020.0002.10143][.0000.01B9.0002.10143] # GREEK ACROPHONIC ATTIC FIVE
+10148 ; [.0FCB.0020.0002.10148][.0000.01B9.0002.10148] # GREEK ACROPHONIC ATTIC FIVE TALENTS
+1014F ; [.0FCB.0020.0002.1014F][.0000.01B9.0002.1014F] # GREEK ACROPHONIC ATTIC FIVE STATERS
+1015F ; [.0FCB.0020.0002.1015F][.0000.01B9.0002.1015F] # GREEK ACROPHONIC TROEZENIAN FIVE
+10173 ; [.0FCB.0020.0002.10173][.0000.01B9.0002.10173] # GREEK ACROPHONIC DELPHIC FIVE MNAS
+10321 ; [.0FCB.0020.0002.10321][.0000.01BA.0002.10321] # OLD ITALIC NUMERAL FIVE
+12403 ; [.0FCB.0020.0002.12403][.0000.01BC.0002.12403] # CUNEIFORM NUMERIC SIGN FIVE ASH
+1240A ; [.0FCB.0020.0002.1240A][.0000.01BC.0002.1240A] # CUNEIFORM NUMERIC SIGN FIVE DISH
+12410 ; [.0FCB.0020.0002.12410][.0000.01BC.0002.12410] # CUNEIFORM NUMERIC SIGN FIVE U
+12419 ; [.0FCB.0020.0002.12419][.0000.01BC.0002.12419] # CUNEIFORM NUMERIC SIGN FIVE GESH2
+12422 ; [.0FCB.0020.0002.12422][.0000.01BC.0002.12422] # CUNEIFORM NUMERIC SIGN FIVE GESHU
+12427 ; [.0FCB.0020.0002.12427][.0000.01BC.0002.12427] # CUNEIFORM NUMERIC SIGN FIVE SHAR2
+12431 ; [.0FCB.0020.0002.12431][.0000.01BC.0002.12431] # CUNEIFORM NUMERIC SIGN FIVE SHARU
+12439 ; [.0FCB.0020.0002.12439][.0000.01BC.0002.12439] # CUNEIFORM NUMERIC SIGN FIVE BURU
+1244D ; [.0FCB.0020.0002.1244D][.0000.01BC.0002.1244D] # CUNEIFORM NUMERIC SIGN FIVE ASH TENU
+12454 ; [.0FCB.0020.0002.12454][.0000.01BC.0002.12454] # CUNEIFORM NUMERIC SIGN FIVE BAN2
+12455 ; [.0FCB.0020.0002.12455][.0000.01BC.0002.12455] # CUNEIFORM NUMERIC SIGN FIVE BAN2 VARIANT FORM
+1D364 ; [.0FCB.0020.0002.1D364][.0000.01BF.0002.1D364] # COUNTING ROD UNIT DIGIT FIVE
+32BF ; [.0FCB.0020.0006.32BF][.0FC6.0020.0006.32BF] # CIRCLED NUMBER FIFTY; QQKN
+215A ; [.0FCB.0020.001E.215A][*0300.0020.001E.215A][.0FCC.0020.001F.215A] # VULGAR FRACTION FIVE SIXTHS; QQKN
+215D ; [.0FCB.0020.001E.215D][*0300.0020.001E.215D][.0FCE.0020.001F.215D] # VULGAR FRACTION FIVE EIGHTHS; QQKN
+33E4 ; [.0FCB.0020.0004.33E4][.FB40.0020.0004.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY FIVE; QQKN
+32C4 ; [.0FCB.0020.0004.32C4][.FB40.0020.0004.6708][.E708.0000.0000.6708] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR MAY; QQKN
+335D ; [.0FCB.0020.0004.335D][.FB40.0020.0004.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR FIVE; QQKN
+0036 ; [.0FCC.0020.0002.0036] # DIGIT SIX
+FF16 ; [.0FCC.0020.0003.FF16] # FULLWIDTH DIGIT SIX; QQK
+2479 ; [*02B1.0020.0004.2479][.0FCC.0020.0004.2479][*02B2.0020.001F.2479] # PARENTHESIZED DIGIT SIX; QQKN
+248D ; [.0FCC.0020.0004.248D][*0266.0020.0004.248D] # DIGIT SIX FULL STOP; QQKN
+1D7D4 ; [.0FCC.0020.0005.1D7D4] # MATHEMATICAL BOLD DIGIT SIX; QQK
+1D7DE ; [.0FCC.0020.0005.1D7DE] # MATHEMATICAL DOUBLE-STRUCK DIGIT SIX; QQK
+1D7E8 ; [.0FCC.0020.0005.1D7E8] # MATHEMATICAL SANS-SERIF DIGIT SIX; QQK
+1D7F2 ; [.0FCC.0020.0005.1D7F2] # MATHEMATICAL SANS-SERIF BOLD DIGIT SIX; QQK
+1D7FC ; [.0FCC.0020.0005.1D7FC] # MATHEMATICAL MONOSPACE DIGIT SIX; QQK
+2465 ; [.0FCC.0020.0006.2465] # CIRCLED DIGIT SIX; QQK
+24FA ; [.0FCC.0020.0006.24FA] # DOUBLE CIRCLED DIGIT SIX; QQK
+277B ; [.0FCC.0020.0006.277B] # DINGBAT NEGATIVE CIRCLED DIGIT SIX; QQK
+2785 ; [.0FCC.0020.0006.2785] # DINGBAT CIRCLED SANS-SERIF DIGIT SIX; QQK
+278F ; [.0FCC.0020.0006.278F] # DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX; QQK
+2076 ; [.0FCC.0020.0014.2076] # SUPERSCRIPT SIX; QQK
+2086 ; [.0FCC.0020.0015.2086] # SUBSCRIPT SIX; QQK
+0666 ; [.0FCC.0020.0002.0666][.0000.019F.0002.0666] # ARABIC-INDIC DIGIT SIX
+06F6 ; [.0FCC.0020.0002.06F6][.0000.01A0.0002.06F6] # EXTENDED ARABIC-INDIC DIGIT SIX
+07C6 ; [.0FCC.0020.0002.07C6][.0000.01A1.0002.07C6] # NKO DIGIT SIX
+136E ; [.0FCC.0020.0002.136E][.0000.01A2.0002.136E] # ETHIOPIC DIGIT SIX
+104A6 ; [.0FCC.0020.0002.104A6][.0000.01A3.0002.104A6] # OSMANYA DIGIT SIX
+096C ; [.0FCC.0020.0002.096C][.0000.01A4.0002.096C] # DEVANAGARI DIGIT SIX
+09EC ; [.0FCC.0020.0002.09EC][.0000.01A5.0002.09EC] # BENGALI DIGIT SIX
+0A6C ; [.0FCC.0020.0002.0A6C][.0000.01A6.0002.0A6C] # GURMUKHI DIGIT SIX
+0AEC ; [.0FCC.0020.0002.0AEC][.0000.01A7.0002.0AEC] # GUJARATI DIGIT SIX
+0B6C ; [.0FCC.0020.0002.0B6C][.0000.01A8.0002.0B6C] # ORIYA DIGIT SIX
+0BEC ; [.0FCC.0020.0002.0BEC][.0000.01A9.0002.0BEC] # TAMIL DIGIT SIX
+0C6C ; [.0FCC.0020.0002.0C6C][.0000.01AA.0002.0C6C] # TELUGU DIGIT SIX
+0CEC ; [.0FCC.0020.0002.0CEC][.0000.01AB.0002.0CEC] # KANNADA DIGIT SIX
+0D6C ; [.0FCC.0020.0002.0D6C][.0000.01AC.0002.0D6C] # MALAYALAM DIGIT SIX
+194C ; [.0FCC.0020.0002.194C][.0000.01AD.0002.194C] # LIMBU DIGIT SIX
+19D6 ; [.0FCC.0020.0002.19D6][.0000.01AE.0002.19D6] # NEW TAI LUE DIGIT SIX
+0E56 ; [.0FCC.0020.0002.0E56][.0000.01AF.0002.0E56] # THAI DIGIT SIX
+0ED6 ; [.0FCC.0020.0002.0ED6][.0000.01B0.0002.0ED6] # LAO DIGIT SIX
+0F26 ; [.0FCC.0020.0002.0F26][.0000.01B1.0002.0F26] # TIBETAN DIGIT SIX
+0F2F ; [.0FCC.0020.0004.0F2F][.0000.01B1.0004.0F2F] # TIBETAN DIGIT HALF SIX; QQK
+1046 ; [.0FCC.0020.0002.1046][.0000.01B2.0002.1046] # MYANMAR DIGIT SIX
+17E6 ; [.0FCC.0020.0002.17E6][.0000.01B3.0002.17E6] # KHMER DIGIT SIX
+17F6 ; [.0FCC.0020.0002.17F6][.0000.01B4.0002.17F6] # KHMER SYMBOL LEK ATTAK PRAM-MUOY
+1B56 ; [.0FCC.0020.0002.1B56][.0000.01B5.0002.1B56] # BALINESE DIGIT SIX
+1816 ; [.0FCC.0020.0002.1816][.0000.01B6.0002.1816] # MONGOLIAN DIGIT SIX
+3026 ; [.0FCC.0020.0002.3026][.0000.01B7.0002.3026] # HANGZHOU NUMERAL SIX
+1010C ; [.0FCC.0020.0002.1010C][.0000.01B8.0002.1010C] # AEGEAN NUMBER SIX
+12404 ; [.0FCC.0020.0002.12404][.0000.01BC.0002.12404] # CUNEIFORM NUMERIC SIGN SIX ASH
+1240B ; [.0FCC.0020.0002.1240B][.0000.01BC.0002.1240B] # CUNEIFORM NUMERIC SIGN SIX DISH
+12411 ; [.0FCC.0020.0002.12411][.0000.01BC.0002.12411] # CUNEIFORM NUMERIC SIGN SIX U
+1241A ; [.0FCC.0020.0002.1241A][.0000.01BC.0002.1241A] # CUNEIFORM NUMERIC SIGN SIX GESH2
+12428 ; [.0FCC.0020.0002.12428][.0000.01BC.0002.12428] # CUNEIFORM NUMERIC SIGN SIX SHAR2
+12440 ; [.0FCC.0020.0002.12440][.0000.01BC.0002.12440] # CUNEIFORM NUMERIC SIGN SIX VARIANT FORM ASH9
+1244E ; [.0FCC.0020.0002.1244E][.0000.01BC.0002.1244E] # CUNEIFORM NUMERIC SIGN SIX ASH TENU
+1D365 ; [.0FCC.0020.0002.1D365][.0000.01BF.0002.1D365] # COUNTING ROD UNIT DIGIT SIX
+33E5 ; [.0FCC.0020.0004.33E5][.FB40.0020.0004.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SIX; QQKN
+32C5 ; [.0FCC.0020.0004.32C5][.FB40.0020.0004.6708][.E708.0000.0000.6708] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR JUNE; QQKN
+335E ; [.0FCC.0020.0004.335E][.FB40.0020.0004.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SIX; QQKN
+0037 ; [.0FCD.0020.0002.0037] # DIGIT SEVEN
+FF17 ; [.0FCD.0020.0003.FF17] # FULLWIDTH DIGIT SEVEN; QQK
+247A ; [*02B1.0020.0004.247A][.0FCD.0020.0004.247A][*02B2.0020.001F.247A] # PARENTHESIZED DIGIT SEVEN; QQKN
+248E ; [.0FCD.0020.0004.248E][*0266.0020.0004.248E] # DIGIT SEVEN FULL STOP; QQKN
+1D7D5 ; [.0FCD.0020.0005.1D7D5] # MATHEMATICAL BOLD DIGIT SEVEN; QQK
+1D7DF ; [.0FCD.0020.0005.1D7DF] # MATHEMATICAL DOUBLE-STRUCK DIGIT SEVEN; QQK
+1D7E9 ; [.0FCD.0020.0005.1D7E9] # MATHEMATICAL SANS-SERIF DIGIT SEVEN; QQK
+1D7F3 ; [.0FCD.0020.0005.1D7F3] # MATHEMATICAL SANS-SERIF BOLD DIGIT SEVEN; QQK
+1D7FD ; [.0FCD.0020.0005.1D7FD] # MATHEMATICAL MONOSPACE DIGIT SEVEN; QQK
+2466 ; [.0FCD.0020.0006.2466] # CIRCLED DIGIT SEVEN; QQK
+24FB ; [.0FCD.0020.0006.24FB] # DOUBLE CIRCLED DIGIT SEVEN; QQK
+277C ; [.0FCD.0020.0006.277C] # DINGBAT NEGATIVE CIRCLED DIGIT SEVEN; QQK
+2786 ; [.0FCD.0020.0006.2786] # DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN; QQK
+2790 ; [.0FCD.0020.0006.2790] # DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN; QQK
+2077 ; [.0FCD.0020.0014.2077] # SUPERSCRIPT SEVEN; QQK
+2087 ; [.0FCD.0020.0015.2087] # SUBSCRIPT SEVEN; QQK
+0667 ; [.0FCD.0020.0002.0667][.0000.019F.0002.0667] # ARABIC-INDIC DIGIT SEVEN
+06F7 ; [.0FCD.0020.0002.06F7][.0000.01A0.0002.06F7] # EXTENDED ARABIC-INDIC DIGIT SEVEN
+07C7 ; [.0FCD.0020.0002.07C7][.0000.01A1.0002.07C7] # NKO DIGIT SEVEN
+136F ; [.0FCD.0020.0002.136F][.0000.01A2.0002.136F] # ETHIOPIC DIGIT SEVEN
+104A7 ; [.0FCD.0020.0002.104A7][.0000.01A3.0002.104A7] # OSMANYA DIGIT SEVEN
+096D ; [.0FCD.0020.0002.096D][.0000.01A4.0002.096D] # DEVANAGARI DIGIT SEVEN
+09ED ; [.0FCD.0020.0002.09ED][.0000.01A5.0002.09ED] # BENGALI DIGIT SEVEN
+0A6D ; [.0FCD.0020.0002.0A6D][.0000.01A6.0002.0A6D] # GURMUKHI DIGIT SEVEN
+0AED ; [.0FCD.0020.0002.0AED][.0000.01A7.0002.0AED] # GUJARATI DIGIT SEVEN
+0B6D ; [.0FCD.0020.0002.0B6D][.0000.01A8.0002.0B6D] # ORIYA DIGIT SEVEN
+0BED ; [.0FCD.0020.0002.0BED][.0000.01A9.0002.0BED] # TAMIL DIGIT SEVEN
+0C6D ; [.0FCD.0020.0002.0C6D][.0000.01AA.0002.0C6D] # TELUGU DIGIT SEVEN
+0CED ; [.0FCD.0020.0002.0CED][.0000.01AB.0002.0CED] # KANNADA DIGIT SEVEN
+0D6D ; [.0FCD.0020.0002.0D6D][.0000.01AC.0002.0D6D] # MALAYALAM DIGIT SEVEN
+194D ; [.0FCD.0020.0002.194D][.0000.01AD.0002.194D] # LIMBU DIGIT SEVEN
+19D7 ; [.0FCD.0020.0002.19D7][.0000.01AE.0002.19D7] # NEW TAI LUE DIGIT SEVEN
+0E57 ; [.0FCD.0020.0002.0E57][.0000.01AF.0002.0E57] # THAI DIGIT SEVEN
+0ED7 ; [.0FCD.0020.0002.0ED7][.0000.01B0.0002.0ED7] # LAO DIGIT SEVEN
+0F27 ; [.0FCD.0020.0002.0F27][.0000.01B1.0002.0F27] # TIBETAN DIGIT SEVEN
+0F30 ; [.0FCD.0020.0004.0F30][.0000.01B1.0004.0F30] # TIBETAN DIGIT HALF SEVEN; QQK
+1047 ; [.0FCD.0020.0002.1047][.0000.01B2.0002.1047] # MYANMAR DIGIT SEVEN
+17E7 ; [.0FCD.0020.0002.17E7][.0000.01B3.0002.17E7] # KHMER DIGIT SEVEN
+17F7 ; [.0FCD.0020.0002.17F7][.0000.01B4.0002.17F7] # KHMER SYMBOL LEK ATTAK PRAM-PII
+1B57 ; [.0FCD.0020.0002.1B57][.0000.01B5.0002.1B57] # BALINESE DIGIT SEVEN
+1817 ; [.0FCD.0020.0002.1817][.0000.01B6.0002.1817] # MONGOLIAN DIGIT SEVEN
+3027 ; [.0FCD.0020.0002.3027][.0000.01B7.0002.3027] # HANGZHOU NUMERAL SEVEN
+1010D ; [.0FCD.0020.0002.1010D][.0000.01B8.0002.1010D] # AEGEAN NUMBER SEVEN
+12405 ; [.0FCD.0020.0002.12405][.0000.01BC.0002.12405] # CUNEIFORM NUMERIC SIGN SEVEN ASH
+1240C ; [.0FCD.0020.0002.1240C][.0000.01BC.0002.1240C] # CUNEIFORM NUMERIC SIGN SEVEN DISH
+12412 ; [.0FCD.0020.0002.12412][.0000.01BC.0002.12412] # CUNEIFORM NUMERIC SIGN SEVEN U
+1241B ; [.0FCD.0020.0002.1241B][.0000.01BC.0002.1241B] # CUNEIFORM NUMERIC SIGN SEVEN GESH2
+12429 ; [.0FCD.0020.0002.12429][.0000.01BC.0002.12429] # CUNEIFORM NUMERIC SIGN SEVEN SHAR2
+12441 ; [.0FCD.0020.0002.12441][.0000.01BC.0002.12441] # CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN3
+12442 ; [.0FCD.0020.0002.12442][.0000.01BC.0002.12442] # CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN A
+12443 ; [.0FCD.0020.0002.12443][.0000.01BC.0002.12443] # CUNEIFORM NUMERIC SIGN SEVEN VARIANT FORM IMIN B
+1D366 ; [.0FCD.0020.0002.1D366][.0000.01BF.0002.1D366] # COUNTING ROD UNIT DIGIT SEVEN
+215E ; [.0FCD.0020.001E.215E][*0300.0020.001E.215E][.0FCE.0020.001F.215E] # VULGAR FRACTION SEVEN EIGHTHS; QQKN
+33E6 ; [.0FCD.0020.0004.33E6][.FB40.0020.0004.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY SEVEN; QQKN
+32C6 ; [.0FCD.0020.0004.32C6][.FB40.0020.0004.6708][.E708.0000.0000.6708] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR JULY; QQKN
+335F ; [.0FCD.0020.0004.335F][.FB40.0020.0004.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR SEVEN; QQKN
+0038 ; [.0FCE.0020.0002.0038] # DIGIT EIGHT
+FF18 ; [.0FCE.0020.0003.FF18] # FULLWIDTH DIGIT EIGHT; QQK
+247B ; [*02B1.0020.0004.247B][.0FCE.0020.0004.247B][*02B2.0020.001F.247B] # PARENTHESIZED DIGIT EIGHT; QQKN
+248F ; [.0FCE.0020.0004.248F][*0266.0020.0004.248F] # DIGIT EIGHT FULL STOP; QQKN
+1D7D6 ; [.0FCE.0020.0005.1D7D6] # MATHEMATICAL BOLD DIGIT EIGHT; QQK
+1D7E0 ; [.0FCE.0020.0005.1D7E0] # MATHEMATICAL DOUBLE-STRUCK DIGIT EIGHT; QQK
+1D7EA ; [.0FCE.0020.0005.1D7EA] # MATHEMATICAL SANS-SERIF DIGIT EIGHT; QQK
+1D7F4 ; [.0FCE.0020.0005.1D7F4] # MATHEMATICAL SANS-SERIF BOLD DIGIT EIGHT; QQK
+1D7FE ; [.0FCE.0020.0005.1D7FE] # MATHEMATICAL MONOSPACE DIGIT EIGHT; QQK
+2467 ; [.0FCE.0020.0006.2467] # CIRCLED DIGIT EIGHT; QQK
+24FC ; [.0FCE.0020.0006.24FC] # DOUBLE CIRCLED DIGIT EIGHT; QQK
+277D ; [.0FCE.0020.0006.277D] # DINGBAT NEGATIVE CIRCLED DIGIT EIGHT; QQK
+2787 ; [.0FCE.0020.0006.2787] # DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT; QQK
+2791 ; [.0FCE.0020.0006.2791] # DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT; QQK
+2078 ; [.0FCE.0020.0014.2078] # SUPERSCRIPT EIGHT; QQK
+2088 ; [.0FCE.0020.0015.2088] # SUBSCRIPT EIGHT; QQK
+0668 ; [.0FCE.0020.0002.0668][.0000.019F.0002.0668] # ARABIC-INDIC DIGIT EIGHT
+06F8 ; [.0FCE.0020.0002.06F8][.0000.01A0.0002.06F8] # EXTENDED ARABIC-INDIC DIGIT EIGHT
+07C8 ; [.0FCE.0020.0002.07C8][.0000.01A1.0002.07C8] # NKO DIGIT EIGHT
+1370 ; [.0FCE.0020.0002.1370][.0000.01A2.0002.1370] # ETHIOPIC DIGIT EIGHT
+104A8 ; [.0FCE.0020.0002.104A8][.0000.01A3.0002.104A8] # OSMANYA DIGIT EIGHT
+096E ; [.0FCE.0020.0002.096E][.0000.01A4.0002.096E] # DEVANAGARI DIGIT EIGHT
+09EE ; [.0FCE.0020.0002.09EE][.0000.01A5.0002.09EE] # BENGALI DIGIT EIGHT
+0A6E ; [.0FCE.0020.0002.0A6E][.0000.01A6.0002.0A6E] # GURMUKHI DIGIT EIGHT
+0AEE ; [.0FCE.0020.0002.0AEE][.0000.01A7.0002.0AEE] # GUJARATI DIGIT EIGHT
+0B6E ; [.0FCE.0020.0002.0B6E][.0000.01A8.0002.0B6E] # ORIYA DIGIT EIGHT
+0BEE ; [.0FCE.0020.0002.0BEE][.0000.01A9.0002.0BEE] # TAMIL DIGIT EIGHT
+0C6E ; [.0FCE.0020.0002.0C6E][.0000.01AA.0002.0C6E] # TELUGU DIGIT EIGHT
+0CEE ; [.0FCE.0020.0002.0CEE][.0000.01AB.0002.0CEE] # KANNADA DIGIT EIGHT
+0D6E ; [.0FCE.0020.0002.0D6E][.0000.01AC.0002.0D6E] # MALAYALAM DIGIT EIGHT
+194E ; [.0FCE.0020.0002.194E][.0000.01AD.0002.194E] # LIMBU DIGIT EIGHT
+19D8 ; [.0FCE.0020.0002.19D8][.0000.01AE.0002.19D8] # NEW TAI LUE DIGIT EIGHT
+0E58 ; [.0FCE.0020.0002.0E58][.0000.01AF.0002.0E58] # THAI DIGIT EIGHT
+0ED8 ; [.0FCE.0020.0002.0ED8][.0000.01B0.0002.0ED8] # LAO DIGIT EIGHT
+0F28 ; [.0FCE.0020.0002.0F28][.0000.01B1.0002.0F28] # TIBETAN DIGIT EIGHT
+0F31 ; [.0FCE.0020.0004.0F31][.0000.01B1.0004.0F31] # TIBETAN DIGIT HALF EIGHT; QQK
+1048 ; [.0FCE.0020.0002.1048][.0000.01B2.0002.1048] # MYANMAR DIGIT EIGHT
+17E8 ; [.0FCE.0020.0002.17E8][.0000.01B3.0002.17E8] # KHMER DIGIT EIGHT
+17F8 ; [.0FCE.0020.0002.17F8][.0000.01B4.0002.17F8] # KHMER SYMBOL LEK ATTAK PRAM-BEI
+1B58 ; [.0FCE.0020.0002.1B58][.0000.01B5.0002.1B58] # BALINESE DIGIT EIGHT
+1818 ; [.0FCE.0020.0002.1818][.0000.01B6.0002.1818] # MONGOLIAN DIGIT EIGHT
+3028 ; [.0FCE.0020.0002.3028][.0000.01B7.0002.3028] # HANGZHOU NUMERAL EIGHT
+1010E ; [.0FCE.0020.0002.1010E][.0000.01B8.0002.1010E] # AEGEAN NUMBER EIGHT
+12406 ; [.0FCE.0020.0002.12406][.0000.01BC.0002.12406] # CUNEIFORM NUMERIC SIGN EIGHT ASH
+1240D ; [.0FCE.0020.0002.1240D][.0000.01BC.0002.1240D] # CUNEIFORM NUMERIC SIGN EIGHT DISH
+12413 ; [.0FCE.0020.0002.12413][.0000.01BC.0002.12413] # CUNEIFORM NUMERIC SIGN EIGHT U
+1241C ; [.0FCE.0020.0002.1241C][.0000.01BC.0002.1241C] # CUNEIFORM NUMERIC SIGN EIGHT GESH2
+1242A ; [.0FCE.0020.0002.1242A][.0000.01BC.0002.1242A] # CUNEIFORM NUMERIC SIGN EIGHT SHAR2
+12444 ; [.0FCE.0020.0002.12444][.0000.01BC.0002.12444] # CUNEIFORM NUMERIC SIGN EIGHT VARIANT FORM USSU
+12445 ; [.0FCE.0020.0002.12445][.0000.01BC.0002.12445] # CUNEIFORM NUMERIC SIGN EIGHT VARIANT FORM USSU3
+1D367 ; [.0FCE.0020.0002.1D367][.0000.01BF.0002.1D367] # COUNTING ROD UNIT DIGIT EIGHT
+33E7 ; [.0FCE.0020.0004.33E7][.FB40.0020.0004.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY EIGHT; QQKN
+32C7 ; [.0FCE.0020.0004.32C7][.FB40.0020.0004.6708][.E708.0000.0000.6708] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR AUGUST; QQKN
+3360 ; [.0FCE.0020.0004.3360][.FB40.0020.0004.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR EIGHT; QQKN
+0039 ; [.0FCF.0020.0002.0039] # DIGIT NINE
+FF19 ; [.0FCF.0020.0003.FF19] # FULLWIDTH DIGIT NINE; QQK
+247C ; [*02B1.0020.0004.247C][.0FCF.0020.0004.247C][*02B2.0020.001F.247C] # PARENTHESIZED DIGIT NINE; QQKN
+2490 ; [.0FCF.0020.0004.2490][*0266.0020.0004.2490] # DIGIT NINE FULL STOP; QQKN
+1D7D7 ; [.0FCF.0020.0005.1D7D7] # MATHEMATICAL BOLD DIGIT NINE; QQK
+1D7E1 ; [.0FCF.0020.0005.1D7E1] # MATHEMATICAL DOUBLE-STRUCK DIGIT NINE; QQK
+1D7EB ; [.0FCF.0020.0005.1D7EB] # MATHEMATICAL SANS-SERIF DIGIT NINE; QQK
+1D7F5 ; [.0FCF.0020.0005.1D7F5] # MATHEMATICAL SANS-SERIF BOLD DIGIT NINE; QQK
+1D7FF ; [.0FCF.0020.0005.1D7FF] # MATHEMATICAL MONOSPACE DIGIT NINE; QQK
+2468 ; [.0FCF.0020.0006.2468] # CIRCLED DIGIT NINE; QQK
+24FD ; [.0FCF.0020.0006.24FD] # DOUBLE CIRCLED DIGIT NINE; QQK
+277E ; [.0FCF.0020.0006.277E] # DINGBAT NEGATIVE CIRCLED DIGIT NINE; QQK
+2788 ; [.0FCF.0020.0006.2788] # DINGBAT CIRCLED SANS-SERIF DIGIT NINE; QQK
+2792 ; [.0FCF.0020.0006.2792] # DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE; QQK
+2079 ; [.0FCF.0020.0014.2079] # SUPERSCRIPT NINE; QQK
+2089 ; [.0FCF.0020.0015.2089] # SUBSCRIPT NINE; QQK
+0669 ; [.0FCF.0020.0002.0669][.0000.019F.0002.0669] # ARABIC-INDIC DIGIT NINE
+06F9 ; [.0FCF.0020.0002.06F9][.0000.01A0.0002.06F9] # EXTENDED ARABIC-INDIC DIGIT NINE
+07C9 ; [.0FCF.0020.0002.07C9][.0000.01A1.0002.07C9] # NKO DIGIT NINE
+1371 ; [.0FCF.0020.0002.1371][.0000.01A2.0002.1371] # ETHIOPIC DIGIT NINE
+104A9 ; [.0FCF.0020.0002.104A9][.0000.01A3.0002.104A9] # OSMANYA DIGIT NINE
+096F ; [.0FCF.0020.0002.096F][.0000.01A4.0002.096F] # DEVANAGARI DIGIT NINE
+09EF ; [.0FCF.0020.0002.09EF][.0000.01A5.0002.09EF] # BENGALI DIGIT NINE
+0A6F ; [.0FCF.0020.0002.0A6F][.0000.01A6.0002.0A6F] # GURMUKHI DIGIT NINE
+0AEF ; [.0FCF.0020.0002.0AEF][.0000.01A7.0002.0AEF] # GUJARATI DIGIT NINE
+0B6F ; [.0FCF.0020.0002.0B6F][.0000.01A8.0002.0B6F] # ORIYA DIGIT NINE
+0BEF ; [.0FCF.0020.0002.0BEF][.0000.01A9.0002.0BEF] # TAMIL DIGIT NINE
+0C6F ; [.0FCF.0020.0002.0C6F][.0000.01AA.0002.0C6F] # TELUGU DIGIT NINE
+0CEF ; [.0FCF.0020.0002.0CEF][.0000.01AB.0002.0CEF] # KANNADA DIGIT NINE
+0D6F ; [.0FCF.0020.0002.0D6F][.0000.01AC.0002.0D6F] # MALAYALAM DIGIT NINE
+194F ; [.0FCF.0020.0002.194F][.0000.01AD.0002.194F] # LIMBU DIGIT NINE
+19D9 ; [.0FCF.0020.0002.19D9][.0000.01AE.0002.19D9] # NEW TAI LUE DIGIT NINE
+0E59 ; [.0FCF.0020.0002.0E59][.0000.01AF.0002.0E59] # THAI DIGIT NINE
+0ED9 ; [.0FCF.0020.0002.0ED9][.0000.01B0.0002.0ED9] # LAO DIGIT NINE
+0F29 ; [.0FCF.0020.0002.0F29][.0000.01B1.0002.0F29] # TIBETAN DIGIT NINE
+0F32 ; [.0FCF.0020.0004.0F32][.0000.01B1.0004.0F32] # TIBETAN DIGIT HALF NINE; QQK
+1049 ; [.0FCF.0020.0002.1049][.0000.01B2.0002.1049] # MYANMAR DIGIT NINE
+17E9 ; [.0FCF.0020.0002.17E9][.0000.01B3.0002.17E9] # KHMER DIGIT NINE
+17F9 ; [.0FCF.0020.0002.17F9][.0000.01B4.0002.17F9] # KHMER SYMBOL LEK ATTAK PRAM-BUON
+1B59 ; [.0FCF.0020.0002.1B59][.0000.01B5.0002.1B59] # BALINESE DIGIT NINE
+1819 ; [.0FCF.0020.0002.1819][.0000.01B6.0002.1819] # MONGOLIAN DIGIT NINE
+3029 ; [.0FCF.0020.0002.3029][.0000.01B7.0002.3029] # HANGZHOU NUMERAL NINE
+1010F ; [.0FCF.0020.0002.1010F][.0000.01B8.0002.1010F] # AEGEAN NUMBER NINE
+12407 ; [.0FCF.0020.0002.12407][.0000.01BC.0002.12407] # CUNEIFORM NUMERIC SIGN NINE ASH
+1240E ; [.0FCF.0020.0002.1240E][.0000.01BC.0002.1240E] # CUNEIFORM NUMERIC SIGN NINE DISH
+12414 ; [.0FCF.0020.0002.12414][.0000.01BC.0002.12414] # CUNEIFORM NUMERIC SIGN NINE U
+1241D ; [.0FCF.0020.0002.1241D][.0000.01BC.0002.1241D] # CUNEIFORM NUMERIC SIGN NINE GESH2
+1242B ; [.0FCF.0020.0002.1242B][.0000.01BC.0002.1242B] # CUNEIFORM NUMERIC SIGN NINE SHAR2
+12446 ; [.0FCF.0020.0002.12446][.0000.01BC.0002.12446] # CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU
+12447 ; [.0FCF.0020.0002.12447][.0000.01BC.0002.12447] # CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU3
+12448 ; [.0FCF.0020.0002.12448][.0000.01BC.0002.12448] # CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU4
+12449 ; [.0FCF.0020.0002.12449][.0000.01BC.0002.12449] # CUNEIFORM NUMERIC SIGN NINE VARIANT FORM ILIMMU A
+1D368 ; [.0FCF.0020.0002.1D368][.0000.01BF.0002.1D368] # COUNTING ROD UNIT DIGIT NINE
+33E8 ; [.0FCF.0020.0004.33E8][.FB40.0020.0004.65E5][.E5E5.0000.0000.65E5] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY NINE; QQKN
+32C8 ; [.0FCF.0020.0004.32C8][.FB40.0020.0004.6708][.E708.0000.0000.6708] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR SEPTEMBER; QQKN
+3361 ; [.0FCF.0020.0004.3361][.FB40.0020.0004.70B9][.F0B9.0000.0000.70B9] # IDEOGRAPHIC TELEGRAPH SYMBOL FOR HOUR NINE; QQKN
+0061 ; [.0FD0.0020.0002.0061] # LATIN SMALL LETTER A
+FF41 ; [.0FD0.0020.0003.FF41] # FULLWIDTH LATIN SMALL LETTER A; QQK
+0363 ; [.0FD0.0020.0004.0363] # COMBINING LATIN SMALL LETTER A; QQK
+249C ; [*02B1.0020.0004.249C][.0FD0.0020.0004.249C][*02B2.0020.001F.249C] # PARENTHESIZED LATIN SMALL LETTER A; QQKN
+1D41A ; [.0FD0.0020.0005.1D41A] # MATHEMATICAL BOLD SMALL A; QQK
+1D44E ; [.0FD0.0020.0005.1D44E] # MATHEMATICAL ITALIC SMALL A; QQK
+1D482 ; [.0FD0.0020.0005.1D482] # MATHEMATICAL BOLD ITALIC SMALL A; QQK
+1D4B6 ; [.0FD0.0020.0005.1D4B6] # MATHEMATICAL SCRIPT SMALL A; QQK
+1D4EA ; [.0FD0.0020.0005.1D4EA] # MATHEMATICAL BOLD SCRIPT SMALL A; QQK
+1D51E ; [.0FD0.0020.0005.1D51E] # MATHEMATICAL FRAKTUR SMALL A; QQK
+1D552 ; [.0FD0.0020.0005.1D552] # MATHEMATICAL DOUBLE-STRUCK SMALL A; QQK
+1D586 ; [.0FD0.0020.0005.1D586] # MATHEMATICAL BOLD FRAKTUR SMALL A; QQK
+1D5BA ; [.0FD0.0020.0005.1D5BA] # MATHEMATICAL SANS-SERIF SMALL A; QQK
+1D5EE ; [.0FD0.0020.0005.1D5EE] # MATHEMATICAL SANS-SERIF BOLD SMALL A; QQK
+1D622 ; [.0FD0.0020.0005.1D622] # MATHEMATICAL SANS-SERIF ITALIC SMALL A; QQK
+1D656 ; [.0FD0.0020.0005.1D656] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL A; QQK
+1D68A ; [.0FD0.0020.0005.1D68A] # MATHEMATICAL MONOSPACE SMALL A; QQK
+24D0 ; [.0FD0.0020.0006.24D0] # CIRCLED LATIN SMALL LETTER A; QQK
+0041 ; [.0FD0.0020.0008.0041] # LATIN CAPITAL LETTER A
+FF21 ; [.0FD0.0020.0009.FF21] # FULLWIDTH LATIN CAPITAL LETTER A; QQK
+1D400 ; [.0FD0.0020.000B.1D400] # MATHEMATICAL BOLD CAPITAL A; QQK
+1D434 ; [.0FD0.0020.000B.1D434] # MATHEMATICAL ITALIC CAPITAL A; QQK
+1D468 ; [.0FD0.0020.000B.1D468] # MATHEMATICAL BOLD ITALIC CAPITAL A; QQK
+1D49C ; [.0FD0.0020.000B.1D49C] # MATHEMATICAL SCRIPT CAPITAL A; QQK
+1D4D0 ; [.0FD0.0020.000B.1D4D0] # MATHEMATICAL BOLD SCRIPT CAPITAL A; QQK
+1D504 ; [.0FD0.0020.000B.1D504] # MATHEMATICAL FRAKTUR CAPITAL A; QQK
+1D538 ; [.0FD0.0020.000B.1D538] # MATHEMATICAL DOUBLE-STRUCK CAPITAL A; QQK
+1D56C ; [.0FD0.0020.000B.1D56C] # MATHEMATICAL BOLD FRAKTUR CAPITAL A; QQK
+1D5A0 ; [.0FD0.0020.000B.1D5A0] # MATHEMATICAL SANS-SERIF CAPITAL A; QQK
+1D5D4 ; [.0FD0.0020.000B.1D5D4] # MATHEMATICAL SANS-SERIF BOLD CAPITAL A; QQK
+1D608 ; [.0FD0.0020.000B.1D608] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL A; QQK
+1D63C ; [.0FD0.0020.000B.1D63C] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL A; QQK
+1D670 ; [.0FD0.0020.000B.1D670] # MATHEMATICAL MONOSPACE CAPITAL A; QQK
+24B6 ; [.0FD0.0020.000C.24B6] # CIRCLED LATIN CAPITAL LETTER A; QQK
+00AA ; [.0FD0.0020.0014.00AA] # FEMININE ORDINAL INDICATOR; QQK
+1D43 ; [.0FD0.0020.0014.1D43] # MODIFIER LETTER SMALL A; QQK
+2090 ; [.0FD0.0020.0015.2090] # LATIN SUBSCRIPT SMALL LETTER A; QQK
+1D2C ; [.0FD0.0020.001D.1D2C] # MODIFIER LETTER CAPITAL A; QQK
+00E1 ; [.0FD0.0020.0002.0061][.0000.0032.0002.0301] # LATIN SMALL LETTER A WITH ACUTE; QQCM
+00C1 ; [.0FD0.0020.0008.0041][.0000.0032.0002.0301] # LATIN CAPITAL LETTER A WITH ACUTE; QQCM
+00E0 ; [.0FD0.0020.0002.0061][.0000.0035.0002.0300] # LATIN SMALL LETTER A WITH GRAVE; QQCM
+00C0 ; [.0FD0.0020.0008.0041][.0000.0035.0002.0300] # LATIN CAPITAL LETTER A WITH GRAVE; QQCM
+0103 ; [.0FD0.0020.0002.0061][.0000.0037.0002.0306] # LATIN SMALL LETTER A WITH BREVE; QQCM
+0102 ; [.0FD0.0020.0008.0041][.0000.0037.0002.0306] # LATIN CAPITAL LETTER A WITH BREVE; QQCM
+1EAF ; [.0FD0.0020.0002.0061][.0000.0037.0002.0306][.0000.0032.0002.0301] # LATIN SMALL LETTER A WITH BREVE AND ACUTE; QQCM
+1EAE ; [.0FD0.0020.0008.0041][.0000.0037.0002.0306][.0000.0032.0002.0301] # LATIN CAPITAL LETTER A WITH BREVE AND ACUTE; QQCM
+1EB1 ; [.0FD0.0020.0002.0061][.0000.0037.0002.0306][.0000.0035.0002.0300] # LATIN SMALL LETTER A WITH BREVE AND GRAVE; QQCM
+1EB0 ; [.0FD0.0020.0008.0041][.0000.0037.0002.0306][.0000.0035.0002.0300] # LATIN CAPITAL LETTER A WITH BREVE AND GRAVE; QQCM
+1EB5 ; [.0FD0.0020.0002.0061][.0000.0037.0002.0306][.0000.004E.0002.0303] # LATIN SMALL LETTER A WITH BREVE AND TILDE; QQCM
+1EB4 ; [.0FD0.0020.0008.0041][.0000.0037.0002.0306][.0000.004E.0002.0303] # LATIN CAPITAL LETTER A WITH BREVE AND TILDE; QQCM
+1EB3 ; [.0FD0.0020.0002.0061][.0000.0037.0002.0306][.0000.0060.0002.0309] # LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE; QQCM
+1EB2 ; [.0FD0.0020.0008.0041][.0000.0037.0002.0306][.0000.0060.0002.0309] # LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE; QQCM
+00E2 ; [.0FD0.0020.0002.0061][.0000.003C.0002.0302] # LATIN SMALL LETTER A WITH CIRCUMFLEX; QQCM
+00C2 ; [.0FD0.0020.0008.0041][.0000.003C.0002.0302] # LATIN CAPITAL LETTER A WITH CIRCUMFLEX; QQCM
+1EA5 ; [.0FD0.0020.0002.0061][.0000.003C.0002.0302][.0000.0032.0002.0301] # LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE; QQCM
+1EA4 ; [.0FD0.0020.0008.0041][.0000.003C.0002.0302][.0000.0032.0002.0301] # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE; QQCM
+1EA7 ; [.0FD0.0020.0002.0061][.0000.003C.0002.0302][.0000.0035.0002.0300] # LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE; QQCM
+1EA6 ; [.0FD0.0020.0008.0041][.0000.003C.0002.0302][.0000.0035.0002.0300] # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE; QQCM
+1EAB ; [.0FD0.0020.0002.0061][.0000.003C.0002.0302][.0000.004E.0002.0303] # LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE; QQCM
+1EAA ; [.0FD0.0020.0008.0041][.0000.003C.0002.0302][.0000.004E.0002.0303] # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE; QQCM
+1EA9 ; [.0FD0.0020.0002.0061][.0000.003C.0002.0302][.0000.0060.0002.0309] # LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE; QQCM
+1EA8 ; [.0FD0.0020.0008.0041][.0000.003C.0002.0302][.0000.0060.0002.0309] # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE; QQCM
+01CE ; [.0FD0.0020.0002.0061][.0000.0041.0002.030C] # LATIN SMALL LETTER A WITH CARON; QQCM
+01CD ; [.0FD0.0020.0008.0041][.0000.0041.0002.030C] # LATIN CAPITAL LETTER A WITH CARON; QQCM
+00E5 ; [.0FD0.0020.0002.0061][.0000.0043.0002.030A] # LATIN SMALL LETTER A WITH RING ABOVE; QQCM
+00C5 ; [.0FD0.0020.0008.0041][.0000.0043.0002.030A] # LATIN CAPITAL LETTER A WITH RING ABOVE; QQCM
+212B ; [.0FD0.0020.0008.0041][.0000.0043.0002.030A] # ANGSTROM SIGN; QQCM
+01FB ; [.0FD0.0020.0002.0061][.0000.0043.0002.030A][.0000.0032.0002.0301] # LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE; QQCM
+01FA ; [.0FD0.0020.0008.0041][.0000.0043.0002.030A][.0000.0032.0002.0301] # LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE; QQCM
+00E4 ; [.0FD0.0020.0002.0061][.0000.0047.0002.0308] # LATIN SMALL LETTER A WITH DIAERESIS; QQCM
+00C4 ; [.0FD0.0020.0008.0041][.0000.0047.0002.0308] # LATIN CAPITAL LETTER A WITH DIAERESIS; QQCM
+01DF ; [.0FD0.0020.0002.0061][.0000.0047.0002.0308][.0000.005B.0002.0304] # LATIN SMALL LETTER A WITH DIAERESIS AND MACRON; QQCM
+01DE ; [.0FD0.0020.0008.0041][.0000.0047.0002.0308][.0000.005B.0002.0304] # LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON; QQCM
+00E3 ; [.0FD0.0020.0002.0061][.0000.004E.0002.0303] # LATIN SMALL LETTER A WITH TILDE; QQCM
+00C3 ; [.0FD0.0020.0008.0041][.0000.004E.0002.0303] # LATIN CAPITAL LETTER A WITH TILDE; QQCM
+0227 ; [.0FD0.0020.0002.0061][.0000.0052.0002.0307] # LATIN SMALL LETTER A WITH DOT ABOVE; QQCM
+0226 ; [.0FD0.0020.0008.0041][.0000.0052.0002.0307] # LATIN CAPITAL LETTER A WITH DOT ABOVE; QQCM
+01E1 ; [.0FD0.0020.0002.0061][.0000.0052.0002.0307][.0000.005B.0002.0304] # LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON; QQCM
+01E0 ; [.0FD0.0020.0008.0041][.0000.0052.0002.0307][.0000.005B.0002.0304] # LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON; QQCM
+0105 ; [.0FD0.0020.0002.0061][.0000.0059.0002.0328] # LATIN SMALL LETTER A WITH OGONEK; QQCM
+0104 ; [.0FD0.0020.0008.0041][.0000.0059.0002.0328] # LATIN CAPITAL LETTER A WITH OGONEK; QQCM
+0101 ; [.0FD0.0020.0002.0061][.0000.005B.0002.0304] # LATIN SMALL LETTER A WITH MACRON; QQCM
+0100 ; [.0FD0.0020.0008.0041][.0000.005B.0002.0304] # LATIN CAPITAL LETTER A WITH MACRON; QQCM
+1EA3 ; [.0FD0.0020.0002.0061][.0000.0060.0002.0309] # LATIN SMALL LETTER A WITH HOOK ABOVE; QQCM
+1EA2 ; [.0FD0.0020.0008.0041][.0000.0060.0002.0309] # LATIN CAPITAL LETTER A WITH HOOK ABOVE; QQCM
+0201 ; [.0FD0.0020.0002.0061][.0000.0063.0002.030F] # LATIN SMALL LETTER A WITH DOUBLE GRAVE; QQCM
+0200 ; [.0FD0.0020.0008.0041][.0000.0063.0002.030F] # LATIN CAPITAL LETTER A WITH DOUBLE GRAVE; QQCM
+0203 ; [.0FD0.0020.0002.0061][.0000.0065.0002.0311] # LATIN SMALL LETTER A WITH INVERTED BREVE; QQCM
+0202 ; [.0FD0.0020.0008.0041][.0000.0065.0002.0311] # LATIN CAPITAL LETTER A WITH INVERTED BREVE; QQCM
+1EA1 ; [.0FD0.0020.0002.0061][.0000.007A.0002.0323] # LATIN SMALL LETTER A WITH DOT BELOW; QQCM
+1EA0 ; [.0FD0.0020.0008.0041][.0000.007A.0002.0323] # LATIN CAPITAL LETTER A WITH DOT BELOW; QQCM
+1EB7 ; [.0FD0.0020.0002.0061][.0000.007A.0002.0323][.0000.0037.0002.0306] # LATIN SMALL LETTER A WITH BREVE AND DOT BELOW; QQCM
+1EB6 ; [.0FD0.0020.0008.0041][.0000.007A.0002.0323][.0000.0037.0002.0306] # LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW; QQCM
+1EAD ; [.0FD0.0020.0002.0061][.0000.007A.0002.0323][.0000.003C.0002.0302] # LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW; QQCM
+1EAC ; [.0FD0.0020.0008.0041][.0000.007A.0002.0323][.0000.003C.0002.0302] # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW; QQCM
+1E01 ; [.0FD0.0020.0002.0061][.0000.0080.0002.0325] # LATIN SMALL LETTER A WITH RING BELOW; QQCM
+1E00 ; [.0FD0.0020.0008.0041][.0000.0080.0002.0325] # LATIN CAPITAL LETTER A WITH RING BELOW; QQCM
+2100 ; [.0FD0.0020.0004.2100][*02FF.0020.0004.2100][.0FFE.0020.001F.2100] # ACCOUNT OF; QQKN
+00E6 ; [.0FD0.0020.0004.00E6][.0000.0199.0004.00E6][.1029.0020.001F.00E6] # LATIN SMALL LETTER AE; QQKN
+00C6 ; [.0FD0.0020.000A.00C6][.0000.0199.0004.00C6][.1029.0020.001F.00C6] # LATIN CAPITAL LETTER AE; QQKN
+1D2D ; [.0FD0.0020.0014.1D2D][.0000.0199.0014.1D2D][.1029.0020.001F.1D2D] # MODIFIER LETTER CAPITAL AE; QQKN
+01FD ; [.0FD0.0020.0004.01FD][.0000.0199.0004.01FD][.1029.0020.001F.01FD][.0000.0032.0002.01FD] # LATIN SMALL LETTER AE WITH ACUTE; QQKN
+01FC ; [.0FD0.0020.000A.01FC][.0000.0199.0004.01FC][.1029.0020.001F.01FC][.0000.0032.0002.01FC] # LATIN CAPITAL LETTER AE WITH ACUTE; QQKN
+01E3 ; [.0FD0.0020.0004.01E3][.0000.0199.0004.01E3][.1029.0020.001F.01E3][.0000.005B.0002.01E3] # LATIN SMALL LETTER AE WITH MACRON; QQKN
+01E2 ; [.0FD0.0020.000A.01E2][.0000.0199.0004.01E2][.1029.0020.001F.01E2][.0000.005B.0002.01E2] # LATIN CAPITAL LETTER AE WITH MACRON; QQKN
+33C2 ; [.0FD0.0020.001C.33C2][*0266.0020.001C.33C2][.1110.0020.001F.33C2][*0266.0020.001F.33C2] # SQUARE AM; QQKN
+33DF ; [.0FD0.0020.001D.33DF][*04C7.0020.001C.33DF][.1110.0020.001F.33DF] # SQUARE A OVER M; QQKN
+2101 ; [.0FD0.0020.0004.2101][*02FF.0020.0004.2101][.11AF.0020.001F.2101] # ADDRESSED TO THE SUBJECT; QQKN
+3373 ; [.0FD0.0020.001D.3373][.11EE.0020.001D.3373] # SQUARE AU; QQKN
+1E9A ; [.0FD0.0020.0004.1E9A][.1298.0020.0004.1E9A] # LATIN SMALL LETTER A WITH RIGHT HALF RING; QQKN
+1D00 ; [.0FD4.0020.0002.1D00] # LATIN LETTER SMALL CAPITAL A
+2C65 ; [.0FD5.0020.0002.2C65] # LATIN SMALL LETTER A WITH STROKE
+023A ; [.0FD5.0020.0008.023A] # LATIN CAPITAL LETTER A WITH STROKE
+1D8F ; [.0FD6.0020.0002.1D8F] # LATIN SMALL LETTER A WITH RETROFLEX HOOK
+1D01 ; [.0FD7.0020.0002.1D01] # LATIN LETTER SMALL CAPITAL AE
+1D02 ; [.0FD8.0020.0002.1D02] # LATIN SMALL LETTER TURNED AE
+1D46 ; [.0FD8.0020.0014.1D46] # MODIFIER LETTER SMALL TURNED AE; QQK
+0250 ; [.0FD9.0020.0002.0250] # LATIN SMALL LETTER TURNED A
+1D44 ; [.0FD9.0020.0014.1D44] # MODIFIER LETTER SMALL TURNED A; QQK
+0251 ; [.0FDD.0020.0002.0251] # LATIN SMALL LETTER ALPHA
+1D45 ; [.0FDD.0020.0014.1D45] # MODIFIER LETTER SMALL ALPHA; QQK
+1D90 ; [.0FE1.0020.0002.1D90] # LATIN SMALL LETTER ALPHA WITH RETROFLEX HOOK
+0252 ; [.0FE2.0020.0002.0252] # LATIN SMALL LETTER TURNED ALPHA
+1D9B ; [.0FE2.0020.0014.1D9B] # MODIFIER LETTER SMALL TURNED ALPHA; QQK
+0062 ; [.0FE6.0020.0002.0062] # LATIN SMALL LETTER B
+FF42 ; [.0FE6.0020.0003.FF42] # FULLWIDTH LATIN SMALL LETTER B; QQK
+249D ; [*02B1.0020.0004.249D][.0FE6.0020.0004.249D][*02B2.0020.001F.249D] # PARENTHESIZED LATIN SMALL LETTER B; QQKN
+1D41B ; [.0FE6.0020.0005.1D41B] # MATHEMATICAL BOLD SMALL B; QQK
+1D44F ; [.0FE6.0020.0005.1D44F] # MATHEMATICAL ITALIC SMALL B; QQK
+1D483 ; [.0FE6.0020.0005.1D483] # MATHEMATICAL BOLD ITALIC SMALL B; QQK
+1D4B7 ; [.0FE6.0020.0005.1D4B7] # MATHEMATICAL SCRIPT SMALL B; QQK
+1D4EB ; [.0FE6.0020.0005.1D4EB] # MATHEMATICAL BOLD SCRIPT SMALL B; QQK
+1D51F ; [.0FE6.0020.0005.1D51F] # MATHEMATICAL FRAKTUR SMALL B; QQK
+1D553 ; [.0FE6.0020.0005.1D553] # MATHEMATICAL DOUBLE-STRUCK SMALL B; QQK
+1D587 ; [.0FE6.0020.0005.1D587] # MATHEMATICAL BOLD FRAKTUR SMALL B; QQK
+1D5BB ; [.0FE6.0020.0005.1D5BB] # MATHEMATICAL SANS-SERIF SMALL B; QQK
+1D5EF ; [.0FE6.0020.0005.1D5EF] # MATHEMATICAL SANS-SERIF BOLD SMALL B; QQK
+1D623 ; [.0FE6.0020.0005.1D623] # MATHEMATICAL SANS-SERIF ITALIC SMALL B; QQK
+1D657 ; [.0FE6.0020.0005.1D657] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL B; QQK
+1D68B ; [.0FE6.0020.0005.1D68B] # MATHEMATICAL MONOSPACE SMALL B; QQK
+24D1 ; [.0FE6.0020.0006.24D1] # CIRCLED LATIN SMALL LETTER B; QQK
+0042 ; [.0FE6.0020.0008.0042] # LATIN CAPITAL LETTER B
+FF22 ; [.0FE6.0020.0009.FF22] # FULLWIDTH LATIN CAPITAL LETTER B; QQK
+212C ; [.0FE6.0020.000B.212C] # SCRIPT CAPITAL B; QQK
+1D401 ; [.0FE6.0020.000B.1D401] # MATHEMATICAL BOLD CAPITAL B; QQK
+1D435 ; [.0FE6.0020.000B.1D435] # MATHEMATICAL ITALIC CAPITAL B; QQK
+1D469 ; [.0FE6.0020.000B.1D469] # MATHEMATICAL BOLD ITALIC CAPITAL B; QQK
+1D4D1 ; [.0FE6.0020.000B.1D4D1] # MATHEMATICAL BOLD SCRIPT CAPITAL B; QQK
+1D505 ; [.0FE6.0020.000B.1D505] # MATHEMATICAL FRAKTUR CAPITAL B; QQK
+1D539 ; [.0FE6.0020.000B.1D539] # MATHEMATICAL DOUBLE-STRUCK CAPITAL B; QQK
+1D56D ; [.0FE6.0020.000B.1D56D] # MATHEMATICAL BOLD FRAKTUR CAPITAL B; QQK
+1D5A1 ; [.0FE6.0020.000B.1D5A1] # MATHEMATICAL SANS-SERIF CAPITAL B; QQK
+1D5D5 ; [.0FE6.0020.000B.1D5D5] # MATHEMATICAL SANS-SERIF BOLD CAPITAL B; QQK
+1D609 ; [.0FE6.0020.000B.1D609] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL B; QQK
+1D63D ; [.0FE6.0020.000B.1D63D] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL B; QQK
+1D671 ; [.0FE6.0020.000B.1D671] # MATHEMATICAL MONOSPACE CAPITAL B; QQK
+24B7 ; [.0FE6.0020.000C.24B7] # CIRCLED LATIN CAPITAL LETTER B; QQK
+1D47 ; [.0FE6.0020.0014.1D47] # MODIFIER LETTER SMALL B; QQK
+1D2E ; [.0FE6.0020.001D.1D2E] # MODIFIER LETTER CAPITAL B; QQK
+1E03 ; [.0FE6.0020.0002.0062][.0000.0052.0002.0307] # LATIN SMALL LETTER B WITH DOT ABOVE; QQCM
+1E02 ; [.0FE6.0020.0008.0042][.0000.0052.0002.0307] # LATIN CAPITAL LETTER B WITH DOT ABOVE; QQCM
+1E05 ; [.0FE6.0020.0002.0062][.0000.007A.0002.0323] # LATIN SMALL LETTER B WITH DOT BELOW; QQCM
+1E04 ; [.0FE6.0020.0008.0042][.0000.007A.0002.0323] # LATIN CAPITAL LETTER B WITH DOT BELOW; QQCM
+1E07 ; [.0FE6.0020.0002.0062][.0000.008A.0002.0331] # LATIN SMALL LETTER B WITH LINE BELOW; QQCM
+1E06 ; [.0FE6.0020.0008.0042][.0000.008A.0002.0331] # LATIN CAPITAL LETTER B WITH LINE BELOW; QQCM
+3374 ; [.0FE6.0020.001C.3374][.0FD0.0020.001C.3374][.117E.0020.001F.3374] # SQUARE BAR; QQKN
+33C3 ; [.0FE6.0020.001D.33C3][.116E.0020.001C.33C3] # SQUARE BQ; QQKN
+0299 ; [.0FEA.0020.0002.0299] # LATIN LETTER SMALL CAPITAL B
+0180 ; [.0FEE.0020.0002.0180] # LATIN SMALL LETTER B WITH STROKE
+0243 ; [.0FEE.0020.0008.0243] # LATIN CAPITAL LETTER B WITH STROKE
+1D2F ; [.0FF2.0020.0002.1D2F] # MODIFIER LETTER CAPITAL BARRED B
+1D03 ; [.0FF3.0020.0002.1D03] # LATIN LETTER SMALL CAPITAL BARRED B
+1D6C ; [.0FF4.0020.0002.1D6C] # LATIN SMALL LETTER B WITH MIDDLE TILDE
+1D80 ; [.0FF5.0020.0002.1D80] # LATIN SMALL LETTER B WITH PALATAL HOOK
+0253 ; [.0FF6.0020.0002.0253] # LATIN SMALL LETTER B WITH HOOK
+0181 ; [.0FF6.0020.0008.0181] # LATIN CAPITAL LETTER B WITH HOOK
+0183 ; [.0FFA.0020.0002.0183] # LATIN SMALL LETTER B WITH TOPBAR
+0182 ; [.0FFA.0020.0008.0182] # LATIN CAPITAL LETTER B WITH TOPBAR
+0063 ; [.0FFE.0020.0002.0063] # LATIN SMALL LETTER C
+FF43 ; [.0FFE.0020.0003.FF43] # FULLWIDTH LATIN SMALL LETTER C; QQK
+0368 ; [.0FFE.0020.0004.0368] # COMBINING LATIN SMALL LETTER C; QQK
+217D ; [.0FFE.0020.0004.217D] # SMALL ROMAN NUMERAL ONE HUNDRED; QQK
+249E ; [*02B1.0020.0004.249E][.0FFE.0020.0004.249E][*02B2.0020.001F.249E] # PARENTHESIZED LATIN SMALL LETTER C; QQKN
+1D41C ; [.0FFE.0020.0005.1D41C] # MATHEMATICAL BOLD SMALL C; QQK
+1D450 ; [.0FFE.0020.0005.1D450] # MATHEMATICAL ITALIC SMALL C; QQK
+1D484 ; [.0FFE.0020.0005.1D484] # MATHEMATICAL BOLD ITALIC SMALL C; QQK
+1D4B8 ; [.0FFE.0020.0005.1D4B8] # MATHEMATICAL SCRIPT SMALL C; QQK
+1D4EC ; [.0FFE.0020.0005.1D4EC] # MATHEMATICAL BOLD SCRIPT SMALL C; QQK
+1D520 ; [.0FFE.0020.0005.1D520] # MATHEMATICAL FRAKTUR SMALL C; QQK
+1D554 ; [.0FFE.0020.0005.1D554] # MATHEMATICAL DOUBLE-STRUCK SMALL C; QQK
+1D588 ; [.0FFE.0020.0005.1D588] # MATHEMATICAL BOLD FRAKTUR SMALL C; QQK
+1D5BC ; [.0FFE.0020.0005.1D5BC] # MATHEMATICAL SANS-SERIF SMALL C; QQK
+1D5F0 ; [.0FFE.0020.0005.1D5F0] # MATHEMATICAL SANS-SERIF BOLD SMALL C; QQK
+1D624 ; [.0FFE.0020.0005.1D624] # MATHEMATICAL SANS-SERIF ITALIC SMALL C; QQK
+1D658 ; [.0FFE.0020.0005.1D658] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL C; QQK
+1D68C ; [.0FFE.0020.0005.1D68C] # MATHEMATICAL MONOSPACE SMALL C; QQK
+24D2 ; [.0FFE.0020.0006.24D2] # CIRCLED LATIN SMALL LETTER C; QQK
+0043 ; [.0FFE.0020.0008.0043] # LATIN CAPITAL LETTER C
+FF23 ; [.0FFE.0020.0009.FF23] # FULLWIDTH LATIN CAPITAL LETTER C; QQK
+2103 ; [*03BF.0020.0004.2103][.0FFE.0020.000A.2103] # DEGREE CELSIUS; QQKN
+216D ; [.0FFE.0020.000A.216D] # ROMAN NUMERAL ONE HUNDRED; QQK
+2102 ; [.0FFE.0020.000B.2102] # DOUBLE-STRUCK CAPITAL C; QQK
+212D ; [.0FFE.0020.000B.212D] # BLACK-LETTER CAPITAL C; QQK
+1D402 ; [.0FFE.0020.000B.1D402] # MATHEMATICAL BOLD CAPITAL C; QQK
+1D436 ; [.0FFE.0020.000B.1D436] # MATHEMATICAL ITALIC CAPITAL C; QQK
+1D46A ; [.0FFE.0020.000B.1D46A] # MATHEMATICAL BOLD ITALIC CAPITAL C; QQK
+1D49E ; [.0FFE.0020.000B.1D49E] # MATHEMATICAL SCRIPT CAPITAL C; QQK
+1D4D2 ; [.0FFE.0020.000B.1D4D2] # MATHEMATICAL BOLD SCRIPT CAPITAL C; QQK
+1D56E ; [.0FFE.0020.000B.1D56E] # MATHEMATICAL BOLD FRAKTUR CAPITAL C; QQK
+1D5A2 ; [.0FFE.0020.000B.1D5A2] # MATHEMATICAL SANS-SERIF CAPITAL C; QQK
+1D5D6 ; [.0FFE.0020.000B.1D5D6] # MATHEMATICAL SANS-SERIF BOLD CAPITAL C; QQK
+1D60A ; [.0FFE.0020.000B.1D60A] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL C; QQK
+1D63E ; [.0FFE.0020.000B.1D63E] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL C; QQK
+1D672 ; [.0FFE.0020.000B.1D672] # MATHEMATICAL MONOSPACE CAPITAL C; QQK
+24B8 ; [.0FFE.0020.000C.24B8] # CIRCLED LATIN CAPITAL LETTER C; QQK
+1D9C ; [.0FFE.0020.0014.1D9C] # MODIFIER LETTER SMALL C; QQK
+0107 ; [.0FFE.0020.0002.0063][.0000.0032.0002.0301] # LATIN SMALL LETTER C WITH ACUTE; QQCM
+0106 ; [.0FFE.0020.0008.0043][.0000.0032.0002.0301] # LATIN CAPITAL LETTER C WITH ACUTE; QQCM
+0109 ; [.0FFE.0020.0002.0063][.0000.003C.0002.0302] # LATIN SMALL LETTER C WITH CIRCUMFLEX; QQCM
+0108 ; [.0FFE.0020.0008.0043][.0000.003C.0002.0302] # LATIN CAPITAL LETTER C WITH CIRCUMFLEX; QQCM
+010D ; [.0FFE.0020.0002.0063][.0000.0041.0002.030C] # LATIN SMALL LETTER C WITH CARON; QQCM
+010C ; [.0FFE.0020.0008.0043][.0000.0041.0002.030C] # LATIN CAPITAL LETTER C WITH CARON; QQCM
+010B ; [.0FFE.0020.0002.0063][.0000.0052.0002.0307] # LATIN SMALL LETTER C WITH DOT ABOVE; QQCM
+010A ; [.0FFE.0020.0008.0043][.0000.0052.0002.0307] # LATIN CAPITAL LETTER C WITH DOT ABOVE; QQCM
+00E7 ; [.0FFE.0020.0002.0063][.0000.0056.0002.0327] # LATIN SMALL LETTER C WITH CEDILLA; QQCM
+00C7 ; [.0FFE.0020.0008.0043][.0000.0056.0002.0327] # LATIN CAPITAL LETTER C WITH CEDILLA; QQCM
+1E09 ; [.0FFE.0020.0002.0063][.0000.0056.0002.0327][.0000.0032.0002.0301] # LATIN SMALL LETTER C WITH CEDILLA AND ACUTE; QQCM
+1E08 ; [.0FFE.0020.0008.0043][.0000.0056.0002.0327][.0000.0032.0002.0301] # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE; QQCM
+3388 ; [.0FFE.0020.001C.3388][.0FD0.0020.001C.3388][.10E5.0020.001F.3388] # SQUARE CAL; QQKN
+33C4 ; [.0FFE.0020.001C.33C4][.0FFE.0020.001C.33C4] # SQUARE CC; QQKN
+33C5 ; [.0FFE.0020.001C.33C5][.1010.0020.001C.33C5] # SQUARE CD; QQKN
+33C6 ; [.0FFE.0020.001D.33C6][*04C7.0020.001C.33C6][.10D6.0020.001F.33C6][.106A.0020.001F.33C6] # SQUARE C OVER KG; QQKN
+339D ; [.0FFE.0020.001C.339D][.1110.0020.001C.339D] # SQUARE CM; QQKN
+33A0 ; [.0FFE.0020.001C.33A0][.1110.0020.001C.33A0][.0FC8.0020.001F.33A0] # SQUARE CM SQUARED; QQKN
+33A4 ; [.0FFE.0020.001C.33A4][.1110.0020.001C.33A4][.0FC9.0020.001F.33A4] # SQUARE CM CUBED; QQKN
+2105 ; [.0FFE.0020.0004.2105][*02FF.0020.0004.2105][.113B.0020.001F.2105] # CARE OF; QQKN
+33C7 ; [.0FFE.0020.001D.33C7][.113B.0020.001C.33C7][*0266.0020.001F.33C7] # SQUARE CO; QQKN
+2106 ; [.0FFE.0020.0004.2106][*02FF.0020.0004.2106][.11EE.0020.001F.2106] # CADA UNA; QQKN
+1D04 ; [.1002.0020.0002.1D04] # LATIN LETTER SMALL CAPITAL C
+023C ; [.1003.0020.0002.023C] # LATIN SMALL LETTER C WITH STROKE
+023B ; [.1003.0020.0008.023B] # LATIN CAPITAL LETTER C WITH STROKE
+0188 ; [.1007.0020.0002.0188] # LATIN SMALL LETTER C WITH HOOK
+0187 ; [.1007.0020.0008.0187] # LATIN CAPITAL LETTER C WITH HOOK
+0255 ; [.100B.0020.0002.0255] # LATIN SMALL LETTER C WITH CURL
+1D9D ; [.100B.0020.0014.1D9D] # MODIFIER LETTER SMALL C WITH CURL; QQK
+2184 ; [.100F.0020.0002.2184] # LATIN SMALL LETTER REVERSED C
+2183 ; [.100F.0020.0008.2183] # ROMAN NUMERAL REVERSED ONE HUNDRED
+0064 ; [.1010.0020.0002.0064] # LATIN SMALL LETTER D
+FF44 ; [.1010.0020.0003.FF44] # FULLWIDTH LATIN SMALL LETTER D; QQK
+0369 ; [.1010.0020.0004.0369] # COMBINING LATIN SMALL LETTER D; QQK
+217E ; [.1010.0020.0004.217E] # SMALL ROMAN NUMERAL FIVE HUNDRED; QQK
+249F ; [*02B1.0020.0004.249F][.1010.0020.0004.249F][*02B2.0020.001F.249F] # PARENTHESIZED LATIN SMALL LETTER D; QQKN
+2146 ; [.1010.0020.0005.2146] # DOUBLE-STRUCK ITALIC SMALL D; QQK
+1D41D ; [.1010.0020.0005.1D41D] # MATHEMATICAL BOLD SMALL D; QQK
+1D451 ; [.1010.0020.0005.1D451] # MATHEMATICAL ITALIC SMALL D; QQK
+1D485 ; [.1010.0020.0005.1D485] # MATHEMATICAL BOLD ITALIC SMALL D; QQK
+1D4B9 ; [.1010.0020.0005.1D4B9] # MATHEMATICAL SCRIPT SMALL D; QQK
+1D4ED ; [.1010.0020.0005.1D4ED] # MATHEMATICAL BOLD SCRIPT SMALL D; QQK
+1D521 ; [.1010.0020.0005.1D521] # MATHEMATICAL FRAKTUR SMALL D; QQK
+1D555 ; [.1010.0020.0005.1D555] # MATHEMATICAL DOUBLE-STRUCK SMALL D; QQK
+1D589 ; [.1010.0020.0005.1D589] # MATHEMATICAL BOLD FRAKTUR SMALL D; QQK
+1D5BD ; [.1010.0020.0005.1D5BD] # MATHEMATICAL SANS-SERIF SMALL D; QQK
+1D5F1 ; [.1010.0020.0005.1D5F1] # MATHEMATICAL SANS-SERIF BOLD SMALL D; QQK
+1D625 ; [.1010.0020.0005.1D625] # MATHEMATICAL SANS-SERIF ITALIC SMALL D; QQK
+1D659 ; [.1010.0020.0005.1D659] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL D; QQK
+1D68D ; [.1010.0020.0005.1D68D] # MATHEMATICAL MONOSPACE SMALL D; QQK
+24D3 ; [.1010.0020.0006.24D3] # CIRCLED LATIN SMALL LETTER D; QQK
+0044 ; [.1010.0020.0008.0044] # LATIN CAPITAL LETTER D
+FF24 ; [.1010.0020.0009.FF24] # FULLWIDTH LATIN CAPITAL LETTER D; QQK
+216E ; [.1010.0020.000A.216E] # ROMAN NUMERAL FIVE HUNDRED; QQK
+2145 ; [.1010.0020.000B.2145] # DOUBLE-STRUCK ITALIC CAPITAL D; QQK
+1D403 ; [.1010.0020.000B.1D403] # MATHEMATICAL BOLD CAPITAL D; QQK
+1D437 ; [.1010.0020.000B.1D437] # MATHEMATICAL ITALIC CAPITAL D; QQK
+1D46B ; [.1010.0020.000B.1D46B] # MATHEMATICAL BOLD ITALIC CAPITAL D; QQK
+1D49F ; [.1010.0020.000B.1D49F] # MATHEMATICAL SCRIPT CAPITAL D; QQK
+1D4D3 ; [.1010.0020.000B.1D4D3] # MATHEMATICAL BOLD SCRIPT CAPITAL D; QQK
+1D507 ; [.1010.0020.000B.1D507] # MATHEMATICAL FRAKTUR CAPITAL D; QQK
+1D53B ; [.1010.0020.000B.1D53B] # MATHEMATICAL DOUBLE-STRUCK CAPITAL D; QQK
+1D56F ; [.1010.0020.000B.1D56F] # MATHEMATICAL BOLD FRAKTUR CAPITAL D; QQK
+1D5A3 ; [.1010.0020.000B.1D5A3] # MATHEMATICAL SANS-SERIF CAPITAL D; QQK
+1D5D7 ; [.1010.0020.000B.1D5D7] # MATHEMATICAL SANS-SERIF BOLD CAPITAL D; QQK
+1D60B ; [.1010.0020.000B.1D60B] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL D; QQK
+1D63F ; [.1010.0020.000B.1D63F] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL D; QQK
+1D673 ; [.1010.0020.000B.1D673] # MATHEMATICAL MONOSPACE CAPITAL D; QQK
+24B9 ; [.1010.0020.000C.24B9] # CIRCLED LATIN CAPITAL LETTER D; QQK
+1D48 ; [.1010.0020.0014.1D48] # MODIFIER LETTER SMALL D; QQK
+1D30 ; [.1010.0020.001D.1D30] # MODIFIER LETTER CAPITAL D; QQK
+010F ; [.1010.0020.0002.0064][.0000.0041.0002.030C] # LATIN SMALL LETTER D WITH CARON; QQCM
+010E ; [.1010.0020.0008.0044][.0000.0041.0002.030C] # LATIN CAPITAL LETTER D WITH CARON; QQCM
+1E0B ; [.1010.0020.0002.0064][.0000.0052.0002.0307] # LATIN SMALL LETTER D WITH DOT ABOVE; QQCM
+1E0A ; [.1010.0020.0008.0044][.0000.0052.0002.0307] # LATIN CAPITAL LETTER D WITH DOT ABOVE; QQCM
+1E11 ; [.1010.0020.0002.0064][.0000.0056.0002.0327] # LATIN SMALL LETTER D WITH CEDILLA; QQCM
+1E10 ; [.1010.0020.0008.0044][.0000.0056.0002.0327] # LATIN CAPITAL LETTER D WITH CEDILLA; QQCM
+1E0D ; [.1010.0020.0002.0064][.0000.007A.0002.0323] # LATIN SMALL LETTER D WITH DOT BELOW; QQCM
+1E0C ; [.1010.0020.0008.0044][.0000.007A.0002.0323] # LATIN CAPITAL LETTER D WITH DOT BELOW; QQCM
+1E13 ; [.1010.0020.0002.0064][.0000.0086.0002.032D] # LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW; QQCM
+1E12 ; [.1010.0020.0008.0044][.0000.0086.0002.032D] # LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW; QQCM
+1E0F ; [.1010.0020.0002.0064][.0000.008A.0002.0331] # LATIN SMALL LETTER D WITH LINE BELOW; QQCM
+1E0E ; [.1010.0020.0008.0044][.0000.008A.0002.0331] # LATIN CAPITAL LETTER D WITH LINE BELOW; QQCM
+0111 ; [.1010.0020.0002.0064][.0000.008D.0002.0335] # LATIN SMALL LETTER D WITH STROKE; QQCM
+0110 ; [.1010.0020.0008.0044][.0000.008D.0002.0335] # LATIN CAPITAL LETTER D WITH STROKE; QQCM
+00F0 ; [.1010.0020.0004.00F0][.0000.0199.0004.00F0] # LATIN SMALL LETTER ETH; QQKN
+00D0 ; [.1010.0020.000A.00D0][.0000.0199.0004.00D0] # LATIN CAPITAL LETTER ETH; QQKN
+1D9E ; [.1010.0020.0014.1D9E][.0000.0199.0014.1D9E] # MODIFIER LETTER SMALL ETH; QQKN
+3372 ; [.1010.0020.001C.3372][.0FD0.0020.001C.3372] # SQUARE DA; QQKN
+0238 ; [.1010.0020.0004.0238][.0FE6.0020.0004.0238] # LATIN SMALL LETTER DB DIGRAPH; QQKN
+33C8 ; [.1010.0020.001C.33C8][.0FE6.0020.001D.33C8] # SQUARE DB; QQKN
+3397 ; [.1010.0020.001C.3397][.10E5.0020.001C.3397] # SQUARE DL; QQKN
+3377 ; [.1010.0020.001C.3377][.1110.0020.001C.3377] # SQUARE DM; QQKN
+3378 ; [.1010.0020.001C.3378][.1110.0020.001C.3378][.0FC8.0020.001F.3378] # SQUARE DM SQUARED; QQKN
+3379 ; [.1010.0020.001C.3379][.1110.0020.001C.3379][.0FC9.0020.001F.3379] # SQUARE DM CUBED; QQKN
+01F3 ; [.1010.0020.0004.01F3][.1243.0020.0004.01F3] # LATIN SMALL LETTER DZ; QQKN
+02A3 ; [.1010.0020.0004.02A3][.1243.0020.0004.02A3] # LATIN SMALL LETTER DZ DIGRAPH; QQKN
+01F2 ; [.1010.0020.000A.01F2][.1243.0020.0004.01F2] # LATIN CAPITAL LETTER D WITH SMALL LETTER Z; QQKN
+01F1 ; [.1010.0020.000A.01F1][.1243.0020.000A.01F1] # LATIN CAPITAL LETTER DZ; QQKN
+01C6 ; [.1010.0020.0004.01C6][.1243.0020.0004.01C6][.0000.0041.001F.01C6] # LATIN SMALL LETTER DZ WITH CARON; QQKN
+01C5 ; [.1010.0020.000A.01C5][.1243.0020.0004.01C5][.0000.0041.001F.01C5] # LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON; QQKN
+01C4 ; [.1010.0020.000A.01C4][.1243.0020.000A.01C4][.0000.0041.001F.01C4] # LATIN CAPITAL LETTER DZ WITH CARON; QQKN
+02A5 ; [.1010.0020.0004.02A5][.1256.0020.0004.02A5] # LATIN SMALL LETTER DZ DIGRAPH WITH CURL; QQKN
+02A4 ; [.1010.0020.0004.02A4][.125F.0020.0004.02A4] # LATIN SMALL LETTER DEZH DIGRAPH; QQKN
+1D05 ; [.1014.0020.0002.1D05] # LATIN LETTER SMALL CAPITAL D
+1D06 ; [.1015.0020.0002.1D06] # LATIN LETTER SMALL CAPITAL ETH
+1D6D ; [.1016.0020.0002.1D6D] # LATIN SMALL LETTER D WITH MIDDLE TILDE
+1D81 ; [.1017.0020.0002.1D81] # LATIN SMALL LETTER D WITH PALATAL HOOK
+0256 ; [.1018.0020.0002.0256] # LATIN SMALL LETTER D WITH TAIL
+0189 ; [.1018.0020.0008.0189] # LATIN CAPITAL LETTER AFRICAN D
+0257 ; [.101C.0020.0002.0257] # LATIN SMALL LETTER D WITH HOOK
+018A ; [.101C.0020.0008.018A] # LATIN CAPITAL LETTER D WITH HOOK
+1D91 ; [.1020.0020.0002.1D91] # LATIN SMALL LETTER D WITH HOOK AND TAIL
+018C ; [.1021.0020.0002.018C] # LATIN SMALL LETTER D WITH TOPBAR
+018B ; [.1021.0020.0008.018B] # LATIN CAPITAL LETTER D WITH TOPBAR
+0221 ; [.1025.0020.0002.0221] # LATIN SMALL LETTER D WITH CURL
+0065 ; [.1029.0020.0002.0065] # LATIN SMALL LETTER E
+FF45 ; [.1029.0020.0003.FF45] # FULLWIDTH LATIN SMALL LETTER E; QQK
+0364 ; [.1029.0020.0004.0364] # COMBINING LATIN SMALL LETTER E; QQK
+24A0 ; [*02B1.0020.0004.24A0][.1029.0020.0004.24A0][*02B2.0020.001F.24A0] # PARENTHESIZED LATIN SMALL LETTER E; QQKN
+212F ; [.1029.0020.0005.212F] # SCRIPT SMALL E; QQK
+2147 ; [.1029.0020.0005.2147] # DOUBLE-STRUCK ITALIC SMALL E; QQK
+1D41E ; [.1029.0020.0005.1D41E] # MATHEMATICAL BOLD SMALL E; QQK
+1D452 ; [.1029.0020.0005.1D452] # MATHEMATICAL ITALIC SMALL E; QQK
+1D486 ; [.1029.0020.0005.1D486] # MATHEMATICAL BOLD ITALIC SMALL E; QQK
+1D4EE ; [.1029.0020.0005.1D4EE] # MATHEMATICAL BOLD SCRIPT SMALL E; QQK
+1D522 ; [.1029.0020.0005.1D522] # MATHEMATICAL FRAKTUR SMALL E; QQK
+1D556 ; [.1029.0020.0005.1D556] # MATHEMATICAL DOUBLE-STRUCK SMALL E; QQK
+1D58A ; [.1029.0020.0005.1D58A] # MATHEMATICAL BOLD FRAKTUR SMALL E; QQK
+1D5BE ; [.1029.0020.0005.1D5BE] # MATHEMATICAL SANS-SERIF SMALL E; QQK
+1D5F2 ; [.1029.0020.0005.1D5F2] # MATHEMATICAL SANS-SERIF BOLD SMALL E; QQK
+1D626 ; [.1029.0020.0005.1D626] # MATHEMATICAL SANS-SERIF ITALIC SMALL E; QQK
+1D65A ; [.1029.0020.0005.1D65A] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL E; QQK
+1D68E ; [.1029.0020.0005.1D68E] # MATHEMATICAL MONOSPACE SMALL E; QQK
+24D4 ; [.1029.0020.0006.24D4] # CIRCLED LATIN SMALL LETTER E; QQK
+0045 ; [.1029.0020.0008.0045] # LATIN CAPITAL LETTER E
+FF25 ; [.1029.0020.0009.FF25] # FULLWIDTH LATIN CAPITAL LETTER E; QQK
+2130 ; [.1029.0020.000B.2130] # SCRIPT CAPITAL E; QQK
+1D404 ; [.1029.0020.000B.1D404] # MATHEMATICAL BOLD CAPITAL E; QQK
+1D438 ; [.1029.0020.000B.1D438] # MATHEMATICAL ITALIC CAPITAL E; QQK
+1D46C ; [.1029.0020.000B.1D46C] # MATHEMATICAL BOLD ITALIC CAPITAL E; QQK
+1D4D4 ; [.1029.0020.000B.1D4D4] # MATHEMATICAL BOLD SCRIPT CAPITAL E; QQK
+1D508 ; [.1029.0020.000B.1D508] # MATHEMATICAL FRAKTUR CAPITAL E; QQK
+1D53C ; [.1029.0020.000B.1D53C] # MATHEMATICAL DOUBLE-STRUCK CAPITAL E; QQK
+1D570 ; [.1029.0020.000B.1D570] # MATHEMATICAL BOLD FRAKTUR CAPITAL E; QQK
+1D5A4 ; [.1029.0020.000B.1D5A4] # MATHEMATICAL SANS-SERIF CAPITAL E; QQK
+1D5D8 ; [.1029.0020.000B.1D5D8] # MATHEMATICAL SANS-SERIF BOLD CAPITAL E; QQK
+1D60C ; [.1029.0020.000B.1D60C] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL E; QQK
+1D640 ; [.1029.0020.000B.1D640] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL E; QQK
+1D674 ; [.1029.0020.000B.1D674] # MATHEMATICAL MONOSPACE CAPITAL E; QQK
+24BA ; [.1029.0020.000C.24BA] # CIRCLED LATIN CAPITAL LETTER E; QQK
+1D49 ; [.1029.0020.0014.1D49] # MODIFIER LETTER SMALL E; QQK
+2091 ; [.1029.0020.0015.2091] # LATIN SUBSCRIPT SMALL LETTER E; QQK
+1D31 ; [.1029.0020.001D.1D31] # MODIFIER LETTER CAPITAL E; QQK
+00E9 ; [.1029.0020.0002.0065][.0000.0032.0002.0301] # LATIN SMALL LETTER E WITH ACUTE; QQCM
+00C9 ; [.1029.0020.0008.0045][.0000.0032.0002.0301] # LATIN CAPITAL LETTER E WITH ACUTE; QQCM
+00E8 ; [.1029.0020.0002.0065][.0000.0035.0002.0300] # LATIN SMALL LETTER E WITH GRAVE; QQCM
+00C8 ; [.1029.0020.0008.0045][.0000.0035.0002.0300] # LATIN CAPITAL LETTER E WITH GRAVE; QQCM
+0115 ; [.1029.0020.0002.0065][.0000.0037.0002.0306] # LATIN SMALL LETTER E WITH BREVE; QQCM
+0114 ; [.1029.0020.0008.0045][.0000.0037.0002.0306] # LATIN CAPITAL LETTER E WITH BREVE; QQCM
+00EA ; [.1029.0020.0002.0065][.0000.003C.0002.0302] # LATIN SMALL LETTER E WITH CIRCUMFLEX; QQCM
+00CA ; [.1029.0020.0008.0045][.0000.003C.0002.0302] # LATIN CAPITAL LETTER E WITH CIRCUMFLEX; QQCM
+1EBF ; [.1029.0020.0002.0065][.0000.003C.0002.0302][.0000.0032.0002.0301] # LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE; QQCM
+1EBE ; [.1029.0020.0008.0045][.0000.003C.0002.0302][.0000.0032.0002.0301] # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE; QQCM
+1EC1 ; [.1029.0020.0002.0065][.0000.003C.0002.0302][.0000.0035.0002.0300] # LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE; QQCM
+1EC0 ; [.1029.0020.0008.0045][.0000.003C.0002.0302][.0000.0035.0002.0300] # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE; QQCM
+1EC5 ; [.1029.0020.0002.0065][.0000.003C.0002.0302][.0000.004E.0002.0303] # LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE; QQCM
+1EC4 ; [.1029.0020.0008.0045][.0000.003C.0002.0302][.0000.004E.0002.0303] # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE; QQCM
+1EC3 ; [.1029.0020.0002.0065][.0000.003C.0002.0302][.0000.0060.0002.0309] # LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE; QQCM
+1EC2 ; [.1029.0020.0008.0045][.0000.003C.0002.0302][.0000.0060.0002.0309] # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE; QQCM
+011B ; [.1029.0020.0002.0065][.0000.0041.0002.030C] # LATIN SMALL LETTER E WITH CARON; QQCM
+011A ; [.1029.0020.0008.0045][.0000.0041.0002.030C] # LATIN CAPITAL LETTER E WITH CARON; QQCM
+00EB ; [.1029.0020.0002.0065][.0000.0047.0002.0308] # LATIN SMALL LETTER E WITH DIAERESIS; QQCM
+00CB ; [.1029.0020.0008.0045][.0000.0047.0002.0308] # LATIN CAPITAL LETTER E WITH DIAERESIS; QQCM
+1EBD ; [.1029.0020.0002.0065][.0000.004E.0002.0303] # LATIN SMALL LETTER E WITH TILDE; QQCM
+1EBC ; [.1029.0020.0008.0045][.0000.004E.0002.0303] # LATIN CAPITAL LETTER E WITH TILDE; QQCM
+0117 ; [.1029.0020.0002.0065][.0000.0052.0002.0307] # LATIN SMALL LETTER E WITH DOT ABOVE; QQCM
+0116 ; [.1029.0020.0008.0045][.0000.0052.0002.0307] # LATIN CAPITAL LETTER E WITH DOT ABOVE; QQCM
+0229 ; [.1029.0020.0002.0065][.0000.0056.0002.0327] # LATIN SMALL LETTER E WITH CEDILLA; QQCM
+0228 ; [.1029.0020.0008.0045][.0000.0056.0002.0327] # LATIN CAPITAL LETTER E WITH CEDILLA; QQCM
+1E1D ; [.1029.0020.0002.0065][.0000.0056.0002.0327][.0000.0037.0002.0306] # LATIN SMALL LETTER E WITH CEDILLA AND BREVE; QQCM
+1E1C ; [.1029.0020.0008.0045][.0000.0056.0002.0327][.0000.0037.0002.0306] # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE; QQCM
+0119 ; [.1029.0020.0002.0065][.0000.0059.0002.0328] # LATIN SMALL LETTER E WITH OGONEK; QQCM
+0118 ; [.1029.0020.0008.0045][.0000.0059.0002.0328] # LATIN CAPITAL LETTER E WITH OGONEK; QQCM
+0113 ; [.1029.0020.0002.0065][.0000.005B.0002.0304] # LATIN SMALL LETTER E WITH MACRON; QQCM
+0112 ; [.1029.0020.0008.0045][.0000.005B.0002.0304] # LATIN CAPITAL LETTER E WITH MACRON; QQCM
+1E17 ; [.1029.0020.0002.0065][.0000.005B.0002.0304][.0000.0032.0002.0301] # LATIN SMALL LETTER E WITH MACRON AND ACUTE; QQCM
+1E16 ; [.1029.0020.0008.0045][.0000.005B.0002.0304][.0000.0032.0002.0301] # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE; QQCM
+1E15 ; [.1029.0020.0002.0065][.0000.005B.0002.0304][.0000.0035.0002.0300] # LATIN SMALL LETTER E WITH MACRON AND GRAVE; QQCM
+1E14 ; [.1029.0020.0008.0045][.0000.005B.0002.0304][.0000.0035.0002.0300] # LATIN CAPITAL LETTER E WITH MACRON AND GRAVE; QQCM
+1EBB ; [.1029.0020.0002.0065][.0000.0060.0002.0309] # LATIN SMALL LETTER E WITH HOOK ABOVE; QQCM
+1EBA ; [.1029.0020.0008.0045][.0000.0060.0002.0309] # LATIN CAPITAL LETTER E WITH HOOK ABOVE; QQCM
+0205 ; [.1029.0020.0002.0065][.0000.0063.0002.030F] # LATIN SMALL LETTER E WITH DOUBLE GRAVE; QQCM
+0204 ; [.1029.0020.0008.0045][.0000.0063.0002.030F] # LATIN CAPITAL LETTER E WITH DOUBLE GRAVE; QQCM
+0207 ; [.1029.0020.0002.0065][.0000.0065.0002.0311] # LATIN SMALL LETTER E WITH INVERTED BREVE; QQCM
+0206 ; [.1029.0020.0008.0045][.0000.0065.0002.0311] # LATIN CAPITAL LETTER E WITH INVERTED BREVE; QQCM
+1EB9 ; [.1029.0020.0002.0065][.0000.007A.0002.0323] # LATIN SMALL LETTER E WITH DOT BELOW; QQCM
+1EB8 ; [.1029.0020.0008.0045][.0000.007A.0002.0323] # LATIN CAPITAL LETTER E WITH DOT BELOW; QQCM
+1EC7 ; [.1029.0020.0002.0065][.0000.007A.0002.0323][.0000.003C.0002.0302] # LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW; QQCM
+1EC6 ; [.1029.0020.0008.0045][.0000.007A.0002.0323][.0000.003C.0002.0302] # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW; QQCM
+1E19 ; [.1029.0020.0002.0065][.0000.0086.0002.032D] # LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW; QQCM
+1E18 ; [.1029.0020.0008.0045][.0000.0086.0002.032D] # LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW; QQCM
+1E1B ; [.1029.0020.0002.0065][.0000.0089.0002.0330] # LATIN SMALL LETTER E WITH TILDE BELOW; QQCM
+1E1A ; [.1029.0020.0008.0045][.0000.0089.0002.0330] # LATIN CAPITAL LETTER E WITH TILDE BELOW; QQCM
+32CD ; [.1029.0020.001C.32CD][.117E.0020.001C.32CD][.106A.0020.001F.32CD] # SQUARE ERG; QQKN
+32CE ; [.1029.0020.001C.32CE][.1216.0020.001D.32CE] # SQUARE EV; QQKN
+1D07 ; [.102D.0020.0002.1D07] # LATIN LETTER SMALL CAPITAL E
+0247 ; [.102E.0020.0002.0247] # LATIN SMALL LETTER E WITH STROKE
+0246 ; [.102E.0020.0008.0246] # LATIN CAPITAL LETTER E WITH STROKE
+1D92 ; [.1032.0020.0002.1D92] # LATIN SMALL LETTER E WITH RETROFLEX HOOK
+01DD ; [.1033.0020.0002.01DD] # LATIN SMALL LETTER TURNED E
+018E ; [.1033.0020.0008.018E] # LATIN CAPITAL LETTER REVERSED E
+1D32 ; [.1033.0020.001D.1D32] # MODIFIER LETTER CAPITAL REVERSED E; QQK
+0259 ; [.1037.0020.0002.0259] # LATIN SMALL LETTER SCHWA
+018F ; [.1037.0020.0008.018F] # LATIN CAPITAL LETTER SCHWA
+1D4A ; [.1037.0020.0014.1D4A] # MODIFIER LETTER SMALL SCHWA; QQK
+2094 ; [.1037.0020.0015.2094] # LATIN SUBSCRIPT SMALL LETTER SCHWA; QQK
+1D95 ; [.103B.0020.0002.1D95] # LATIN SMALL LETTER SCHWA WITH RETROFLEX HOOK
+025B ; [.103C.0020.0002.025B] # LATIN SMALL LETTER OPEN E
+0190 ; [.103C.0020.0008.0190] # LATIN CAPITAL LETTER OPEN E
+2107 ; [.103C.0020.000A.2107] # EULER CONSTANT; QQK
+1D4B ; [.103C.0020.0014.1D4B] # MODIFIER LETTER SMALL OPEN E; QQK
+1D93 ; [.1040.0020.0002.1D93] # LATIN SMALL LETTER OPEN E WITH RETROFLEX HOOK
+0258 ; [.1041.0020.0002.0258] # LATIN SMALL LETTER REVERSED E
+025A ; [.1045.0020.0002.025A] # LATIN SMALL LETTER SCHWA WITH HOOK
+025C ; [.1049.0020.0002.025C] # LATIN SMALL LETTER REVERSED OPEN E
+1D9F ; [.1049.0020.0014.1D9F] # MODIFIER LETTER SMALL REVERSED OPEN E; QQK
+1D94 ; [.104D.0020.0002.1D94] # LATIN SMALL LETTER REVERSED OPEN E WITH RETROFLEX HOOK
+1D08 ; [.104E.0020.0002.1D08] # LATIN SMALL LETTER TURNED OPEN E
+1D4C ; [.104E.0020.0014.1D4C] # MODIFIER LETTER SMALL TURNED OPEN E; QQK
+025D ; [.104F.0020.0002.025D] # LATIN SMALL LETTER REVERSED OPEN E WITH HOOK
+025E ; [.1053.0020.0002.025E] # LATIN SMALL LETTER CLOSED REVERSED OPEN E
+029A ; [.1057.0020.0002.029A] # LATIN SMALL LETTER CLOSED OPEN E
+0264 ; [.105B.0020.0002.0264] # LATIN SMALL LETTER RAMS HORN
+0066 ; [.105F.0020.0002.0066] # LATIN SMALL LETTER F
+FF46 ; [.105F.0020.0003.FF46] # FULLWIDTH LATIN SMALL LETTER F; QQK
+24A1 ; [*02B1.0020.0004.24A1][.105F.0020.0004.24A1][*02B2.0020.001F.24A1] # PARENTHESIZED LATIN SMALL LETTER F; QQKN
+1D41F ; [.105F.0020.0005.1D41F] # MATHEMATICAL BOLD SMALL F; QQK
+1D453 ; [.105F.0020.0005.1D453] # MATHEMATICAL ITALIC SMALL F; QQK
+1D487 ; [.105F.0020.0005.1D487] # MATHEMATICAL BOLD ITALIC SMALL F; QQK
+1D4BB ; [.105F.0020.0005.1D4BB] # MATHEMATICAL SCRIPT SMALL F; QQK
+1D4EF ; [.105F.0020.0005.1D4EF] # MATHEMATICAL BOLD SCRIPT SMALL F; QQK
+1D523 ; [.105F.0020.0005.1D523] # MATHEMATICAL FRAKTUR SMALL F; QQK
+1D557 ; [.105F.0020.0005.1D557] # MATHEMATICAL DOUBLE-STRUCK SMALL F; QQK
+1D58B ; [.105F.0020.0005.1D58B] # MATHEMATICAL BOLD FRAKTUR SMALL F; QQK
+1D5BF ; [.105F.0020.0005.1D5BF] # MATHEMATICAL SANS-SERIF SMALL F; QQK
+1D5F3 ; [.105F.0020.0005.1D5F3] # MATHEMATICAL SANS-SERIF BOLD SMALL F; QQK
+1D627 ; [.105F.0020.0005.1D627] # MATHEMATICAL SANS-SERIF ITALIC SMALL F; QQK
+1D65B ; [.105F.0020.0005.1D65B] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL F; QQK
+1D68F ; [.105F.0020.0005.1D68F] # MATHEMATICAL MONOSPACE SMALL F; QQK
+24D5 ; [.105F.0020.0006.24D5] # CIRCLED LATIN SMALL LETTER F; QQK
+0046 ; [.105F.0020.0008.0046] # LATIN CAPITAL LETTER F
+FF26 ; [.105F.0020.0009.FF26] # FULLWIDTH LATIN CAPITAL LETTER F; QQK
+2109 ; [*03BF.0020.0004.2109][.105F.0020.000A.2109] # DEGREE FAHRENHEIT; QQKN
+2131 ; [.105F.0020.000B.2131] # SCRIPT CAPITAL F; QQK
+1D405 ; [.105F.0020.000B.1D405] # MATHEMATICAL BOLD CAPITAL F; QQK
+1D439 ; [.105F.0020.000B.1D439] # MATHEMATICAL ITALIC CAPITAL F; QQK
+1D46D ; [.105F.0020.000B.1D46D] # MATHEMATICAL BOLD ITALIC CAPITAL F; QQK
+1D4D5 ; [.105F.0020.000B.1D4D5] # MATHEMATICAL BOLD SCRIPT CAPITAL F; QQK
+1D509 ; [.105F.0020.000B.1D509] # MATHEMATICAL FRAKTUR CAPITAL F; QQK
+1D53D ; [.105F.0020.000B.1D53D] # MATHEMATICAL DOUBLE-STRUCK CAPITAL F; QQK
+1D571 ; [.105F.0020.000B.1D571] # MATHEMATICAL BOLD FRAKTUR CAPITAL F; QQK
+1D5A5 ; [.105F.0020.000B.1D5A5] # MATHEMATICAL SANS-SERIF CAPITAL F; QQK
+1D5D9 ; [.105F.0020.000B.1D5D9] # MATHEMATICAL SANS-SERIF BOLD CAPITAL F; QQK
+1D60D ; [.105F.0020.000B.1D60D] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL F; QQK
+1D641 ; [.105F.0020.000B.1D641] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL F; QQK
+1D675 ; [.105F.0020.000B.1D675] # MATHEMATICAL MONOSPACE CAPITAL F; QQK
+24BB ; [.105F.0020.000C.24BB] # CIRCLED LATIN CAPITAL LETTER F; QQK
+1DA0 ; [.105F.0020.0014.1DA0] # MODIFIER LETTER SMALL F; QQK
+1E1F ; [.105F.0020.0002.0066][.0000.0052.0002.0307] # LATIN SMALL LETTER F WITH DOT ABOVE; QQCM
+1E1E ; [.105F.0020.0008.0046][.0000.0052.0002.0307] # LATIN CAPITAL LETTER F WITH DOT ABOVE; QQCM
+213B ; [.105F.0020.000A.213B][.0FD0.0020.000A.213B][.122E.0020.001F.213B] # FACSIMILE SIGN; QQKN
+FB00 ; [.105F.0020.0004.FB00][.105F.0020.0004.FB00] # LATIN SMALL LIGATURE FF; QQKN
+FB03 ; [.105F.0020.0004.FB03][.105F.0020.0004.FB03][.10A5.0020.001F.FB03] # LATIN SMALL LIGATURE FFI; QQKN
+FB04 ; [.105F.0020.0004.FB04][.105F.0020.0004.FB04][.10E5.0020.001F.FB04] # LATIN SMALL LIGATURE FFL; QQKN
+FB01 ; [.105F.0020.0004.FB01][.10A5.0020.0004.FB01] # LATIN SMALL LIGATURE FI; QQKN
+FB02 ; [.105F.0020.0004.FB02][.10E5.0020.0004.FB02] # LATIN SMALL LIGATURE FL; QQKN
+3399 ; [.105F.0020.001C.3399][.1110.0020.001C.3399] # SQUARE FM; QQKN
+02A9 ; [.105F.0020.0004.02A9][.1137.0020.0004.02A9] # LATIN SMALL LETTER FENG DIGRAPH; QQKN
+1D6E ; [.1063.0020.0002.1D6E] # LATIN SMALL LETTER F WITH MIDDLE TILDE
+1D82 ; [.1064.0020.0002.1D82] # LATIN SMALL LETTER F WITH PALATAL HOOK
+0192 ; [.1065.0020.0002.0192] # LATIN SMALL LETTER F WITH HOOK
+0191 ; [.1065.0020.0008.0191] # LATIN CAPITAL LETTER F WITH HOOK
+214E ; [.1069.0020.0002.214E] # TURNED SMALL F
+2132 ; [.1069.0020.0008.2132] # TURNED CAPITAL F
+0067 ; [.106A.0020.0002.0067] # LATIN SMALL LETTER G
+FF47 ; [.106A.0020.0003.FF47] # FULLWIDTH LATIN SMALL LETTER G; QQK
+24A2 ; [*02B1.0020.0004.24A2][.106A.0020.0004.24A2][*02B2.0020.001F.24A2] # PARENTHESIZED LATIN SMALL LETTER G; QQKN
+210A ; [.106A.0020.0005.210A] # SCRIPT SMALL G; QQK
+1D420 ; [.106A.0020.0005.1D420] # MATHEMATICAL BOLD SMALL G; QQK
+1D454 ; [.106A.0020.0005.1D454] # MATHEMATICAL ITALIC SMALL G; QQK
+1D488 ; [.106A.0020.0005.1D488] # MATHEMATICAL BOLD ITALIC SMALL G; QQK
+1D4F0 ; [.106A.0020.0005.1D4F0] # MATHEMATICAL BOLD SCRIPT SMALL G; QQK
+1D524 ; [.106A.0020.0005.1D524] # MATHEMATICAL FRAKTUR SMALL G; QQK
+1D558 ; [.106A.0020.0005.1D558] # MATHEMATICAL DOUBLE-STRUCK SMALL G; QQK
+1D58C ; [.106A.0020.0005.1D58C] # MATHEMATICAL BOLD FRAKTUR SMALL G; QQK
+1D5C0 ; [.106A.0020.0005.1D5C0] # MATHEMATICAL SANS-SERIF SMALL G; QQK
+1D5F4 ; [.106A.0020.0005.1D5F4] # MATHEMATICAL SANS-SERIF BOLD SMALL G; QQK
+1D628 ; [.106A.0020.0005.1D628] # MATHEMATICAL SANS-SERIF ITALIC SMALL G; QQK
+1D65C ; [.106A.0020.0005.1D65C] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL G; QQK
+1D690 ; [.106A.0020.0005.1D690] # MATHEMATICAL MONOSPACE SMALL G; QQK
+24D6 ; [.106A.0020.0006.24D6] # CIRCLED LATIN SMALL LETTER G; QQK
+0047 ; [.106A.0020.0008.0047] # LATIN CAPITAL LETTER G
+FF27 ; [.106A.0020.0009.FF27] # FULLWIDTH LATIN CAPITAL LETTER G; QQK
+1D406 ; [.106A.0020.000B.1D406] # MATHEMATICAL BOLD CAPITAL G; QQK
+1D43A ; [.106A.0020.000B.1D43A] # MATHEMATICAL ITALIC CAPITAL G; QQK
+1D46E ; [.106A.0020.000B.1D46E] # MATHEMATICAL BOLD ITALIC CAPITAL G; QQK
+1D4A2 ; [.106A.0020.000B.1D4A2] # MATHEMATICAL SCRIPT CAPITAL G; QQK
+1D4D6 ; [.106A.0020.000B.1D4D6] # MATHEMATICAL BOLD SCRIPT CAPITAL G; QQK
+1D50A ; [.106A.0020.000B.1D50A] # MATHEMATICAL FRAKTUR CAPITAL G; QQK
+1D53E ; [.106A.0020.000B.1D53E] # MATHEMATICAL DOUBLE-STRUCK CAPITAL G; QQK
+1D572 ; [.106A.0020.000B.1D572] # MATHEMATICAL BOLD FRAKTUR CAPITAL G; QQK
+1D5A6 ; [.106A.0020.000B.1D5A6] # MATHEMATICAL SANS-SERIF CAPITAL G; QQK
+1D5DA ; [.106A.0020.000B.1D5DA] # MATHEMATICAL SANS-SERIF BOLD CAPITAL G; QQK
+1D60E ; [.106A.0020.000B.1D60E] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL G; QQK
+1D642 ; [.106A.0020.000B.1D642] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL G; QQK
+1D676 ; [.106A.0020.000B.1D676] # MATHEMATICAL MONOSPACE CAPITAL G; QQK
+24BC ; [.106A.0020.000C.24BC] # CIRCLED LATIN CAPITAL LETTER G; QQK
+1D4D ; [.106A.0020.0014.1D4D] # MODIFIER LETTER SMALL G; QQK
+1D33 ; [.106A.0020.001D.1D33] # MODIFIER LETTER CAPITAL G; QQK
+01F5 ; [.106A.0020.0002.0067][.0000.0032.0002.0301] # LATIN SMALL LETTER G WITH ACUTE; QQCM
+01F4 ; [.106A.0020.0008.0047][.0000.0032.0002.0301] # LATIN CAPITAL LETTER G WITH ACUTE; QQCM
+011F ; [.106A.0020.0002.0067][.0000.0037.0002.0306] # LATIN SMALL LETTER G WITH BREVE; QQCM
+011E ; [.106A.0020.0008.0047][.0000.0037.0002.0306] # LATIN CAPITAL LETTER G WITH BREVE; QQCM
+011D ; [.106A.0020.0002.0067][.0000.003C.0002.0302] # LATIN SMALL LETTER G WITH CIRCUMFLEX; QQCM
+011C ; [.106A.0020.0008.0047][.0000.003C.0002.0302] # LATIN CAPITAL LETTER G WITH CIRCUMFLEX; QQCM
+01E7 ; [.106A.0020.0002.0067][.0000.0041.0002.030C] # LATIN SMALL LETTER G WITH CARON; QQCM
+01E6 ; [.106A.0020.0008.0047][.0000.0041.0002.030C] # LATIN CAPITAL LETTER G WITH CARON; QQCM
+0121 ; [.106A.0020.0002.0067][.0000.0052.0002.0307] # LATIN SMALL LETTER G WITH DOT ABOVE; QQCM
+0120 ; [.106A.0020.0008.0047][.0000.0052.0002.0307] # LATIN CAPITAL LETTER G WITH DOT ABOVE; QQCM
+0123 ; [.106A.0020.0002.0067][.0000.0056.0002.0327] # LATIN SMALL LETTER G WITH CEDILLA; QQCM
+0122 ; [.106A.0020.0008.0047][.0000.0056.0002.0327] # LATIN CAPITAL LETTER G WITH CEDILLA; QQCM
+1E21 ; [.106A.0020.0002.0067][.0000.005B.0002.0304] # LATIN SMALL LETTER G WITH MACRON; QQCM
+1E20 ; [.106A.0020.0008.0047][.0000.005B.0002.0304] # LATIN CAPITAL LETTER G WITH MACRON; QQCM
+33FF ; [.106A.0020.001C.33FF][.0FD0.0020.001C.33FF][.10E5.0020.001F.33FF] # SQUARE GAL; QQKN
+3387 ; [.106A.0020.001D.3387][.0FE6.0020.001D.3387] # SQUARE GB; QQKN
+3393 ; [.106A.0020.001D.3393][.108D.0020.001D.3393][.1243.0020.001F.3393] # SQUARE GHZ; QQKN
+33AC ; [.106A.0020.001D.33AC][.115D.0020.001D.33AC][.0FD0.0020.001F.33AC] # SQUARE GPA; QQKN
+33C9 ; [.106A.0020.001D.33C9][.1233.0020.001C.33C9] # SQUARE GY; QQKN
+0261 ; [.106E.0020.0002.0261] # LATIN SMALL LETTER SCRIPT G
+1DA2 ; [.106E.0020.0014.1DA2] # MODIFIER LETTER SMALL SCRIPT G; QQK
+1D79 ; [.1072.0020.0002.1D79] # LATIN SMALL LETTER INSULAR G
+0262 ; [.1073.0020.0002.0262] # LATIN LETTER SMALL CAPITAL G
+01E5 ; [.1077.0020.0002.01E5] # LATIN SMALL LETTER G WITH STROKE
+01E4 ; [.1077.0020.0008.01E4] # LATIN CAPITAL LETTER G WITH STROKE
+1D83 ; [.107B.0020.0002.1D83] # LATIN SMALL LETTER G WITH PALATAL HOOK
+0260 ; [.107C.0020.0002.0260] # LATIN SMALL LETTER G WITH HOOK
+0193 ; [.107C.0020.0008.0193] # LATIN CAPITAL LETTER G WITH HOOK
+029B ; [.1080.0020.0002.029B] # LATIN LETTER SMALL CAPITAL G WITH HOOK
+1D77 ; [.1084.0020.0002.1D77] # LATIN SMALL LETTER TURNED G
+0263 ; [.1085.0020.0002.0263] # LATIN SMALL LETTER GAMMA
+0194 ; [.1085.0020.0008.0194] # LATIN CAPITAL LETTER GAMMA
+02E0 ; [.1085.0020.0014.02E0] # MODIFIER LETTER SMALL GAMMA; QQK
+01A3 ; [.1089.0020.0002.01A3] # LATIN SMALL LETTER OI
+01A2 ; [.1089.0020.0008.01A2] # LATIN CAPITAL LETTER OI
+0068 ; [.108D.0020.0002.0068] # LATIN SMALL LETTER H
+FF48 ; [.108D.0020.0003.FF48] # FULLWIDTH LATIN SMALL LETTER H; QQK
+036A ; [.108D.0020.0004.036A] # COMBINING LATIN SMALL LETTER H; QQK
+24A3 ; [*02B1.0020.0004.24A3][.108D.0020.0004.24A3][*02B2.0020.001F.24A3] # PARENTHESIZED LATIN SMALL LETTER H; QQKN
+210E ; [.108D.0020.0005.210E] # PLANCK CONSTANT; QQK
+1D421 ; [.108D.0020.0005.1D421] # MATHEMATICAL BOLD SMALL H; QQK
+1D489 ; [.108D.0020.0005.1D489] # MATHEMATICAL BOLD ITALIC SMALL H; QQK
+1D4BD ; [.108D.0020.0005.1D4BD] # MATHEMATICAL SCRIPT SMALL H; QQK
+1D4F1 ; [.108D.0020.0005.1D4F1] # MATHEMATICAL BOLD SCRIPT SMALL H; QQK
+1D525 ; [.108D.0020.0005.1D525] # MATHEMATICAL FRAKTUR SMALL H; QQK
+1D559 ; [.108D.0020.0005.1D559] # MATHEMATICAL DOUBLE-STRUCK SMALL H; QQK
+1D58D ; [.108D.0020.0005.1D58D] # MATHEMATICAL BOLD FRAKTUR SMALL H; QQK
+1D5C1 ; [.108D.0020.0005.1D5C1] # MATHEMATICAL SANS-SERIF SMALL H; QQK
+1D5F5 ; [.108D.0020.0005.1D5F5] # MATHEMATICAL SANS-SERIF BOLD SMALL H; QQK
+1D629 ; [.108D.0020.0005.1D629] # MATHEMATICAL SANS-SERIF ITALIC SMALL H; QQK
+1D65D ; [.108D.0020.0005.1D65D] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL H; QQK
+1D691 ; [.108D.0020.0005.1D691] # MATHEMATICAL MONOSPACE SMALL H; QQK
+24D7 ; [.108D.0020.0006.24D7] # CIRCLED LATIN SMALL LETTER H; QQK
+0048 ; [.108D.0020.0008.0048] # LATIN CAPITAL LETTER H
+FF28 ; [.108D.0020.0009.FF28] # FULLWIDTH LATIN CAPITAL LETTER H; QQK
+210B ; [.108D.0020.000B.210B] # SCRIPT CAPITAL H; QQK
+210C ; [.108D.0020.000B.210C] # BLACK-LETTER CAPITAL H; QQK
+210D ; [.108D.0020.000B.210D] # DOUBLE-STRUCK CAPITAL H; QQK
+1D407 ; [.108D.0020.000B.1D407] # MATHEMATICAL BOLD CAPITAL H; QQK
+1D43B ; [.108D.0020.000B.1D43B] # MATHEMATICAL ITALIC CAPITAL H; QQK
+1D46F ; [.108D.0020.000B.1D46F] # MATHEMATICAL BOLD ITALIC CAPITAL H; QQK
+1D4D7 ; [.108D.0020.000B.1D4D7] # MATHEMATICAL BOLD SCRIPT CAPITAL H; QQK
+1D573 ; [.108D.0020.000B.1D573] # MATHEMATICAL BOLD FRAKTUR CAPITAL H; QQK
+1D5A7 ; [.108D.0020.000B.1D5A7] # MATHEMATICAL SANS-SERIF CAPITAL H; QQK
+1D5DB ; [.108D.0020.000B.1D5DB] # MATHEMATICAL SANS-SERIF BOLD CAPITAL H; QQK
+1D60F ; [.108D.0020.000B.1D60F] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL H; QQK
+1D643 ; [.108D.0020.000B.1D643] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL H; QQK
+1D677 ; [.108D.0020.000B.1D677] # MATHEMATICAL MONOSPACE CAPITAL H; QQK
+24BD ; [.108D.0020.000C.24BD] # CIRCLED LATIN CAPITAL LETTER H; QQK
+02B0 ; [.108D.0020.0014.02B0] # MODIFIER LETTER SMALL H; QQK
+1D34 ; [.108D.0020.001D.1D34] # MODIFIER LETTER CAPITAL H; QQK
+0125 ; [.108D.0020.0002.0068][.0000.003C.0002.0302] # LATIN SMALL LETTER H WITH CIRCUMFLEX; QQCM
+0124 ; [.108D.0020.0008.0048][.0000.003C.0002.0302] # LATIN CAPITAL LETTER H WITH CIRCUMFLEX; QQCM
+021F ; [.108D.0020.0002.0068][.0000.0041.0002.030C] # LATIN SMALL LETTER H WITH CARON; QQCM
+021E ; [.108D.0020.0008.0048][.0000.0041.0002.030C] # LATIN CAPITAL LETTER H WITH CARON; QQCM
+1E27 ; [.108D.0020.0002.0068][.0000.0047.0002.0308] # LATIN SMALL LETTER H WITH DIAERESIS; QQCM
+1E26 ; [.108D.0020.0008.0048][.0000.0047.0002.0308] # LATIN CAPITAL LETTER H WITH DIAERESIS; QQCM
+1E23 ; [.108D.0020.0002.0068][.0000.0052.0002.0307] # LATIN SMALL LETTER H WITH DOT ABOVE; QQCM
+1E22 ; [.108D.0020.0008.0048][.0000.0052.0002.0307] # LATIN CAPITAL LETTER H WITH DOT ABOVE; QQCM
+1E29 ; [.108D.0020.0002.0068][.0000.0056.0002.0327] # LATIN SMALL LETTER H WITH CEDILLA; QQCM
+1E28 ; [.108D.0020.0008.0048][.0000.0056.0002.0327] # LATIN CAPITAL LETTER H WITH CEDILLA; QQCM
+1E25 ; [.108D.0020.0002.0068][.0000.007A.0002.0323] # LATIN SMALL LETTER H WITH DOT BELOW; QQCM
+1E24 ; [.108D.0020.0008.0048][.0000.007A.0002.0323] # LATIN CAPITAL LETTER H WITH DOT BELOW; QQCM
+1E2B ; [.108D.0020.0002.0068][.0000.0087.0002.032E] # LATIN SMALL LETTER H WITH BREVE BELOW; QQCM
+1E2A ; [.108D.0020.0008.0048][.0000.0087.0002.032E] # LATIN CAPITAL LETTER H WITH BREVE BELOW; QQCM
+1E96 ; [.108D.0020.0002.0068][.0000.008A.0002.0331] # LATIN SMALL LETTER H WITH LINE BELOW; QQCM
+0127 ; [.108D.0020.0002.0068][.0000.008D.0002.0335] # LATIN SMALL LETTER H WITH STROKE; QQCM
+210F ; [.108D.0020.0002.210F][.0000.008D.0002.210F] # PLANCK CONSTANT OVER TWO PI; QQKN
+0126 ; [.108D.0020.0008.0048][.0000.008D.0002.0335] # LATIN CAPITAL LETTER H WITH STROKE; QQCM
+33CA ; [.108D.0020.001C.33CA][.0FD0.0020.001C.33CA] # SQUARE HA; QQKN
+32CC ; [.108D.0020.001D.32CC][.106A.0020.001C.32CC] # SQUARE HG; QQKN
+33CB ; [.108D.0020.001D.33CB][.115D.0020.001D.33CB] # SQUARE HP; QQKN
+3371 ; [.108D.0020.001C.3371][.115D.0020.001D.3371][.0FD0.0020.001F.3371] # SQUARE HPA; QQKN
+3390 ; [.108D.0020.001D.3390][.1243.0020.001C.3390] # SQUARE HZ; QQKN
+029C ; [.1091.0020.0002.029C] # LATIN LETTER SMALL CAPITAL H
+0195 ; [.1095.0020.0002.0195] # LATIN SMALL LETTER HV
+01F6 ; [.1095.0020.0008.01F6] # LATIN CAPITAL LETTER HWAIR
+0266 ; [.1099.0020.0002.0266] # LATIN SMALL LETTER H WITH HOOK
+02B1 ; [.1099.0020.0014.02B1] # MODIFIER LETTER SMALL H WITH HOOK; QQK
+2C68 ; [.109D.0020.0002.2C68] # LATIN SMALL LETTER H WITH DESCENDER
+2C67 ; [.109D.0020.0008.2C67] # LATIN CAPITAL LETTER H WITH DESCENDER
+2C76 ; [.109E.0020.0002.2C76] # LATIN SMALL LETTER HALF H
+2C75 ; [.109E.0020.0008.2C75] # LATIN CAPITAL LETTER HALF H
+0267 ; [.109F.0020.0002.0267] # LATIN SMALL LETTER HENG WITH HOOK
+02BB ; [.10A3.0020.0002.02BB] # MODIFIER LETTER TURNED COMMA
+02BD ; [.10A4.0020.0002.02BD] # MODIFIER LETTER REVERSED COMMA
+0069 ; [.10A5.0020.0002.0069] # LATIN SMALL LETTER I
+FF49 ; [.10A5.0020.0003.FF49] # FULLWIDTH LATIN SMALL LETTER I; QQK
+0365 ; [.10A5.0020.0004.0365] # COMBINING LATIN SMALL LETTER I; QQK
+2170 ; [.10A5.0020.0004.2170] # SMALL ROMAN NUMERAL ONE; QQK
+24A4 ; [*02B1.0020.0004.24A4][.10A5.0020.0004.24A4][*02B2.0020.001F.24A4] # PARENTHESIZED LATIN SMALL LETTER I; QQKN
+2139 ; [.10A5.0020.0005.2139] # INFORMATION SOURCE; QQK
+2148 ; [.10A5.0020.0005.2148] # DOUBLE-STRUCK ITALIC SMALL I; QQK
+1D422 ; [.10A5.0020.0005.1D422] # MATHEMATICAL BOLD SMALL I; QQK
+1D456 ; [.10A5.0020.0005.1D456] # MATHEMATICAL ITALIC SMALL I; QQK
+1D48A ; [.10A5.0020.0005.1D48A] # MATHEMATICAL BOLD ITALIC SMALL I; QQK
+1D4BE ; [.10A5.0020.0005.1D4BE] # MATHEMATICAL SCRIPT SMALL I; QQK
+1D4F2 ; [.10A5.0020.0005.1D4F2] # MATHEMATICAL BOLD SCRIPT SMALL I; QQK
+1D526 ; [.10A5.0020.0005.1D526] # MATHEMATICAL FRAKTUR SMALL I; QQK
+1D55A ; [.10A5.0020.0005.1D55A] # MATHEMATICAL DOUBLE-STRUCK SMALL I; QQK
+1D58E ; [.10A5.0020.0005.1D58E] # MATHEMATICAL BOLD FRAKTUR SMALL I; QQK
+1D5C2 ; [.10A5.0020.0005.1D5C2] # MATHEMATICAL SANS-SERIF SMALL I; QQK
+1D5F6 ; [.10A5.0020.0005.1D5F6] # MATHEMATICAL SANS-SERIF BOLD SMALL I; QQK
+1D62A ; [.10A5.0020.0005.1D62A] # MATHEMATICAL SANS-SERIF ITALIC SMALL I; QQK
+1D65E ; [.10A5.0020.0005.1D65E] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I; QQK
+1D692 ; [.10A5.0020.0005.1D692] # MATHEMATICAL MONOSPACE SMALL I; QQK
+24D8 ; [.10A5.0020.0006.24D8] # CIRCLED LATIN SMALL LETTER I; QQK
+0049 ; [.10A5.0020.0008.0049] # LATIN CAPITAL LETTER I
+FF29 ; [.10A5.0020.0009.FF29] # FULLWIDTH LATIN CAPITAL LETTER I; QQK
+2160 ; [.10A5.0020.000A.2160] # ROMAN NUMERAL ONE; QQK
+2110 ; [.10A5.0020.000B.2110] # SCRIPT CAPITAL I; QQK
+2111 ; [.10A5.0020.000B.2111] # BLACK-LETTER CAPITAL I; QQK
+1D408 ; [.10A5.0020.000B.1D408] # MATHEMATICAL BOLD CAPITAL I; QQK
+1D43C ; [.10A5.0020.000B.1D43C] # MATHEMATICAL ITALIC CAPITAL I; QQK
+1D470 ; [.10A5.0020.000B.1D470] # MATHEMATICAL BOLD ITALIC CAPITAL I; QQK
+1D4D8 ; [.10A5.0020.000B.1D4D8] # MATHEMATICAL BOLD SCRIPT CAPITAL I; QQK
+1D540 ; [.10A5.0020.000B.1D540] # MATHEMATICAL DOUBLE-STRUCK CAPITAL I; QQK
+1D574 ; [.10A5.0020.000B.1D574] # MATHEMATICAL BOLD FRAKTUR CAPITAL I; QQK
+1D5A8 ; [.10A5.0020.000B.1D5A8] # MATHEMATICAL SANS-SERIF CAPITAL I; QQK
+1D5DC ; [.10A5.0020.000B.1D5DC] # MATHEMATICAL SANS-SERIF BOLD CAPITAL I; QQK
+1D610 ; [.10A5.0020.000B.1D610] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL I; QQK
+1D644 ; [.10A5.0020.000B.1D644] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL I; QQK
+1D678 ; [.10A5.0020.000B.1D678] # MATHEMATICAL MONOSPACE CAPITAL I; QQK
+24BE ; [.10A5.0020.000C.24BE] # CIRCLED LATIN CAPITAL LETTER I; QQK
+2071 ; [.10A5.0020.0014.2071] # SUPERSCRIPT LATIN SMALL LETTER I; QQK
+1D62 ; [.10A5.0020.0015.1D62] # LATIN SUBSCRIPT SMALL LETTER I; QQK
+1D35 ; [.10A5.0020.001D.1D35] # MODIFIER LETTER CAPITAL I; QQK
+00ED ; [.10A5.0020.0002.0069][.0000.0032.0002.0301] # LATIN SMALL LETTER I WITH ACUTE; QQCM
+00CD ; [.10A5.0020.0008.0049][.0000.0032.0002.0301] # LATIN CAPITAL LETTER I WITH ACUTE; QQCM
+00EC ; [.10A5.0020.0002.0069][.0000.0035.0002.0300] # LATIN SMALL LETTER I WITH GRAVE; QQCM
+00CC ; [.10A5.0020.0008.0049][.0000.0035.0002.0300] # LATIN CAPITAL LETTER I WITH GRAVE; QQCM
+012D ; [.10A5.0020.0002.0069][.0000.0037.0002.0306] # LATIN SMALL LETTER I WITH BREVE; QQCM
+012C ; [.10A5.0020.0008.0049][.0000.0037.0002.0306] # LATIN CAPITAL LETTER I WITH BREVE; QQCM
+00EE ; [.10A5.0020.0002.0069][.0000.003C.0002.0302] # LATIN SMALL LETTER I WITH CIRCUMFLEX; QQCM
+00CE ; [.10A5.0020.0008.0049][.0000.003C.0002.0302] # LATIN CAPITAL LETTER I WITH CIRCUMFLEX; QQCM
+01D0 ; [.10A5.0020.0002.0069][.0000.0041.0002.030C] # LATIN SMALL LETTER I WITH CARON; QQCM
+01CF ; [.10A5.0020.0008.0049][.0000.0041.0002.030C] # LATIN CAPITAL LETTER I WITH CARON; QQCM
+00EF ; [.10A5.0020.0002.0069][.0000.0047.0002.0308] # LATIN SMALL LETTER I WITH DIAERESIS; QQCM
+00CF ; [.10A5.0020.0008.0049][.0000.0047.0002.0308] # LATIN CAPITAL LETTER I WITH DIAERESIS; QQCM
+1E2F ; [.10A5.0020.0002.0069][.0000.0047.0002.0308][.0000.0032.0002.0301] # LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE; QQCM
+1E2E ; [.10A5.0020.0008.0049][.0000.0047.0002.0308][.0000.0032.0002.0301] # LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE; QQCM
+0129 ; [.10A5.0020.0002.0069][.0000.004E.0002.0303] # LATIN SMALL LETTER I WITH TILDE; QQCM
+0128 ; [.10A5.0020.0008.0049][.0000.004E.0002.0303] # LATIN CAPITAL LETTER I WITH TILDE; QQCM
+0130 ; [.10A5.0020.0008.0049][.0000.0052.0002.0307] # LATIN CAPITAL LETTER I WITH DOT ABOVE; QQCM
+012F ; [.10A5.0020.0002.0069][.0000.0059.0002.0328] # LATIN SMALL LETTER I WITH OGONEK; QQCM
+012E ; [.10A5.0020.0008.0049][.0000.0059.0002.0328] # LATIN CAPITAL LETTER I WITH OGONEK; QQCM
+012B ; [.10A5.0020.0002.0069][.0000.005B.0002.0304] # LATIN SMALL LETTER I WITH MACRON; QQCM
+012A ; [.10A5.0020.0008.0049][.0000.005B.0002.0304] # LATIN CAPITAL LETTER I WITH MACRON; QQCM
+1EC9 ; [.10A5.0020.0002.0069][.0000.0060.0002.0309] # LATIN SMALL LETTER I WITH HOOK ABOVE; QQCM
+1EC8 ; [.10A5.0020.0008.0049][.0000.0060.0002.0309] # LATIN CAPITAL LETTER I WITH HOOK ABOVE; QQCM
+0209 ; [.10A5.0020.0002.0069][.0000.0063.0002.030F] # LATIN SMALL LETTER I WITH DOUBLE GRAVE; QQCM
+0208 ; [.10A5.0020.0008.0049][.0000.0063.0002.030F] # LATIN CAPITAL LETTER I WITH DOUBLE GRAVE; QQCM
+020B ; [.10A5.0020.0002.0069][.0000.0065.0002.0311] # LATIN SMALL LETTER I WITH INVERTED BREVE; QQCM
+020A ; [.10A5.0020.0008.0049][.0000.0065.0002.0311] # LATIN CAPITAL LETTER I WITH INVERTED BREVE; QQCM
+1ECB ; [.10A5.0020.0002.0069][.0000.007A.0002.0323] # LATIN SMALL LETTER I WITH DOT BELOW; QQCM
+1ECA ; [.10A5.0020.0008.0049][.0000.007A.0002.0323] # LATIN CAPITAL LETTER I WITH DOT BELOW; QQCM
+1E2D ; [.10A5.0020.0002.0069][.0000.0089.0002.0330] # LATIN SMALL LETTER I WITH TILDE BELOW; QQCM
+1E2C ; [.10A5.0020.0008.0049][.0000.0089.0002.0330] # LATIN CAPITAL LETTER I WITH TILDE BELOW; QQCM
+2171 ; [.10A5.0020.0004.2171][.10A5.0020.0004.2171] # SMALL ROMAN NUMERAL TWO; QQKN
+2161 ; [.10A5.0020.000A.2161][.10A5.0020.000A.2161] # ROMAN NUMERAL TWO; QQKN
+2172 ; [.10A5.0020.0004.2172][.10A5.0020.0004.2172][.10A5.0020.001F.2172] # SMALL ROMAN NUMERAL THREE; QQKN
+2162 ; [.10A5.0020.000A.2162][.10A5.0020.000A.2162][.10A5.0020.001F.2162] # ROMAN NUMERAL THREE; QQKN
+0133 ; [.10A5.0020.0004.0133][.10BD.0020.0004.0133] # LATIN SMALL LIGATURE IJ; QQKN
+0132 ; [.10A5.0020.000A.0132][.10BD.0020.000A.0132] # LATIN CAPITAL LIGATURE IJ; QQKN
+33CC ; [.10A5.0020.001C.33CC][.111B.0020.001C.33CC] # SQUARE IN; QQKN
+337A ; [.10A5.0020.001D.337A][.11EE.0020.001D.337A] # SQUARE IU; QQKN
+2173 ; [.10A5.0020.0004.2173][.1216.0020.0004.2173] # SMALL ROMAN NUMERAL FOUR; QQKN
+2163 ; [.10A5.0020.000A.2163][.1216.0020.000A.2163] # ROMAN NUMERAL FOUR; QQKN
+2178 ; [.10A5.0020.0004.2178][.122E.0020.0004.2178] # SMALL ROMAN NUMERAL NINE; QQKN
+2168 ; [.10A5.0020.000A.2168][.122E.0020.000A.2168] # ROMAN NUMERAL NINE; QQKN
+0131 ; [.10A9.0020.0002.0131] # LATIN SMALL LETTER DOTLESS I
+1D6A4 ; [.10A9.0020.0005.1D6A4] # MATHEMATICAL ITALIC SMALL DOTLESS I; QQK
+026A ; [.10AD.0020.0002.026A] # LATIN LETTER SMALL CAPITAL I
+1DA6 ; [.10AD.0020.0014.1DA6] # MODIFIER LETTER SMALL CAPITAL I; QQK
+1D09 ; [.10B1.0020.0002.1D09] # LATIN SMALL LETTER TURNED I
+1D4E ; [.10B1.0020.0014.1D4E] # MODIFIER LETTER SMALL TURNED I; QQK
+0268 ; [.10B2.0020.0002.0268] # LATIN SMALL LETTER I WITH STROKE
+0197 ; [.10B2.0020.0008.0197] # LATIN CAPITAL LETTER I WITH STROKE
+1DA4 ; [.10B2.0020.0014.1DA4] # MODIFIER LETTER SMALL I WITH STROKE; QQK
+1D7B ; [.10B6.0020.0002.1D7B] # LATIN SMALL CAPITAL LETTER I WITH STROKE
+1DA7 ; [.10B6.0020.0014.1DA7] # MODIFIER LETTER SMALL CAPITAL I WITH STROKE; QQK
+1D96 ; [.10B7.0020.0002.1D96] # LATIN SMALL LETTER I WITH RETROFLEX HOOK
+0269 ; [.10B8.0020.0002.0269] # LATIN SMALL LETTER IOTA
+0196 ; [.10B8.0020.0008.0196] # LATIN CAPITAL LETTER IOTA
+1DA5 ; [.10B8.0020.0014.1DA5] # MODIFIER LETTER SMALL IOTA; QQK
+1D7C ; [.10BC.0020.0002.1D7C] # LATIN SMALL LETTER IOTA WITH STROKE
+006A ; [.10BD.0020.0002.006A] # LATIN SMALL LETTER J
+FF4A ; [.10BD.0020.0003.FF4A] # FULLWIDTH LATIN SMALL LETTER J; QQK
+24A5 ; [*02B1.0020.0004.24A5][.10BD.0020.0004.24A5][*02B2.0020.001F.24A5] # PARENTHESIZED LATIN SMALL LETTER J; QQKN
+2149 ; [.10BD.0020.0005.2149] # DOUBLE-STRUCK ITALIC SMALL J; QQK
+1D423 ; [.10BD.0020.0005.1D423] # MATHEMATICAL BOLD SMALL J; QQK
+1D457 ; [.10BD.0020.0005.1D457] # MATHEMATICAL ITALIC SMALL J; QQK
+1D48B ; [.10BD.0020.0005.1D48B] # MATHEMATICAL BOLD ITALIC SMALL J; QQK
+1D4BF ; [.10BD.0020.0005.1D4BF] # MATHEMATICAL SCRIPT SMALL J; QQK
+1D4F3 ; [.10BD.0020.0005.1D4F3] # MATHEMATICAL BOLD SCRIPT SMALL J; QQK
+1D527 ; [.10BD.0020.0005.1D527] # MATHEMATICAL FRAKTUR SMALL J; QQK
+1D55B ; [.10BD.0020.0005.1D55B] # MATHEMATICAL DOUBLE-STRUCK SMALL J; QQK
+1D58F ; [.10BD.0020.0005.1D58F] # MATHEMATICAL BOLD FRAKTUR SMALL J; QQK
+1D5C3 ; [.10BD.0020.0005.1D5C3] # MATHEMATICAL SANS-SERIF SMALL J; QQK
+1D5F7 ; [.10BD.0020.0005.1D5F7] # MATHEMATICAL SANS-SERIF BOLD SMALL J; QQK
+1D62B ; [.10BD.0020.0005.1D62B] # MATHEMATICAL SANS-SERIF ITALIC SMALL J; QQK
+1D65F ; [.10BD.0020.0005.1D65F] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J; QQK
+1D693 ; [.10BD.0020.0005.1D693] # MATHEMATICAL MONOSPACE SMALL J; QQK
+24D9 ; [.10BD.0020.0006.24D9] # CIRCLED LATIN SMALL LETTER J; QQK
+004A ; [.10BD.0020.0008.004A] # LATIN CAPITAL LETTER J
+FF2A ; [.10BD.0020.0009.FF2A] # FULLWIDTH LATIN CAPITAL LETTER J; QQK
+1D409 ; [.10BD.0020.000B.1D409] # MATHEMATICAL BOLD CAPITAL J; QQK
+1D43D ; [.10BD.0020.000B.1D43D] # MATHEMATICAL ITALIC CAPITAL J; QQK
+1D471 ; [.10BD.0020.000B.1D471] # MATHEMATICAL BOLD ITALIC CAPITAL J; QQK
+1D4A5 ; [.10BD.0020.000B.1D4A5] # MATHEMATICAL SCRIPT CAPITAL J; QQK
+1D4D9 ; [.10BD.0020.000B.1D4D9] # MATHEMATICAL BOLD SCRIPT CAPITAL J; QQK
+1D50D ; [.10BD.0020.000B.1D50D] # MATHEMATICAL FRAKTUR CAPITAL J; QQK
+1D541 ; [.10BD.0020.000B.1D541] # MATHEMATICAL DOUBLE-STRUCK CAPITAL J; QQK
+1D575 ; [.10BD.0020.000B.1D575] # MATHEMATICAL BOLD FRAKTUR CAPITAL J; QQK
+1D5A9 ; [.10BD.0020.000B.1D5A9] # MATHEMATICAL SANS-SERIF CAPITAL J; QQK
+1D5DD ; [.10BD.0020.000B.1D5DD] # MATHEMATICAL SANS-SERIF BOLD CAPITAL J; QQK
+1D611 ; [.10BD.0020.000B.1D611] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL J; QQK
+1D645 ; [.10BD.0020.000B.1D645] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL J; QQK
+1D679 ; [.10BD.0020.000B.1D679] # MATHEMATICAL MONOSPACE CAPITAL J; QQK
+24BF ; [.10BD.0020.000C.24BF] # CIRCLED LATIN CAPITAL LETTER J; QQK
+02B2 ; [.10BD.0020.0014.02B2] # MODIFIER LETTER SMALL J; QQK
+1D36 ; [.10BD.0020.001D.1D36] # MODIFIER LETTER CAPITAL J; QQK
+0135 ; [.10BD.0020.0002.006A][.0000.003C.0002.0302] # LATIN SMALL LETTER J WITH CIRCUMFLEX; QQCM
+0134 ; [.10BD.0020.0008.004A][.0000.003C.0002.0302] # LATIN CAPITAL LETTER J WITH CIRCUMFLEX; QQCM
+01F0 ; [.10BD.0020.0002.006A][.0000.0041.0002.030C] # LATIN SMALL LETTER J WITH CARON; QQCM
+0237 ; [.10C1.0020.0002.0237] # LATIN SMALL LETTER DOTLESS J
+1D6A5 ; [.10C1.0020.0005.1D6A5] # MATHEMATICAL ITALIC SMALL DOTLESS J; QQK
+1D0A ; [.10C5.0020.0002.1D0A] # LATIN LETTER SMALL CAPITAL J
+0249 ; [.10C6.0020.0002.0249] # LATIN SMALL LETTER J WITH STROKE
+0248 ; [.10C6.0020.0008.0248] # LATIN CAPITAL LETTER J WITH STROKE
+029D ; [.10CA.0020.0002.029D] # LATIN SMALL LETTER J WITH CROSSED-TAIL
+1DA8 ; [.10CA.0020.0014.1DA8] # MODIFIER LETTER SMALL J WITH CROSSED-TAIL; QQK
+025F ; [.10CE.0020.0002.025F] # LATIN SMALL LETTER DOTLESS J WITH STROKE
+1DA1 ; [.10CE.0020.0014.1DA1] # MODIFIER LETTER SMALL DOTLESS J WITH STROKE; QQK
+0284 ; [.10D2.0020.0002.0284] # LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK
+006B ; [.10D6.0020.0002.006B] # LATIN SMALL LETTER K
+FF4B ; [.10D6.0020.0003.FF4B] # FULLWIDTH LATIN SMALL LETTER K; QQK
+24A6 ; [*02B1.0020.0004.24A6][.10D6.0020.0004.24A6][*02B2.0020.001F.24A6] # PARENTHESIZED LATIN SMALL LETTER K; QQKN
+1D424 ; [.10D6.0020.0005.1D424] # MATHEMATICAL BOLD SMALL K; QQK
+1D458 ; [.10D6.0020.0005.1D458] # MATHEMATICAL ITALIC SMALL K; QQK
+1D48C ; [.10D6.0020.0005.1D48C] # MATHEMATICAL BOLD ITALIC SMALL K; QQK
+1D4C0 ; [.10D6.0020.0005.1D4C0] # MATHEMATICAL SCRIPT SMALL K; QQK
+1D4F4 ; [.10D6.0020.0005.1D4F4] # MATHEMATICAL BOLD SCRIPT SMALL K; QQK
+1D528 ; [.10D6.0020.0005.1D528] # MATHEMATICAL FRAKTUR SMALL K; QQK
+1D55C ; [.10D6.0020.0005.1D55C] # MATHEMATICAL DOUBLE-STRUCK SMALL K; QQK
+1D590 ; [.10D6.0020.0005.1D590] # MATHEMATICAL BOLD FRAKTUR SMALL K; QQK
+1D5C4 ; [.10D6.0020.0005.1D5C4] # MATHEMATICAL SANS-SERIF SMALL K; QQK
+1D5F8 ; [.10D6.0020.0005.1D5F8] # MATHEMATICAL SANS-SERIF BOLD SMALL K; QQK
+1D62C ; [.10D6.0020.0005.1D62C] # MATHEMATICAL SANS-SERIF ITALIC SMALL K; QQK
+1D660 ; [.10D6.0020.0005.1D660] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL K; QQK
+1D694 ; [.10D6.0020.0005.1D694] # MATHEMATICAL MONOSPACE SMALL K; QQK
+24DA ; [.10D6.0020.0006.24DA] # CIRCLED LATIN SMALL LETTER K; QQK
+004B ; [.10D6.0020.0008.004B] # LATIN CAPITAL LETTER K
+212A ; [.10D6.0020.0008.212A] # KELVIN SIGN; QQC
+FF2B ; [.10D6.0020.0009.FF2B] # FULLWIDTH LATIN CAPITAL LETTER K; QQK
+1D40A ; [.10D6.0020.000B.1D40A] # MATHEMATICAL BOLD CAPITAL K; QQK
+1D43E ; [.10D6.0020.000B.1D43E] # MATHEMATICAL ITALIC CAPITAL K; QQK
+1D472 ; [.10D6.0020.000B.1D472] # MATHEMATICAL BOLD ITALIC CAPITAL K; QQK
+1D4A6 ; [.10D6.0020.000B.1D4A6] # MATHEMATICAL SCRIPT CAPITAL K; QQK
+1D4DA ; [.10D6.0020.000B.1D4DA] # MATHEMATICAL BOLD SCRIPT CAPITAL K; QQK
+1D50E ; [.10D6.0020.000B.1D50E] # MATHEMATICAL FRAKTUR CAPITAL K; QQK
+1D542 ; [.10D6.0020.000B.1D542] # MATHEMATICAL DOUBLE-STRUCK CAPITAL K; QQK
+1D576 ; [.10D6.0020.000B.1D576] # MATHEMATICAL BOLD FRAKTUR CAPITAL K; QQK
+1D5AA ; [.10D6.0020.000B.1D5AA] # MATHEMATICAL SANS-SERIF CAPITAL K; QQK
+1D5DE ; [.10D6.0020.000B.1D5DE] # MATHEMATICAL SANS-SERIF BOLD CAPITAL K; QQK
+1D612 ; [.10D6.0020.000B.1D612] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL K; QQK
+1D646 ; [.10D6.0020.000B.1D646] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL K; QQK
+1D67A ; [.10D6.0020.000B.1D67A] # MATHEMATICAL MONOSPACE CAPITAL K; QQK
+24C0 ; [.10D6.0020.000C.24C0] # CIRCLED LATIN CAPITAL LETTER K; QQK
+1D4F ; [.10D6.0020.0014.1D4F] # MODIFIER LETTER SMALL K; QQK
+1D37 ; [.10D6.0020.001D.1D37] # MODIFIER LETTER CAPITAL K; QQK
+1E31 ; [.10D6.0020.0002.006B][.0000.0032.0002.0301] # LATIN SMALL LETTER K WITH ACUTE; QQCM
+1E30 ; [.10D6.0020.0008.004B][.0000.0032.0002.0301] # LATIN CAPITAL LETTER K WITH ACUTE; QQCM
+01E9 ; [.10D6.0020.0002.006B][.0000.0041.0002.030C] # LATIN SMALL LETTER K WITH CARON; QQCM
+01E8 ; [.10D6.0020.0008.004B][.0000.0041.0002.030C] # LATIN CAPITAL LETTER K WITH CARON; QQCM
+0137 ; [.10D6.0020.0002.006B][.0000.0056.0002.0327] # LATIN SMALL LETTER K WITH CEDILLA; QQCM
+0136 ; [.10D6.0020.0008.004B][.0000.0056.0002.0327] # LATIN CAPITAL LETTER K WITH CEDILLA; QQCM
+1E33 ; [.10D6.0020.0002.006B][.0000.007A.0002.0323] # LATIN SMALL LETTER K WITH DOT BELOW; QQCM
+1E32 ; [.10D6.0020.0008.004B][.0000.007A.0002.0323] # LATIN CAPITAL LETTER K WITH DOT BELOW; QQCM
+1E35 ; [.10D6.0020.0002.006B][.0000.008A.0002.0331] # LATIN SMALL LETTER K WITH LINE BELOW; QQCM
+1E34 ; [.10D6.0020.0008.004B][.0000.008A.0002.0331] # LATIN CAPITAL LETTER K WITH LINE BELOW; QQCM
+3384 ; [.10D6.0020.001C.3384][.0FD0.0020.001D.3384] # SQUARE KA; QQKN
+3385 ; [.10D6.0020.001D.3385][.0FE6.0020.001D.3385] # SQUARE KB; QQKN
+3389 ; [.10D6.0020.001C.3389][.0FFE.0020.001C.3389][.0FD0.0020.001F.3389][.10E5.0020.001F.3389] # SQUARE KCAL; QQKN
+338F ; [.10D6.0020.001C.338F][.106A.0020.001C.338F] # SQUARE KG; QQKN
+3391 ; [.10D6.0020.001C.3391][.108D.0020.001D.3391][.1243.0020.001F.3391] # SQUARE KHZ; QQKN
+33CD ; [.10D6.0020.001D.33CD][.10D6.0020.001D.33CD] # SQUARE KK; QQKN
+3398 ; [.10D6.0020.001C.3398][.10E5.0020.001C.3398] # SQUARE KL; QQKN
+339E ; [.10D6.0020.001C.339E][.1110.0020.001C.339E] # SQUARE KM; QQKN
+33CE ; [.10D6.0020.001D.33CE][.1110.0020.001D.33CE] # SQUARE KM CAPITAL; QQKN
+33A2 ; [.10D6.0020.001C.33A2][.1110.0020.001C.33A2][.0FC8.0020.001F.33A2] # SQUARE KM SQUARED; QQKN
+33A6 ; [.10D6.0020.001C.33A6][.1110.0020.001C.33A6][.0FC9.0020.001F.33A6] # SQUARE KM CUBED; QQKN
+33AA ; [.10D6.0020.001C.33AA][.115D.0020.001D.33AA][.0FD0.0020.001F.33AA] # SQUARE KPA; QQKN
+33CF ; [.10D6.0020.001C.33CF][.11CF.0020.001C.33CF] # SQUARE KT; QQKN
+33B8 ; [.10D6.0020.001C.33B8][.1216.0020.001D.33B8] # SQUARE KV; QQKN
+33BE ; [.10D6.0020.001C.33BE][.1225.0020.001D.33BE] # SQUARE KW; QQKN
+33C0 ; [.10D6.0020.001C.33C0][.12F3.0020.001D.33C0] # SQUARE K OHM; QQKN
+1D0B ; [.10DA.0020.0002.1D0B] # LATIN LETTER SMALL CAPITAL K
+1D84 ; [.10DB.0020.0002.1D84] # LATIN SMALL LETTER K WITH PALATAL HOOK
+0199 ; [.10DC.0020.0002.0199] # LATIN SMALL LETTER K WITH HOOK
+0198 ; [.10DC.0020.0008.0198] # LATIN CAPITAL LETTER K WITH HOOK
+2C6A ; [.10E0.0020.0002.2C6A] # LATIN SMALL LETTER K WITH DESCENDER
+2C69 ; [.10E0.0020.0008.2C69] # LATIN CAPITAL LETTER K WITH DESCENDER
+029E ; [.10E1.0020.0002.029E] # LATIN SMALL LETTER TURNED K
+006C ; [.10E5.0020.0002.006C] # LATIN SMALL LETTER L
+FF4C ; [.10E5.0020.0003.FF4C] # FULLWIDTH LATIN SMALL LETTER L; QQK
+217C ; [.10E5.0020.0004.217C] # SMALL ROMAN NUMERAL FIFTY; QQK
+24A7 ; [*02B1.0020.0004.24A7][.10E5.0020.0004.24A7][*02B2.0020.001F.24A7] # PARENTHESIZED LATIN SMALL LETTER L; QQKN
+2113 ; [.10E5.0020.0005.2113] # SCRIPT SMALL L; QQK
+1D425 ; [.10E5.0020.0005.1D425] # MATHEMATICAL BOLD SMALL L; QQK
+1D459 ; [.10E5.0020.0005.1D459] # MATHEMATICAL ITALIC SMALL L; QQK
+1D48D ; [.10E5.0020.0005.1D48D] # MATHEMATICAL BOLD ITALIC SMALL L; QQK
+1D4C1 ; [.10E5.0020.0005.1D4C1] # MATHEMATICAL SCRIPT SMALL L; QQK
+1D4F5 ; [.10E5.0020.0005.1D4F5] # MATHEMATICAL BOLD SCRIPT SMALL L; QQK
+1D529 ; [.10E5.0020.0005.1D529] # MATHEMATICAL FRAKTUR SMALL L; QQK
+1D55D ; [.10E5.0020.0005.1D55D] # MATHEMATICAL DOUBLE-STRUCK SMALL L; QQK
+1D591 ; [.10E5.0020.0005.1D591] # MATHEMATICAL BOLD FRAKTUR SMALL L; QQK
+1D5C5 ; [.10E5.0020.0005.1D5C5] # MATHEMATICAL SANS-SERIF SMALL L; QQK
+1D5F9 ; [.10E5.0020.0005.1D5F9] # MATHEMATICAL SANS-SERIF BOLD SMALL L; QQK
+1D62D ; [.10E5.0020.0005.1D62D] # MATHEMATICAL SANS-SERIF ITALIC SMALL L; QQK
+1D661 ; [.10E5.0020.0005.1D661] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL L; QQK
+1D695 ; [.10E5.0020.0005.1D695] # MATHEMATICAL MONOSPACE SMALL L; QQK
+24DB ; [.10E5.0020.0006.24DB] # CIRCLED LATIN SMALL LETTER L; QQK
+004C ; [.10E5.0020.0008.004C] # LATIN CAPITAL LETTER L
+FF2C ; [.10E5.0020.0009.FF2C] # FULLWIDTH LATIN CAPITAL LETTER L; QQK
+216C ; [.10E5.0020.000A.216C] # ROMAN NUMERAL FIFTY; QQK
+2112 ; [.10E5.0020.000B.2112] # SCRIPT CAPITAL L; QQK
+1D40B ; [.10E5.0020.000B.1D40B] # MATHEMATICAL BOLD CAPITAL L; QQK
+1D43F ; [.10E5.0020.000B.1D43F] # MATHEMATICAL ITALIC CAPITAL L; QQK
+1D473 ; [.10E5.0020.000B.1D473] # MATHEMATICAL BOLD ITALIC CAPITAL L; QQK
+1D4DB ; [.10E5.0020.000B.1D4DB] # MATHEMATICAL BOLD SCRIPT CAPITAL L; QQK
+1D50F ; [.10E5.0020.000B.1D50F] # MATHEMATICAL FRAKTUR CAPITAL L; QQK
+1D543 ; [.10E5.0020.000B.1D543] # MATHEMATICAL DOUBLE-STRUCK CAPITAL L; QQK
+1D577 ; [.10E5.0020.000B.1D577] # MATHEMATICAL BOLD FRAKTUR CAPITAL L; QQK
+1D5AB ; [.10E5.0020.000B.1D5AB] # MATHEMATICAL SANS-SERIF CAPITAL L; QQK
+1D5DF ; [.10E5.0020.000B.1D5DF] # MATHEMATICAL SANS-SERIF BOLD CAPITAL L; QQK
+1D613 ; [.10E5.0020.000B.1D613] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL L; QQK
+1D647 ; [.10E5.0020.000B.1D647] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL L; QQK
+1D67B ; [.10E5.0020.000B.1D67B] # MATHEMATICAL MONOSPACE CAPITAL L; QQK
+24C1 ; [.10E5.0020.000C.24C1] # CIRCLED LATIN CAPITAL LETTER L; QQK
+02E1 ; [.10E5.0020.0014.02E1] # MODIFIER LETTER SMALL L; QQK
+1D38 ; [.10E5.0020.001D.1D38] # MODIFIER LETTER CAPITAL L; QQK
+013A ; [.10E5.0020.0002.006C][.0000.0032.0002.0301] # LATIN SMALL LETTER L WITH ACUTE; QQCM
+0139 ; [.10E5.0020.0008.004C][.0000.0032.0002.0301] # LATIN CAPITAL LETTER L WITH ACUTE; QQCM
+013E ; [.10E5.0020.0002.006C][.0000.0041.0002.030C] # LATIN SMALL LETTER L WITH CARON; QQCM
+013D ; [.10E5.0020.0008.004C][.0000.0041.0002.030C] # LATIN CAPITAL LETTER L WITH CARON; QQCM
+013C ; [.10E5.0020.0002.006C][.0000.0056.0002.0327] # LATIN SMALL LETTER L WITH CEDILLA; QQCM
+013B ; [.10E5.0020.0008.004C][.0000.0056.0002.0327] # LATIN CAPITAL LETTER L WITH CEDILLA; QQCM
+1E37 ; [.10E5.0020.0002.006C][.0000.007A.0002.0323] # LATIN SMALL LETTER L WITH DOT BELOW; QQCM
+1E36 ; [.10E5.0020.0008.004C][.0000.007A.0002.0323] # LATIN CAPITAL LETTER L WITH DOT BELOW; QQCM
+1E39 ; [.10E5.0020.0002.006C][.0000.007A.0002.0323][.0000.005B.0002.0304] # LATIN SMALL LETTER L WITH DOT BELOW AND MACRON; QQCM
+1E38 ; [.10E5.0020.0008.004C][.0000.007A.0002.0323][.0000.005B.0002.0304] # LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON; QQCM
+1E3D ; [.10E5.0020.0002.006C][.0000.0086.0002.032D] # LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW; QQCM
+1E3C ; [.10E5.0020.0008.004C][.0000.0086.0002.032D] # LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW; QQCM
+1E3B ; [.10E5.0020.0002.006C][.0000.008A.0002.0331] # LATIN SMALL LETTER L WITH LINE BELOW; QQCM
+1E3A ; [.10E5.0020.0008.004C][.0000.008A.0002.0331] # LATIN CAPITAL LETTER L WITH LINE BELOW; QQCM
+0142 ; [.10E5.0020.0002.006C][.0000.008D.0002.0335] # LATIN SMALL LETTER L WITH STROKE; QQCM
+0141 ; [.10E5.0020.0008.004C][.0000.008D.0002.0335] # LATIN CAPITAL LETTER L WITH STROKE; QQCM
+0140 ; [.10E5.0020.0004.0140][.0000.0199.0004.0140][*0273.0020.001F.0140] # LATIN SMALL LETTER L WITH MIDDLE DOT; QQKN
+013F ; [.10E5.0020.000A.013F][.0000.0199.0004.013F][*0273.0020.001F.013F] # LATIN CAPITAL LETTER L WITH MIDDLE DOT; QQKN
+01C9 ; [.10E5.0020.0004.01C9][.10BD.0020.0004.01C9] # LATIN SMALL LETTER LJ; QQKN
+01C8 ; [.10E5.0020.000A.01C8][.10BD.0020.0004.01C8] # LATIN CAPITAL LETTER L WITH SMALL LETTER J; QQKN
+01C7 ; [.10E5.0020.000A.01C7][.10BD.0020.000A.01C7] # LATIN CAPITAL LETTER LJ; QQKN
+33D0 ; [.10E5.0020.001C.33D0][.1110.0020.001C.33D0] # SQUARE LM; QQKN
+33D1 ; [.10E5.0020.001C.33D1][.111B.0020.001C.33D1] # SQUARE LN; QQKN
+33D2 ; [.10E5.0020.001C.33D2][.113B.0020.001C.33D2][.106A.0020.001F.33D2] # SQUARE LOG; QQKN
+02AA ; [.10E5.0020.0004.02AA][.11AF.0020.0004.02AA] # LATIN SMALL LETTER LS DIGRAPH; QQKN
+32CF ; [.10E5.0020.001D.32CF][.11CF.0020.001D.32CF][.1010.0020.001F.32CF] # LIMITED LIABILITY SIGN; QQKN
+33D3 ; [.10E5.0020.001C.33D3][.122E.0020.001C.33D3] # SQUARE LX; QQKN
+02AB ; [.10E5.0020.0004.02AB][.1243.0020.0004.02AB] # LATIN SMALL LETTER LZ DIGRAPH; QQKN
+029F ; [.10E9.0020.0002.029F] # LATIN LETTER SMALL CAPITAL L
+1DAB ; [.10E9.0020.0014.1DAB] # MODIFIER LETTER SMALL CAPITAL L; QQK
+1D0C ; [.10ED.0020.0002.1D0C] # LATIN LETTER SMALL CAPITAL L WITH STROKE
+019A ; [.10EE.0020.0002.019A] # LATIN SMALL LETTER L WITH BAR
+023D ; [.10EE.0020.0008.023D] # LATIN CAPITAL LETTER L WITH BAR
+2C61 ; [.10F2.0020.0002.2C61] # LATIN SMALL LETTER L WITH DOUBLE BAR
+2C60 ; [.10F2.0020.0008.2C60] # LATIN CAPITAL LETTER L WITH DOUBLE BAR
+026B ; [.10F3.0020.0002.026B] # LATIN SMALL LETTER L WITH MIDDLE TILDE
+2C62 ; [.10F3.0020.0008.2C62] # LATIN CAPITAL LETTER L WITH MIDDLE TILDE
+026C ; [.10F7.0020.0002.026C] # LATIN SMALL LETTER L WITH BELT
+1D85 ; [.10FB.0020.0002.1D85] # LATIN SMALL LETTER L WITH PALATAL HOOK
+1DAA ; [.10FB.0020.0014.1DAA] # MODIFIER LETTER SMALL L WITH PALATAL HOOK; QQK
+026D ; [.10FC.0020.0002.026D] # LATIN SMALL LETTER L WITH RETROFLEX HOOK
+1DA9 ; [.10FC.0020.0014.1DA9] # MODIFIER LETTER SMALL L WITH RETROFLEX HOOK; QQK
+0234 ; [.1100.0020.0002.0234] # LATIN SMALL LETTER L WITH CURL
+026E ; [.1104.0020.0002.026E] # LATIN SMALL LETTER LEZH
+019B ; [.1108.0020.0002.019B] # LATIN SMALL LETTER LAMBDA WITH STROKE
+028E ; [.110C.0020.0002.028E] # LATIN SMALL LETTER TURNED Y
+006D ; [.1110.0020.0002.006D] # LATIN SMALL LETTER M
+FF4D ; [.1110.0020.0003.FF4D] # FULLWIDTH LATIN SMALL LETTER M; QQK
+036B ; [.1110.0020.0004.036B] # COMBINING LATIN SMALL LETTER M; QQK
+217F ; [.1110.0020.0004.217F] # SMALL ROMAN NUMERAL ONE THOUSAND; QQK
+24A8 ; [*02B1.0020.0004.24A8][.1110.0020.0004.24A8][*02B2.0020.001F.24A8] # PARENTHESIZED LATIN SMALL LETTER M; QQKN
+1D426 ; [.1110.0020.0005.1D426] # MATHEMATICAL BOLD SMALL M; QQK
+1D45A ; [.1110.0020.0005.1D45A] # MATHEMATICAL ITALIC SMALL M; QQK
+1D48E ; [.1110.0020.0005.1D48E] # MATHEMATICAL BOLD ITALIC SMALL M; QQK
+1D4C2 ; [.1110.0020.0005.1D4C2] # MATHEMATICAL SCRIPT SMALL M; QQK
+1D4F6 ; [.1110.0020.0005.1D4F6] # MATHEMATICAL BOLD SCRIPT SMALL M; QQK
+1D52A ; [.1110.0020.0005.1D52A] # MATHEMATICAL FRAKTUR SMALL M; QQK
+1D55E ; [.1110.0020.0005.1D55E] # MATHEMATICAL DOUBLE-STRUCK SMALL M; QQK
+1D592 ; [.1110.0020.0005.1D592] # MATHEMATICAL BOLD FRAKTUR SMALL M; QQK
+1D5C6 ; [.1110.0020.0005.1D5C6] # MATHEMATICAL SANS-SERIF SMALL M; QQK
+1D5FA ; [.1110.0020.0005.1D5FA] # MATHEMATICAL SANS-SERIF BOLD SMALL M; QQK
+1D62E ; [.1110.0020.0005.1D62E] # MATHEMATICAL SANS-SERIF ITALIC SMALL M; QQK
+1D662 ; [.1110.0020.0005.1D662] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL M; QQK
+1D696 ; [.1110.0020.0005.1D696] # MATHEMATICAL MONOSPACE SMALL M; QQK
+24DC ; [.1110.0020.0006.24DC] # CIRCLED LATIN SMALL LETTER M; QQK
+004D ; [.1110.0020.0008.004D] # LATIN CAPITAL LETTER M
+FF2D ; [.1110.0020.0009.FF2D] # FULLWIDTH LATIN CAPITAL LETTER M; QQK
+216F ; [.1110.0020.000A.216F] # ROMAN NUMERAL ONE THOUSAND; QQK
+2133 ; [.1110.0020.000B.2133] # SCRIPT CAPITAL M; QQK
+1D40C ; [.1110.0020.000B.1D40C] # MATHEMATICAL BOLD CAPITAL M; QQK
+1D440 ; [.1110.0020.000B.1D440] # MATHEMATICAL ITALIC CAPITAL M; QQK
+1D474 ; [.1110.0020.000B.1D474] # MATHEMATICAL BOLD ITALIC CAPITAL M; QQK
+1D4DC ; [.1110.0020.000B.1D4DC] # MATHEMATICAL BOLD SCRIPT CAPITAL M; QQK
+1D510 ; [.1110.0020.000B.1D510] # MATHEMATICAL FRAKTUR CAPITAL M; QQK
+1D544 ; [.1110.0020.000B.1D544] # MATHEMATICAL DOUBLE-STRUCK CAPITAL M; QQK
+1D578 ; [.1110.0020.000B.1D578] # MATHEMATICAL BOLD FRAKTUR CAPITAL M; QQK
+1D5AC ; [.1110.0020.000B.1D5AC] # MATHEMATICAL SANS-SERIF CAPITAL M; QQK
+1D5E0 ; [.1110.0020.000B.1D5E0] # MATHEMATICAL SANS-SERIF BOLD CAPITAL M; QQK
+1D614 ; [.1110.0020.000B.1D614] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL M; QQK
+1D648 ; [.1110.0020.000B.1D648] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL M; QQK
+1D67C ; [.1110.0020.000B.1D67C] # MATHEMATICAL MONOSPACE CAPITAL M; QQK
+24C2 ; [.1110.0020.000C.24C2] # CIRCLED LATIN CAPITAL LETTER M; QQK
+1D50 ; [.1110.0020.0014.1D50] # MODIFIER LETTER SMALL M; QQK
+1D39 ; [.1110.0020.001D.1D39] # MODIFIER LETTER CAPITAL M; QQK
+1E3F ; [.1110.0020.0002.006D][.0000.0032.0002.0301] # LATIN SMALL LETTER M WITH ACUTE; QQCM
+1E3E ; [.1110.0020.0008.004D][.0000.0032.0002.0301] # LATIN CAPITAL LETTER M WITH ACUTE; QQCM
+1E41 ; [.1110.0020.0002.006D][.0000.0052.0002.0307] # LATIN SMALL LETTER M WITH DOT ABOVE; QQCM
+1E40 ; [.1110.0020.0008.004D][.0000.0052.0002.0307] # LATIN CAPITAL LETTER M WITH DOT ABOVE; QQCM
+1E43 ; [.1110.0020.0002.006D][.0000.007A.0002.0323] # LATIN SMALL LETTER M WITH DOT BELOW; QQCM
+1E42 ; [.1110.0020.0008.004D][.0000.007A.0002.0323] # LATIN CAPITAL LETTER M WITH DOT BELOW; QQCM
+33A1 ; [.1110.0020.001C.33A1][.0FC8.0020.001C.33A1] # SQUARE M SQUARED; QQKN
+33A5 ; [.1110.0020.001C.33A5][.0FC9.0020.001C.33A5] # SQUARE M CUBED; QQKN
+3383 ; [.1110.0020.001C.3383][.0FD0.0020.001D.3383] # SQUARE MA; QQKN
+33D4 ; [.1110.0020.001C.33D4][.0FE6.0020.001C.33D4] # SQUARE MB SMALL; QQKN
+3386 ; [.1110.0020.001D.3386][.0FE6.0020.001D.3386] # SQUARE MB; QQKN
+338E ; [.1110.0020.001C.338E][.106A.0020.001C.338E] # SQUARE MG; QQKN
+3392 ; [.1110.0020.001D.3392][.108D.0020.001D.3392][.1243.0020.001F.3392] # SQUARE MHZ; QQKN
+33D5 ; [.1110.0020.001C.33D5][.10A5.0020.001C.33D5][.10E5.0020.001F.33D5] # SQUARE MIL; QQKN
+3396 ; [.1110.0020.001C.3396][.10E5.0020.001C.3396] # SQUARE ML; QQKN
+339C ; [.1110.0020.001C.339C][.1110.0020.001C.339C] # SQUARE MM; QQKN
+339F ; [.1110.0020.001C.339F][.1110.0020.001C.339F][.0FC8.0020.001F.339F] # SQUARE MM SQUARED; QQKN
+33A3 ; [.1110.0020.001C.33A3][.1110.0020.001C.33A3][.0FC9.0020.001F.33A3] # SQUARE MM CUBED; QQKN
+33D6 ; [.1110.0020.001C.33D6][.113B.0020.001C.33D6][.10E5.0020.001F.33D6] # SQUARE MOL; QQKN
+33AB ; [.1110.0020.001D.33AB][.115D.0020.001D.33AB][.0FD0.0020.001F.33AB] # SQUARE MPA; QQKN
+33B3 ; [.1110.0020.001C.33B3][.11AF.0020.001C.33B3] # SQUARE MS; QQKN
+33A7 ; [.1110.0020.001C.33A7][*04C7.0020.001C.33A7][.11AF.0020.001F.33A7] # SQUARE M OVER S; QQKN
+33A8 ; [.1110.0020.001C.33A8][*04C7.0020.001C.33A8][.11AF.0020.001F.33A8][.0FC8.0020.001F.33A8] # SQUARE M OVER S SQUARED; QQKN
+33B7 ; [.1110.0020.001C.33B7][.1216.0020.001D.33B7] # SQUARE MV; QQKN
+33B9 ; [.1110.0020.001D.33B9][.1216.0020.001D.33B9] # SQUARE MV MEGA; QQKN
+33BD ; [.1110.0020.001C.33BD][.1225.0020.001D.33BD] # SQUARE MW; QQKN
+33BF ; [.1110.0020.001D.33BF][.1225.0020.001D.33BF] # SQUARE MW MEGA; QQKN
+33C1 ; [.1110.0020.001D.33C1][.12F3.0020.001D.33C1] # SQUARE M OHM; QQKN
+1D0D ; [.1114.0020.0002.1D0D] # LATIN LETTER SMALL CAPITAL M
+1D6F ; [.1115.0020.0002.1D6F] # LATIN SMALL LETTER M WITH MIDDLE TILDE
+1D86 ; [.1116.0020.0002.1D86] # LATIN SMALL LETTER M WITH PALATAL HOOK
+0271 ; [.1117.0020.0002.0271] # LATIN SMALL LETTER M WITH HOOK
+1DAC ; [.1117.0020.0014.1DAC] # MODIFIER LETTER SMALL M WITH HOOK; QQK
+006E ; [.111B.0020.0002.006E] # LATIN SMALL LETTER N
+FF4E ; [.111B.0020.0003.FF4E] # FULLWIDTH LATIN SMALL LETTER N; QQK
+24A9 ; [*02B1.0020.0004.24A9][.111B.0020.0004.24A9][*02B2.0020.001F.24A9] # PARENTHESIZED LATIN SMALL LETTER N; QQKN
+1D427 ; [.111B.0020.0005.1D427] # MATHEMATICAL BOLD SMALL N; QQK
+1D45B ; [.111B.0020.0005.1D45B] # MATHEMATICAL ITALIC SMALL N; QQK
+1D48F ; [.111B.0020.0005.1D48F] # MATHEMATICAL BOLD ITALIC SMALL N; QQK
+1D4C3 ; [.111B.0020.0005.1D4C3] # MATHEMATICAL SCRIPT SMALL N; QQK
+1D4F7 ; [.111B.0020.0005.1D4F7] # MATHEMATICAL BOLD SCRIPT SMALL N; QQK
+1D52B ; [.111B.0020.0005.1D52B] # MATHEMATICAL FRAKTUR SMALL N; QQK
+1D55F ; [.111B.0020.0005.1D55F] # MATHEMATICAL DOUBLE-STRUCK SMALL N; QQK
+1D593 ; [.111B.0020.0005.1D593] # MATHEMATICAL BOLD FRAKTUR SMALL N; QQK
+1D5C7 ; [.111B.0020.0005.1D5C7] # MATHEMATICAL SANS-SERIF SMALL N; QQK
+1D5FB ; [.111B.0020.0005.1D5FB] # MATHEMATICAL SANS-SERIF BOLD SMALL N; QQK
+1D62F ; [.111B.0020.0005.1D62F] # MATHEMATICAL SANS-SERIF ITALIC SMALL N; QQK
+1D663 ; [.111B.0020.0005.1D663] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL N; QQK
+1D697 ; [.111B.0020.0005.1D697] # MATHEMATICAL MONOSPACE SMALL N; QQK
+24DD ; [.111B.0020.0006.24DD] # CIRCLED LATIN SMALL LETTER N; QQK
+004E ; [.111B.0020.0008.004E] # LATIN CAPITAL LETTER N
+FF2E ; [.111B.0020.0009.FF2E] # FULLWIDTH LATIN CAPITAL LETTER N; QQK
+2115 ; [.111B.0020.000B.2115] # DOUBLE-STRUCK CAPITAL N; QQK
+1D40D ; [.111B.0020.000B.1D40D] # MATHEMATICAL BOLD CAPITAL N; QQK
+1D441 ; [.111B.0020.000B.1D441] # MATHEMATICAL ITALIC CAPITAL N; QQK
+1D475 ; [.111B.0020.000B.1D475] # MATHEMATICAL BOLD ITALIC CAPITAL N; QQK
+1D4A9 ; [.111B.0020.000B.1D4A9] # MATHEMATICAL SCRIPT CAPITAL N; QQK
+1D4DD ; [.111B.0020.000B.1D4DD] # MATHEMATICAL BOLD SCRIPT CAPITAL N; QQK
+1D511 ; [.111B.0020.000B.1D511] # MATHEMATICAL FRAKTUR CAPITAL N; QQK
+1D579 ; [.111B.0020.000B.1D579] # MATHEMATICAL BOLD FRAKTUR CAPITAL N; QQK
+1D5AD ; [.111B.0020.000B.1D5AD] # MATHEMATICAL SANS-SERIF CAPITAL N; QQK
+1D5E1 ; [.111B.0020.000B.1D5E1] # MATHEMATICAL SANS-SERIF BOLD CAPITAL N; QQK
+1D615 ; [.111B.0020.000B.1D615] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL N; QQK
+1D649 ; [.111B.0020.000B.1D649] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL N; QQK
+1D67D ; [.111B.0020.000B.1D67D] # MATHEMATICAL MONOSPACE CAPITAL N; QQK
+24C3 ; [.111B.0020.000C.24C3] # CIRCLED LATIN CAPITAL LETTER N; QQK
+207F ; [.111B.0020.0014.207F] # SUPERSCRIPT LATIN SMALL LETTER N; QQK
+1D3A ; [.111B.0020.001D.1D3A] # MODIFIER LETTER CAPITAL N; QQK
+0144 ; [.111B.0020.0002.006E][.0000.0032.0002.0301] # LATIN SMALL LETTER N WITH ACUTE; QQCM
+0143 ; [.111B.0020.0008.004E][.0000.0032.0002.0301] # LATIN CAPITAL LETTER N WITH ACUTE; QQCM
+01F9 ; [.111B.0020.0002.006E][.0000.0035.0002.0300] # LATIN SMALL LETTER N WITH GRAVE; QQCM
+01F8 ; [.111B.0020.0008.004E][.0000.0035.0002.0300] # LATIN CAPITAL LETTER N WITH GRAVE; QQCM
+0148 ; [.111B.0020.0002.006E][.0000.0041.0002.030C] # LATIN SMALL LETTER N WITH CARON; QQCM
+0147 ; [.111B.0020.0008.004E][.0000.0041.0002.030C] # LATIN CAPITAL LETTER N WITH CARON; QQCM
+00F1 ; [.111B.0020.0002.006E][.0000.004E.0002.0303] # LATIN SMALL LETTER N WITH TILDE; QQCM
+00D1 ; [.111B.0020.0008.004E][.0000.004E.0002.0303] # LATIN CAPITAL LETTER N WITH TILDE; QQCM
+1E45 ; [.111B.0020.0002.006E][.0000.0052.0002.0307] # LATIN SMALL LETTER N WITH DOT ABOVE; QQCM
+1E44 ; [.111B.0020.0008.004E][.0000.0052.0002.0307] # LATIN CAPITAL LETTER N WITH DOT ABOVE; QQCM
+0146 ; [.111B.0020.0002.006E][.0000.0056.0002.0327] # LATIN SMALL LETTER N WITH CEDILLA; QQCM
+0145 ; [.111B.0020.0008.004E][.0000.0056.0002.0327] # LATIN CAPITAL LETTER N WITH CEDILLA; QQCM
+1E47 ; [.111B.0020.0002.006E][.0000.007A.0002.0323] # LATIN SMALL LETTER N WITH DOT BELOW; QQCM
+1E46 ; [.111B.0020.0008.004E][.0000.007A.0002.0323] # LATIN CAPITAL LETTER N WITH DOT BELOW; QQCM
+1E4B ; [.111B.0020.0002.006E][.0000.0086.0002.032D] # LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW; QQCM
+1E4A ; [.111B.0020.0008.004E][.0000.0086.0002.032D] # LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW; QQCM
+1E49 ; [.111B.0020.0002.006E][.0000.008A.0002.0331] # LATIN SMALL LETTER N WITH LINE BELOW; QQCM
+1E48 ; [.111B.0020.0008.004E][.0000.008A.0002.0331] # LATIN CAPITAL LETTER N WITH LINE BELOW; QQCM
+3381 ; [.111B.0020.001C.3381][.0FD0.0020.001D.3381] # SQUARE NA; QQKN
+338B ; [.111B.0020.001C.338B][.105F.0020.001D.338B] # SQUARE NF; QQKN
+01CC ; [.111B.0020.0004.01CC][.10BD.0020.0004.01CC] # LATIN SMALL LETTER NJ; QQKN
+01CB ; [.111B.0020.000A.01CB][.10BD.0020.0004.01CB] # LATIN CAPITAL LETTER N WITH SMALL LETTER J; QQKN
+01CA ; [.111B.0020.000A.01CA][.10BD.0020.000A.01CA] # LATIN CAPITAL LETTER NJ; QQKN
+339A ; [.111B.0020.001C.339A][.1110.0020.001C.339A] # SQUARE NM; QQKN
+2116 ; [.111B.0020.000A.2116][.113B.0020.0004.2116] # NUMERO SIGN; QQKN
+33B1 ; [.111B.0020.001C.33B1][.11AF.0020.001C.33B1] # SQUARE NS; QQKN
+33B5 ; [.111B.0020.001C.33B5][.1216.0020.001D.33B5] # SQUARE NV; QQKN
+33BB ; [.111B.0020.001C.33BB][.1225.0020.001D.33BB] # SQUARE NW; QQKN
+0274 ; [.111F.0020.0002.0274] # LATIN LETTER SMALL CAPITAL N
+1DB0 ; [.111F.0020.0014.1DB0] # MODIFIER LETTER SMALL CAPITAL N; QQK
+1D3B ; [.1123.0020.0002.1D3B] # MODIFIER LETTER CAPITAL REVERSED N
+1D0E ; [.1124.0020.0002.1D0E] # LATIN LETTER SMALL CAPITAL REVERSED N
+1D70 ; [.1125.0020.0002.1D70] # LATIN SMALL LETTER N WITH MIDDLE TILDE
+0272 ; [.1126.0020.0002.0272] # LATIN SMALL LETTER N WITH LEFT HOOK
+019D ; [.1126.0020.0008.019D] # LATIN CAPITAL LETTER N WITH LEFT HOOK
+1DAE ; [.1126.0020.0014.1DAE] # MODIFIER LETTER SMALL N WITH LEFT HOOK; QQK
+019E ; [.112A.0020.0002.019E] # LATIN SMALL LETTER N WITH LONG RIGHT LEG
+0220 ; [.112A.0020.0008.0220] # LATIN CAPITAL LETTER N WITH LONG RIGHT LEG
+1D87 ; [.112E.0020.0002.1D87] # LATIN SMALL LETTER N WITH PALATAL HOOK
+0273 ; [.112F.0020.0002.0273] # LATIN SMALL LETTER N WITH RETROFLEX HOOK
+1DAF ; [.112F.0020.0014.1DAF] # MODIFIER LETTER SMALL N WITH RETROFLEX HOOK; QQK
+0235 ; [.1133.0020.0002.0235] # LATIN SMALL LETTER N WITH CURL
+014B ; [.1137.0020.0002.014B] # LATIN SMALL LETTER ENG
+014A ; [.1137.0020.0008.014A] # LATIN CAPITAL LETTER ENG
+1D51 ; [.1137.0020.0014.1D51] # MODIFIER LETTER SMALL ENG; QQK
+006F ; [.113B.0020.0002.006F] # LATIN SMALL LETTER O
+FF4F ; [.113B.0020.0003.FF4F] # FULLWIDTH LATIN SMALL LETTER O; QQK
+0366 ; [.113B.0020.0004.0366] # COMBINING LATIN SMALL LETTER O; QQK
+24AA ; [*02B1.0020.0004.24AA][.113B.0020.0004.24AA][*02B2.0020.001F.24AA] # PARENTHESIZED LATIN SMALL LETTER O; QQKN
+2134 ; [.113B.0020.0005.2134] # SCRIPT SMALL O; QQK
+1D428 ; [.113B.0020.0005.1D428] # MATHEMATICAL BOLD SMALL O; QQK
+1D45C ; [.113B.0020.0005.1D45C] # MATHEMATICAL ITALIC SMALL O; QQK
+1D490 ; [.113B.0020.0005.1D490] # MATHEMATICAL BOLD ITALIC SMALL O; QQK
+1D4F8 ; [.113B.0020.0005.1D4F8] # MATHEMATICAL BOLD SCRIPT SMALL O; QQK
+1D52C ; [.113B.0020.0005.1D52C] # MATHEMATICAL FRAKTUR SMALL O; QQK
+1D560 ; [.113B.0020.0005.1D560] # MATHEMATICAL DOUBLE-STRUCK SMALL O; QQK
+1D594 ; [.113B.0020.0005.1D594] # MATHEMATICAL BOLD FRAKTUR SMALL O; QQK
+1D5C8 ; [.113B.0020.0005.1D5C8] # MATHEMATICAL SANS-SERIF SMALL O; QQK
+1D5FC ; [.113B.0020.0005.1D5FC] # MATHEMATICAL SANS-SERIF BOLD SMALL O; QQK
+1D630 ; [.113B.0020.0005.1D630] # MATHEMATICAL SANS-SERIF ITALIC SMALL O; QQK
+1D664 ; [.113B.0020.0005.1D664] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL O; QQK
+1D698 ; [.113B.0020.0005.1D698] # MATHEMATICAL MONOSPACE SMALL O; QQK
+24DE ; [.113B.0020.0006.24DE] # CIRCLED LATIN SMALL LETTER O; QQK
+004F ; [.113B.0020.0008.004F] # LATIN CAPITAL LETTER O
+FF2F ; [.113B.0020.0009.FF2F] # FULLWIDTH LATIN CAPITAL LETTER O; QQK
+1D40E ; [.113B.0020.000B.1D40E] # MATHEMATICAL BOLD CAPITAL O; QQK
+1D442 ; [.113B.0020.000B.1D442] # MATHEMATICAL ITALIC CAPITAL O; QQK
+1D476 ; [.113B.0020.000B.1D476] # MATHEMATICAL BOLD ITALIC CAPITAL O; QQK
+1D4AA ; [.113B.0020.000B.1D4AA] # MATHEMATICAL SCRIPT CAPITAL O; QQK
+1D4DE ; [.113B.0020.000B.1D4DE] # MATHEMATICAL BOLD SCRIPT CAPITAL O; QQK
+1D512 ; [.113B.0020.000B.1D512] # MATHEMATICAL FRAKTUR CAPITAL O; QQK
+1D546 ; [.113B.0020.000B.1D546] # MATHEMATICAL DOUBLE-STRUCK CAPITAL O; QQK
+1D57A ; [.113B.0020.000B.1D57A] # MATHEMATICAL BOLD FRAKTUR CAPITAL O; QQK
+1D5AE ; [.113B.0020.000B.1D5AE] # MATHEMATICAL SANS-SERIF CAPITAL O; QQK
+1D5E2 ; [.113B.0020.000B.1D5E2] # MATHEMATICAL SANS-SERIF BOLD CAPITAL O; QQK
+1D616 ; [.113B.0020.000B.1D616] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL O; QQK
+1D64A ; [.113B.0020.000B.1D64A] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL O; QQK
+1D67E ; [.113B.0020.000B.1D67E] # MATHEMATICAL MONOSPACE CAPITAL O; QQK
+24C4 ; [.113B.0020.000C.24C4] # CIRCLED LATIN CAPITAL LETTER O; QQK
+00BA ; [.113B.0020.0014.00BA] # MASCULINE ORDINAL INDICATOR; QQK
+1D52 ; [.113B.0020.0014.1D52] # MODIFIER LETTER SMALL O; QQK
+2092 ; [.113B.0020.0015.2092] # LATIN SUBSCRIPT SMALL LETTER O; QQK
+1D3C ; [.113B.0020.001D.1D3C] # MODIFIER LETTER CAPITAL O; QQK
+00F3 ; [.113B.0020.0002.006F][.0000.0032.0002.0301] # LATIN SMALL LETTER O WITH ACUTE; QQCM
+00D3 ; [.113B.0020.0008.004F][.0000.0032.0002.0301] # LATIN CAPITAL LETTER O WITH ACUTE; QQCM
+00F2 ; [.113B.0020.0002.006F][.0000.0035.0002.0300] # LATIN SMALL LETTER O WITH GRAVE; QQCM
+00D2 ; [.113B.0020.0008.004F][.0000.0035.0002.0300] # LATIN CAPITAL LETTER O WITH GRAVE; QQCM
+014F ; [.113B.0020.0002.006F][.0000.0037.0002.0306] # LATIN SMALL LETTER O WITH BREVE; QQCM
+014E ; [.113B.0020.0008.004F][.0000.0037.0002.0306] # LATIN CAPITAL LETTER O WITH BREVE; QQCM
+00F4 ; [.113B.0020.0002.006F][.0000.003C.0002.0302] # LATIN SMALL LETTER O WITH CIRCUMFLEX; QQCM
+00D4 ; [.113B.0020.0008.004F][.0000.003C.0002.0302] # LATIN CAPITAL LETTER O WITH CIRCUMFLEX; QQCM
+1ED1 ; [.113B.0020.0002.006F][.0000.003C.0002.0302][.0000.0032.0002.0301] # LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE; QQCM
+1ED0 ; [.113B.0020.0008.004F][.0000.003C.0002.0302][.0000.0032.0002.0301] # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE; QQCM
+1ED3 ; [.113B.0020.0002.006F][.0000.003C.0002.0302][.0000.0035.0002.0300] # LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE; QQCM
+1ED2 ; [.113B.0020.0008.004F][.0000.003C.0002.0302][.0000.0035.0002.0300] # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE; QQCM
+1ED7 ; [.113B.0020.0002.006F][.0000.003C.0002.0302][.0000.004E.0002.0303] # LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE; QQCM
+1ED6 ; [.113B.0020.0008.004F][.0000.003C.0002.0302][.0000.004E.0002.0303] # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE; QQCM
+1ED5 ; [.113B.0020.0002.006F][.0000.003C.0002.0302][.0000.0060.0002.0309] # LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE; QQCM
+1ED4 ; [.113B.0020.0008.004F][.0000.003C.0002.0302][.0000.0060.0002.0309] # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE; QQCM
+01D2 ; [.113B.0020.0002.006F][.0000.0041.0002.030C] # LATIN SMALL LETTER O WITH CARON; QQCM
+01D1 ; [.113B.0020.0008.004F][.0000.0041.0002.030C] # LATIN CAPITAL LETTER O WITH CARON; QQCM
+00F6 ; [.113B.0020.0002.006F][.0000.0047.0002.0308] # LATIN SMALL LETTER O WITH DIAERESIS; QQCM
+00D6 ; [.113B.0020.0008.004F][.0000.0047.0002.0308] # LATIN CAPITAL LETTER O WITH DIAERESIS; QQCM
+022B ; [.113B.0020.0002.006F][.0000.0047.0002.0308][.0000.005B.0002.0304] # LATIN SMALL LETTER O WITH DIAERESIS AND MACRON; QQCM
+022A ; [.113B.0020.0008.004F][.0000.0047.0002.0308][.0000.005B.0002.0304] # LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON; QQCM
+0151 ; [.113B.0020.0002.006F][.0000.004D.0002.030B] # LATIN SMALL LETTER O WITH DOUBLE ACUTE; QQCM
+0150 ; [.113B.0020.0008.004F][.0000.004D.0002.030B] # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE; QQCM
+00F5 ; [.113B.0020.0002.006F][.0000.004E.0002.0303] # LATIN SMALL LETTER O WITH TILDE; QQCM
+00D5 ; [.113B.0020.0008.004F][.0000.004E.0002.0303] # LATIN CAPITAL LETTER O WITH TILDE; QQCM
+1E4D ; [.113B.0020.0002.006F][.0000.004E.0002.0303][.0000.0032.0002.0301] # LATIN SMALL LETTER O WITH TILDE AND ACUTE; QQCM
+1E4C ; [.113B.0020.0008.004F][.0000.004E.0002.0303][.0000.0032.0002.0301] # LATIN CAPITAL LETTER O WITH TILDE AND ACUTE; QQCM
+1E4F ; [.113B.0020.0002.006F][.0000.004E.0002.0303][.0000.0047.0002.0308] # LATIN SMALL LETTER O WITH TILDE AND DIAERESIS; QQCM
+1E4E ; [.113B.0020.0008.004F][.0000.004E.0002.0303][.0000.0047.0002.0308] # LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS; QQCM
+022D ; [.113B.0020.0002.006F][.0000.004E.0002.0303][.0000.005B.0002.0304] # LATIN SMALL LETTER O WITH TILDE AND MACRON; QQCM
+022C ; [.113B.0020.0008.004F][.0000.004E.0002.0303][.0000.005B.0002.0304] # LATIN CAPITAL LETTER O WITH TILDE AND MACRON; QQCM
+022F ; [.113B.0020.0002.006F][.0000.0052.0002.0307] # LATIN SMALL LETTER O WITH DOT ABOVE; QQCM
+022E ; [.113B.0020.0008.004F][.0000.0052.0002.0307] # LATIN CAPITAL LETTER O WITH DOT ABOVE; QQCM
+0231 ; [.113B.0020.0002.006F][.0000.0052.0002.0307][.0000.005B.0002.0304] # LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON; QQCM
+0230 ; [.113B.0020.0008.004F][.0000.0052.0002.0307][.0000.005B.0002.0304] # LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON; QQCM
+00F8 ; [.113B.0020.0002.006F][.0000.0054.0002.0338] # LATIN SMALL LETTER O WITH STROKE; QQCM
+00D8 ; [.113B.0020.0008.004F][.0000.0054.0002.0338] # LATIN CAPITAL LETTER O WITH STROKE; QQCM
+01FF ; [.113B.0020.0002.006F][.0000.0054.0002.0338][.0000.0032.0002.0301] # LATIN SMALL LETTER O WITH STROKE AND ACUTE; QQCM
+01FE ; [.113B.0020.0008.004F][.0000.0054.0002.0338][.0000.0032.0002.0301] # LATIN CAPITAL LETTER O WITH STROKE AND ACUTE; QQCM
+01EB ; [.113B.0020.0002.006F][.0000.0059.0002.0328] # LATIN SMALL LETTER O WITH OGONEK; QQCM
+01EA ; [.113B.0020.0008.004F][.0000.0059.0002.0328] # LATIN CAPITAL LETTER O WITH OGONEK; QQCM
+01ED ; [.113B.0020.0002.006F][.0000.0059.0002.0328][.0000.005B.0002.0304] # LATIN SMALL LETTER O WITH OGONEK AND MACRON; QQCM
+01EC ; [.113B.0020.0008.004F][.0000.0059.0002.0328][.0000.005B.0002.0304] # LATIN CAPITAL LETTER O WITH OGONEK AND MACRON; QQCM
+014D ; [.113B.0020.0002.006F][.0000.005B.0002.0304] # LATIN SMALL LETTER O WITH MACRON; QQCM
+014C ; [.113B.0020.0008.004F][.0000.005B.0002.0304] # LATIN CAPITAL LETTER O WITH MACRON; QQCM
+1E53 ; [.113B.0020.0002.006F][.0000.005B.0002.0304][.0000.0032.0002.0301] # LATIN SMALL LETTER O WITH MACRON AND ACUTE; QQCM
+1E52 ; [.113B.0020.0008.004F][.0000.005B.0002.0304][.0000.0032.0002.0301] # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE; QQCM
+1E51 ; [.113B.0020.0002.006F][.0000.005B.0002.0304][.0000.0035.0002.0300] # LATIN SMALL LETTER O WITH MACRON AND GRAVE; QQCM
+1E50 ; [.113B.0020.0008.004F][.0000.005B.0002.0304][.0000.0035.0002.0300] # LATIN CAPITAL LETTER O WITH MACRON AND GRAVE; QQCM
+1ECF ; [.113B.0020.0002.006F][.0000.0060.0002.0309] # LATIN SMALL LETTER O WITH HOOK ABOVE; QQCM
+1ECE ; [.113B.0020.0008.004F][.0000.0060.0002.0309] # LATIN CAPITAL LETTER O WITH HOOK ABOVE; QQCM
+020D ; [.113B.0020.0002.006F][.0000.0063.0002.030F] # LATIN SMALL LETTER O WITH DOUBLE GRAVE; QQCM
+020C ; [.113B.0020.0008.004F][.0000.0063.0002.030F] # LATIN CAPITAL LETTER O WITH DOUBLE GRAVE; QQCM
+020F ; [.113B.0020.0002.006F][.0000.0065.0002.0311] # LATIN SMALL LETTER O WITH INVERTED BREVE; QQCM
+020E ; [.113B.0020.0008.004F][.0000.0065.0002.0311] # LATIN CAPITAL LETTER O WITH INVERTED BREVE; QQCM
+01A1 ; [.113B.0020.0002.006F][.0000.006D.0002.031B] # LATIN SMALL LETTER O WITH HORN; QQCM
+01A0 ; [.113B.0020.0008.004F][.0000.006D.0002.031B] # LATIN CAPITAL LETTER O WITH HORN; QQCM
+1EDB ; [.113B.0020.0002.006F][.0000.006D.0002.031B][.0000.0032.0002.0301] # LATIN SMALL LETTER O WITH HORN AND ACUTE; QQCM
+1EDA ; [.113B.0020.0008.004F][.0000.006D.0002.031B][.0000.0032.0002.0301] # LATIN CAPITAL LETTER O WITH HORN AND ACUTE; QQCM
+1EDD ; [.113B.0020.0002.006F][.0000.006D.0002.031B][.0000.0035.0002.0300] # LATIN SMALL LETTER O WITH HORN AND GRAVE; QQCM
+1EDC ; [.113B.0020.0008.004F][.0000.006D.0002.031B][.0000.0035.0002.0300] # LATIN CAPITAL LETTER O WITH HORN AND GRAVE; QQCM
+1EE1 ; [.113B.0020.0002.006F][.0000.006D.0002.031B][.0000.004E.0002.0303] # LATIN SMALL LETTER O WITH HORN AND TILDE; QQCM
+1EE0 ; [.113B.0020.0008.004F][.0000.006D.0002.031B][.0000.004E.0002.0303] # LATIN CAPITAL LETTER O WITH HORN AND TILDE; QQCM
+1EDF ; [.113B.0020.0002.006F][.0000.006D.0002.031B][.0000.0060.0002.0309] # LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE; QQCM
+1EDE ; [.113B.0020.0008.004F][.0000.006D.0002.031B][.0000.0060.0002.0309] # LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE; QQCM
+1EE3 ; [.113B.0020.0002.006F][.0000.006D.0002.031B][.0000.007A.0002.0323] # LATIN SMALL LETTER O WITH HORN AND DOT BELOW; QQCM
+1EE2 ; [.113B.0020.0008.004F][.0000.006D.0002.031B][.0000.007A.0002.0323] # LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW; QQCM
+1ECD ; [.113B.0020.0002.006F][.0000.007A.0002.0323] # LATIN SMALL LETTER O WITH DOT BELOW; QQCM
+1ECC ; [.113B.0020.0008.004F][.0000.007A.0002.0323] # LATIN CAPITAL LETTER O WITH DOT BELOW; QQCM
+1ED9 ; [.113B.0020.0002.006F][.0000.007A.0002.0323][.0000.003C.0002.0302] # LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW; QQCM
+1ED8 ; [.113B.0020.0008.004F][.0000.007A.0002.0323][.0000.003C.0002.0302] # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW; QQCM
+0153 ; [.113B.0020.0004.0153][.0000.0199.0004.0153][.1029.0020.001F.0153] # LATIN SMALL LIGATURE OE; QQKN
+0152 ; [.113B.0020.000A.0152][.0000.0199.0004.0152][.1029.0020.001F.0152] # LATIN CAPITAL LIGATURE OE; QQKN
+3375 ; [.113B.0020.001C.3375][.1216.0020.001D.3375] # SQUARE OV; QQKN
+1D0F ; [.113F.0020.0002.1D0F] # LATIN LETTER SMALL CAPITAL O
+1D11 ; [.1140.0020.0002.1D11] # LATIN SMALL LETTER SIDEWAYS O
+0276 ; [.1141.0020.0002.0276] # LATIN LETTER SMALL CAPITAL OE
+1D14 ; [.1145.0020.0002.1D14] # LATIN SMALL LETTER TURNED OE
+1D13 ; [.1146.0020.0002.1D13] # LATIN SMALL LETTER SIDEWAYS O WITH STROKE
+0254 ; [.1147.0020.0002.0254] # LATIN SMALL LETTER OPEN O
+0186 ; [.1147.0020.0008.0186] # LATIN CAPITAL LETTER OPEN O
+1D53 ; [.1147.0020.0014.1D53] # MODIFIER LETTER SMALL OPEN O; QQK
+1D10 ; [.114B.0020.0002.1D10] # LATIN LETTER SMALL CAPITAL OPEN O
+1D12 ; [.114C.0020.0002.1D12] # LATIN SMALL LETTER SIDEWAYS OPEN O
+1D97 ; [.114D.0020.0002.1D97] # LATIN SMALL LETTER OPEN O WITH RETROFLEX HOOK
+1D16 ; [.114E.0020.0002.1D16] # LATIN SMALL LETTER TOP HALF O
+1D54 ; [.114E.0020.0014.1D54] # MODIFIER LETTER SMALL TOP HALF O; QQK
+1D17 ; [.114F.0020.0002.1D17] # LATIN SMALL LETTER BOTTOM HALF O
+1D55 ; [.114F.0020.0014.1D55] # MODIFIER LETTER SMALL BOTTOM HALF O; QQK
+0275 ; [.1150.0020.0002.0275] # LATIN SMALL LETTER BARRED O
+019F ; [.1150.0020.0008.019F] # LATIN CAPITAL LETTER O WITH MIDDLE TILDE
+1DB1 ; [.1150.0020.0014.1DB1] # MODIFIER LETTER SMALL BARRED O; QQK
+0277 ; [.1154.0020.0002.0277] # LATIN SMALL LETTER CLOSED OMEGA
+0223 ; [.1158.0020.0002.0223] # LATIN SMALL LETTER OU
+0222 ; [.1158.0020.0008.0222] # LATIN CAPITAL LETTER OU
+1D3D ; [.1158.0020.001D.1D3D] # MODIFIER LETTER CAPITAL OU; QQK
+1D15 ; [.115C.0020.0002.1D15] # LATIN LETTER SMALL CAPITAL OU
+0070 ; [.115D.0020.0002.0070] # LATIN SMALL LETTER P
+FF50 ; [.115D.0020.0003.FF50] # FULLWIDTH LATIN SMALL LETTER P; QQK
+24AB ; [*02B1.0020.0004.24AB][.115D.0020.0004.24AB][*02B2.0020.001F.24AB] # PARENTHESIZED LATIN SMALL LETTER P; QQKN
+1D429 ; [.115D.0020.0005.1D429] # MATHEMATICAL BOLD SMALL P; QQK
+1D45D ; [.115D.0020.0005.1D45D] # MATHEMATICAL ITALIC SMALL P; QQK
+1D491 ; [.115D.0020.0005.1D491] # MATHEMATICAL BOLD ITALIC SMALL P; QQK
+1D4C5 ; [.115D.0020.0005.1D4C5] # MATHEMATICAL SCRIPT SMALL P; QQK
+1D4F9 ; [.115D.0020.0005.1D4F9] # MATHEMATICAL BOLD SCRIPT SMALL P; QQK
+1D52D ; [.115D.0020.0005.1D52D] # MATHEMATICAL FRAKTUR SMALL P; QQK
+1D561 ; [.115D.0020.0005.1D561] # MATHEMATICAL DOUBLE-STRUCK SMALL P; QQK
+1D595 ; [.115D.0020.0005.1D595] # MATHEMATICAL BOLD FRAKTUR SMALL P; QQK
+1D5C9 ; [.115D.0020.0005.1D5C9] # MATHEMATICAL SANS-SERIF SMALL P; QQK
+1D5FD ; [.115D.0020.0005.1D5FD] # MATHEMATICAL SANS-SERIF BOLD SMALL P; QQK
+1D631 ; [.115D.0020.0005.1D631] # MATHEMATICAL SANS-SERIF ITALIC SMALL P; QQK
+1D665 ; [.115D.0020.0005.1D665] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL P; QQK
+1D699 ; [.115D.0020.0005.1D699] # MATHEMATICAL MONOSPACE SMALL P; QQK
+24DF ; [.115D.0020.0006.24DF] # CIRCLED LATIN SMALL LETTER P; QQK
+0050 ; [.115D.0020.0008.0050] # LATIN CAPITAL LETTER P
+FF30 ; [.115D.0020.0009.FF30] # FULLWIDTH LATIN CAPITAL LETTER P; QQK
+2119 ; [.115D.0020.000B.2119] # DOUBLE-STRUCK CAPITAL P; QQK
+1D40F ; [.115D.0020.000B.1D40F] # MATHEMATICAL BOLD CAPITAL P; QQK
+1D443 ; [.115D.0020.000B.1D443] # MATHEMATICAL ITALIC CAPITAL P; QQK
+1D477 ; [.115D.0020.000B.1D477] # MATHEMATICAL BOLD ITALIC CAPITAL P; QQK
+1D4AB ; [.115D.0020.000B.1D4AB] # MATHEMATICAL SCRIPT CAPITAL P; QQK
+1D4DF ; [.115D.0020.000B.1D4DF] # MATHEMATICAL BOLD SCRIPT CAPITAL P; QQK
+1D513 ; [.115D.0020.000B.1D513] # MATHEMATICAL FRAKTUR CAPITAL P; QQK
+1D57B ; [.115D.0020.000B.1D57B] # MATHEMATICAL BOLD FRAKTUR CAPITAL P; QQK
+1D5AF ; [.115D.0020.000B.1D5AF] # MATHEMATICAL SANS-SERIF CAPITAL P; QQK
+1D5E3 ; [.115D.0020.000B.1D5E3] # MATHEMATICAL SANS-SERIF BOLD CAPITAL P; QQK
+1D617 ; [.115D.0020.000B.1D617] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL P; QQK
+1D64B ; [.115D.0020.000B.1D64B] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL P; QQK
+1D67F ; [.115D.0020.000B.1D67F] # MATHEMATICAL MONOSPACE CAPITAL P; QQK
+24C5 ; [.115D.0020.000C.24C5] # CIRCLED LATIN CAPITAL LETTER P; QQK
+1D56 ; [.115D.0020.0014.1D56] # MODIFIER LETTER SMALL P; QQK
+1D3E ; [.115D.0020.001D.1D3E] # MODIFIER LETTER CAPITAL P; QQK
+1E55 ; [.115D.0020.0002.0070][.0000.0032.0002.0301] # LATIN SMALL LETTER P WITH ACUTE; QQCM
+1E54 ; [.115D.0020.0008.0050][.0000.0032.0002.0301] # LATIN CAPITAL LETTER P WITH ACUTE; QQCM
+1E57 ; [.115D.0020.0002.0070][.0000.0052.0002.0307] # LATIN SMALL LETTER P WITH DOT ABOVE; QQCM
+1E56 ; [.115D.0020.0008.0050][.0000.0052.0002.0307] # LATIN CAPITAL LETTER P WITH DOT ABOVE; QQCM
+3380 ; [.115D.0020.001C.3380][.0FD0.0020.001D.3380] # SQUARE PA AMPS; QQKN
+33A9 ; [.115D.0020.001D.33A9][.0FD0.0020.001C.33A9] # SQUARE PA; QQKN
+3376 ; [.115D.0020.001C.3376][.0FFE.0020.001C.3376] # SQUARE PC; QQKN
+338A ; [.115D.0020.001C.338A][.105F.0020.001D.338A] # SQUARE PF; QQKN
+33D7 ; [.115D.0020.001D.33D7][.108D.0020.001D.33D7] # SQUARE PH; QQKN
+33D8 ; [.115D.0020.001C.33D8][*0266.0020.001C.33D8][.1110.0020.001F.33D8][*0266.0020.001F.33D8] # SQUARE PM; QQKN
+33D9 ; [.115D.0020.001D.33D9][.115D.0020.001D.33D9][.1110.0020.001F.33D9] # SQUARE PPM; QQKN
+33DA ; [.115D.0020.001D.33DA][.117E.0020.001D.33DA] # SQUARE PR; QQKN
+33B0 ; [.115D.0020.001C.33B0][.11AF.0020.001C.33B0] # SQUARE PS; QQKN
+3250 ; [.115D.0020.001D.3250][.11CF.0020.001D.3250][.1029.0020.001F.3250] # PARTNERSHIP SIGN; QQKN
+33B4 ; [.115D.0020.001C.33B4][.1216.0020.001D.33B4] # SQUARE PV; QQKN
+33BA ; [.115D.0020.001C.33BA][.1225.0020.001D.33BA] # SQUARE PW; QQKN
+1D18 ; [.1161.0020.0002.1D18] # LATIN LETTER SMALL CAPITAL P
+1D7D ; [.1162.0020.0002.1D7D] # LATIN SMALL LETTER P WITH STROKE
+2C63 ; [.1162.0020.0008.2C63] # LATIN CAPITAL LETTER P WITH STROKE
+1D71 ; [.1163.0020.0002.1D71] # LATIN SMALL LETTER P WITH MIDDLE TILDE
+1D88 ; [.1164.0020.0002.1D88] # LATIN SMALL LETTER P WITH PALATAL HOOK
+01A5 ; [.1165.0020.0002.01A5] # LATIN SMALL LETTER P WITH HOOK
+01A4 ; [.1165.0020.0008.01A4] # LATIN CAPITAL LETTER P WITH HOOK
+0278 ; [.1169.0020.0002.0278] # LATIN SMALL LETTER PHI
+1DB2 ; [.1169.0020.0014.1DB2] # MODIFIER LETTER SMALL PHI; QQK
+2C77 ; [.116D.0020.0002.2C77] # LATIN SMALL LETTER TAILLESS PHI
+0071 ; [.116E.0020.0002.0071] # LATIN SMALL LETTER Q
+FF51 ; [.116E.0020.0003.FF51] # FULLWIDTH LATIN SMALL LETTER Q; QQK
+24AC ; [*02B1.0020.0004.24AC][.116E.0020.0004.24AC][*02B2.0020.001F.24AC] # PARENTHESIZED LATIN SMALL LETTER Q; QQKN
+1D42A ; [.116E.0020.0005.1D42A] # MATHEMATICAL BOLD SMALL Q; QQK
+1D45E ; [.116E.0020.0005.1D45E] # MATHEMATICAL ITALIC SMALL Q; QQK
+1D492 ; [.116E.0020.0005.1D492] # MATHEMATICAL BOLD ITALIC SMALL Q; QQK
+1D4C6 ; [.116E.0020.0005.1D4C6] # MATHEMATICAL SCRIPT SMALL Q; QQK
+1D4FA ; [.116E.0020.0005.1D4FA] # MATHEMATICAL BOLD SCRIPT SMALL Q; QQK
+1D52E ; [.116E.0020.0005.1D52E] # MATHEMATICAL FRAKTUR SMALL Q; QQK
+1D562 ; [.116E.0020.0005.1D562] # MATHEMATICAL DOUBLE-STRUCK SMALL Q; QQK
+1D596 ; [.116E.0020.0005.1D596] # MATHEMATICAL BOLD FRAKTUR SMALL Q; QQK
+1D5CA ; [.116E.0020.0005.1D5CA] # MATHEMATICAL SANS-SERIF SMALL Q; QQK
+1D5FE ; [.116E.0020.0005.1D5FE] # MATHEMATICAL SANS-SERIF BOLD SMALL Q; QQK
+1D632 ; [.116E.0020.0005.1D632] # MATHEMATICAL SANS-SERIF ITALIC SMALL Q; QQK
+1D666 ; [.116E.0020.0005.1D666] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Q; QQK
+1D69A ; [.116E.0020.0005.1D69A] # MATHEMATICAL MONOSPACE SMALL Q; QQK
+24E0 ; [.116E.0020.0006.24E0] # CIRCLED LATIN SMALL LETTER Q; QQK
+0051 ; [.116E.0020.0008.0051] # LATIN CAPITAL LETTER Q
+FF31 ; [.116E.0020.0009.FF31] # FULLWIDTH LATIN CAPITAL LETTER Q; QQK
+211A ; [.116E.0020.000B.211A] # DOUBLE-STRUCK CAPITAL Q; QQK
+1D410 ; [.116E.0020.000B.1D410] # MATHEMATICAL BOLD CAPITAL Q; QQK
+1D444 ; [.116E.0020.000B.1D444] # MATHEMATICAL ITALIC CAPITAL Q; QQK
+1D478 ; [.116E.0020.000B.1D478] # MATHEMATICAL BOLD ITALIC CAPITAL Q; QQK
+1D4AC ; [.116E.0020.000B.1D4AC] # MATHEMATICAL SCRIPT CAPITAL Q; QQK
+1D4E0 ; [.116E.0020.000B.1D4E0] # MATHEMATICAL BOLD SCRIPT CAPITAL Q; QQK
+1D514 ; [.116E.0020.000B.1D514] # MATHEMATICAL FRAKTUR CAPITAL Q; QQK
+1D57C ; [.116E.0020.000B.1D57C] # MATHEMATICAL BOLD FRAKTUR CAPITAL Q; QQK
+1D5B0 ; [.116E.0020.000B.1D5B0] # MATHEMATICAL SANS-SERIF CAPITAL Q; QQK
+1D5E4 ; [.116E.0020.000B.1D5E4] # MATHEMATICAL SANS-SERIF BOLD CAPITAL Q; QQK
+1D618 ; [.116E.0020.000B.1D618] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL Q; QQK
+1D64C ; [.116E.0020.000B.1D64C] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Q; QQK
+1D680 ; [.116E.0020.000B.1D680] # MATHEMATICAL MONOSPACE CAPITAL Q; QQK
+24C6 ; [.116E.0020.000C.24C6] # CIRCLED LATIN CAPITAL LETTER Q; QQK
+0239 ; [.116E.0020.0004.0239][.115D.0020.0004.0239] # LATIN SMALL LETTER QP DIGRAPH; QQKN
+02A0 ; [.1172.0020.0002.02A0] # LATIN SMALL LETTER Q WITH HOOK
+024B ; [.1176.0020.0002.024B] # LATIN SMALL LETTER Q WITH HOOK TAIL
+024A ; [.1176.0020.0008.024A] # LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL
+0138 ; [.117A.0020.0002.0138] # LATIN SMALL LETTER KRA
+0072 ; [.117E.0020.0002.0072] # LATIN SMALL LETTER R
+FF52 ; [.117E.0020.0003.FF52] # FULLWIDTH LATIN SMALL LETTER R; QQK
+036C ; [.117E.0020.0004.036C] # COMBINING LATIN SMALL LETTER R; QQK
+24AD ; [*02B1.0020.0004.24AD][.117E.0020.0004.24AD][*02B2.0020.001F.24AD] # PARENTHESIZED LATIN SMALL LETTER R; QQKN
+1D42B ; [.117E.0020.0005.1D42B] # MATHEMATICAL BOLD SMALL R; QQK
+1D45F ; [.117E.0020.0005.1D45F] # MATHEMATICAL ITALIC SMALL R; QQK
+1D493 ; [.117E.0020.0005.1D493] # MATHEMATICAL BOLD ITALIC SMALL R; QQK
+1D4C7 ; [.117E.0020.0005.1D4C7] # MATHEMATICAL SCRIPT SMALL R; QQK
+1D4FB ; [.117E.0020.0005.1D4FB] # MATHEMATICAL BOLD SCRIPT SMALL R; QQK
+1D52F ; [.117E.0020.0005.1D52F] # MATHEMATICAL FRAKTUR SMALL R; QQK
+1D563 ; [.117E.0020.0005.1D563] # MATHEMATICAL DOUBLE-STRUCK SMALL R; QQK
+1D597 ; [.117E.0020.0005.1D597] # MATHEMATICAL BOLD FRAKTUR SMALL R; QQK
+1D5CB ; [.117E.0020.0005.1D5CB] # MATHEMATICAL SANS-SERIF SMALL R; QQK
+1D5FF ; [.117E.0020.0005.1D5FF] # MATHEMATICAL SANS-SERIF BOLD SMALL R; QQK
+1D633 ; [.117E.0020.0005.1D633] # MATHEMATICAL SANS-SERIF ITALIC SMALL R; QQK
+1D667 ; [.117E.0020.0005.1D667] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL R; QQK
+1D69B ; [.117E.0020.0005.1D69B] # MATHEMATICAL MONOSPACE SMALL R; QQK
+24E1 ; [.117E.0020.0006.24E1] # CIRCLED LATIN SMALL LETTER R; QQK
+0052 ; [.117E.0020.0008.0052] # LATIN CAPITAL LETTER R
+FF32 ; [.117E.0020.0009.FF32] # FULLWIDTH LATIN CAPITAL LETTER R; QQK
+211B ; [.117E.0020.000B.211B] # SCRIPT CAPITAL R; QQK
+211C ; [.117E.0020.000B.211C] # BLACK-LETTER CAPITAL R; QQK
+211D ; [.117E.0020.000B.211D] # DOUBLE-STRUCK CAPITAL R; QQK
+1D411 ; [.117E.0020.000B.1D411] # MATHEMATICAL BOLD CAPITAL R; QQK
+1D445 ; [.117E.0020.000B.1D445] # MATHEMATICAL ITALIC CAPITAL R; QQK
+1D479 ; [.117E.0020.000B.1D479] # MATHEMATICAL BOLD ITALIC CAPITAL R; QQK
+1D4E1 ; [.117E.0020.000B.1D4E1] # MATHEMATICAL BOLD SCRIPT CAPITAL R; QQK
+1D57D ; [.117E.0020.000B.1D57D] # MATHEMATICAL BOLD FRAKTUR CAPITAL R; QQK
+1D5B1 ; [.117E.0020.000B.1D5B1] # MATHEMATICAL SANS-SERIF CAPITAL R; QQK
+1D5E5 ; [.117E.0020.000B.1D5E5] # MATHEMATICAL SANS-SERIF BOLD CAPITAL R; QQK
+1D619 ; [.117E.0020.000B.1D619] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL R; QQK
+1D64D ; [.117E.0020.000B.1D64D] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL R; QQK
+1D681 ; [.117E.0020.000B.1D681] # MATHEMATICAL MONOSPACE CAPITAL R; QQK
+24C7 ; [.117E.0020.000C.24C7] # CIRCLED LATIN CAPITAL LETTER R; QQK
+02B3 ; [.117E.0020.0014.02B3] # MODIFIER LETTER SMALL R; QQK
+1D63 ; [.117E.0020.0015.1D63] # LATIN SUBSCRIPT SMALL LETTER R; QQK
+1D3F ; [.117E.0020.001D.1D3F] # MODIFIER LETTER CAPITAL R; QQK
+0155 ; [.117E.0020.0002.0072][.0000.0032.0002.0301] # LATIN SMALL LETTER R WITH ACUTE; QQCM
+0154 ; [.117E.0020.0008.0052][.0000.0032.0002.0301] # LATIN CAPITAL LETTER R WITH ACUTE; QQCM
+0159 ; [.117E.0020.0002.0072][.0000.0041.0002.030C] # LATIN SMALL LETTER R WITH CARON; QQCM
+0158 ; [.117E.0020.0008.0052][.0000.0041.0002.030C] # LATIN CAPITAL LETTER R WITH CARON; QQCM
+1E59 ; [.117E.0020.0002.0072][.0000.0052.0002.0307] # LATIN SMALL LETTER R WITH DOT ABOVE; QQCM
+1E58 ; [.117E.0020.0008.0052][.0000.0052.0002.0307] # LATIN CAPITAL LETTER R WITH DOT ABOVE; QQCM
+0157 ; [.117E.0020.0002.0072][.0000.0056.0002.0327] # LATIN SMALL LETTER R WITH CEDILLA; QQCM
+0156 ; [.117E.0020.0008.0052][.0000.0056.0002.0327] # LATIN CAPITAL LETTER R WITH CEDILLA; QQCM
+0211 ; [.117E.0020.0002.0072][.0000.0063.0002.030F] # LATIN SMALL LETTER R WITH DOUBLE GRAVE; QQCM
+0210 ; [.117E.0020.0008.0052][.0000.0063.0002.030F] # LATIN CAPITAL LETTER R WITH DOUBLE GRAVE; QQCM
+0213 ; [.117E.0020.0002.0072][.0000.0065.0002.0311] # LATIN SMALL LETTER R WITH INVERTED BREVE; QQCM
+0212 ; [.117E.0020.0008.0052][.0000.0065.0002.0311] # LATIN CAPITAL LETTER R WITH INVERTED BREVE; QQCM
+1E5B ; [.117E.0020.0002.0072][.0000.007A.0002.0323] # LATIN SMALL LETTER R WITH DOT BELOW; QQCM
+1E5A ; [.117E.0020.0008.0052][.0000.007A.0002.0323] # LATIN CAPITAL LETTER R WITH DOT BELOW; QQCM
+1E5D ; [.117E.0020.0002.0072][.0000.007A.0002.0323][.0000.005B.0002.0304] # LATIN SMALL LETTER R WITH DOT BELOW AND MACRON; QQCM
+1E5C ; [.117E.0020.0008.0052][.0000.007A.0002.0323][.0000.005B.0002.0304] # LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON; QQCM
+1E5F ; [.117E.0020.0002.0072][.0000.008A.0002.0331] # LATIN SMALL LETTER R WITH LINE BELOW; QQCM
+1E5E ; [.117E.0020.0008.0052][.0000.008A.0002.0331] # LATIN CAPITAL LETTER R WITH LINE BELOW; QQCM
+33AD ; [.117E.0020.001C.33AD][.0FD0.0020.001C.33AD][.1010.0020.001F.33AD] # SQUARE RAD; QQKN
+33AE ; [.117E.0020.001C.33AE][.0FD0.0020.001C.33AE][.1010.0020.001F.33AE][*04C7.0020.001F.33AE][.11AF.0020.001F.33AE] # SQUARE RAD OVER S; QQKN
+33AF ; [.117E.0020.001C.33AF][.0FD0.0020.001C.33AF][.1010.0020.001F.33AF][*04C7.0020.001F.33AF][.11AF.0020.001F.33AF][.0FC8.0020.001F.33AF] # SQUARE RAD OVER S SQUARED; QQKN
+20A8 ; [.117E.0020.000A.20A8][.11AF.0020.0004.20A8] # RUPEE SIGN; QQKN
+0280 ; [.1182.0020.0002.0280] # LATIN LETTER SMALL CAPITAL R
+01A6 ; [.1182.0020.0008.01A6] # LATIN LETTER YR
+1D19 ; [.1186.0020.0002.1D19] # LATIN LETTER SMALL CAPITAL REVERSED R
+024D ; [.1187.0020.0002.024D] # LATIN SMALL LETTER R WITH STROKE
+024C ; [.1187.0020.0008.024C] # LATIN CAPITAL LETTER R WITH STROKE
+1D72 ; [.118B.0020.0002.1D72] # LATIN SMALL LETTER R WITH MIDDLE TILDE
+0279 ; [.118C.0020.0002.0279] # LATIN SMALL LETTER TURNED R
+02B4 ; [.118C.0020.0014.02B4] # MODIFIER LETTER SMALL TURNED R; QQK
+1D1A ; [.1190.0020.0002.1D1A] # LATIN LETTER SMALL CAPITAL TURNED R
+027A ; [.1191.0020.0002.027A] # LATIN SMALL LETTER TURNED R WITH LONG LEG
+1D89 ; [.1195.0020.0002.1D89] # LATIN SMALL LETTER R WITH PALATAL HOOK
+027B ; [.1196.0020.0002.027B] # LATIN SMALL LETTER TURNED R WITH HOOK
+02B5 ; [.1196.0020.0014.02B5] # MODIFIER LETTER SMALL TURNED R WITH HOOK; QQK
+027C ; [.119A.0020.0002.027C] # LATIN SMALL LETTER R WITH LONG LEG
+027D ; [.119E.0020.0002.027D] # LATIN SMALL LETTER R WITH TAIL
+2C64 ; [.119E.0020.0008.2C64] # LATIN CAPITAL LETTER R WITH TAIL
+027E ; [.11A2.0020.0002.027E] # LATIN SMALL LETTER R WITH FISHHOOK
+1D73 ; [.11A6.0020.0002.1D73] # LATIN SMALL LETTER R WITH FISHHOOK AND MIDDLE TILDE
+027F ; [.11A7.0020.0002.027F] # LATIN SMALL LETTER REVERSED R WITH FISHHOOK
+0281 ; [.11AB.0020.0002.0281] # LATIN LETTER SMALL CAPITAL INVERTED R
+02B6 ; [.11AB.0020.0014.02B6] # MODIFIER LETTER SMALL CAPITAL INVERTED R; QQK
+0073 ; [.11AF.0020.0002.0073] # LATIN SMALL LETTER S
+FF53 ; [.11AF.0020.0003.FF53] # FULLWIDTH LATIN SMALL LETTER S; QQK
+24AE ; [*02B1.0020.0004.24AE][.11AF.0020.0004.24AE][*02B2.0020.001F.24AE] # PARENTHESIZED LATIN SMALL LETTER S; QQKN
+1D42C ; [.11AF.0020.0005.1D42C] # MATHEMATICAL BOLD SMALL S; QQK
+1D460 ; [.11AF.0020.0005.1D460] # MATHEMATICAL ITALIC SMALL S; QQK
+1D494 ; [.11AF.0020.0005.1D494] # MATHEMATICAL BOLD ITALIC SMALL S; QQK
+1D4C8 ; [.11AF.0020.0005.1D4C8] # MATHEMATICAL SCRIPT SMALL S; QQK
+1D4FC ; [.11AF.0020.0005.1D4FC] # MATHEMATICAL BOLD SCRIPT SMALL S; QQK
+1D530 ; [.11AF.0020.0005.1D530] # MATHEMATICAL FRAKTUR SMALL S; QQK
+1D564 ; [.11AF.0020.0005.1D564] # MATHEMATICAL DOUBLE-STRUCK SMALL S; QQK
+1D598 ; [.11AF.0020.0005.1D598] # MATHEMATICAL BOLD FRAKTUR SMALL S; QQK
+1D5CC ; [.11AF.0020.0005.1D5CC] # MATHEMATICAL SANS-SERIF SMALL S; QQK
+1D600 ; [.11AF.0020.0005.1D600] # MATHEMATICAL SANS-SERIF BOLD SMALL S; QQK
+1D634 ; [.11AF.0020.0005.1D634] # MATHEMATICAL SANS-SERIF ITALIC SMALL S; QQK
+1D668 ; [.11AF.0020.0005.1D668] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL S; QQK
+1D69C ; [.11AF.0020.0005.1D69C] # MATHEMATICAL MONOSPACE SMALL S; QQK
+24E2 ; [.11AF.0020.0006.24E2] # CIRCLED LATIN SMALL LETTER S; QQK
+0053 ; [.11AF.0020.0008.0053] # LATIN CAPITAL LETTER S
+FF33 ; [.11AF.0020.0009.FF33] # FULLWIDTH LATIN CAPITAL LETTER S; QQK
+1D412 ; [.11AF.0020.000B.1D412] # MATHEMATICAL BOLD CAPITAL S; QQK
+1D446 ; [.11AF.0020.000B.1D446] # MATHEMATICAL ITALIC CAPITAL S; QQK
+1D47A ; [.11AF.0020.000B.1D47A] # MATHEMATICAL BOLD ITALIC CAPITAL S; QQK
+1D4AE ; [.11AF.0020.000B.1D4AE] # MATHEMATICAL SCRIPT CAPITAL S; QQK
+1D4E2 ; [.11AF.0020.000B.1D4E2] # MATHEMATICAL BOLD SCRIPT CAPITAL S; QQK
+1D516 ; [.11AF.0020.000B.1D516] # MATHEMATICAL FRAKTUR CAPITAL S; QQK
+1D54A ; [.11AF.0020.000B.1D54A] # MATHEMATICAL DOUBLE-STRUCK CAPITAL S; QQK
+1D57E ; [.11AF.0020.000B.1D57E] # MATHEMATICAL BOLD FRAKTUR CAPITAL S; QQK
+1D5B2 ; [.11AF.0020.000B.1D5B2] # MATHEMATICAL SANS-SERIF CAPITAL S; QQK
+1D5E6 ; [.11AF.0020.000B.1D5E6] # MATHEMATICAL SANS-SERIF BOLD CAPITAL S; QQK
+1D61A ; [.11AF.0020.000B.1D61A] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL S; QQK
+1D64E ; [.11AF.0020.000B.1D64E] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL S; QQK
+1D682 ; [.11AF.0020.000B.1D682] # MATHEMATICAL MONOSPACE CAPITAL S; QQK
+24C8 ; [.11AF.0020.000C.24C8] # CIRCLED LATIN CAPITAL LETTER S; QQK
+02E2 ; [.11AF.0020.0014.02E2] # MODIFIER LETTER SMALL S; QQK
+015B ; [.11AF.0020.0002.0073][.0000.0032.0002.0301] # LATIN SMALL LETTER S WITH ACUTE; QQCM
+015A ; [.11AF.0020.0008.0053][.0000.0032.0002.0301] # LATIN CAPITAL LETTER S WITH ACUTE; QQCM
+1E65 ; [.11AF.0020.0002.0073][.0000.0032.0002.0301][.0000.0052.0002.0307] # LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE; QQCM
+1E64 ; [.11AF.0020.0008.0053][.0000.0032.0002.0301][.0000.0052.0002.0307] # LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE; QQCM
+015D ; [.11AF.0020.0002.0073][.0000.003C.0002.0302] # LATIN SMALL LETTER S WITH CIRCUMFLEX; QQCM
+015C ; [.11AF.0020.0008.0053][.0000.003C.0002.0302] # LATIN CAPITAL LETTER S WITH CIRCUMFLEX; QQCM
+0161 ; [.11AF.0020.0002.0073][.0000.0041.0002.030C] # LATIN SMALL LETTER S WITH CARON; QQCM
+0160 ; [.11AF.0020.0008.0053][.0000.0041.0002.030C] # LATIN CAPITAL LETTER S WITH CARON; QQCM
+1E67 ; [.11AF.0020.0002.0073][.0000.0041.0002.030C][.0000.0052.0002.0307] # LATIN SMALL LETTER S WITH CARON AND DOT ABOVE; QQCM
+1E66 ; [.11AF.0020.0008.0053][.0000.0041.0002.030C][.0000.0052.0002.0307] # LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE; QQCM
+1E61 ; [.11AF.0020.0002.0073][.0000.0052.0002.0307] # LATIN SMALL LETTER S WITH DOT ABOVE; QQCM
+1E60 ; [.11AF.0020.0008.0053][.0000.0052.0002.0307] # LATIN CAPITAL LETTER S WITH DOT ABOVE; QQCM
+015F ; [.11AF.0020.0002.0073][.0000.0056.0002.0327] # LATIN SMALL LETTER S WITH CEDILLA; QQCM
+015E ; [.11AF.0020.0008.0053][.0000.0056.0002.0327] # LATIN CAPITAL LETTER S WITH CEDILLA; QQCM
+1E63 ; [.11AF.0020.0002.0073][.0000.007A.0002.0323] # LATIN SMALL LETTER S WITH DOT BELOW; QQCM
+1E62 ; [.11AF.0020.0008.0053][.0000.007A.0002.0323] # LATIN CAPITAL LETTER S WITH DOT BELOW; QQCM
+1E69 ; [.11AF.0020.0002.0073][.0000.007A.0002.0323][.0000.0052.0002.0307] # LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE; QQCM
+1E68 ; [.11AF.0020.0008.0053][.0000.007A.0002.0323][.0000.0052.0002.0307] # LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE; QQCM
+0219 ; [.11AF.0020.0002.0073][.0000.0081.0002.0326] # LATIN SMALL LETTER S WITH COMMA BELOW; QQCM
+0218 ; [.11AF.0020.0008.0053][.0000.0081.0002.0326] # LATIN CAPITAL LETTER S WITH COMMA BELOW; QQCM
+017F ; [.11AF.0020.0004.017F][.0000.019A.0004.017F] # LATIN SMALL LETTER LONG S; QQKN
+1E9B ; [.11AF.0020.0004.1E9B][.0000.019A.0004.1E9B][.0000.0052.0002.1E9B] # LATIN SMALL LETTER LONG S WITH DOT ABOVE; QQKN
+2120 ; [.11AF.0020.0014.2120][.1110.0020.0014.2120] # SERVICE MARK; QQKN
+33DB ; [.11AF.0020.001C.33DB][.117E.0020.001C.33DB] # SQUARE SR; QQKN
+00DF ; [.11AF.0020.0004.00DF][.0000.0199.0004.00DF][.11AF.0020.001F.00DF] # LATIN SMALL LETTER SHARP S; QQKN
+FB06 ; [.11AF.0020.0004.FB06][.11CF.0020.0004.FB06] # LATIN SMALL LIGATURE ST; QQKN
+FB05 ; [.11AF.0020.0004.FB05][.0000.019A.0004.FB05][.11CF.0020.001F.FB05] # LATIN SMALL LIGATURE LONG S T; QQKN
+33DC ; [.11AF.0020.001D.33DC][.1216.0020.001C.33DC] # SQUARE SV; QQKN
+1D74 ; [.11B3.0020.0002.1D74] # LATIN SMALL LETTER S WITH MIDDLE TILDE
+1D8A ; [.11B4.0020.0002.1D8A] # LATIN SMALL LETTER S WITH PALATAL HOOK
+0282 ; [.11B5.0020.0002.0282] # LATIN SMALL LETTER S WITH HOOK
+1DB3 ; [.11B5.0020.0014.1DB3] # MODIFIER LETTER SMALL S WITH HOOK; QQK
+023F ; [.11B9.0020.0002.023F] # LATIN SMALL LETTER S WITH SWASH TAIL
+0283 ; [.11BD.0020.0002.0283] # LATIN SMALL LETTER ESH
+01A9 ; [.11BD.0020.0008.01A9] # LATIN CAPITAL LETTER ESH
+1DB4 ; [.11BD.0020.0014.1DB4] # MODIFIER LETTER SMALL ESH; QQK
+1D8B ; [.11C1.0020.0002.1D8B] # LATIN SMALL LETTER ESH WITH PALATAL HOOK
+01AA ; [.11C2.0020.0002.01AA] # LATIN LETTER REVERSED ESH LOOP
+0285 ; [.11C6.0020.0002.0285] # LATIN SMALL LETTER SQUAT REVERSED ESH
+1D98 ; [.11CA.0020.0002.1D98] # LATIN SMALL LETTER ESH WITH RETROFLEX HOOK
+0286 ; [.11CB.0020.0002.0286] # LATIN SMALL LETTER ESH WITH CURL
+0074 ; [.11CF.0020.0002.0074] # LATIN SMALL LETTER T
+FF54 ; [.11CF.0020.0003.FF54] # FULLWIDTH LATIN SMALL LETTER T; QQK
+036D ; [.11CF.0020.0004.036D] # COMBINING LATIN SMALL LETTER T; QQK
+24AF ; [*02B1.0020.0004.24AF][.11CF.0020.0004.24AF][*02B2.0020.001F.24AF] # PARENTHESIZED LATIN SMALL LETTER T; QQKN
+1D42D ; [.11CF.0020.0005.1D42D] # MATHEMATICAL BOLD SMALL T; QQK
+1D461 ; [.11CF.0020.0005.1D461] # MATHEMATICAL ITALIC SMALL T; QQK
+1D495 ; [.11CF.0020.0005.1D495] # MATHEMATICAL BOLD ITALIC SMALL T; QQK
+1D4C9 ; [.11CF.0020.0005.1D4C9] # MATHEMATICAL SCRIPT SMALL T; QQK
+1D4FD ; [.11CF.0020.0005.1D4FD] # MATHEMATICAL BOLD SCRIPT SMALL T; QQK
+1D531 ; [.11CF.0020.0005.1D531] # MATHEMATICAL FRAKTUR SMALL T; QQK
+1D565 ; [.11CF.0020.0005.1D565] # MATHEMATICAL DOUBLE-STRUCK SMALL T; QQK
+1D599 ; [.11CF.0020.0005.1D599] # MATHEMATICAL BOLD FRAKTUR SMALL T; QQK
+1D5CD ; [.11CF.0020.0005.1D5CD] # MATHEMATICAL SANS-SERIF SMALL T; QQK
+1D601 ; [.11CF.0020.0005.1D601] # MATHEMATICAL SANS-SERIF BOLD SMALL T; QQK
+1D635 ; [.11CF.0020.0005.1D635] # MATHEMATICAL SANS-SERIF ITALIC SMALL T; QQK
+1D669 ; [.11CF.0020.0005.1D669] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL T; QQK
+1D69D ; [.11CF.0020.0005.1D69D] # MATHEMATICAL MONOSPACE SMALL T; QQK
+24E3 ; [.11CF.0020.0006.24E3] # CIRCLED LATIN SMALL LETTER T; QQK
+0054 ; [.11CF.0020.0008.0054] # LATIN CAPITAL LETTER T
+FF34 ; [.11CF.0020.0009.FF34] # FULLWIDTH LATIN CAPITAL LETTER T; QQK
+1D413 ; [.11CF.0020.000B.1D413] # MATHEMATICAL BOLD CAPITAL T; QQK
+1D447 ; [.11CF.0020.000B.1D447] # MATHEMATICAL ITALIC CAPITAL T; QQK
+1D47B ; [.11CF.0020.000B.1D47B] # MATHEMATICAL BOLD ITALIC CAPITAL T; QQK
+1D4AF ; [.11CF.0020.000B.1D4AF] # MATHEMATICAL SCRIPT CAPITAL T; QQK
+1D4E3 ; [.11CF.0020.000B.1D4E3] # MATHEMATICAL BOLD SCRIPT CAPITAL T; QQK
+1D517 ; [.11CF.0020.000B.1D517] # MATHEMATICAL FRAKTUR CAPITAL T; QQK
+1D54B ; [.11CF.0020.000B.1D54B] # MATHEMATICAL DOUBLE-STRUCK CAPITAL T; QQK
+1D57F ; [.11CF.0020.000B.1D57F] # MATHEMATICAL BOLD FRAKTUR CAPITAL T; QQK
+1D5B3 ; [.11CF.0020.000B.1D5B3] # MATHEMATICAL SANS-SERIF CAPITAL T; QQK
+1D5E7 ; [.11CF.0020.000B.1D5E7] # MATHEMATICAL SANS-SERIF BOLD CAPITAL T; QQK
+1D61B ; [.11CF.0020.000B.1D61B] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL T; QQK
+1D64F ; [.11CF.0020.000B.1D64F] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL T; QQK
+1D683 ; [.11CF.0020.000B.1D683] # MATHEMATICAL MONOSPACE CAPITAL T; QQK
+24C9 ; [.11CF.0020.000C.24C9] # CIRCLED LATIN CAPITAL LETTER T; QQK
+1D57 ; [.11CF.0020.0014.1D57] # MODIFIER LETTER SMALL T; QQK
+1D40 ; [.11CF.0020.001D.1D40] # MODIFIER LETTER CAPITAL T; QQK
+0165 ; [.11CF.0020.0002.0074][.0000.0041.0002.030C] # LATIN SMALL LETTER T WITH CARON; QQCM
+0164 ; [.11CF.0020.0008.0054][.0000.0041.0002.030C] # LATIN CAPITAL LETTER T WITH CARON; QQCM
+1E97 ; [.11CF.0020.0002.0074][.0000.0047.0002.0308] # LATIN SMALL LETTER T WITH DIAERESIS; QQCM
+1E6B ; [.11CF.0020.0002.0074][.0000.0052.0002.0307] # LATIN SMALL LETTER T WITH DOT ABOVE; QQCM
+1E6A ; [.11CF.0020.0008.0054][.0000.0052.0002.0307] # LATIN CAPITAL LETTER T WITH DOT ABOVE; QQCM
+0163 ; [.11CF.0020.0002.0074][.0000.0056.0002.0327] # LATIN SMALL LETTER T WITH CEDILLA; QQCM
+0162 ; [.11CF.0020.0008.0054][.0000.0056.0002.0327] # LATIN CAPITAL LETTER T WITH CEDILLA; QQCM
+1E6D ; [.11CF.0020.0002.0074][.0000.007A.0002.0323] # LATIN SMALL LETTER T WITH DOT BELOW; QQCM
+1E6C ; [.11CF.0020.0008.0054][.0000.007A.0002.0323] # LATIN CAPITAL LETTER T WITH DOT BELOW; QQCM
+021B ; [.11CF.0020.0002.0074][.0000.0081.0002.0326] # LATIN SMALL LETTER T WITH COMMA BELOW; QQCM
+021A ; [.11CF.0020.0008.0054][.0000.0081.0002.0326] # LATIN CAPITAL LETTER T WITH COMMA BELOW; QQCM
+1E71 ; [.11CF.0020.0002.0074][.0000.0086.0002.032D] # LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW; QQCM
+1E70 ; [.11CF.0020.0008.0054][.0000.0086.0002.032D] # LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW; QQCM
+1E6F ; [.11CF.0020.0002.0074][.0000.008A.0002.0331] # LATIN SMALL LETTER T WITH LINE BELOW; QQCM
+1E6E ; [.11CF.0020.0008.0054][.0000.008A.0002.0331] # LATIN CAPITAL LETTER T WITH LINE BELOW; QQCM
+02A8 ; [.11CF.0020.0004.02A8][.100B.0020.0004.02A8] # LATIN SMALL LETTER TC DIGRAPH WITH CURL; QQKN
+2121 ; [.11CF.0020.000A.2121][.1029.0020.000A.2121][.10E5.0020.001F.2121] # TELEPHONE SIGN; QQKN
+1D7A ; [.11CF.0020.0004.1D7A][.0000.019A.0004.1D7A][.108D.0020.001F.1D7A] # LATIN SMALL LETTER TH WITH STRIKETHROUGH; QQKN
+3394 ; [.11CF.0020.001D.3394][.108D.0020.001D.3394][.1243.0020.001F.3394] # SQUARE THZ; QQKN
+2122 ; [.11CF.0020.0014.2122][.1110.0020.0014.2122] # TRADE MARK SIGN; QQKN
+01BE ; [.11CF.0020.0004.01BE][.11AF.0020.0004.01BE] # LATIN LETTER INVERTED GLOTTAL STOP WITH STROKE; QQKN
+02A6 ; [.11CF.0020.0004.02A6][.11AF.0020.0004.02A6] # LATIN SMALL LETTER TS DIGRAPH; QQKN
+02A7 ; [.11CF.0020.0004.02A7][.11BD.0020.0004.02A7] # LATIN SMALL LETTER TESH DIGRAPH; QQKN
+1D1B ; [.11D3.0020.0002.1D1B] # LATIN LETTER SMALL CAPITAL T
+0167 ; [.11D4.0020.0002.0167] # LATIN SMALL LETTER T WITH STROKE
+0166 ; [.11D4.0020.0008.0166] # LATIN CAPITAL LETTER T WITH STROKE
+2C66 ; [.11D8.0020.0002.2C66] # LATIN SMALL LETTER T WITH DIAGONAL STROKE
+023E ; [.11D8.0020.0008.023E] # LATIN CAPITAL LETTER T WITH DIAGONAL STROKE
+1D75 ; [.11D9.0020.0002.1D75] # LATIN SMALL LETTER T WITH MIDDLE TILDE
+01AB ; [.11DA.0020.0002.01AB] # LATIN SMALL LETTER T WITH PALATAL HOOK
+1DB5 ; [.11DA.0020.0014.1DB5] # MODIFIER LETTER SMALL T WITH PALATAL HOOK; QQK
+01AD ; [.11DE.0020.0002.01AD] # LATIN SMALL LETTER T WITH HOOK
+01AC ; [.11DE.0020.0008.01AC] # LATIN CAPITAL LETTER T WITH HOOK
+0288 ; [.11E2.0020.0002.0288] # LATIN SMALL LETTER T WITH RETROFLEX HOOK
+01AE ; [.11E2.0020.0008.01AE] # LATIN CAPITAL LETTER T WITH RETROFLEX HOOK
+0236 ; [.11E6.0020.0002.0236] # LATIN SMALL LETTER T WITH CURL
+0287 ; [.11EA.0020.0002.0287] # LATIN SMALL LETTER TURNED T
+0075 ; [.11EE.0020.0002.0075] # LATIN SMALL LETTER U
+FF55 ; [.11EE.0020.0003.FF55] # FULLWIDTH LATIN SMALL LETTER U; QQK
+0367 ; [.11EE.0020.0004.0367] # COMBINING LATIN SMALL LETTER U; QQK
+24B0 ; [*02B1.0020.0004.24B0][.11EE.0020.0004.24B0][*02B2.0020.001F.24B0] # PARENTHESIZED LATIN SMALL LETTER U; QQKN
+1D42E ; [.11EE.0020.0005.1D42E] # MATHEMATICAL BOLD SMALL U; QQK
+1D462 ; [.11EE.0020.0005.1D462] # MATHEMATICAL ITALIC SMALL U; QQK
+1D496 ; [.11EE.0020.0005.1D496] # MATHEMATICAL BOLD ITALIC SMALL U; QQK
+1D4CA ; [.11EE.0020.0005.1D4CA] # MATHEMATICAL SCRIPT SMALL U; QQK
+1D4FE ; [.11EE.0020.0005.1D4FE] # MATHEMATICAL BOLD SCRIPT SMALL U; QQK
+1D532 ; [.11EE.0020.0005.1D532] # MATHEMATICAL FRAKTUR SMALL U; QQK
+1D566 ; [.11EE.0020.0005.1D566] # MATHEMATICAL DOUBLE-STRUCK SMALL U; QQK
+1D59A ; [.11EE.0020.0005.1D59A] # MATHEMATICAL BOLD FRAKTUR SMALL U; QQK
+1D5CE ; [.11EE.0020.0005.1D5CE] # MATHEMATICAL SANS-SERIF SMALL U; QQK
+1D602 ; [.11EE.0020.0005.1D602] # MATHEMATICAL SANS-SERIF BOLD SMALL U; QQK
+1D636 ; [.11EE.0020.0005.1D636] # MATHEMATICAL SANS-SERIF ITALIC SMALL U; QQK
+1D66A ; [.11EE.0020.0005.1D66A] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL U; QQK
+1D69E ; [.11EE.0020.0005.1D69E] # MATHEMATICAL MONOSPACE SMALL U; QQK
+24E4 ; [.11EE.0020.0006.24E4] # CIRCLED LATIN SMALL LETTER U; QQK
+0055 ; [.11EE.0020.0008.0055] # LATIN CAPITAL LETTER U
+FF35 ; [.11EE.0020.0009.FF35] # FULLWIDTH LATIN CAPITAL LETTER U; QQK
+1D414 ; [.11EE.0020.000B.1D414] # MATHEMATICAL BOLD CAPITAL U; QQK
+1D448 ; [.11EE.0020.000B.1D448] # MATHEMATICAL ITALIC CAPITAL U; QQK
+1D47C ; [.11EE.0020.000B.1D47C] # MATHEMATICAL BOLD ITALIC CAPITAL U; QQK
+1D4B0 ; [.11EE.0020.000B.1D4B0] # MATHEMATICAL SCRIPT CAPITAL U; QQK
+1D4E4 ; [.11EE.0020.000B.1D4E4] # MATHEMATICAL BOLD SCRIPT CAPITAL U; QQK
+1D518 ; [.11EE.0020.000B.1D518] # MATHEMATICAL FRAKTUR CAPITAL U; QQK
+1D54C ; [.11EE.0020.000B.1D54C] # MATHEMATICAL DOUBLE-STRUCK CAPITAL U; QQK
+1D580 ; [.11EE.0020.000B.1D580] # MATHEMATICAL BOLD FRAKTUR CAPITAL U; QQK
+1D5B4 ; [.11EE.0020.000B.1D5B4] # MATHEMATICAL SANS-SERIF CAPITAL U; QQK
+1D5E8 ; [.11EE.0020.000B.1D5E8] # MATHEMATICAL SANS-SERIF BOLD CAPITAL U; QQK
+1D61C ; [.11EE.0020.000B.1D61C] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL U; QQK
+1D650 ; [.11EE.0020.000B.1D650] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL U; QQK
+1D684 ; [.11EE.0020.000B.1D684] # MATHEMATICAL MONOSPACE CAPITAL U; QQK
+24CA ; [.11EE.0020.000C.24CA] # CIRCLED LATIN CAPITAL LETTER U; QQK
+1D58 ; [.11EE.0020.0014.1D58] # MODIFIER LETTER SMALL U; QQK
+1D64 ; [.11EE.0020.0015.1D64] # LATIN SUBSCRIPT SMALL LETTER U; QQK
+1D41 ; [.11EE.0020.001D.1D41] # MODIFIER LETTER CAPITAL U; QQK
+00FA ; [.11EE.0020.0002.0075][.0000.0032.0002.0301] # LATIN SMALL LETTER U WITH ACUTE; QQCM
+00DA ; [.11EE.0020.0008.0055][.0000.0032.0002.0301] # LATIN CAPITAL LETTER U WITH ACUTE; QQCM
+00F9 ; [.11EE.0020.0002.0075][.0000.0035.0002.0300] # LATIN SMALL LETTER U WITH GRAVE; QQCM
+00D9 ; [.11EE.0020.0008.0055][.0000.0035.0002.0300] # LATIN CAPITAL LETTER U WITH GRAVE; QQCM
+016D ; [.11EE.0020.0002.0075][.0000.0037.0002.0306] # LATIN SMALL LETTER U WITH BREVE; QQCM
+016C ; [.11EE.0020.0008.0055][.0000.0037.0002.0306] # LATIN CAPITAL LETTER U WITH BREVE; QQCM
+00FB ; [.11EE.0020.0002.0075][.0000.003C.0002.0302] # LATIN SMALL LETTER U WITH CIRCUMFLEX; QQCM
+00DB ; [.11EE.0020.0008.0055][.0000.003C.0002.0302] # LATIN CAPITAL LETTER U WITH CIRCUMFLEX; QQCM
+01D4 ; [.11EE.0020.0002.0075][.0000.0041.0002.030C] # LATIN SMALL LETTER U WITH CARON; QQCM
+01D3 ; [.11EE.0020.0008.0055][.0000.0041.0002.030C] # LATIN CAPITAL LETTER U WITH CARON; QQCM
+016F ; [.11EE.0020.0002.0075][.0000.0043.0002.030A] # LATIN SMALL LETTER U WITH RING ABOVE; QQCM
+016E ; [.11EE.0020.0008.0055][.0000.0043.0002.030A] # LATIN CAPITAL LETTER U WITH RING ABOVE; QQCM
+00FC ; [.11EE.0020.0002.0075][.0000.0047.0002.0308] # LATIN SMALL LETTER U WITH DIAERESIS; QQCM
+00DC ; [.11EE.0020.0008.0055][.0000.0047.0002.0308] # LATIN CAPITAL LETTER U WITH DIAERESIS; QQCM
+01D8 ; [.11EE.0020.0002.0075][.0000.0047.0002.0308][.0000.0032.0002.0301] # LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE; QQCM
+01D7 ; [.11EE.0020.0008.0055][.0000.0047.0002.0308][.0000.0032.0002.0301] # LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE; QQCM
+01DC ; [.11EE.0020.0002.0075][.0000.0047.0002.0308][.0000.0035.0002.0300] # LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE; QQCM
+01DB ; [.11EE.0020.0008.0055][.0000.0047.0002.0308][.0000.0035.0002.0300] # LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE; QQCM
+01DA ; [.11EE.0020.0002.0075][.0000.0047.0002.0308][.0000.0041.0002.030C] # LATIN SMALL LETTER U WITH DIAERESIS AND CARON; QQCM
+01D9 ; [.11EE.0020.0008.0055][.0000.0047.0002.0308][.0000.0041.0002.030C] # LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON; QQCM
+01D6 ; [.11EE.0020.0002.0075][.0000.0047.0002.0308][.0000.005B.0002.0304] # LATIN SMALL LETTER U WITH DIAERESIS AND MACRON; QQCM
+01D5 ; [.11EE.0020.0008.0055][.0000.0047.0002.0308][.0000.005B.0002.0304] # LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON; QQCM
+0171 ; [.11EE.0020.0002.0075][.0000.004D.0002.030B] # LATIN SMALL LETTER U WITH DOUBLE ACUTE; QQCM
+0170 ; [.11EE.0020.0008.0055][.0000.004D.0002.030B] # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE; QQCM
+0169 ; [.11EE.0020.0002.0075][.0000.004E.0002.0303] # LATIN SMALL LETTER U WITH TILDE; QQCM
+0168 ; [.11EE.0020.0008.0055][.0000.004E.0002.0303] # LATIN CAPITAL LETTER U WITH TILDE; QQCM
+1E79 ; [.11EE.0020.0002.0075][.0000.004E.0002.0303][.0000.0032.0002.0301] # LATIN SMALL LETTER U WITH TILDE AND ACUTE; QQCM
+1E78 ; [.11EE.0020.0008.0055][.0000.004E.0002.0303][.0000.0032.0002.0301] # LATIN CAPITAL LETTER U WITH TILDE AND ACUTE; QQCM
+0173 ; [.11EE.0020.0002.0075][.0000.0059.0002.0328] # LATIN SMALL LETTER U WITH OGONEK; QQCM
+0172 ; [.11EE.0020.0008.0055][.0000.0059.0002.0328] # LATIN CAPITAL LETTER U WITH OGONEK; QQCM
+016B ; [.11EE.0020.0002.0075][.0000.005B.0002.0304] # LATIN SMALL LETTER U WITH MACRON; QQCM
+016A ; [.11EE.0020.0008.0055][.0000.005B.0002.0304] # LATIN CAPITAL LETTER U WITH MACRON; QQCM
+1E7B ; [.11EE.0020.0002.0075][.0000.005B.0002.0304][.0000.0047.0002.0308] # LATIN SMALL LETTER U WITH MACRON AND DIAERESIS; QQCM
+1E7A ; [.11EE.0020.0008.0055][.0000.005B.0002.0304][.0000.0047.0002.0308] # LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS; QQCM
+1EE7 ; [.11EE.0020.0002.0075][.0000.0060.0002.0309] # LATIN SMALL LETTER U WITH HOOK ABOVE; QQCM
+1EE6 ; [.11EE.0020.0008.0055][.0000.0060.0002.0309] # LATIN CAPITAL LETTER U WITH HOOK ABOVE; QQCM
+0215 ; [.11EE.0020.0002.0075][.0000.0063.0002.030F] # LATIN SMALL LETTER U WITH DOUBLE GRAVE; QQCM
+0214 ; [.11EE.0020.0008.0055][.0000.0063.0002.030F] # LATIN CAPITAL LETTER U WITH DOUBLE GRAVE; QQCM
+0217 ; [.11EE.0020.0002.0075][.0000.0065.0002.0311] # LATIN SMALL LETTER U WITH INVERTED BREVE; QQCM
+0216 ; [.11EE.0020.0008.0055][.0000.0065.0002.0311] # LATIN CAPITAL LETTER U WITH INVERTED BREVE; QQCM
+01B0 ; [.11EE.0020.0002.0075][.0000.006D.0002.031B] # LATIN SMALL LETTER U WITH HORN; QQCM
+01AF ; [.11EE.0020.0008.0055][.0000.006D.0002.031B] # LATIN CAPITAL LETTER U WITH HORN; QQCM
+1EE9 ; [.11EE.0020.0002.0075][.0000.006D.0002.031B][.0000.0032.0002.0301] # LATIN SMALL LETTER U WITH HORN AND ACUTE; QQCM
+1EE8 ; [.11EE.0020.0008.0055][.0000.006D.0002.031B][.0000.0032.0002.0301] # LATIN CAPITAL LETTER U WITH HORN AND ACUTE; QQCM
+1EEB ; [.11EE.0020.0002.0075][.0000.006D.0002.031B][.0000.0035.0002.0300] # LATIN SMALL LETTER U WITH HORN AND GRAVE; QQCM
+1EEA ; [.11EE.0020.0008.0055][.0000.006D.0002.031B][.0000.0035.0002.0300] # LATIN CAPITAL LETTER U WITH HORN AND GRAVE; QQCM
+1EEF ; [.11EE.0020.0002.0075][.0000.006D.0002.031B][.0000.004E.0002.0303] # LATIN SMALL LETTER U WITH HORN AND TILDE; QQCM
+1EEE ; [.11EE.0020.0008.0055][.0000.006D.0002.031B][.0000.004E.0002.0303] # LATIN CAPITAL LETTER U WITH HORN AND TILDE; QQCM
+1EED ; [.11EE.0020.0002.0075][.0000.006D.0002.031B][.0000.0060.0002.0309] # LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE; QQCM
+1EEC ; [.11EE.0020.0008.0055][.0000.006D.0002.031B][.0000.0060.0002.0309] # LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE; QQCM
+1EF1 ; [.11EE.0020.0002.0075][.0000.006D.0002.031B][.0000.007A.0002.0323] # LATIN SMALL LETTER U WITH HORN AND DOT BELOW; QQCM
+1EF0 ; [.11EE.0020.0008.0055][.0000.006D.0002.031B][.0000.007A.0002.0323] # LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW; QQCM
+1EE5 ; [.11EE.0020.0002.0075][.0000.007A.0002.0323] # LATIN SMALL LETTER U WITH DOT BELOW; QQCM
+1EE4 ; [.11EE.0020.0008.0055][.0000.007A.0002.0323] # LATIN CAPITAL LETTER U WITH DOT BELOW; QQCM
+1E73 ; [.11EE.0020.0002.0075][.0000.007F.0002.0324] # LATIN SMALL LETTER U WITH DIAERESIS BELOW; QQCM
+1E72 ; [.11EE.0020.0008.0055][.0000.007F.0002.0324] # LATIN CAPITAL LETTER U WITH DIAERESIS BELOW; QQCM
+1E77 ; [.11EE.0020.0002.0075][.0000.0086.0002.032D] # LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW; QQCM
+1E76 ; [.11EE.0020.0008.0055][.0000.0086.0002.032D] # LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW; QQCM
+1E75 ; [.11EE.0020.0002.0075][.0000.0089.0002.0330] # LATIN SMALL LETTER U WITH TILDE BELOW; QQCM
+1E74 ; [.11EE.0020.0008.0055][.0000.0089.0002.0330] # LATIN CAPITAL LETTER U WITH TILDE BELOW; QQCM
+1D1C ; [.11F2.0020.0002.1D1C] # LATIN LETTER SMALL CAPITAL U
+1DB8 ; [.11F2.0020.0014.1DB8] # MODIFIER LETTER SMALL CAPITAL U; QQK
+1D1D ; [.11F3.0020.0002.1D1D] # LATIN SMALL LETTER SIDEWAYS U
+1D59 ; [.11F3.0020.0014.1D59] # MODIFIER LETTER SMALL SIDEWAYS U; QQK
+1D1E ; [.11F4.0020.0002.1D1E] # LATIN SMALL LETTER SIDEWAYS DIAERESIZED U
+1D6B ; [.11F5.0020.0002.1D6B] # LATIN SMALL LETTER UE
+0289 ; [.11F6.0020.0002.0289] # LATIN SMALL LETTER U BAR
+0244 ; [.11F6.0020.0008.0244] # LATIN CAPITAL LETTER U BAR
+1DB6 ; [.11F6.0020.0014.1DB6] # MODIFIER LETTER SMALL U BAR; QQK
+1D7E ; [.11FA.0020.0002.1D7E] # LATIN SMALL CAPITAL LETTER U WITH STROKE
+1D99 ; [.11FB.0020.0002.1D99] # LATIN SMALL LETTER U WITH RETROFLEX HOOK
+0265 ; [.11FC.0020.0002.0265] # LATIN SMALL LETTER TURNED H
+1DA3 ; [.11FC.0020.0014.1DA3] # MODIFIER LETTER SMALL TURNED H; QQK
+02AE ; [.1200.0020.0002.02AE] # LATIN SMALL LETTER TURNED H WITH FISHHOOK
+02AF ; [.1204.0020.0002.02AF] # LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL
+026F ; [.1208.0020.0002.026F] # LATIN SMALL LETTER TURNED M
+019C ; [.1208.0020.0008.019C] # LATIN CAPITAL LETTER TURNED M
+1D5A ; [.1208.0020.0014.1D5A] # MODIFIER LETTER SMALL TURNED M; QQK
+1D1F ; [.120C.0020.0002.1D1F] # LATIN SMALL LETTER SIDEWAYS TURNED M
+0270 ; [.120D.0020.0002.0270] # LATIN SMALL LETTER TURNED M WITH LONG LEG
+1DAD ; [.120D.0020.0014.1DAD] # MODIFIER LETTER SMALL TURNED M WITH LONG LEG; QQK
+028A ; [.1211.0020.0002.028A] # LATIN SMALL LETTER UPSILON
+01B1 ; [.1211.0020.0008.01B1] # LATIN CAPITAL LETTER UPSILON
+1DB7 ; [.1211.0020.0014.1DB7] # MODIFIER LETTER SMALL UPSILON; QQK
+1D7F ; [.1215.0020.0002.1D7F] # LATIN SMALL LETTER UPSILON WITH STROKE
+0076 ; [.1216.0020.0002.0076] # LATIN SMALL LETTER V
+FF56 ; [.1216.0020.0003.FF56] # FULLWIDTH LATIN SMALL LETTER V; QQK
+036E ; [.1216.0020.0004.036E] # COMBINING LATIN SMALL LETTER V; QQK
+2174 ; [.1216.0020.0004.2174] # SMALL ROMAN NUMERAL FIVE; QQK
+24B1 ; [*02B1.0020.0004.24B1][.1216.0020.0004.24B1][*02B2.0020.001F.24B1] # PARENTHESIZED LATIN SMALL LETTER V; QQKN
+1D42F ; [.1216.0020.0005.1D42F] # MATHEMATICAL BOLD SMALL V; QQK
+1D463 ; [.1216.0020.0005.1D463] # MATHEMATICAL ITALIC SMALL V; QQK
+1D497 ; [.1216.0020.0005.1D497] # MATHEMATICAL BOLD ITALIC SMALL V; QQK
+1D4CB ; [.1216.0020.0005.1D4CB] # MATHEMATICAL SCRIPT SMALL V; QQK
+1D4FF ; [.1216.0020.0005.1D4FF] # MATHEMATICAL BOLD SCRIPT SMALL V; QQK
+1D533 ; [.1216.0020.0005.1D533] # MATHEMATICAL FRAKTUR SMALL V; QQK
+1D567 ; [.1216.0020.0005.1D567] # MATHEMATICAL DOUBLE-STRUCK SMALL V; QQK
+1D59B ; [.1216.0020.0005.1D59B] # MATHEMATICAL BOLD FRAKTUR SMALL V; QQK
+1D5CF ; [.1216.0020.0005.1D5CF] # MATHEMATICAL SANS-SERIF SMALL V; QQK
+1D603 ; [.1216.0020.0005.1D603] # MATHEMATICAL SANS-SERIF BOLD SMALL V; QQK
+1D637 ; [.1216.0020.0005.1D637] # MATHEMATICAL SANS-SERIF ITALIC SMALL V; QQK
+1D66B ; [.1216.0020.0005.1D66B] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL V; QQK
+1D69F ; [.1216.0020.0005.1D69F] # MATHEMATICAL MONOSPACE SMALL V; QQK
+24E5 ; [.1216.0020.0006.24E5] # CIRCLED LATIN SMALL LETTER V; QQK
+0056 ; [.1216.0020.0008.0056] # LATIN CAPITAL LETTER V
+FF36 ; [.1216.0020.0009.FF36] # FULLWIDTH LATIN CAPITAL LETTER V; QQK
+2164 ; [.1216.0020.000A.2164] # ROMAN NUMERAL FIVE; QQK
+1D415 ; [.1216.0020.000B.1D415] # MATHEMATICAL BOLD CAPITAL V; QQK
+1D449 ; [.1216.0020.000B.1D449] # MATHEMATICAL ITALIC CAPITAL V; QQK
+1D47D ; [.1216.0020.000B.1D47D] # MATHEMATICAL BOLD ITALIC CAPITAL V; QQK
+1D4B1 ; [.1216.0020.000B.1D4B1] # MATHEMATICAL SCRIPT CAPITAL V; QQK
+1D4E5 ; [.1216.0020.000B.1D4E5] # MATHEMATICAL BOLD SCRIPT CAPITAL V; QQK
+1D519 ; [.1216.0020.000B.1D519] # MATHEMATICAL FRAKTUR CAPITAL V; QQK
+1D54D ; [.1216.0020.000B.1D54D] # MATHEMATICAL DOUBLE-STRUCK CAPITAL V; QQK
+1D581 ; [.1216.0020.000B.1D581] # MATHEMATICAL BOLD FRAKTUR CAPITAL V; QQK
+1D5B5 ; [.1216.0020.000B.1D5B5] # MATHEMATICAL SANS-SERIF CAPITAL V; QQK
+1D5E9 ; [.1216.0020.000B.1D5E9] # MATHEMATICAL SANS-SERIF BOLD CAPITAL V; QQK
+1D61D ; [.1216.0020.000B.1D61D] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL V; QQK
+1D651 ; [.1216.0020.000B.1D651] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL V; QQK
+1D685 ; [.1216.0020.000B.1D685] # MATHEMATICAL MONOSPACE CAPITAL V; QQK
+24CB ; [.1216.0020.000C.24CB] # CIRCLED LATIN CAPITAL LETTER V; QQK
+1D5B ; [.1216.0020.0014.1D5B] # MODIFIER LETTER SMALL V; QQK
+1D65 ; [.1216.0020.0015.1D65] # LATIN SUBSCRIPT SMALL LETTER V; QQK
+1E7D ; [.1216.0020.0002.0076][.0000.004E.0002.0303] # LATIN SMALL LETTER V WITH TILDE; QQCM
+1E7C ; [.1216.0020.0008.0056][.0000.004E.0002.0303] # LATIN CAPITAL LETTER V WITH TILDE; QQCM
+1E7F ; [.1216.0020.0002.0076][.0000.007A.0002.0323] # LATIN SMALL LETTER V WITH DOT BELOW; QQCM
+1E7E ; [.1216.0020.0008.0056][.0000.007A.0002.0323] # LATIN CAPITAL LETTER V WITH DOT BELOW; QQCM
+2175 ; [.1216.0020.0004.2175][.10A5.0020.0004.2175] # SMALL ROMAN NUMERAL SIX; QQKN
+2165 ; [.1216.0020.000A.2165][.10A5.0020.000A.2165] # ROMAN NUMERAL SIX; QQKN
+2176 ; [.1216.0020.0004.2176][.10A5.0020.0004.2176][.10A5.0020.001F.2176] # SMALL ROMAN NUMERAL SEVEN; QQKN
+2166 ; [.1216.0020.000A.2166][.10A5.0020.000A.2166][.10A5.0020.001F.2166] # ROMAN NUMERAL SEVEN; QQKN
+2177 ; [.1216.0020.0004.2177][.10A5.0020.0004.2177][.10A5.0020.001F.2177][.10A5.0020.001F.2177] # SMALL ROMAN NUMERAL EIGHT; QQKN
+2167 ; [.1216.0020.000A.2167][.10A5.0020.000A.2167][.10A5.0020.001F.2167][.10A5.0020.001F.2167] # ROMAN NUMERAL EIGHT; QQKN
+33DE ; [.1216.0020.001D.33DE][*04C7.0020.001C.33DE][.1110.0020.001F.33DE] # SQUARE V OVER M; QQKN
+1D20 ; [.121A.0020.0002.1D20] # LATIN LETTER SMALL CAPITAL V
+1D8C ; [.121B.0020.0002.1D8C] # LATIN SMALL LETTER V WITH PALATAL HOOK
+028B ; [.121C.0020.0002.028B] # LATIN SMALL LETTER V WITH HOOK
+01B2 ; [.121C.0020.0008.01B2] # LATIN CAPITAL LETTER V WITH HOOK
+1DB9 ; [.121C.0020.0014.1DB9] # MODIFIER LETTER SMALL V WITH HOOK; QQK
+2C74 ; [.1220.0020.0002.2C74] # LATIN SMALL LETTER V WITH CURL
+028C ; [.1221.0020.0002.028C] # LATIN SMALL LETTER TURNED V
+0245 ; [.1221.0020.0008.0245] # LATIN CAPITAL LETTER TURNED V
+1DBA ; [.1221.0020.0014.1DBA] # MODIFIER LETTER SMALL TURNED V; QQK
+0077 ; [.1225.0020.0002.0077] # LATIN SMALL LETTER W
+FF57 ; [.1225.0020.0003.FF57] # FULLWIDTH LATIN SMALL LETTER W; QQK
+24B2 ; [*02B1.0020.0004.24B2][.1225.0020.0004.24B2][*02B2.0020.001F.24B2] # PARENTHESIZED LATIN SMALL LETTER W; QQKN
+1D430 ; [.1225.0020.0005.1D430] # MATHEMATICAL BOLD SMALL W; QQK
+1D464 ; [.1225.0020.0005.1D464] # MATHEMATICAL ITALIC SMALL W; QQK
+1D498 ; [.1225.0020.0005.1D498] # MATHEMATICAL BOLD ITALIC SMALL W; QQK
+1D4CC ; [.1225.0020.0005.1D4CC] # MATHEMATICAL SCRIPT SMALL W; QQK
+1D500 ; [.1225.0020.0005.1D500] # MATHEMATICAL BOLD SCRIPT SMALL W; QQK
+1D534 ; [.1225.0020.0005.1D534] # MATHEMATICAL FRAKTUR SMALL W; QQK
+1D568 ; [.1225.0020.0005.1D568] # MATHEMATICAL DOUBLE-STRUCK SMALL W; QQK
+1D59C ; [.1225.0020.0005.1D59C] # MATHEMATICAL BOLD FRAKTUR SMALL W; QQK
+1D5D0 ; [.1225.0020.0005.1D5D0] # MATHEMATICAL SANS-SERIF SMALL W; QQK
+1D604 ; [.1225.0020.0005.1D604] # MATHEMATICAL SANS-SERIF BOLD SMALL W; QQK
+1D638 ; [.1225.0020.0005.1D638] # MATHEMATICAL SANS-SERIF ITALIC SMALL W; QQK
+1D66C ; [.1225.0020.0005.1D66C] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL W; QQK
+1D6A0 ; [.1225.0020.0005.1D6A0] # MATHEMATICAL MONOSPACE SMALL W; QQK
+24E6 ; [.1225.0020.0006.24E6] # CIRCLED LATIN SMALL LETTER W; QQK
+0057 ; [.1225.0020.0008.0057] # LATIN CAPITAL LETTER W
+FF37 ; [.1225.0020.0009.FF37] # FULLWIDTH LATIN CAPITAL LETTER W; QQK
+1D416 ; [.1225.0020.000B.1D416] # MATHEMATICAL BOLD CAPITAL W; QQK
+1D44A ; [.1225.0020.000B.1D44A] # MATHEMATICAL ITALIC CAPITAL W; QQK
+1D47E ; [.1225.0020.000B.1D47E] # MATHEMATICAL BOLD ITALIC CAPITAL W; QQK
+1D4B2 ; [.1225.0020.000B.1D4B2] # MATHEMATICAL SCRIPT CAPITAL W; QQK
+1D4E6 ; [.1225.0020.000B.1D4E6] # MATHEMATICAL BOLD SCRIPT CAPITAL W; QQK
+1D51A ; [.1225.0020.000B.1D51A] # MATHEMATICAL FRAKTUR CAPITAL W; QQK
+1D54E ; [.1225.0020.000B.1D54E] # MATHEMATICAL DOUBLE-STRUCK CAPITAL W; QQK
+1D582 ; [.1225.0020.000B.1D582] # MATHEMATICAL BOLD FRAKTUR CAPITAL W; QQK
+1D5B6 ; [.1225.0020.000B.1D5B6] # MATHEMATICAL SANS-SERIF CAPITAL W; QQK
+1D5EA ; [.1225.0020.000B.1D5EA] # MATHEMATICAL SANS-SERIF BOLD CAPITAL W; QQK
+1D61E ; [.1225.0020.000B.1D61E] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL W; QQK
+1D652 ; [.1225.0020.000B.1D652] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL W; QQK
+1D686 ; [.1225.0020.000B.1D686] # MATHEMATICAL MONOSPACE CAPITAL W; QQK
+24CC ; [.1225.0020.000C.24CC] # CIRCLED LATIN CAPITAL LETTER W; QQK
+02B7 ; [.1225.0020.0014.02B7] # MODIFIER LETTER SMALL W; QQK
+1D42 ; [.1225.0020.001D.1D42] # MODIFIER LETTER CAPITAL W; QQK
+1E83 ; [.1225.0020.0002.0077][.0000.0032.0002.0301] # LATIN SMALL LETTER W WITH ACUTE; QQCM
+1E82 ; [.1225.0020.0008.0057][.0000.0032.0002.0301] # LATIN CAPITAL LETTER W WITH ACUTE; QQCM
+1E81 ; [.1225.0020.0002.0077][.0000.0035.0002.0300] # LATIN SMALL LETTER W WITH GRAVE; QQCM
+1E80 ; [.1225.0020.0008.0057][.0000.0035.0002.0300] # LATIN CAPITAL LETTER W WITH GRAVE; QQCM
+0175 ; [.1225.0020.0002.0077][.0000.003C.0002.0302] # LATIN SMALL LETTER W WITH CIRCUMFLEX; QQCM
+0174 ; [.1225.0020.0008.0057][.0000.003C.0002.0302] # LATIN CAPITAL LETTER W WITH CIRCUMFLEX; QQCM
+1E98 ; [.1225.0020.0002.0077][.0000.0043.0002.030A] # LATIN SMALL LETTER W WITH RING ABOVE; QQCM
+1E85 ; [.1225.0020.0002.0077][.0000.0047.0002.0308] # LATIN SMALL LETTER W WITH DIAERESIS; QQCM
+1E84 ; [.1225.0020.0008.0057][.0000.0047.0002.0308] # LATIN CAPITAL LETTER W WITH DIAERESIS; QQCM
+1E87 ; [.1225.0020.0002.0077][.0000.0052.0002.0307] # LATIN SMALL LETTER W WITH DOT ABOVE; QQCM
+1E86 ; [.1225.0020.0008.0057][.0000.0052.0002.0307] # LATIN CAPITAL LETTER W WITH DOT ABOVE; QQCM
+1E89 ; [.1225.0020.0002.0077][.0000.007A.0002.0323] # LATIN SMALL LETTER W WITH DOT BELOW; QQCM
+1E88 ; [.1225.0020.0008.0057][.0000.007A.0002.0323] # LATIN CAPITAL LETTER W WITH DOT BELOW; QQCM
+33DD ; [.1225.0020.001D.33DD][.0FE6.0020.001C.33DD] # SQUARE WB; QQKN
+1D21 ; [.1229.0020.0002.1D21] # LATIN LETTER SMALL CAPITAL W
+028D ; [.122A.0020.0002.028D] # LATIN SMALL LETTER TURNED W
+0078 ; [.122E.0020.0002.0078] # LATIN SMALL LETTER X
+FF58 ; [.122E.0020.0003.FF58] # FULLWIDTH LATIN SMALL LETTER X; QQK
+036F ; [.122E.0020.0004.036F] # COMBINING LATIN SMALL LETTER X; QQK
+2179 ; [.122E.0020.0004.2179] # SMALL ROMAN NUMERAL TEN; QQK
+24B3 ; [*02B1.0020.0004.24B3][.122E.0020.0004.24B3][*02B2.0020.001F.24B3] # PARENTHESIZED LATIN SMALL LETTER X; QQKN
+1D431 ; [.122E.0020.0005.1D431] # MATHEMATICAL BOLD SMALL X; QQK
+1D465 ; [.122E.0020.0005.1D465] # MATHEMATICAL ITALIC SMALL X; QQK
+1D499 ; [.122E.0020.0005.1D499] # MATHEMATICAL BOLD ITALIC SMALL X; QQK
+1D4CD ; [.122E.0020.0005.1D4CD] # MATHEMATICAL SCRIPT SMALL X; QQK
+1D501 ; [.122E.0020.0005.1D501] # MATHEMATICAL BOLD SCRIPT SMALL X; QQK
+1D535 ; [.122E.0020.0005.1D535] # MATHEMATICAL FRAKTUR SMALL X; QQK
+1D569 ; [.122E.0020.0005.1D569] # MATHEMATICAL DOUBLE-STRUCK SMALL X; QQK
+1D59D ; [.122E.0020.0005.1D59D] # MATHEMATICAL BOLD FRAKTUR SMALL X; QQK
+1D5D1 ; [.122E.0020.0005.1D5D1] # MATHEMATICAL SANS-SERIF SMALL X; QQK
+1D605 ; [.122E.0020.0005.1D605] # MATHEMATICAL SANS-SERIF BOLD SMALL X; QQK
+1D639 ; [.122E.0020.0005.1D639] # MATHEMATICAL SANS-SERIF ITALIC SMALL X; QQK
+1D66D ; [.122E.0020.0005.1D66D] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL X; QQK
+1D6A1 ; [.122E.0020.0005.1D6A1] # MATHEMATICAL MONOSPACE SMALL X; QQK
+24E7 ; [.122E.0020.0006.24E7] # CIRCLED LATIN SMALL LETTER X; QQK
+0058 ; [.122E.0020.0008.0058] # LATIN CAPITAL LETTER X
+FF38 ; [.122E.0020.0009.FF38] # FULLWIDTH LATIN CAPITAL LETTER X; QQK
+2169 ; [.122E.0020.000A.2169] # ROMAN NUMERAL TEN; QQK
+1D417 ; [.122E.0020.000B.1D417] # MATHEMATICAL BOLD CAPITAL X; QQK
+1D44B ; [.122E.0020.000B.1D44B] # MATHEMATICAL ITALIC CAPITAL X; QQK
+1D47F ; [.122E.0020.000B.1D47F] # MATHEMATICAL BOLD ITALIC CAPITAL X; QQK
+1D4B3 ; [.122E.0020.000B.1D4B3] # MATHEMATICAL SCRIPT CAPITAL X; QQK
+1D4E7 ; [.122E.0020.000B.1D4E7] # MATHEMATICAL BOLD SCRIPT CAPITAL X; QQK
+1D51B ; [.122E.0020.000B.1D51B] # MATHEMATICAL FRAKTUR CAPITAL X; QQK
+1D54F ; [.122E.0020.000B.1D54F] # MATHEMATICAL DOUBLE-STRUCK CAPITAL X; QQK
+1D583 ; [.122E.0020.000B.1D583] # MATHEMATICAL BOLD FRAKTUR CAPITAL X; QQK
+1D5B7 ; [.122E.0020.000B.1D5B7] # MATHEMATICAL SANS-SERIF CAPITAL X; QQK
+1D5EB ; [.122E.0020.000B.1D5EB] # MATHEMATICAL SANS-SERIF BOLD CAPITAL X; QQK
+1D61F ; [.122E.0020.000B.1D61F] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL X; QQK
+1D653 ; [.122E.0020.000B.1D653] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL X; QQK
+1D687 ; [.122E.0020.000B.1D687] # MATHEMATICAL MONOSPACE CAPITAL X; QQK
+24CD ; [.122E.0020.000C.24CD] # CIRCLED LATIN CAPITAL LETTER X; QQK
+02E3 ; [.122E.0020.0014.02E3] # MODIFIER LETTER SMALL X; QQK
+2093 ; [.122E.0020.0015.2093] # LATIN SUBSCRIPT SMALL LETTER X; QQK
+1E8D ; [.122E.0020.0002.0078][.0000.0047.0002.0308] # LATIN SMALL LETTER X WITH DIAERESIS; QQCM
+1E8C ; [.122E.0020.0008.0058][.0000.0047.0002.0308] # LATIN CAPITAL LETTER X WITH DIAERESIS; QQCM
+1E8B ; [.122E.0020.0002.0078][.0000.0052.0002.0307] # LATIN SMALL LETTER X WITH DOT ABOVE; QQCM
+1E8A ; [.122E.0020.0008.0058][.0000.0052.0002.0307] # LATIN CAPITAL LETTER X WITH DOT ABOVE; QQCM
+217A ; [.122E.0020.0004.217A][.10A5.0020.0004.217A] # SMALL ROMAN NUMERAL ELEVEN; QQKN
+216A ; [.122E.0020.000A.216A][.10A5.0020.000A.216A] # ROMAN NUMERAL ELEVEN; QQKN
+217B ; [.122E.0020.0004.217B][.10A5.0020.0004.217B][.10A5.0020.001F.217B] # SMALL ROMAN NUMERAL TWELVE; QQKN
+216B ; [.122E.0020.000A.216B][.10A5.0020.000A.216B][.10A5.0020.001F.216B] # ROMAN NUMERAL TWELVE; QQKN
+1D8D ; [.1232.0020.0002.1D8D] # LATIN SMALL LETTER X WITH PALATAL HOOK
+0079 ; [.1233.0020.0002.0079] # LATIN SMALL LETTER Y
+FF59 ; [.1233.0020.0003.FF59] # FULLWIDTH LATIN SMALL LETTER Y; QQK
+24B4 ; [*02B1.0020.0004.24B4][.1233.0020.0004.24B4][*02B2.0020.001F.24B4] # PARENTHESIZED LATIN SMALL LETTER Y; QQKN
+1D432 ; [.1233.0020.0005.1D432] # MATHEMATICAL BOLD SMALL Y; QQK
+1D466 ; [.1233.0020.0005.1D466] # MATHEMATICAL ITALIC SMALL Y; QQK
+1D49A ; [.1233.0020.0005.1D49A] # MATHEMATICAL BOLD ITALIC SMALL Y; QQK
+1D4CE ; [.1233.0020.0005.1D4CE] # MATHEMATICAL SCRIPT SMALL Y; QQK
+1D502 ; [.1233.0020.0005.1D502] # MATHEMATICAL BOLD SCRIPT SMALL Y; QQK
+1D536 ; [.1233.0020.0005.1D536] # MATHEMATICAL FRAKTUR SMALL Y; QQK
+1D56A ; [.1233.0020.0005.1D56A] # MATHEMATICAL DOUBLE-STRUCK SMALL Y; QQK
+1D59E ; [.1233.0020.0005.1D59E] # MATHEMATICAL BOLD FRAKTUR SMALL Y; QQK
+1D5D2 ; [.1233.0020.0005.1D5D2] # MATHEMATICAL SANS-SERIF SMALL Y; QQK
+1D606 ; [.1233.0020.0005.1D606] # MATHEMATICAL SANS-SERIF BOLD SMALL Y; QQK
+1D63A ; [.1233.0020.0005.1D63A] # MATHEMATICAL SANS-SERIF ITALIC SMALL Y; QQK
+1D66E ; [.1233.0020.0005.1D66E] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Y; QQK
+1D6A2 ; [.1233.0020.0005.1D6A2] # MATHEMATICAL MONOSPACE SMALL Y; QQK
+24E8 ; [.1233.0020.0006.24E8] # CIRCLED LATIN SMALL LETTER Y; QQK
+0059 ; [.1233.0020.0008.0059] # LATIN CAPITAL LETTER Y
+FF39 ; [.1233.0020.0009.FF39] # FULLWIDTH LATIN CAPITAL LETTER Y; QQK
+1D418 ; [.1233.0020.000B.1D418] # MATHEMATICAL BOLD CAPITAL Y; QQK
+1D44C ; [.1233.0020.000B.1D44C] # MATHEMATICAL ITALIC CAPITAL Y; QQK
+1D480 ; [.1233.0020.000B.1D480] # MATHEMATICAL BOLD ITALIC CAPITAL Y; QQK
+1D4B4 ; [.1233.0020.000B.1D4B4] # MATHEMATICAL SCRIPT CAPITAL Y; QQK
+1D4E8 ; [.1233.0020.000B.1D4E8] # MATHEMATICAL BOLD SCRIPT CAPITAL Y; QQK
+1D51C ; [.1233.0020.000B.1D51C] # MATHEMATICAL FRAKTUR CAPITAL Y; QQK
+1D550 ; [.1233.0020.000B.1D550] # MATHEMATICAL DOUBLE-STRUCK CAPITAL Y; QQK
+1D584 ; [.1233.0020.000B.1D584] # MATHEMATICAL BOLD FRAKTUR CAPITAL Y; QQK
+1D5B8 ; [.1233.0020.000B.1D5B8] # MATHEMATICAL SANS-SERIF CAPITAL Y; QQK
+1D5EC ; [.1233.0020.000B.1D5EC] # MATHEMATICAL SANS-SERIF BOLD CAPITAL Y; QQK
+1D620 ; [.1233.0020.000B.1D620] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL Y; QQK
+1D654 ; [.1233.0020.000B.1D654] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Y; QQK
+1D688 ; [.1233.0020.000B.1D688] # MATHEMATICAL MONOSPACE CAPITAL Y; QQK
+24CE ; [.1233.0020.000C.24CE] # CIRCLED LATIN CAPITAL LETTER Y; QQK
+02B8 ; [.1233.0020.0014.02B8] # MODIFIER LETTER SMALL Y; QQK
+00FD ; [.1233.0020.0002.0079][.0000.0032.0002.0301] # LATIN SMALL LETTER Y WITH ACUTE; QQCM
+00DD ; [.1233.0020.0008.0059][.0000.0032.0002.0301] # LATIN CAPITAL LETTER Y WITH ACUTE; QQCM
+1EF3 ; [.1233.0020.0002.0079][.0000.0035.0002.0300] # LATIN SMALL LETTER Y WITH GRAVE; QQCM
+1EF2 ; [.1233.0020.0008.0059][.0000.0035.0002.0300] # LATIN CAPITAL LETTER Y WITH GRAVE; QQCM
+0177 ; [.1233.0020.0002.0079][.0000.003C.0002.0302] # LATIN SMALL LETTER Y WITH CIRCUMFLEX; QQCM
+0176 ; [.1233.0020.0008.0059][.0000.003C.0002.0302] # LATIN CAPITAL LETTER Y WITH CIRCUMFLEX; QQCM
+1E99 ; [.1233.0020.0002.0079][.0000.0043.0002.030A] # LATIN SMALL LETTER Y WITH RING ABOVE; QQCM
+00FF ; [.1233.0020.0002.0079][.0000.0047.0002.0308] # LATIN SMALL LETTER Y WITH DIAERESIS; QQCM
+0178 ; [.1233.0020.0008.0059][.0000.0047.0002.0308] # LATIN CAPITAL LETTER Y WITH DIAERESIS; QQCM
+1EF9 ; [.1233.0020.0002.0079][.0000.004E.0002.0303] # LATIN SMALL LETTER Y WITH TILDE; QQCM
+1EF8 ; [.1233.0020.0008.0059][.0000.004E.0002.0303] # LATIN CAPITAL LETTER Y WITH TILDE; QQCM
+1E8F ; [.1233.0020.0002.0079][.0000.0052.0002.0307] # LATIN SMALL LETTER Y WITH DOT ABOVE; QQCM
+1E8E ; [.1233.0020.0008.0059][.0000.0052.0002.0307] # LATIN CAPITAL LETTER Y WITH DOT ABOVE; QQCM
+0233 ; [.1233.0020.0002.0079][.0000.005B.0002.0304] # LATIN SMALL LETTER Y WITH MACRON; QQCM
+0232 ; [.1233.0020.0008.0059][.0000.005B.0002.0304] # LATIN CAPITAL LETTER Y WITH MACRON; QQCM
+1EF7 ; [.1233.0020.0002.0079][.0000.0060.0002.0309] # LATIN SMALL LETTER Y WITH HOOK ABOVE; QQCM
+1EF6 ; [.1233.0020.0008.0059][.0000.0060.0002.0309] # LATIN CAPITAL LETTER Y WITH HOOK ABOVE; QQCM
+1EF5 ; [.1233.0020.0002.0079][.0000.007A.0002.0323] # LATIN SMALL LETTER Y WITH DOT BELOW; QQCM
+1EF4 ; [.1233.0020.0008.0059][.0000.007A.0002.0323] # LATIN CAPITAL LETTER Y WITH DOT BELOW; QQCM
+028F ; [.1237.0020.0002.028F] # LATIN LETTER SMALL CAPITAL Y
+024F ; [.123B.0020.0002.024F] # LATIN SMALL LETTER Y WITH STROKE
+024E ; [.123B.0020.0008.024E] # LATIN CAPITAL LETTER Y WITH STROKE
+01B4 ; [.123F.0020.0002.01B4] # LATIN SMALL LETTER Y WITH HOOK
+01B3 ; [.123F.0020.0008.01B3] # LATIN CAPITAL LETTER Y WITH HOOK
+007A ; [.1243.0020.0002.007A] # LATIN SMALL LETTER Z
+FF5A ; [.1243.0020.0003.FF5A] # FULLWIDTH LATIN SMALL LETTER Z; QQK
+24B5 ; [*02B1.0020.0004.24B5][.1243.0020.0004.24B5][*02B2.0020.001F.24B5] # PARENTHESIZED LATIN SMALL LETTER Z; QQKN
+1D433 ; [.1243.0020.0005.1D433] # MATHEMATICAL BOLD SMALL Z; QQK
+1D467 ; [.1243.0020.0005.1D467] # MATHEMATICAL ITALIC SMALL Z; QQK
+1D49B ; [.1243.0020.0005.1D49B] # MATHEMATICAL BOLD ITALIC SMALL Z; QQK
+1D4CF ; [.1243.0020.0005.1D4CF] # MATHEMATICAL SCRIPT SMALL Z; QQK
+1D503 ; [.1243.0020.0005.1D503] # MATHEMATICAL BOLD SCRIPT SMALL Z; QQK
+1D537 ; [.1243.0020.0005.1D537] # MATHEMATICAL FRAKTUR SMALL Z; QQK
+1D56B ; [.1243.0020.0005.1D56B] # MATHEMATICAL DOUBLE-STRUCK SMALL Z; QQK
+1D59F ; [.1243.0020.0005.1D59F] # MATHEMATICAL BOLD FRAKTUR SMALL Z; QQK
+1D5D3 ; [.1243.0020.0005.1D5D3] # MATHEMATICAL SANS-SERIF SMALL Z; QQK
+1D607 ; [.1243.0020.0005.1D607] # MATHEMATICAL SANS-SERIF BOLD SMALL Z; QQK
+1D63B ; [.1243.0020.0005.1D63B] # MATHEMATICAL SANS-SERIF ITALIC SMALL Z; QQK
+1D66F ; [.1243.0020.0005.1D66F] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL Z; QQK
+1D6A3 ; [.1243.0020.0005.1D6A3] # MATHEMATICAL MONOSPACE SMALL Z; QQK
+24E9 ; [.1243.0020.0006.24E9] # CIRCLED LATIN SMALL LETTER Z; QQK
+005A ; [.1243.0020.0008.005A] # LATIN CAPITAL LETTER Z
+FF3A ; [.1243.0020.0009.FF3A] # FULLWIDTH LATIN CAPITAL LETTER Z; QQK
+2124 ; [.1243.0020.000B.2124] # DOUBLE-STRUCK CAPITAL Z; QQK
+2128 ; [.1243.0020.000B.2128] # BLACK-LETTER CAPITAL Z; QQK
+1D419 ; [.1243.0020.000B.1D419] # MATHEMATICAL BOLD CAPITAL Z; QQK
+1D44D ; [.1243.0020.000B.1D44D] # MATHEMATICAL ITALIC CAPITAL Z; QQK
+1D481 ; [.1243.0020.000B.1D481] # MATHEMATICAL BOLD ITALIC CAPITAL Z; QQK
+1D4B5 ; [.1243.0020.000B.1D4B5] # MATHEMATICAL SCRIPT CAPITAL Z; QQK
+1D4E9 ; [.1243.0020.000B.1D4E9] # MATHEMATICAL BOLD SCRIPT CAPITAL Z; QQK
+1D585 ; [.1243.0020.000B.1D585] # MATHEMATICAL BOLD FRAKTUR CAPITAL Z; QQK
+1D5B9 ; [.1243.0020.000B.1D5B9] # MATHEMATICAL SANS-SERIF CAPITAL Z; QQK
+1D5ED ; [.1243.0020.000B.1D5ED] # MATHEMATICAL SANS-SERIF BOLD CAPITAL Z; QQK
+1D621 ; [.1243.0020.000B.1D621] # MATHEMATICAL SANS-SERIF ITALIC CAPITAL Z; QQK
+1D655 ; [.1243.0020.000B.1D655] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL Z; QQK
+1D689 ; [.1243.0020.000B.1D689] # MATHEMATICAL MONOSPACE CAPITAL Z; QQK
+24CF ; [.1243.0020.000C.24CF] # CIRCLED LATIN CAPITAL LETTER Z; QQK
+1DBB ; [.1243.0020.0014.1DBB] # MODIFIER LETTER SMALL Z; QQK
+017A ; [.1243.0020.0002.007A][.0000.0032.0002.0301] # LATIN SMALL LETTER Z WITH ACUTE; QQCM
+0179 ; [.1243.0020.0008.005A][.0000.0032.0002.0301] # LATIN CAPITAL LETTER Z WITH ACUTE; QQCM
+1E91 ; [.1243.0020.0002.007A][.0000.003C.0002.0302] # LATIN SMALL LETTER Z WITH CIRCUMFLEX; QQCM
+1E90 ; [.1243.0020.0008.005A][.0000.003C.0002.0302] # LATIN CAPITAL LETTER Z WITH CIRCUMFLEX; QQCM
+017E ; [.1243.0020.0002.007A][.0000.0041.0002.030C] # LATIN SMALL LETTER Z WITH CARON; QQCM
+017D ; [.1243.0020.0008.005A][.0000.0041.0002.030C] # LATIN CAPITAL LETTER Z WITH CARON; QQCM
+017C ; [.1243.0020.0002.007A][.0000.0052.0002.0307] # LATIN SMALL LETTER Z WITH DOT ABOVE; QQCM
+017B ; [.1243.0020.0008.005A][.0000.0052.0002.0307] # LATIN CAPITAL LETTER Z WITH DOT ABOVE; QQCM
+1E93 ; [.1243.0020.0002.007A][.0000.007A.0002.0323] # LATIN SMALL LETTER Z WITH DOT BELOW; QQCM
+1E92 ; [.1243.0020.0008.005A][.0000.007A.0002.0323] # LATIN CAPITAL LETTER Z WITH DOT BELOW; QQCM
+1E95 ; [.1243.0020.0002.007A][.0000.008A.0002.0331] # LATIN SMALL LETTER Z WITH LINE BELOW; QQCM
+1E94 ; [.1243.0020.0008.005A][.0000.008A.0002.0331] # LATIN CAPITAL LETTER Z WITH LINE BELOW; QQCM
+018D ; [.1243.0020.0004.018D][.1225.0020.0004.018D] # LATIN SMALL LETTER TURNED DELTA; QQKN
+1D22 ; [.1247.0020.0002.1D22] # LATIN LETTER SMALL CAPITAL Z
+01B6 ; [.1248.0020.0002.01B6] # LATIN SMALL LETTER Z WITH STROKE
+01B5 ; [.1248.0020.0008.01B5] # LATIN CAPITAL LETTER Z WITH STROKE
+1D76 ; [.124C.0020.0002.1D76] # LATIN SMALL LETTER Z WITH MIDDLE TILDE
+1D8E ; [.124D.0020.0002.1D8E] # LATIN SMALL LETTER Z WITH PALATAL HOOK
+0225 ; [.124E.0020.0002.0225] # LATIN SMALL LETTER Z WITH HOOK
+0224 ; [.124E.0020.0008.0224] # LATIN CAPITAL LETTER Z WITH HOOK
+0290 ; [.1252.0020.0002.0290] # LATIN SMALL LETTER Z WITH RETROFLEX HOOK
+1DBC ; [.1252.0020.0014.1DBC] # MODIFIER LETTER SMALL Z WITH RETROFLEX HOOK; QQK
+0291 ; [.1256.0020.0002.0291] # LATIN SMALL LETTER Z WITH CURL
+1DBD ; [.1256.0020.0014.1DBD] # MODIFIER LETTER SMALL Z WITH CURL; QQK
+0240 ; [.125A.0020.0002.0240] # LATIN SMALL LETTER Z WITH SWASH TAIL
+2C6C ; [.125E.0020.0002.2C6C] # LATIN SMALL LETTER Z WITH DESCENDER
+2C6B ; [.125E.0020.0008.2C6B] # LATIN CAPITAL LETTER Z WITH DESCENDER
+0292 ; [.125F.0020.0002.0292] # LATIN SMALL LETTER EZH
+01B7 ; [.125F.0020.0008.01B7] # LATIN CAPITAL LETTER EZH
+1DBE ; [.125F.0020.0014.1DBE] # MODIFIER LETTER SMALL EZH; QQK
+01EF ; [.125F.0020.0002.0292][.0000.0041.0002.030C] # LATIN SMALL LETTER EZH WITH CARON; QQCM
+01EE ; [.125F.0020.0008.01B7][.0000.0041.0002.030C] # LATIN CAPITAL LETTER EZH WITH CARON; QQCM
+1D23 ; [.1263.0020.0002.1D23] # LATIN LETTER SMALL CAPITAL EZH
+01B9 ; [.1264.0020.0002.01B9] # LATIN SMALL LETTER EZH REVERSED
+01B8 ; [.1264.0020.0008.01B8] # LATIN CAPITAL LETTER EZH REVERSED
+1D9A ; [.1268.0020.0002.1D9A] # LATIN SMALL LETTER EZH WITH RETROFLEX HOOK
+01BA ; [.1269.0020.0002.01BA] # LATIN SMALL LETTER EZH WITH TAIL
+0293 ; [.126D.0020.0002.0293] # LATIN SMALL LETTER EZH WITH CURL
+021D ; [.1271.0020.0002.021D] # LATIN SMALL LETTER YOGH
+021C ; [.1271.0020.0008.021C] # LATIN CAPITAL LETTER YOGH
+00FE ; [.1275.0020.0002.00FE] # LATIN SMALL LETTER THORN
+00DE ; [.1275.0020.0008.00DE] # LATIN CAPITAL LETTER THORN
+01BF ; [.1279.0020.0002.01BF] # LATIN LETTER WYNN
+01F7 ; [.1279.0020.0008.01F7] # LATIN CAPITAL LETTER WYNN
+01BB ; [.127D.0020.0002.01BB] # LATIN LETTER TWO WITH STROKE
+01A8 ; [.1281.0020.0002.01A8] # LATIN SMALL LETTER TONE TWO
+01A7 ; [.1281.0020.0008.01A7] # LATIN CAPITAL LETTER TONE TWO
+01BD ; [.1285.0020.0002.01BD] # LATIN SMALL LETTER TONE FIVE
+01BC ; [.1285.0020.0008.01BC] # LATIN CAPITAL LETTER TONE FIVE
+0185 ; [.1289.0020.0002.0185] # LATIN SMALL LETTER TONE SIX
+0184 ; [.1289.0020.0008.0184] # LATIN CAPITAL LETTER TONE SIX
+0294 ; [.128D.0020.0002.0294] # LATIN LETTER GLOTTAL STOP
+0242 ; [.1291.0020.0002.0242] # LATIN SMALL LETTER GLOTTAL STOP
+0241 ; [.1291.0020.0008.0241] # LATIN CAPITAL LETTER GLOTTAL STOP
+02C0 ; [.1295.0020.0002.02C0] # MODIFIER LETTER GLOTTAL STOP
+02BC ; [.1296.0020.0002.02BC] # MODIFIER LETTER APOSTROPHE
+0149 ; [.1296.0020.0004.0149][.111B.0020.0004.0149] # LATIN SMALL LETTER N PRECEDED BY APOSTROPHE; QQKN
+02EE ; [.1297.0020.0002.02EE] # MODIFIER LETTER DOUBLE APOSTROPHE
+02BE ; [.1298.0020.0002.02BE] # MODIFIER LETTER RIGHT HALF RING
+0295 ; [.1299.0020.0002.0295] # LATIN LETTER PHARYNGEAL VOICED FRICATIVE
+02E4 ; [.1299.0020.0014.02E4] # MODIFIER LETTER SMALL REVERSED GLOTTAL STOP; QQK
+02BF ; [.129D.0020.0002.02BF] # MODIFIER LETTER LEFT HALF RING
+02C1 ; [.129E.0020.0002.02C1] # MODIFIER LETTER REVERSED GLOTTAL STOP
+1D24 ; [.129F.0020.0002.1D24] # LATIN LETTER VOICED LARYNGEAL SPIRANT
+1D25 ; [.12A0.0020.0002.1D25] # LATIN LETTER AIN
+1D5C ; [.12A0.0020.0014.1D5C] # MODIFIER LETTER SMALL AIN; QQK
+02A1 ; [.12A1.0020.0002.02A1] # LATIN LETTER GLOTTAL STOP WITH STROKE
+02A2 ; [.12A5.0020.0002.02A2] # LATIN LETTER REVERSED GLOTTAL STOP WITH STROKE
+0296 ; [.12A9.0020.0002.0296] # LATIN LETTER INVERTED GLOTTAL STOP
+01C0 ; [.12AD.0020.0002.01C0] # LATIN LETTER DENTAL CLICK
+01C1 ; [.12B1.0020.0002.01C1] # LATIN LETTER LATERAL CLICK
+01C2 ; [.12B5.0020.0002.01C2] # LATIN LETTER ALVEOLAR CLICK
+01C3 ; [.12B9.0020.0002.01C3] # LATIN LETTER RETROFLEX CLICK
+0297 ; [.12BD.0020.0002.0297] # LATIN LETTER STRETCHED C
+0298 ; [.12C1.0020.0002.0298] # LATIN LETTER BILABIAL CLICK
+02AC ; [.12C5.0020.0002.02AC] # LATIN LETTER BILABIAL PERCUSSIVE
+02AD ; [.12C9.0020.0002.02AD] # LATIN LETTER BIDENTAL PERCUSSIVE
+03B1 ; [.12CD.0020.0002.03B1] # GREEK SMALL LETTER ALPHA
+1D6C2 ; [.12CD.0020.0005.1D6C2] # MATHEMATICAL BOLD SMALL ALPHA; QQK
+1D6FC ; [.12CD.0020.0005.1D6FC] # MATHEMATICAL ITALIC SMALL ALPHA; QQK
+1D736 ; [.12CD.0020.0005.1D736] # MATHEMATICAL BOLD ITALIC SMALL ALPHA; QQK
+1D770 ; [.12CD.0020.0005.1D770] # MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA; QQK
+1D7AA ; [.12CD.0020.0005.1D7AA] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA; QQK
+0391 ; [.12CD.0020.0008.0391] # GREEK CAPITAL LETTER ALPHA
+1D6A8 ; [.12CD.0020.000B.1D6A8] # MATHEMATICAL BOLD CAPITAL ALPHA; QQK
+1D6E2 ; [.12CD.0020.000B.1D6E2] # MATHEMATICAL ITALIC CAPITAL ALPHA; QQK
+1D71C ; [.12CD.0020.000B.1D71C] # MATHEMATICAL BOLD ITALIC CAPITAL ALPHA; QQK
+1D756 ; [.12CD.0020.000B.1D756] # MATHEMATICAL SANS-SERIF BOLD CAPITAL ALPHA; QQK
+1D790 ; [.12CD.0020.000B.1D790] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ALPHA; QQK
+1F00 ; [.12CD.0020.0002.03B1][.0000.0022.0002.0313] # GREEK SMALL LETTER ALPHA WITH PSILI; QQCM
+1F08 ; [.12CD.0020.0008.0391][.0000.0022.0002.0313] # GREEK CAPITAL LETTER ALPHA WITH PSILI; QQCM
+1F04 ; [.12CD.0020.0002.03B1][.0000.0022.0002.0313][.0000.0032.0002.0301] # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA; QQCM
+1F0C ; [.12CD.0020.0008.0391][.0000.0022.0002.0313][.0000.0032.0002.0301] # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA; QQCM
+1F84 ; [.12CD.0020.0002.03B1][.0000.0022.0002.0313][.0000.0032.0002.0301][.0000.0097.0002.0345] # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI; QQCM
+1F8C ; [.12CD.0020.0008.0391][.0000.0022.0002.0313][.0000.0032.0002.0301][.0000.0097.0002.0345] # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI; QQCM
+1F02 ; [.12CD.0020.0002.03B1][.0000.0022.0002.0313][.0000.0035.0002.0300] # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA; QQCM
+1F0A ; [.12CD.0020.0008.0391][.0000.0022.0002.0313][.0000.0035.0002.0300] # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA; QQCM
+1F82 ; [.12CD.0020.0002.03B1][.0000.0022.0002.0313][.0000.0035.0002.0300][.0000.0097.0002.0345] # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI; QQCM
+1F8A ; [.12CD.0020.0008.0391][.0000.0022.0002.0313][.0000.0035.0002.0300][.0000.0097.0002.0345] # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI; QQCM
+1F06 ; [.12CD.0020.0002.03B1][.0000.0022.0002.0313][.0000.0045.0002.0342] # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI; QQCM
+1F0E ; [.12CD.0020.0008.0391][.0000.0022.0002.0313][.0000.0045.0002.0342] # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI; QQCM
+1F86 ; [.12CD.0020.0002.03B1][.0000.0022.0002.0313][.0000.0045.0002.0342][.0000.0097.0002.0345] # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI; QQCM
+1F8E ; [.12CD.0020.0008.0391][.0000.0022.0002.0313][.0000.0045.0002.0342][.0000.0097.0002.0345] # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI; QQCM
+1F80 ; [.12CD.0020.0002.03B1][.0000.0022.0002.0313][.0000.0097.0002.0345] # GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI; QQCM
+1F88 ; [.12CD.0020.0008.0391][.0000.0022.0002.0313][.0000.0097.0002.0345] # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI; QQCM
+1F01 ; [.12CD.0020.0002.03B1][.0000.002A.0002.0314] # GREEK SMALL LETTER ALPHA WITH DASIA; QQCM
+1F09 ; [.12CD.0020.0008.0391][.0000.002A.0002.0314] # GREEK CAPITAL LETTER ALPHA WITH DASIA; QQCM
+1F05 ; [.12CD.0020.0002.03B1][.0000.002A.0002.0314][.0000.0032.0002.0301] # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA; QQCM
+1F0D ; [.12CD.0020.0008.0391][.0000.002A.0002.0314][.0000.0032.0002.0301] # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA; QQCM
+1F85 ; [.12CD.0020.0002.03B1][.0000.002A.0002.0314][.0000.0032.0002.0301][.0000.0097.0002.0345] # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI; QQCM
+1F8D ; [.12CD.0020.0008.0391][.0000.002A.0002.0314][.0000.0032.0002.0301][.0000.0097.0002.0345] # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI; QQCM
+1F03 ; [.12CD.0020.0002.03B1][.0000.002A.0002.0314][.0000.0035.0002.0300] # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA; QQCM
+1F0B ; [.12CD.0020.0008.0391][.0000.002A.0002.0314][.0000.0035.0002.0300] # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA; QQCM
+1F83 ; [.12CD.0020.0002.03B1][.0000.002A.0002.0314][.0000.0035.0002.0300][.0000.0097.0002.0345] # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI; QQCM
+1F8B ; [.12CD.0020.0008.0391][.0000.002A.0002.0314][.0000.0035.0002.0300][.0000.0097.0002.0345] # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI; QQCM
+1F07 ; [.12CD.0020.0002.03B1][.0000.002A.0002.0314][.0000.0045.0002.0342] # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI; QQCM
+1F0F ; [.12CD.0020.0008.0391][.0000.002A.0002.0314][.0000.0045.0002.0342] # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI; QQCM
+1F87 ; [.12CD.0020.0002.03B1][.0000.002A.0002.0314][.0000.0045.0002.0342][.0000.0097.0002.0345] # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI; QQCM
+1F8F ; [.12CD.0020.0008.0391][.0000.002A.0002.0314][.0000.0045.0002.0342][.0000.0097.0002.0345] # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI; QQCM
+1F81 ; [.12CD.0020.0002.03B1][.0000.002A.0002.0314][.0000.0097.0002.0345] # GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI; QQCM
+1F89 ; [.12CD.0020.0008.0391][.0000.002A.0002.0314][.0000.0097.0002.0345] # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI; QQCM
+03AC ; [.12CD.0020.0002.03B1][.0000.0032.0002.0301] # GREEK SMALL LETTER ALPHA WITH TONOS; QQCM
+1F71 ; [.12CD.0020.0002.03B1][.0000.0032.0002.0301] # GREEK SMALL LETTER ALPHA WITH OXIA; QQCM
+0386 ; [.12CD.0020.0008.0391][.0000.0032.0002.0301] # GREEK CAPITAL LETTER ALPHA WITH TONOS; QQCM
+1FBB ; [.12CD.0020.0008.0391][.0000.0032.0002.0301] # GREEK CAPITAL LETTER ALPHA WITH OXIA; QQCM
+1FB4 ; [.12CD.0020.0002.03B1][.0000.0032.0002.0301][.0000.0097.0002.0345] # GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI; QQCM
+1F70 ; [.12CD.0020.0002.03B1][.0000.0035.0002.0300] # GREEK SMALL LETTER ALPHA WITH VARIA; QQCM
+1FBA ; [.12CD.0020.0008.0391][.0000.0035.0002.0300] # GREEK CAPITAL LETTER ALPHA WITH VARIA; QQCM
+1FB2 ; [.12CD.0020.0002.03B1][.0000.0035.0002.0300][.0000.0097.0002.0345] # GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI; QQCM
+1FB0 ; [.12CD.0020.0002.03B1][.0000.0037.0002.0306] # GREEK SMALL LETTER ALPHA WITH VRACHY; QQCM
+1FB8 ; [.12CD.0020.0008.0391][.0000.0037.0002.0306] # GREEK CAPITAL LETTER ALPHA WITH VRACHY; QQCM
+1FB6 ; [.12CD.0020.0002.03B1][.0000.0045.0002.0342] # GREEK SMALL LETTER ALPHA WITH PERISPOMENI; QQCM
+1FB7 ; [.12CD.0020.0002.03B1][.0000.0045.0002.0342][.0000.0097.0002.0345] # GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI; QQCM
+1FB1 ; [.12CD.0020.0002.03B1][.0000.005B.0002.0304] # GREEK SMALL LETTER ALPHA WITH MACRON; QQCM
+1FB9 ; [.12CD.0020.0008.0391][.0000.005B.0002.0304] # GREEK CAPITAL LETTER ALPHA WITH MACRON; QQCM
+1FB3 ; [.12CD.0020.0002.03B1][.0000.0097.0002.0345] # GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI; QQCM
+1FBC ; [.12CD.0020.0008.0391][.0000.0097.0002.0345] # GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI; QQCM
+03B2 ; [.12CE.0020.0002.03B2] # GREEK SMALL LETTER BETA
+03D0 ; [.12CE.0020.0004.03D0] # GREEK BETA SYMBOL; QQK
+1D6C3 ; [.12CE.0020.0005.1D6C3] # MATHEMATICAL BOLD SMALL BETA; QQK
+1D6FD ; [.12CE.0020.0005.1D6FD] # MATHEMATICAL ITALIC SMALL BETA; QQK
+1D737 ; [.12CE.0020.0005.1D737] # MATHEMATICAL BOLD ITALIC SMALL BETA; QQK
+1D771 ; [.12CE.0020.0005.1D771] # MATHEMATICAL SANS-SERIF BOLD SMALL BETA; QQK
+1D7AB ; [.12CE.0020.0005.1D7AB] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL BETA; QQK
+0392 ; [.12CE.0020.0008.0392] # GREEK CAPITAL LETTER BETA
+1D6A9 ; [.12CE.0020.000B.1D6A9] # MATHEMATICAL BOLD CAPITAL BETA; QQK
+1D6E3 ; [.12CE.0020.000B.1D6E3] # MATHEMATICAL ITALIC CAPITAL BETA; QQK
+1D71D ; [.12CE.0020.000B.1D71D] # MATHEMATICAL BOLD ITALIC CAPITAL BETA; QQK
+1D757 ; [.12CE.0020.000B.1D757] # MATHEMATICAL SANS-SERIF BOLD CAPITAL BETA; QQK
+1D791 ; [.12CE.0020.000B.1D791] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL BETA; QQK
+1D5D ; [.12CE.0020.0014.1D5D] # MODIFIER LETTER SMALL BETA; QQK
+1D66 ; [.12CE.0020.0015.1D66] # GREEK SUBSCRIPT SMALL LETTER BETA; QQK
+03B3 ; [.12CF.0020.0002.03B3] # GREEK SMALL LETTER GAMMA
+213D ; [.12CF.0020.0005.213D] # DOUBLE-STRUCK SMALL GAMMA; QQK
+1D6C4 ; [.12CF.0020.0005.1D6C4] # MATHEMATICAL BOLD SMALL GAMMA; QQK
+1D6FE ; [.12CF.0020.0005.1D6FE] # MATHEMATICAL ITALIC SMALL GAMMA; QQK
+1D738 ; [.12CF.0020.0005.1D738] # MATHEMATICAL BOLD ITALIC SMALL GAMMA; QQK
+1D772 ; [.12CF.0020.0005.1D772] # MATHEMATICAL SANS-SERIF BOLD SMALL GAMMA; QQK
+1D7AC ; [.12CF.0020.0005.1D7AC] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL GAMMA; QQK
+0393 ; [.12CF.0020.0008.0393] # GREEK CAPITAL LETTER GAMMA
+213E ; [.12CF.0020.000B.213E] # DOUBLE-STRUCK CAPITAL GAMMA; QQK
+1D6AA ; [.12CF.0020.000B.1D6AA] # MATHEMATICAL BOLD CAPITAL GAMMA; QQK
+1D6E4 ; [.12CF.0020.000B.1D6E4] # MATHEMATICAL ITALIC CAPITAL GAMMA; QQK
+1D71E ; [.12CF.0020.000B.1D71E] # MATHEMATICAL BOLD ITALIC CAPITAL GAMMA; QQK
+1D758 ; [.12CF.0020.000B.1D758] # MATHEMATICAL SANS-SERIF BOLD CAPITAL GAMMA; QQK
+1D792 ; [.12CF.0020.000B.1D792] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL GAMMA; QQK
+1D5E ; [.12CF.0020.0014.1D5E] # MODIFIER LETTER SMALL GREEK GAMMA; QQK
+1D67 ; [.12CF.0020.0015.1D67] # GREEK SUBSCRIPT SMALL LETTER GAMMA; QQK
+1D26 ; [.12D0.0020.0002.1D26] # GREEK LETTER SMALL CAPITAL GAMMA
+03B4 ; [.12D1.0020.0002.03B4] # GREEK SMALL LETTER DELTA
+1D6C5 ; [.12D1.0020.0005.1D6C5] # MATHEMATICAL BOLD SMALL DELTA; QQK
+1D6FF ; [.12D1.0020.0005.1D6FF] # MATHEMATICAL ITALIC SMALL DELTA; QQK
+1D739 ; [.12D1.0020.0005.1D739] # MATHEMATICAL BOLD ITALIC SMALL DELTA; QQK
+1D773 ; [.12D1.0020.0005.1D773] # MATHEMATICAL SANS-SERIF BOLD SMALL DELTA; QQK
+1D7AD ; [.12D1.0020.0005.1D7AD] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL DELTA; QQK
+0394 ; [.12D1.0020.0008.0394] # GREEK CAPITAL LETTER DELTA
+1D6AB ; [.12D1.0020.000B.1D6AB] # MATHEMATICAL BOLD CAPITAL DELTA; QQK
+1D6E5 ; [.12D1.0020.000B.1D6E5] # MATHEMATICAL ITALIC CAPITAL DELTA; QQK
+1D71F ; [.12D1.0020.000B.1D71F] # MATHEMATICAL BOLD ITALIC CAPITAL DELTA; QQK
+1D759 ; [.12D1.0020.000B.1D759] # MATHEMATICAL SANS-SERIF BOLD CAPITAL DELTA; QQK
+1D793 ; [.12D1.0020.000B.1D793] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL DELTA; QQK
+1D5F ; [.12D1.0020.0014.1D5F] # MODIFIER LETTER SMALL DELTA; QQK
+03B5 ; [.12D2.0020.0002.03B5] # GREEK SMALL LETTER EPSILON
+03F5 ; [.12D2.0020.0004.03F5] # GREEK LUNATE EPSILON SYMBOL; QQK
+1D6C6 ; [.12D2.0020.0005.1D6C6] # MATHEMATICAL BOLD SMALL EPSILON; QQK
+1D6DC ; [.12D2.0020.0005.1D6DC] # MATHEMATICAL BOLD EPSILON SYMBOL; QQK
+1D700 ; [.12D2.0020.0005.1D700] # MATHEMATICAL ITALIC SMALL EPSILON; QQK
+1D716 ; [.12D2.0020.0005.1D716] # MATHEMATICAL ITALIC EPSILON SYMBOL; QQK
+1D73A ; [.12D2.0020.0005.1D73A] # MATHEMATICAL BOLD ITALIC SMALL EPSILON; QQK
+1D750 ; [.12D2.0020.0005.1D750] # MATHEMATICAL BOLD ITALIC EPSILON SYMBOL; QQK
+1D774 ; [.12D2.0020.0005.1D774] # MATHEMATICAL SANS-SERIF BOLD SMALL EPSILON; QQK
+1D78A ; [.12D2.0020.0005.1D78A] # MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL; QQK
+1D7AE ; [.12D2.0020.0005.1D7AE] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL EPSILON; QQK
+1D7C4 ; [.12D2.0020.0005.1D7C4] # MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL; QQK
+0395 ; [.12D2.0020.0008.0395] # GREEK CAPITAL LETTER EPSILON
+1D6AC ; [.12D2.0020.000B.1D6AC] # MATHEMATICAL BOLD CAPITAL EPSILON; QQK
+1D6E6 ; [.12D2.0020.000B.1D6E6] # MATHEMATICAL ITALIC CAPITAL EPSILON; QQK
+1D720 ; [.12D2.0020.000B.1D720] # MATHEMATICAL BOLD ITALIC CAPITAL EPSILON; QQK
+1D75A ; [.12D2.0020.000B.1D75A] # MATHEMATICAL SANS-SERIF BOLD CAPITAL EPSILON; QQK
+1D794 ; [.12D2.0020.000B.1D794] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL EPSILON; QQK
+1F10 ; [.12D2.0020.0002.03B5][.0000.0022.0002.0313] # GREEK SMALL LETTER EPSILON WITH PSILI; QQCM
+1F18 ; [.12D2.0020.0008.0395][.0000.0022.0002.0313] # GREEK CAPITAL LETTER EPSILON WITH PSILI; QQCM
+1F14 ; [.12D2.0020.0002.03B5][.0000.0022.0002.0313][.0000.0032.0002.0301] # GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA; QQCM
+1F1C ; [.12D2.0020.0008.0395][.0000.0022.0002.0313][.0000.0032.0002.0301] # GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA; QQCM
+1F12 ; [.12D2.0020.0002.03B5][.0000.0022.0002.0313][.0000.0035.0002.0300] # GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA; QQCM
+1F1A ; [.12D2.0020.0008.0395][.0000.0022.0002.0313][.0000.0035.0002.0300] # GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA; QQCM
+1F11 ; [.12D2.0020.0002.03B5][.0000.002A.0002.0314] # GREEK SMALL LETTER EPSILON WITH DASIA; QQCM
+1F19 ; [.12D2.0020.0008.0395][.0000.002A.0002.0314] # GREEK CAPITAL LETTER EPSILON WITH DASIA; QQCM
+1F15 ; [.12D2.0020.0002.03B5][.0000.002A.0002.0314][.0000.0032.0002.0301] # GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA; QQCM
+1F1D ; [.12D2.0020.0008.0395][.0000.002A.0002.0314][.0000.0032.0002.0301] # GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA; QQCM
+1F13 ; [.12D2.0020.0002.03B5][.0000.002A.0002.0314][.0000.0035.0002.0300] # GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA; QQCM
+1F1B ; [.12D2.0020.0008.0395][.0000.002A.0002.0314][.0000.0035.0002.0300] # GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA; QQCM
+03AD ; [.12D2.0020.0002.03B5][.0000.0032.0002.0301] # GREEK SMALL LETTER EPSILON WITH TONOS; QQCM
+1F73 ; [.12D2.0020.0002.03B5][.0000.0032.0002.0301] # GREEK SMALL LETTER EPSILON WITH OXIA; QQCM
+0388 ; [.12D2.0020.0008.0395][.0000.0032.0002.0301] # GREEK CAPITAL LETTER EPSILON WITH TONOS; QQCM
+1FC9 ; [.12D2.0020.0008.0395][.0000.0032.0002.0301] # GREEK CAPITAL LETTER EPSILON WITH OXIA; QQCM
+1F72 ; [.12D2.0020.0002.03B5][.0000.0035.0002.0300] # GREEK SMALL LETTER EPSILON WITH VARIA; QQCM
+1FC8 ; [.12D2.0020.0008.0395][.0000.0035.0002.0300] # GREEK CAPITAL LETTER EPSILON WITH VARIA; QQCM
+03DD ; [.12D3.0020.0002.03DD] # GREEK SMALL LETTER DIGAMMA
+1D7CB ; [.12D3.0020.0005.1D7CB] # MATHEMATICAL BOLD SMALL DIGAMMA; QQK
+03DC ; [.12D3.0020.0008.03DC] # GREEK LETTER DIGAMMA
+1D7CA ; [.12D3.0020.000B.1D7CA] # MATHEMATICAL BOLD CAPITAL DIGAMMA; QQK
+03DB ; [.12D4.0020.0002.03DB] # GREEK SMALL LETTER STIGMA
+03DA ; [.12D4.0020.0008.03DA] # GREEK LETTER STIGMA
+03B6 ; [.12D5.0020.0002.03B6] # GREEK SMALL LETTER ZETA
+1D6C7 ; [.12D5.0020.0005.1D6C7] # MATHEMATICAL BOLD SMALL ZETA; QQK
+1D701 ; [.12D5.0020.0005.1D701] # MATHEMATICAL ITALIC SMALL ZETA; QQK
+1D73B ; [.12D5.0020.0005.1D73B] # MATHEMATICAL BOLD ITALIC SMALL ZETA; QQK
+1D775 ; [.12D5.0020.0005.1D775] # MATHEMATICAL SANS-SERIF BOLD SMALL ZETA; QQK
+1D7AF ; [.12D5.0020.0005.1D7AF] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ZETA; QQK
+0396 ; [.12D5.0020.0008.0396] # GREEK CAPITAL LETTER ZETA
+1D6AD ; [.12D5.0020.000B.1D6AD] # MATHEMATICAL BOLD CAPITAL ZETA; QQK
+1D6E7 ; [.12D5.0020.000B.1D6E7] # MATHEMATICAL ITALIC CAPITAL ZETA; QQK
+1D721 ; [.12D5.0020.000B.1D721] # MATHEMATICAL BOLD ITALIC CAPITAL ZETA; QQK
+1D75B ; [.12D5.0020.000B.1D75B] # MATHEMATICAL SANS-SERIF BOLD CAPITAL ZETA; QQK
+1D795 ; [.12D5.0020.000B.1D795] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ZETA; QQK
+03B7 ; [.12D6.0020.0002.03B7] # GREEK SMALL LETTER ETA
+1D6C8 ; [.12D6.0020.0005.1D6C8] # MATHEMATICAL BOLD SMALL ETA; QQK
+1D702 ; [.12D6.0020.0005.1D702] # MATHEMATICAL ITALIC SMALL ETA; QQK
+1D73C ; [.12D6.0020.0005.1D73C] # MATHEMATICAL BOLD ITALIC SMALL ETA; QQK
+1D776 ; [.12D6.0020.0005.1D776] # MATHEMATICAL SANS-SERIF BOLD SMALL ETA; QQK
+1D7B0 ; [.12D6.0020.0005.1D7B0] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ETA; QQK
+0397 ; [.12D6.0020.0008.0397] # GREEK CAPITAL LETTER ETA
+1D6AE ; [.12D6.0020.000B.1D6AE] # MATHEMATICAL BOLD CAPITAL ETA; QQK
+1D6E8 ; [.12D6.0020.000B.1D6E8] # MATHEMATICAL ITALIC CAPITAL ETA; QQK
+1D722 ; [.12D6.0020.000B.1D722] # MATHEMATICAL BOLD ITALIC CAPITAL ETA; QQK
+1D75C ; [.12D6.0020.000B.1D75C] # MATHEMATICAL SANS-SERIF BOLD CAPITAL ETA; QQK
+1D796 ; [.12D6.0020.000B.1D796] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL ETA; QQK
+1F20 ; [.12D6.0020.0002.03B7][.0000.0022.0002.0313] # GREEK SMALL LETTER ETA WITH PSILI; QQCM
+1F28 ; [.12D6.0020.0008.0397][.0000.0022.0002.0313] # GREEK CAPITAL LETTER ETA WITH PSILI; QQCM
+1F24 ; [.12D6.0020.0002.03B7][.0000.0022.0002.0313][.0000.0032.0002.0301] # GREEK SMALL LETTER ETA WITH PSILI AND OXIA; QQCM
+1F2C ; [.12D6.0020.0008.0397][.0000.0022.0002.0313][.0000.0032.0002.0301] # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA; QQCM
+1F94 ; [.12D6.0020.0002.03B7][.0000.0022.0002.0313][.0000.0032.0002.0301][.0000.0097.0002.0345] # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI; QQCM
+1F9C ; [.12D6.0020.0008.0397][.0000.0022.0002.0313][.0000.0032.0002.0301][.0000.0097.0002.0345] # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI; QQCM
+1F22 ; [.12D6.0020.0002.03B7][.0000.0022.0002.0313][.0000.0035.0002.0300] # GREEK SMALL LETTER ETA WITH PSILI AND VARIA; QQCM
+1F2A ; [.12D6.0020.0008.0397][.0000.0022.0002.0313][.0000.0035.0002.0300] # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA; QQCM
+1F92 ; [.12D6.0020.0002.03B7][.0000.0022.0002.0313][.0000.0035.0002.0300][.0000.0097.0002.0345] # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI; QQCM
+1F9A ; [.12D6.0020.0008.0397][.0000.0022.0002.0313][.0000.0035.0002.0300][.0000.0097.0002.0345] # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI; QQCM
+1F26 ; [.12D6.0020.0002.03B7][.0000.0022.0002.0313][.0000.0045.0002.0342] # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI; QQCM
+1F2E ; [.12D6.0020.0008.0397][.0000.0022.0002.0313][.0000.0045.0002.0342] # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI; QQCM
+1F96 ; [.12D6.0020.0002.03B7][.0000.0022.0002.0313][.0000.0045.0002.0342][.0000.0097.0002.0345] # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI; QQCM
+1F9E ; [.12D6.0020.0008.0397][.0000.0022.0002.0313][.0000.0045.0002.0342][.0000.0097.0002.0345] # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI; QQCM
+1F90 ; [.12D6.0020.0002.03B7][.0000.0022.0002.0313][.0000.0097.0002.0345] # GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI; QQCM
+1F98 ; [.12D6.0020.0008.0397][.0000.0022.0002.0313][.0000.0097.0002.0345] # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI; QQCM
+1F21 ; [.12D6.0020.0002.03B7][.0000.002A.0002.0314] # GREEK SMALL LETTER ETA WITH DASIA; QQCM
+1F29 ; [.12D6.0020.0008.0397][.0000.002A.0002.0314] # GREEK CAPITAL LETTER ETA WITH DASIA; QQCM
+1F25 ; [.12D6.0020.0002.03B7][.0000.002A.0002.0314][.0000.0032.0002.0301] # GREEK SMALL LETTER ETA WITH DASIA AND OXIA; QQCM
+1F2D ; [.12D6.0020.0008.0397][.0000.002A.0002.0314][.0000.0032.0002.0301] # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA; QQCM
+1F95 ; [.12D6.0020.0002.03B7][.0000.002A.0002.0314][.0000.0032.0002.0301][.0000.0097.0002.0345] # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI; QQCM
+1F9D ; [.12D6.0020.0008.0397][.0000.002A.0002.0314][.0000.0032.0002.0301][.0000.0097.0002.0345] # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI; QQCM
+1F23 ; [.12D6.0020.0002.03B7][.0000.002A.0002.0314][.0000.0035.0002.0300] # GREEK SMALL LETTER ETA WITH DASIA AND VARIA; QQCM
+1F2B ; [.12D6.0020.0008.0397][.0000.002A.0002.0314][.0000.0035.0002.0300] # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA; QQCM
+1F93 ; [.12D6.0020.0002.03B7][.0000.002A.0002.0314][.0000.0035.0002.0300][.0000.0097.0002.0345] # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI; QQCM
+1F9B ; [.12D6.0020.0008.0397][.0000.002A.0002.0314][.0000.0035.0002.0300][.0000.0097.0002.0345] # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI; QQCM
+1F27 ; [.12D6.0020.0002.03B7][.0000.002A.0002.0314][.0000.0045.0002.0342] # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI; QQCM
+1F2F ; [.12D6.0020.0008.0397][.0000.002A.0002.0314][.0000.0045.0002.0342] # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI; QQCM
+1F97 ; [.12D6.0020.0002.03B7][.0000.002A.0002.0314][.0000.0045.0002.0342][.0000.0097.0002.0345] # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI; QQCM
+1F9F ; [.12D6.0020.0008.0397][.0000.002A.0002.0314][.0000.0045.0002.0342][.0000.0097.0002.0345] # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI; QQCM
+1F91 ; [.12D6.0020.0002.03B7][.0000.002A.0002.0314][.0000.0097.0002.0345] # GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI; QQCM
+1F99 ; [.12D6.0020.0008.0397][.0000.002A.0002.0314][.0000.0097.0002.0345] # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI; QQCM
+03AE ; [.12D6.0020.0002.03B7][.0000.0032.0002.0301] # GREEK SMALL LETTER ETA WITH TONOS; QQCM
+1F75 ; [.12D6.0020.0002.03B7][.0000.0032.0002.0301] # GREEK SMALL LETTER ETA WITH OXIA; QQCM
+0389 ; [.12D6.0020.0008.0397][.0000.0032.0002.0301] # GREEK CAPITAL LETTER ETA WITH TONOS; QQCM
+1FCB ; [.12D6.0020.0008.0397][.0000.0032.0002.0301] # GREEK CAPITAL LETTER ETA WITH OXIA; QQCM
+1FC4 ; [.12D6.0020.0002.03B7][.0000.0032.0002.0301][.0000.0097.0002.0345] # GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI; QQCM
+1F74 ; [.12D6.0020.0002.03B7][.0000.0035.0002.0300] # GREEK SMALL LETTER ETA WITH VARIA; QQCM
+1FCA ; [.12D6.0020.0008.0397][.0000.0035.0002.0300] # GREEK CAPITAL LETTER ETA WITH VARIA; QQCM
+1FC2 ; [.12D6.0020.0002.03B7][.0000.0035.0002.0300][.0000.0097.0002.0345] # GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI; QQCM
+1FC6 ; [.12D6.0020.0002.03B7][.0000.0045.0002.0342] # GREEK SMALL LETTER ETA WITH PERISPOMENI; QQCM
+1FC7 ; [.12D6.0020.0002.03B7][.0000.0045.0002.0342][.0000.0097.0002.0345] # GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI; QQCM
+1FC3 ; [.12D6.0020.0002.03B7][.0000.0097.0002.0345] # GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI; QQCM
+1FCC ; [.12D6.0020.0008.0397][.0000.0097.0002.0345] # GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI; QQCM
+03B8 ; [.12D7.0020.0002.03B8] # GREEK SMALL LETTER THETA
+03D1 ; [.12D7.0020.0004.03D1] # GREEK THETA SYMBOL; QQK
+1D6C9 ; [.12D7.0020.0005.1D6C9] # MATHEMATICAL BOLD SMALL THETA; QQK
+1D6DD ; [.12D7.0020.0005.1D6DD] # MATHEMATICAL BOLD THETA SYMBOL; QQK
+1D703 ; [.12D7.0020.0005.1D703] # MATHEMATICAL ITALIC SMALL THETA; QQK
+1D717 ; [.12D7.0020.0005.1D717] # MATHEMATICAL ITALIC THETA SYMBOL; QQK
+1D73D ; [.12D7.0020.0005.1D73D] # MATHEMATICAL BOLD ITALIC SMALL THETA; QQK
+1D751 ; [.12D7.0020.0005.1D751] # MATHEMATICAL BOLD ITALIC THETA SYMBOL; QQK
+1D777 ; [.12D7.0020.0005.1D777] # MATHEMATICAL SANS-SERIF BOLD SMALL THETA; QQK
+1D78B ; [.12D7.0020.0005.1D78B] # MATHEMATICAL SANS-SERIF BOLD THETA SYMBOL; QQK
+1D7B1 ; [.12D7.0020.0005.1D7B1] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL THETA; QQK
+1D7C5 ; [.12D7.0020.0005.1D7C5] # MATHEMATICAL SANS-SERIF BOLD ITALIC THETA SYMBOL; QQK
+0398 ; [.12D7.0020.0008.0398] # GREEK CAPITAL LETTER THETA
+03F4 ; [.12D7.0020.000A.03F4] # GREEK CAPITAL THETA SYMBOL; QQK
+1D6AF ; [.12D7.0020.000B.1D6AF] # MATHEMATICAL BOLD CAPITAL THETA; QQK
+1D6B9 ; [.12D7.0020.000B.1D6B9] # MATHEMATICAL BOLD CAPITAL THETA SYMBOL; QQK
+1D6E9 ; [.12D7.0020.000B.1D6E9] # MATHEMATICAL ITALIC CAPITAL THETA; QQK
+1D6F3 ; [.12D7.0020.000B.1D6F3] # MATHEMATICAL ITALIC CAPITAL THETA SYMBOL; QQK
+1D723 ; [.12D7.0020.000B.1D723] # MATHEMATICAL BOLD ITALIC CAPITAL THETA; QQK
+1D72D ; [.12D7.0020.000B.1D72D] # MATHEMATICAL BOLD ITALIC CAPITAL THETA SYMBOL; QQK
+1D75D ; [.12D7.0020.000B.1D75D] # MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA; QQK
+1D767 ; [.12D7.0020.000B.1D767] # MATHEMATICAL SANS-SERIF BOLD CAPITAL THETA SYMBOL; QQK
+1D797 ; [.12D7.0020.000B.1D797] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA; QQK
+1D7A1 ; [.12D7.0020.000B.1D7A1] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL THETA SYMBOL; QQK
+1DBF ; [.12D7.0020.0014.1DBF] # MODIFIER LETTER SMALL THETA; QQK
+03B9 ; [.12D8.0020.0002.03B9] # GREEK SMALL LETTER IOTA
+1FBE ; [.12D8.0020.0002.1FBE] # GREEK PROSGEGRAMMENI; QQC
+037A ; [.12D8.0020.0004.037A] # GREEK YPOGEGRAMMENI; QQK
+1D6CA ; [.12D8.0020.0005.1D6CA] # MATHEMATICAL BOLD SMALL IOTA; QQK
+1D704 ; [.12D8.0020.0005.1D704] # MATHEMATICAL ITALIC SMALL IOTA; QQK
+1D73E ; [.12D8.0020.0005.1D73E] # MATHEMATICAL BOLD ITALIC SMALL IOTA; QQK
+1D778 ; [.12D8.0020.0005.1D778] # MATHEMATICAL SANS-SERIF BOLD SMALL IOTA; QQK
+1D7B2 ; [.12D8.0020.0005.1D7B2] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL IOTA; QQK
+0399 ; [.12D8.0020.0008.0399] # GREEK CAPITAL LETTER IOTA
+1D6B0 ; [.12D8.0020.000B.1D6B0] # MATHEMATICAL BOLD CAPITAL IOTA; QQK
+1D6EA ; [.12D8.0020.000B.1D6EA] # MATHEMATICAL ITALIC CAPITAL IOTA; QQK
+1D724 ; [.12D8.0020.000B.1D724] # MATHEMATICAL BOLD ITALIC CAPITAL IOTA; QQK
+1D75E ; [.12D8.0020.000B.1D75E] # MATHEMATICAL SANS-SERIF BOLD CAPITAL IOTA; QQK
+1D798 ; [.12D8.0020.000B.1D798] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL IOTA; QQK
+1F30 ; [.12D8.0020.0002.03B9][.0000.0022.0002.0313] # GREEK SMALL LETTER IOTA WITH PSILI; QQCM
+1F38 ; [.12D8.0020.0008.0399][.0000.0022.0002.0313] # GREEK CAPITAL LETTER IOTA WITH PSILI; QQCM
+1F34 ; [.12D8.0020.0002.03B9][.0000.0022.0002.0313][.0000.0032.0002.0301] # GREEK SMALL LETTER IOTA WITH PSILI AND OXIA; QQCM
+1F3C ; [.12D8.0020.0008.0399][.0000.0022.0002.0313][.0000.0032.0002.0301] # GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA; QQCM
+1F32 ; [.12D8.0020.0002.03B9][.0000.0022.0002.0313][.0000.0035.0002.0300] # GREEK SMALL LETTER IOTA WITH PSILI AND VARIA; QQCM
+1F3A ; [.12D8.0020.0008.0399][.0000.0022.0002.0313][.0000.0035.0002.0300] # GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA; QQCM
+1F36 ; [.12D8.0020.0002.03B9][.0000.0022.0002.0313][.0000.0045.0002.0342] # GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI; QQCM
+1F3E ; [.12D8.0020.0008.0399][.0000.0022.0002.0313][.0000.0045.0002.0342] # GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI; QQCM
+1F31 ; [.12D8.0020.0002.03B9][.0000.002A.0002.0314] # GREEK SMALL LETTER IOTA WITH DASIA; QQCM
+1F39 ; [.12D8.0020.0008.0399][.0000.002A.0002.0314] # GREEK CAPITAL LETTER IOTA WITH DASIA; QQCM
+1F35 ; [.12D8.0020.0002.03B9][.0000.002A.0002.0314][.0000.0032.0002.0301] # GREEK SMALL LETTER IOTA WITH DASIA AND OXIA; QQCM
+1F3D ; [.12D8.0020.0008.0399][.0000.002A.0002.0314][.0000.0032.0002.0301] # GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA; QQCM
+1F33 ; [.12D8.0020.0002.03B9][.0000.002A.0002.0314][.0000.0035.0002.0300] # GREEK SMALL LETTER IOTA WITH DASIA AND VARIA; QQCM
+1F3B ; [.12D8.0020.0008.0399][.0000.002A.0002.0314][.0000.0035.0002.0300] # GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA; QQCM
+1F37 ; [.12D8.0020.0002.03B9][.0000.002A.0002.0314][.0000.0045.0002.0342] # GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI; QQCM
+1F3F ; [.12D8.0020.0008.0399][.0000.002A.0002.0314][.0000.0045.0002.0342] # GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI; QQCM
+03AF ; [.12D8.0020.0002.03B9][.0000.0032.0002.0301] # GREEK SMALL LETTER IOTA WITH TONOS; QQCM
+1F77 ; [.12D8.0020.0002.03B9][.0000.0032.0002.0301] # GREEK SMALL LETTER IOTA WITH OXIA; QQCM
+038A ; [.12D8.0020.0008.0399][.0000.0032.0002.0301] # GREEK CAPITAL LETTER IOTA WITH TONOS; QQCM
+1FDB ; [.12D8.0020.0008.0399][.0000.0032.0002.0301] # GREEK CAPITAL LETTER IOTA WITH OXIA; QQCM
+1F76 ; [.12D8.0020.0002.03B9][.0000.0035.0002.0300] # GREEK SMALL LETTER IOTA WITH VARIA; QQCM
+1FDA ; [.12D8.0020.0008.0399][.0000.0035.0002.0300] # GREEK CAPITAL LETTER IOTA WITH VARIA; QQCM
+1FD0 ; [.12D8.0020.0002.03B9][.0000.0037.0002.0306] # GREEK SMALL LETTER IOTA WITH VRACHY; QQCM
+1FD8 ; [.12D8.0020.0008.0399][.0000.0037.0002.0306] # GREEK CAPITAL LETTER IOTA WITH VRACHY; QQCM
+1FD6 ; [.12D8.0020.0002.03B9][.0000.0045.0002.0342] # GREEK SMALL LETTER IOTA WITH PERISPOMENI; QQCM
+03CA ; [.12D8.0020.0002.03B9][.0000.0047.0002.0308] # GREEK SMALL LETTER IOTA WITH DIALYTIKA; QQCM
+03AA ; [.12D8.0020.0008.0399][.0000.0047.0002.0308] # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA; QQCM
+0390 ; [.12D8.0020.0002.03B9][.0000.0047.0002.0308][.0000.0032.0002.0301] # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS; QQCM
+1FD3 ; [.12D8.0020.0002.03B9][.0000.0047.0002.0308][.0000.0032.0002.0301] # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA; QQCM
+1FD2 ; [.12D8.0020.0002.03B9][.0000.0047.0002.0308][.0000.0035.0002.0300] # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA; QQCM
+1FD7 ; [.12D8.0020.0002.03B9][.0000.0047.0002.0308][.0000.0045.0002.0342] # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI; QQCM
+1FD1 ; [.12D8.0020.0002.03B9][.0000.005B.0002.0304] # GREEK SMALL LETTER IOTA WITH MACRON; QQCM
+1FD9 ; [.12D8.0020.0008.0399][.0000.005B.0002.0304] # GREEK CAPITAL LETTER IOTA WITH MACRON; QQCM
+03F3 ; [.12D9.0020.0002.03F3] # GREEK LETTER YOT
+03BA ; [.12DA.0020.0002.03BA] # GREEK SMALL LETTER KAPPA
+03F0 ; [.12DA.0020.0004.03F0] # GREEK KAPPA SYMBOL; QQK
+1D6CB ; [.12DA.0020.0005.1D6CB] # MATHEMATICAL BOLD SMALL KAPPA; QQK
+1D6DE ; [.12DA.0020.0005.1D6DE] # MATHEMATICAL BOLD KAPPA SYMBOL; QQK
+1D705 ; [.12DA.0020.0005.1D705] # MATHEMATICAL ITALIC SMALL KAPPA; QQK
+1D718 ; [.12DA.0020.0005.1D718] # MATHEMATICAL ITALIC KAPPA SYMBOL; QQK
+1D73F ; [.12DA.0020.0005.1D73F] # MATHEMATICAL BOLD ITALIC SMALL KAPPA; QQK
+1D752 ; [.12DA.0020.0005.1D752] # MATHEMATICAL BOLD ITALIC KAPPA SYMBOL; QQK
+1D779 ; [.12DA.0020.0005.1D779] # MATHEMATICAL SANS-SERIF BOLD SMALL KAPPA; QQK
+1D78C ; [.12DA.0020.0005.1D78C] # MATHEMATICAL SANS-SERIF BOLD KAPPA SYMBOL; QQK
+1D7B3 ; [.12DA.0020.0005.1D7B3] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL KAPPA; QQK
+1D7C6 ; [.12DA.0020.0005.1D7C6] # MATHEMATICAL SANS-SERIF BOLD ITALIC KAPPA SYMBOL; QQK
+039A ; [.12DA.0020.0008.039A] # GREEK CAPITAL LETTER KAPPA
+1D6B1 ; [.12DA.0020.000B.1D6B1] # MATHEMATICAL BOLD CAPITAL KAPPA; QQK
+1D6EB ; [.12DA.0020.000B.1D6EB] # MATHEMATICAL ITALIC CAPITAL KAPPA; QQK
+1D725 ; [.12DA.0020.000B.1D725] # MATHEMATICAL BOLD ITALIC CAPITAL KAPPA; QQK
+1D75F ; [.12DA.0020.000B.1D75F] # MATHEMATICAL SANS-SERIF BOLD CAPITAL KAPPA; QQK
+1D799 ; [.12DA.0020.000B.1D799] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL KAPPA; QQK
+03D7 ; [.12DA.0020.0004.03D7][.12CD.0020.0004.03D7][.12D8.0020.001F.03D7] # GREEK KAI SYMBOL; QQKN
+03BB ; [.12DB.0020.0002.03BB] # GREEK SMALL LETTER LAMDA
+1D6CC ; [.12DB.0020.0005.1D6CC] # MATHEMATICAL BOLD SMALL LAMDA; QQK
+1D706 ; [.12DB.0020.0005.1D706] # MATHEMATICAL ITALIC SMALL LAMDA; QQK
+1D740 ; [.12DB.0020.0005.1D740] # MATHEMATICAL BOLD ITALIC SMALL LAMDA; QQK
+1D77A ; [.12DB.0020.0005.1D77A] # MATHEMATICAL SANS-SERIF BOLD SMALL LAMDA; QQK
+1D7B4 ; [.12DB.0020.0005.1D7B4] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL LAMDA; QQK
+039B ; [.12DB.0020.0008.039B] # GREEK CAPITAL LETTER LAMDA
+1D6B2 ; [.12DB.0020.000B.1D6B2] # MATHEMATICAL BOLD CAPITAL LAMDA; QQK
+1D6EC ; [.12DB.0020.000B.1D6EC] # MATHEMATICAL ITALIC CAPITAL LAMDA; QQK
+1D726 ; [.12DB.0020.000B.1D726] # MATHEMATICAL BOLD ITALIC CAPITAL LAMDA; QQK
+1D760 ; [.12DB.0020.000B.1D760] # MATHEMATICAL SANS-SERIF BOLD CAPITAL LAMDA; QQK
+1D79A ; [.12DB.0020.000B.1D79A] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL LAMDA; QQK
+1D27 ; [.12DC.0020.0002.1D27] # GREEK LETTER SMALL CAPITAL LAMDA
+03BC ; [.12DD.0020.0002.03BC] # GREEK SMALL LETTER MU
+00B5 ; [.12DD.0020.0004.00B5] # MICRO SIGN; QQK
+1D6CD ; [.12DD.0020.0005.1D6CD] # MATHEMATICAL BOLD SMALL MU; QQK
+1D707 ; [.12DD.0020.0005.1D707] # MATHEMATICAL ITALIC SMALL MU; QQK
+1D741 ; [.12DD.0020.0005.1D741] # MATHEMATICAL BOLD ITALIC SMALL MU; QQK
+1D77B ; [.12DD.0020.0005.1D77B] # MATHEMATICAL SANS-SERIF BOLD SMALL MU; QQK
+1D7B5 ; [.12DD.0020.0005.1D7B5] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL MU; QQK
+039C ; [.12DD.0020.0008.039C] # GREEK CAPITAL LETTER MU
+1D6B3 ; [.12DD.0020.000B.1D6B3] # MATHEMATICAL BOLD CAPITAL MU; QQK
+1D6ED ; [.12DD.0020.000B.1D6ED] # MATHEMATICAL ITALIC CAPITAL MU; QQK
+1D727 ; [.12DD.0020.000B.1D727] # MATHEMATICAL BOLD ITALIC CAPITAL MU; QQK
+1D761 ; [.12DD.0020.000B.1D761] # MATHEMATICAL SANS-SERIF BOLD CAPITAL MU; QQK
+1D79B ; [.12DD.0020.000B.1D79B] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL MU; QQK
+3382 ; [.12DD.0020.001C.3382][.0FD0.0020.001D.3382] # SQUARE MU A; QQKN
+338C ; [.12DD.0020.001C.338C][.105F.0020.001D.338C] # SQUARE MU F; QQKN
+338D ; [.12DD.0020.001C.338D][.106A.0020.001C.338D] # SQUARE MU G; QQKN
+3395 ; [.12DD.0020.001C.3395][.10E5.0020.001C.3395] # SQUARE MU L; QQKN
+339B ; [.12DD.0020.001C.339B][.1110.0020.001C.339B] # SQUARE MU M; QQKN
+33B2 ; [.12DD.0020.001C.33B2][.11AF.0020.001C.33B2] # SQUARE MU S; QQKN
+33B6 ; [.12DD.0020.001C.33B6][.1216.0020.001D.33B6] # SQUARE MU V; QQKN
+33BC ; [.12DD.0020.001C.33BC][.1225.0020.001D.33BC] # SQUARE MU W; QQKN
+03BD ; [.12DE.0020.0002.03BD] # GREEK SMALL LETTER NU
+1D6CE ; [.12DE.0020.0005.1D6CE] # MATHEMATICAL BOLD SMALL NU; QQK
+1D708 ; [.12DE.0020.0005.1D708] # MATHEMATICAL ITALIC SMALL NU; QQK
+1D742 ; [.12DE.0020.0005.1D742] # MATHEMATICAL BOLD ITALIC SMALL NU; QQK
+1D77C ; [.12DE.0020.0005.1D77C] # MATHEMATICAL SANS-SERIF BOLD SMALL NU; QQK
+1D7B6 ; [.12DE.0020.0005.1D7B6] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL NU; QQK
+039D ; [.12DE.0020.0008.039D] # GREEK CAPITAL LETTER NU
+1D6B4 ; [.12DE.0020.000B.1D6B4] # MATHEMATICAL BOLD CAPITAL NU; QQK
+1D6EE ; [.12DE.0020.000B.1D6EE] # MATHEMATICAL ITALIC CAPITAL NU; QQK
+1D728 ; [.12DE.0020.000B.1D728] # MATHEMATICAL BOLD ITALIC CAPITAL NU; QQK
+1D762 ; [.12DE.0020.000B.1D762] # MATHEMATICAL SANS-SERIF BOLD CAPITAL NU; QQK
+1D79C ; [.12DE.0020.000B.1D79C] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL NU; QQK
+03BE ; [.12DF.0020.0002.03BE] # GREEK SMALL LETTER XI
+1D6CF ; [.12DF.0020.0005.1D6CF] # MATHEMATICAL BOLD SMALL XI; QQK
+1D709 ; [.12DF.0020.0005.1D709] # MATHEMATICAL ITALIC SMALL XI; QQK
+1D743 ; [.12DF.0020.0005.1D743] # MATHEMATICAL BOLD ITALIC SMALL XI; QQK
+1D77D ; [.12DF.0020.0005.1D77D] # MATHEMATICAL SANS-SERIF BOLD SMALL XI; QQK
+1D7B7 ; [.12DF.0020.0005.1D7B7] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL XI; QQK
+039E ; [.12DF.0020.0008.039E] # GREEK CAPITAL LETTER XI
+1D6B5 ; [.12DF.0020.000B.1D6B5] # MATHEMATICAL BOLD CAPITAL XI; QQK
+1D6EF ; [.12DF.0020.000B.1D6EF] # MATHEMATICAL ITALIC CAPITAL XI; QQK
+1D729 ; [.12DF.0020.000B.1D729] # MATHEMATICAL BOLD ITALIC CAPITAL XI; QQK
+1D763 ; [.12DF.0020.000B.1D763] # MATHEMATICAL SANS-SERIF BOLD CAPITAL XI; QQK
+1D79D ; [.12DF.0020.000B.1D79D] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL XI; QQK
+03BF ; [.12E0.0020.0002.03BF] # GREEK SMALL LETTER OMICRON
+1D6D0 ; [.12E0.0020.0005.1D6D0] # MATHEMATICAL BOLD SMALL OMICRON; QQK
+1D70A ; [.12E0.0020.0005.1D70A] # MATHEMATICAL ITALIC SMALL OMICRON; QQK
+1D744 ; [.12E0.0020.0005.1D744] # MATHEMATICAL BOLD ITALIC SMALL OMICRON; QQK
+1D77E ; [.12E0.0020.0005.1D77E] # MATHEMATICAL SANS-SERIF BOLD SMALL OMICRON; QQK
+1D7B8 ; [.12E0.0020.0005.1D7B8] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMICRON; QQK
+039F ; [.12E0.0020.0008.039F] # GREEK CAPITAL LETTER OMICRON
+1D6B6 ; [.12E0.0020.000B.1D6B6] # MATHEMATICAL BOLD CAPITAL OMICRON; QQK
+1D6F0 ; [.12E0.0020.000B.1D6F0] # MATHEMATICAL ITALIC CAPITAL OMICRON; QQK
+1D72A ; [.12E0.0020.000B.1D72A] # MATHEMATICAL BOLD ITALIC CAPITAL OMICRON; QQK
+1D764 ; [.12E0.0020.000B.1D764] # MATHEMATICAL SANS-SERIF BOLD CAPITAL OMICRON; QQK
+1D79E ; [.12E0.0020.000B.1D79E] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMICRON; QQK
+1F40 ; [.12E0.0020.0002.03BF][.0000.0022.0002.0313] # GREEK SMALL LETTER OMICRON WITH PSILI; QQCM
+1F48 ; [.12E0.0020.0008.039F][.0000.0022.0002.0313] # GREEK CAPITAL LETTER OMICRON WITH PSILI; QQCM
+1F44 ; [.12E0.0020.0002.03BF][.0000.0022.0002.0313][.0000.0032.0002.0301] # GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA; QQCM
+1F4C ; [.12E0.0020.0008.039F][.0000.0022.0002.0313][.0000.0032.0002.0301] # GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA; QQCM
+1F42 ; [.12E0.0020.0002.03BF][.0000.0022.0002.0313][.0000.0035.0002.0300] # GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA; QQCM
+1F4A ; [.12E0.0020.0008.039F][.0000.0022.0002.0313][.0000.0035.0002.0300] # GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA; QQCM
+1F41 ; [.12E0.0020.0002.03BF][.0000.002A.0002.0314] # GREEK SMALL LETTER OMICRON WITH DASIA; QQCM
+1F49 ; [.12E0.0020.0008.039F][.0000.002A.0002.0314] # GREEK CAPITAL LETTER OMICRON WITH DASIA; QQCM
+1F45 ; [.12E0.0020.0002.03BF][.0000.002A.0002.0314][.0000.0032.0002.0301] # GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA; QQCM
+1F4D ; [.12E0.0020.0008.039F][.0000.002A.0002.0314][.0000.0032.0002.0301] # GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA; QQCM
+1F43 ; [.12E0.0020.0002.03BF][.0000.002A.0002.0314][.0000.0035.0002.0300] # GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA; QQCM
+1F4B ; [.12E0.0020.0008.039F][.0000.002A.0002.0314][.0000.0035.0002.0300] # GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA; QQCM
+03CC ; [.12E0.0020.0002.03BF][.0000.0032.0002.0301] # GREEK SMALL LETTER OMICRON WITH TONOS; QQCM
+1F79 ; [.12E0.0020.0002.03BF][.0000.0032.0002.0301] # GREEK SMALL LETTER OMICRON WITH OXIA; QQCM
+038C ; [.12E0.0020.0008.039F][.0000.0032.0002.0301] # GREEK CAPITAL LETTER OMICRON WITH TONOS; QQCM
+1FF9 ; [.12E0.0020.0008.039F][.0000.0032.0002.0301] # GREEK CAPITAL LETTER OMICRON WITH OXIA; QQCM
+1F78 ; [.12E0.0020.0002.03BF][.0000.0035.0002.0300] # GREEK SMALL LETTER OMICRON WITH VARIA; QQCM
+1FF8 ; [.12E0.0020.0008.039F][.0000.0035.0002.0300] # GREEK CAPITAL LETTER OMICRON WITH VARIA; QQCM
+03C0 ; [.12E1.0020.0002.03C0] # GREEK SMALL LETTER PI
+03D6 ; [.12E1.0020.0004.03D6] # GREEK PI SYMBOL; QQK
+213C ; [.12E1.0020.0005.213C] # DOUBLE-STRUCK SMALL PI; QQK
+1D6D1 ; [.12E1.0020.0005.1D6D1] # MATHEMATICAL BOLD SMALL PI; QQK
+1D6E1 ; [.12E1.0020.0005.1D6E1] # MATHEMATICAL BOLD PI SYMBOL; QQK
+1D70B ; [.12E1.0020.0005.1D70B] # MATHEMATICAL ITALIC SMALL PI; QQK
+1D71B ; [.12E1.0020.0005.1D71B] # MATHEMATICAL ITALIC PI SYMBOL; QQK
+1D745 ; [.12E1.0020.0005.1D745] # MATHEMATICAL BOLD ITALIC SMALL PI; QQK
+1D755 ; [.12E1.0020.0005.1D755] # MATHEMATICAL BOLD ITALIC PI SYMBOL; QQK
+1D77F ; [.12E1.0020.0005.1D77F] # MATHEMATICAL SANS-SERIF BOLD SMALL PI; QQK
+1D78F ; [.12E1.0020.0005.1D78F] # MATHEMATICAL SANS-SERIF BOLD PI SYMBOL; QQK
+1D7B9 ; [.12E1.0020.0005.1D7B9] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PI; QQK
+1D7C9 ; [.12E1.0020.0005.1D7C9] # MATHEMATICAL SANS-SERIF BOLD ITALIC PI SYMBOL; QQK
+03A0 ; [.12E1.0020.0008.03A0] # GREEK CAPITAL LETTER PI
+213F ; [.12E1.0020.000B.213F] # DOUBLE-STRUCK CAPITAL PI; QQK
+1D6B7 ; [.12E1.0020.000B.1D6B7] # MATHEMATICAL BOLD CAPITAL PI; QQK
+1D6F1 ; [.12E1.0020.000B.1D6F1] # MATHEMATICAL ITALIC CAPITAL PI; QQK
+1D72B ; [.12E1.0020.000B.1D72B] # MATHEMATICAL BOLD ITALIC CAPITAL PI; QQK
+1D765 ; [.12E1.0020.000B.1D765] # MATHEMATICAL SANS-SERIF BOLD CAPITAL PI; QQK
+1D79F ; [.12E1.0020.000B.1D79F] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PI; QQK
+1D28 ; [.12E2.0020.0002.1D28] # GREEK LETTER SMALL CAPITAL PI
+03FB ; [.12E3.0020.0002.03FB] # GREEK SMALL LETTER SAN
+03FA ; [.12E3.0020.0008.03FA] # GREEK CAPITAL LETTER SAN
+03DF ; [.12E4.0020.0002.03DF] # GREEK SMALL LETTER KOPPA
+03DE ; [.12E4.0020.0008.03DE] # GREEK LETTER KOPPA
+03D9 ; [.12E5.0020.0002.03D9] # GREEK SMALL LETTER ARCHAIC KOPPA
+03D8 ; [.12E5.0020.0008.03D8] # GREEK LETTER ARCHAIC KOPPA
+03C1 ; [.12E6.0020.0002.03C1] # GREEK SMALL LETTER RHO
+03F1 ; [.12E6.0020.0004.03F1] # GREEK RHO SYMBOL; QQK
+1D6D2 ; [.12E6.0020.0005.1D6D2] # MATHEMATICAL BOLD SMALL RHO; QQK
+1D6E0 ; [.12E6.0020.0005.1D6E0] # MATHEMATICAL BOLD RHO SYMBOL; QQK
+1D70C ; [.12E6.0020.0005.1D70C] # MATHEMATICAL ITALIC SMALL RHO; QQK
+1D71A ; [.12E6.0020.0005.1D71A] # MATHEMATICAL ITALIC RHO SYMBOL; QQK
+1D746 ; [.12E6.0020.0005.1D746] # MATHEMATICAL BOLD ITALIC SMALL RHO; QQK
+1D754 ; [.12E6.0020.0005.1D754] # MATHEMATICAL BOLD ITALIC RHO SYMBOL; QQK
+1D780 ; [.12E6.0020.0005.1D780] # MATHEMATICAL SANS-SERIF BOLD SMALL RHO; QQK
+1D78E ; [.12E6.0020.0005.1D78E] # MATHEMATICAL SANS-SERIF BOLD RHO SYMBOL; QQK
+1D7BA ; [.12E6.0020.0005.1D7BA] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL RHO; QQK
+1D7C8 ; [.12E6.0020.0005.1D7C8] # MATHEMATICAL SANS-SERIF BOLD ITALIC RHO SYMBOL; QQK
+03A1 ; [.12E6.0020.0008.03A1] # GREEK CAPITAL LETTER RHO
+1D6B8 ; [.12E6.0020.000B.1D6B8] # MATHEMATICAL BOLD CAPITAL RHO; QQK
+1D6F2 ; [.12E6.0020.000B.1D6F2] # MATHEMATICAL ITALIC CAPITAL RHO; QQK
+1D72C ; [.12E6.0020.000B.1D72C] # MATHEMATICAL BOLD ITALIC CAPITAL RHO; QQK
+1D766 ; [.12E6.0020.000B.1D766] # MATHEMATICAL SANS-SERIF BOLD CAPITAL RHO; QQK
+1D7A0 ; [.12E6.0020.000B.1D7A0] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL RHO; QQK
+1D68 ; [.12E6.0020.0015.1D68] # GREEK SUBSCRIPT SMALL LETTER RHO; QQK
+1FE4 ; [.12E6.0020.0002.03C1][.0000.0022.0002.0313] # GREEK SMALL LETTER RHO WITH PSILI; QQCM
+1FE5 ; [.12E6.0020.0002.03C1][.0000.002A.0002.0314] # GREEK SMALL LETTER RHO WITH DASIA; QQCM
+1FEC ; [.12E6.0020.0008.03A1][.0000.002A.0002.0314] # GREEK CAPITAL LETTER RHO WITH DASIA; QQCM
+1D29 ; [.12E7.0020.0002.1D29] # GREEK LETTER SMALL CAPITAL RHO
+03FC ; [.12E8.0020.0002.03FC] # GREEK RHO WITH STROKE SYMBOL
+03C3 ; [.12E9.0020.0002.03C3] # GREEK SMALL LETTER SIGMA
+03F2 ; [.12E9.0020.0004.03F2] # GREEK LUNATE SIGMA SYMBOL; QQK
+1D6D3 ; [.12E9.0020.0005.1D6D3] # MATHEMATICAL BOLD SMALL FINAL SIGMA; QQK
+1D6D4 ; [.12E9.0020.0005.1D6D4] # MATHEMATICAL BOLD SMALL SIGMA; QQK
+1D70D ; [.12E9.0020.0005.1D70D] # MATHEMATICAL ITALIC SMALL FINAL SIGMA; QQK
+1D70E ; [.12E9.0020.0005.1D70E] # MATHEMATICAL ITALIC SMALL SIGMA; QQK
+1D747 ; [.12E9.0020.0005.1D747] # MATHEMATICAL BOLD ITALIC SMALL FINAL SIGMA; QQK
+1D748 ; [.12E9.0020.0005.1D748] # MATHEMATICAL BOLD ITALIC SMALL SIGMA; QQK
+1D781 ; [.12E9.0020.0005.1D781] # MATHEMATICAL SANS-SERIF BOLD SMALL FINAL SIGMA; QQK
+1D782 ; [.12E9.0020.0005.1D782] # MATHEMATICAL SANS-SERIF BOLD SMALL SIGMA; QQK
+1D7BB ; [.12E9.0020.0005.1D7BB] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL FINAL SIGMA; QQK
+1D7BC ; [.12E9.0020.0005.1D7BC] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL SIGMA; QQK
+03A3 ; [.12E9.0020.0008.03A3] # GREEK CAPITAL LETTER SIGMA
+03F9 ; [.12E9.0020.000A.03F9] # GREEK CAPITAL LUNATE SIGMA SYMBOL; QQK
+1D6BA ; [.12E9.0020.000B.1D6BA] # MATHEMATICAL BOLD CAPITAL SIGMA; QQK
+1D6F4 ; [.12E9.0020.000B.1D6F4] # MATHEMATICAL ITALIC CAPITAL SIGMA; QQK
+1D72E ; [.12E9.0020.000B.1D72E] # MATHEMATICAL BOLD ITALIC CAPITAL SIGMA; QQK
+1D768 ; [.12E9.0020.000B.1D768] # MATHEMATICAL SANS-SERIF BOLD CAPITAL SIGMA; QQK
+1D7A2 ; [.12E9.0020.000B.1D7A2] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL SIGMA; QQK
+03C2 ; [.12E9.0020.0019.03C2] # GREEK SMALL LETTER FINAL SIGMA; QQK
+037C ; [.12EA.0020.0002.037C] # GREEK SMALL DOTTED LUNATE SIGMA SYMBOL
+03FE ; [.12EA.0020.0008.03FE] # GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL
+037B ; [.12EB.0020.0002.037B] # GREEK SMALL REVERSED LUNATE SIGMA SYMBOL
+03FD ; [.12EB.0020.0008.03FD] # GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL
+037D ; [.12EC.0020.0002.037D] # GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL
+03FF ; [.12EC.0020.0008.03FF] # GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL
+03C4 ; [.12ED.0020.0002.03C4] # GREEK SMALL LETTER TAU
+1D6D5 ; [.12ED.0020.0005.1D6D5] # MATHEMATICAL BOLD SMALL TAU; QQK
+1D70F ; [.12ED.0020.0005.1D70F] # MATHEMATICAL ITALIC SMALL TAU; QQK
+1D749 ; [.12ED.0020.0005.1D749] # MATHEMATICAL BOLD ITALIC SMALL TAU; QQK
+1D783 ; [.12ED.0020.0005.1D783] # MATHEMATICAL SANS-SERIF BOLD SMALL TAU; QQK
+1D7BD ; [.12ED.0020.0005.1D7BD] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL TAU; QQK
+03A4 ; [.12ED.0020.0008.03A4] # GREEK CAPITAL LETTER TAU
+1D6BB ; [.12ED.0020.000B.1D6BB] # MATHEMATICAL BOLD CAPITAL TAU; QQK
+1D6F5 ; [.12ED.0020.000B.1D6F5] # MATHEMATICAL ITALIC CAPITAL TAU; QQK
+1D72F ; [.12ED.0020.000B.1D72F] # MATHEMATICAL BOLD ITALIC CAPITAL TAU; QQK
+1D769 ; [.12ED.0020.000B.1D769] # MATHEMATICAL SANS-SERIF BOLD CAPITAL TAU; QQK
+1D7A3 ; [.12ED.0020.000B.1D7A3] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL TAU; QQK
+03C5 ; [.12EE.0020.0002.03C5] # GREEK SMALL LETTER UPSILON
+1D6D6 ; [.12EE.0020.0005.1D6D6] # MATHEMATICAL BOLD SMALL UPSILON; QQK
+1D710 ; [.12EE.0020.0005.1D710] # MATHEMATICAL ITALIC SMALL UPSILON; QQK
+1D74A ; [.12EE.0020.0005.1D74A] # MATHEMATICAL BOLD ITALIC SMALL UPSILON; QQK
+1D784 ; [.12EE.0020.0005.1D784] # MATHEMATICAL SANS-SERIF BOLD SMALL UPSILON; QQK
+1D7BE ; [.12EE.0020.0005.1D7BE] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL UPSILON; QQK
+03A5 ; [.12EE.0020.0008.03A5] # GREEK CAPITAL LETTER UPSILON
+03D2 ; [.12EE.0020.000A.03D2] # GREEK UPSILON WITH HOOK SYMBOL; QQK
+1D6BC ; [.12EE.0020.000B.1D6BC] # MATHEMATICAL BOLD CAPITAL UPSILON; QQK
+1D6F6 ; [.12EE.0020.000B.1D6F6] # MATHEMATICAL ITALIC CAPITAL UPSILON; QQK
+1D730 ; [.12EE.0020.000B.1D730] # MATHEMATICAL BOLD ITALIC CAPITAL UPSILON; QQK
+1D76A ; [.12EE.0020.000B.1D76A] # MATHEMATICAL SANS-SERIF BOLD CAPITAL UPSILON; QQK
+1D7A4 ; [.12EE.0020.000B.1D7A4] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL UPSILON; QQK
+1F50 ; [.12EE.0020.0002.03C5][.0000.0022.0002.0313] # GREEK SMALL LETTER UPSILON WITH PSILI; QQCM
+1F54 ; [.12EE.0020.0002.03C5][.0000.0022.0002.0313][.0000.0032.0002.0301] # GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA; QQCM
+1F52 ; [.12EE.0020.0002.03C5][.0000.0022.0002.0313][.0000.0035.0002.0300] # GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA; QQCM
+1F56 ; [.12EE.0020.0002.03C5][.0000.0022.0002.0313][.0000.0045.0002.0342] # GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI; QQCM
+1F51 ; [.12EE.0020.0002.03C5][.0000.002A.0002.0314] # GREEK SMALL LETTER UPSILON WITH DASIA; QQCM
+1F59 ; [.12EE.0020.0008.03A5][.0000.002A.0002.0314] # GREEK CAPITAL LETTER UPSILON WITH DASIA; QQCM
+1F55 ; [.12EE.0020.0002.03C5][.0000.002A.0002.0314][.0000.0032.0002.0301] # GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA; QQCM
+1F5D ; [.12EE.0020.0008.03A5][.0000.002A.0002.0314][.0000.0032.0002.0301] # GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA; QQCM
+1F53 ; [.12EE.0020.0002.03C5][.0000.002A.0002.0314][.0000.0035.0002.0300] # GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA; QQCM
+1F5B ; [.12EE.0020.0008.03A5][.0000.002A.0002.0314][.0000.0035.0002.0300] # GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA; QQCM
+1F57 ; [.12EE.0020.0002.03C5][.0000.002A.0002.0314][.0000.0045.0002.0342] # GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI; QQCM
+1F5F ; [.12EE.0020.0008.03A5][.0000.002A.0002.0314][.0000.0045.0002.0342] # GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI; QQCM
+03CD ; [.12EE.0020.0002.03C5][.0000.0032.0002.0301] # GREEK SMALL LETTER UPSILON WITH TONOS; QQCM
+1F7B ; [.12EE.0020.0002.03C5][.0000.0032.0002.0301] # GREEK SMALL LETTER UPSILON WITH OXIA; QQCM
+038E ; [.12EE.0020.0008.03A5][.0000.0032.0002.0301] # GREEK CAPITAL LETTER UPSILON WITH TONOS; QQCM
+1FEB ; [.12EE.0020.0008.03A5][.0000.0032.0002.0301] # GREEK CAPITAL LETTER UPSILON WITH OXIA; QQCM
+03D3 ; [.12EE.0020.000A.03D3][.0000.0032.0002.03D3] # GREEK UPSILON WITH ACUTE AND HOOK SYMBOL; QQKN
+1F7A ; [.12EE.0020.0002.03C5][.0000.0035.0002.0300] # GREEK SMALL LETTER UPSILON WITH VARIA; QQCM
+1FEA ; [.12EE.0020.0008.03A5][.0000.0035.0002.0300] # GREEK CAPITAL LETTER UPSILON WITH VARIA; QQCM
+1FE0 ; [.12EE.0020.0002.03C5][.0000.0037.0002.0306] # GREEK SMALL LETTER UPSILON WITH VRACHY; QQCM
+1FE8 ; [.12EE.0020.0008.03A5][.0000.0037.0002.0306] # GREEK CAPITAL LETTER UPSILON WITH VRACHY; QQCM
+1FE6 ; [.12EE.0020.0002.03C5][.0000.0045.0002.0342] # GREEK SMALL LETTER UPSILON WITH PERISPOMENI; QQCM
+03CB ; [.12EE.0020.0002.03C5][.0000.0047.0002.0308] # GREEK SMALL LETTER UPSILON WITH DIALYTIKA; QQCM
+03AB ; [.12EE.0020.0008.03A5][.0000.0047.0002.0308] # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA; QQCM
+03D4 ; [.12EE.0020.000A.03D4][.0000.0047.0002.03D4] # GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL; QQKN
+03B0 ; [.12EE.0020.0002.03C5][.0000.0047.0002.0308][.0000.0032.0002.0301] # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS; QQCM
+1FE3 ; [.12EE.0020.0002.03C5][.0000.0047.0002.0308][.0000.0032.0002.0301] # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA; QQCM
+1FE2 ; [.12EE.0020.0002.03C5][.0000.0047.0002.0308][.0000.0035.0002.0300] # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA; QQCM
+1FE7 ; [.12EE.0020.0002.03C5][.0000.0047.0002.0308][.0000.0045.0002.0342] # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI; QQCM
+1FE1 ; [.12EE.0020.0002.03C5][.0000.005B.0002.0304] # GREEK SMALL LETTER UPSILON WITH MACRON; QQCM
+1FE9 ; [.12EE.0020.0008.03A5][.0000.005B.0002.0304] # GREEK CAPITAL LETTER UPSILON WITH MACRON; QQCM
+03C6 ; [.12EF.0020.0002.03C6] # GREEK SMALL LETTER PHI
+03D5 ; [.12EF.0020.0004.03D5] # GREEK PHI SYMBOL; QQK
+1D6D7 ; [.12EF.0020.0005.1D6D7] # MATHEMATICAL BOLD SMALL PHI; QQK
+1D6DF ; [.12EF.0020.0005.1D6DF] # MATHEMATICAL BOLD PHI SYMBOL; QQK
+1D711 ; [.12EF.0020.0005.1D711] # MATHEMATICAL ITALIC SMALL PHI; QQK
+1D719 ; [.12EF.0020.0005.1D719] # MATHEMATICAL ITALIC PHI SYMBOL; QQK
+1D74B ; [.12EF.0020.0005.1D74B] # MATHEMATICAL BOLD ITALIC SMALL PHI; QQK
+1D753 ; [.12EF.0020.0005.1D753] # MATHEMATICAL BOLD ITALIC PHI SYMBOL; QQK
+1D785 ; [.12EF.0020.0005.1D785] # MATHEMATICAL SANS-SERIF BOLD SMALL PHI; QQK
+1D78D ; [.12EF.0020.0005.1D78D] # MATHEMATICAL SANS-SERIF BOLD PHI SYMBOL; QQK
+1D7BF ; [.12EF.0020.0005.1D7BF] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PHI; QQK
+1D7C7 ; [.12EF.0020.0005.1D7C7] # MATHEMATICAL SANS-SERIF BOLD ITALIC PHI SYMBOL; QQK
+03A6 ; [.12EF.0020.0008.03A6] # GREEK CAPITAL LETTER PHI
+1D6BD ; [.12EF.0020.000B.1D6BD] # MATHEMATICAL BOLD CAPITAL PHI; QQK
+1D6F7 ; [.12EF.0020.000B.1D6F7] # MATHEMATICAL ITALIC CAPITAL PHI; QQK
+1D731 ; [.12EF.0020.000B.1D731] # MATHEMATICAL BOLD ITALIC CAPITAL PHI; QQK
+1D76B ; [.12EF.0020.000B.1D76B] # MATHEMATICAL SANS-SERIF BOLD CAPITAL PHI; QQK
+1D7A5 ; [.12EF.0020.000B.1D7A5] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PHI; QQK
+1D60 ; [.12EF.0020.0014.1D60] # MODIFIER LETTER SMALL GREEK PHI; QQK
+1D69 ; [.12EF.0020.0015.1D69] # GREEK SUBSCRIPT SMALL LETTER PHI; QQK
+03C7 ; [.12F0.0020.0002.03C7] # GREEK SMALL LETTER CHI
+1D6D8 ; [.12F0.0020.0005.1D6D8] # MATHEMATICAL BOLD SMALL CHI; QQK
+1D712 ; [.12F0.0020.0005.1D712] # MATHEMATICAL ITALIC SMALL CHI; QQK
+1D74C ; [.12F0.0020.0005.1D74C] # MATHEMATICAL BOLD ITALIC SMALL CHI; QQK
+1D786 ; [.12F0.0020.0005.1D786] # MATHEMATICAL SANS-SERIF BOLD SMALL CHI; QQK
+1D7C0 ; [.12F0.0020.0005.1D7C0] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL CHI; QQK
+03A7 ; [.12F0.0020.0008.03A7] # GREEK CAPITAL LETTER CHI
+1D6BE ; [.12F0.0020.000B.1D6BE] # MATHEMATICAL BOLD CAPITAL CHI; QQK
+1D6F8 ; [.12F0.0020.000B.1D6F8] # MATHEMATICAL ITALIC CAPITAL CHI; QQK
+1D732 ; [.12F0.0020.000B.1D732] # MATHEMATICAL BOLD ITALIC CAPITAL CHI; QQK
+1D76C ; [.12F0.0020.000B.1D76C] # MATHEMATICAL SANS-SERIF BOLD CAPITAL CHI; QQK
+1D7A6 ; [.12F0.0020.000B.1D7A6] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL CHI; QQK
+1D61 ; [.12F0.0020.0014.1D61] # MODIFIER LETTER SMALL CHI; QQK
+1D6A ; [.12F0.0020.0015.1D6A] # GREEK SUBSCRIPT SMALL LETTER CHI; QQK
+03C8 ; [.12F1.0020.0002.03C8] # GREEK SMALL LETTER PSI
+1D6D9 ; [.12F1.0020.0005.1D6D9] # MATHEMATICAL BOLD SMALL PSI; QQK
+1D713 ; [.12F1.0020.0005.1D713] # MATHEMATICAL ITALIC SMALL PSI; QQK
+1D74D ; [.12F1.0020.0005.1D74D] # MATHEMATICAL BOLD ITALIC SMALL PSI; QQK
+1D787 ; [.12F1.0020.0005.1D787] # MATHEMATICAL SANS-SERIF BOLD SMALL PSI; QQK
+1D7C1 ; [.12F1.0020.0005.1D7C1] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL PSI; QQK
+03A8 ; [.12F1.0020.0008.03A8] # GREEK CAPITAL LETTER PSI
+1D6BF ; [.12F1.0020.000B.1D6BF] # MATHEMATICAL BOLD CAPITAL PSI; QQK
+1D6F9 ; [.12F1.0020.000B.1D6F9] # MATHEMATICAL ITALIC CAPITAL PSI; QQK
+1D733 ; [.12F1.0020.000B.1D733] # MATHEMATICAL BOLD ITALIC CAPITAL PSI; QQK
+1D76D ; [.12F1.0020.000B.1D76D] # MATHEMATICAL SANS-SERIF BOLD CAPITAL PSI; QQK
+1D7A7 ; [.12F1.0020.000B.1D7A7] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL PSI; QQK
+1D2A ; [.12F2.0020.0002.1D2A] # GREEK LETTER SMALL CAPITAL PSI
+03C9 ; [.12F3.0020.0002.03C9] # GREEK SMALL LETTER OMEGA
+1D6DA ; [.12F3.0020.0005.1D6DA] # MATHEMATICAL BOLD SMALL OMEGA; QQK
+1D714 ; [.12F3.0020.0005.1D714] # MATHEMATICAL ITALIC SMALL OMEGA; QQK
+1D74E ; [.12F3.0020.0005.1D74E] # MATHEMATICAL BOLD ITALIC SMALL OMEGA; QQK
+1D788 ; [.12F3.0020.0005.1D788] # MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA; QQK
+1D7C2 ; [.12F3.0020.0005.1D7C2] # MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA; QQK
+03A9 ; [.12F3.0020.0008.03A9] # GREEK CAPITAL LETTER OMEGA
+2126 ; [.12F3.0020.0008.2126] # OHM SIGN; QQC
+1D6C0 ; [.12F3.0020.000B.1D6C0] # MATHEMATICAL BOLD CAPITAL OMEGA; QQK
+1D6FA ; [.12F3.0020.000B.1D6FA] # MATHEMATICAL ITALIC CAPITAL OMEGA; QQK
+1D734 ; [.12F3.0020.000B.1D734] # MATHEMATICAL BOLD ITALIC CAPITAL OMEGA; QQK
+1D76E ; [.12F3.0020.000B.1D76E] # MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA; QQK
+1D7A8 ; [.12F3.0020.000B.1D7A8] # MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA; QQK
+1F60 ; [.12F3.0020.0002.03C9][.0000.0022.0002.0313] # GREEK SMALL LETTER OMEGA WITH PSILI; QQCM
+1F68 ; [.12F3.0020.0008.03A9][.0000.0022.0002.0313] # GREEK CAPITAL LETTER OMEGA WITH PSILI; QQCM
+1F64 ; [.12F3.0020.0002.03C9][.0000.0022.0002.0313][.0000.0032.0002.0301] # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA; QQCM
+1F6C ; [.12F3.0020.0008.03A9][.0000.0022.0002.0313][.0000.0032.0002.0301] # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA; QQCM
+1FA4 ; [.12F3.0020.0002.03C9][.0000.0022.0002.0313][.0000.0032.0002.0301][.0000.0097.0002.0345] # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI; QQCM
+1FAC ; [.12F3.0020.0008.03A9][.0000.0022.0002.0313][.0000.0032.0002.0301][.0000.0097.0002.0345] # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI; QQCM
+1F62 ; [.12F3.0020.0002.03C9][.0000.0022.0002.0313][.0000.0035.0002.0300] # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA; QQCM
+1F6A ; [.12F3.0020.0008.03A9][.0000.0022.0002.0313][.0000.0035.0002.0300] # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA; QQCM
+1FA2 ; [.12F3.0020.0002.03C9][.0000.0022.0002.0313][.0000.0035.0002.0300][.0000.0097.0002.0345] # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI; QQCM
+1FAA ; [.12F3.0020.0008.03A9][.0000.0022.0002.0313][.0000.0035.0002.0300][.0000.0097.0002.0345] # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI; QQCM
+1F66 ; [.12F3.0020.0002.03C9][.0000.0022.0002.0313][.0000.0045.0002.0342] # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI; QQCM
+1F6E ; [.12F3.0020.0008.03A9][.0000.0022.0002.0313][.0000.0045.0002.0342] # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI; QQCM
+1FA6 ; [.12F3.0020.0002.03C9][.0000.0022.0002.0313][.0000.0045.0002.0342][.0000.0097.0002.0345] # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI; QQCM
+1FAE ; [.12F3.0020.0008.03A9][.0000.0022.0002.0313][.0000.0045.0002.0342][.0000.0097.0002.0345] # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI; QQCM
+1FA0 ; [.12F3.0020.0002.03C9][.0000.0022.0002.0313][.0000.0097.0002.0345] # GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI; QQCM
+1FA8 ; [.12F3.0020.0008.03A9][.0000.0022.0002.0313][.0000.0097.0002.0345] # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI; QQCM
+1F61 ; [.12F3.0020.0002.03C9][.0000.002A.0002.0314] # GREEK SMALL LETTER OMEGA WITH DASIA; QQCM
+1F69 ; [.12F3.0020.0008.03A9][.0000.002A.0002.0314] # GREEK CAPITAL LETTER OMEGA WITH DASIA; QQCM
+1F65 ; [.12F3.0020.0002.03C9][.0000.002A.0002.0314][.0000.0032.0002.0301] # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA; QQCM
+1F6D ; [.12F3.0020.0008.03A9][.0000.002A.0002.0314][.0000.0032.0002.0301] # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA; QQCM
+1FA5 ; [.12F3.0020.0002.03C9][.0000.002A.0002.0314][.0000.0032.0002.0301][.0000.0097.0002.0345] # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI; QQCM
+1FAD ; [.12F3.0020.0008.03A9][.0000.002A.0002.0314][.0000.0032.0002.0301][.0000.0097.0002.0345] # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI; QQCM
+1F63 ; [.12F3.0020.0002.03C9][.0000.002A.0002.0314][.0000.0035.0002.0300] # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA; QQCM
+1F6B ; [.12F3.0020.0008.03A9][.0000.002A.0002.0314][.0000.0035.0002.0300] # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA; QQCM
+1FA3 ; [.12F3.0020.0002.03C9][.0000.002A.0002.0314][.0000.0035.0002.0300][.0000.0097.0002.0345] # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI; QQCM
+1FAB ; [.12F3.0020.0008.03A9][.0000.002A.0002.0314][.0000.0035.0002.0300][.0000.0097.0002.0345] # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI; QQCM
+1F67 ; [.12F3.0020.0002.03C9][.0000.002A.0002.0314][.0000.0045.0002.0342] # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI; QQCM
+1F6F ; [.12F3.0020.0008.03A9][.0000.002A.0002.0314][.0000.0045.0002.0342] # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI; QQCM
+1FA7 ; [.12F3.0020.0002.03C9][.0000.002A.0002.0314][.0000.0045.0002.0342][.0000.0097.0002.0345] # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI; QQCM
+1FAF ; [.12F3.0020.0008.03A9][.0000.002A.0002.0314][.0000.0045.0002.0342][.0000.0097.0002.0345] # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI; QQCM
+1FA1 ; [.12F3.0020.0002.03C9][.0000.002A.0002.0314][.0000.0097.0002.0345] # GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI; QQCM
+1FA9 ; [.12F3.0020.0008.03A9][.0000.002A.0002.0314][.0000.0097.0002.0345] # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI; QQCM
+03CE ; [.12F3.0020.0002.03C9][.0000.0032.0002.0301] # GREEK SMALL LETTER OMEGA WITH TONOS; QQCM
+1F7D ; [.12F3.0020.0002.03C9][.0000.0032.0002.0301] # GREEK SMALL LETTER OMEGA WITH OXIA; QQCM
+038F ; [.12F3.0020.0008.03A9][.0000.0032.0002.0301] # GREEK CAPITAL LETTER OMEGA WITH TONOS; QQCM
+1FFB ; [.12F3.0020.0008.03A9][.0000.0032.0002.0301] # GREEK CAPITAL LETTER OMEGA WITH OXIA; QQCM
+1FF4 ; [.12F3.0020.0002.03C9][.0000.0032.0002.0301][.0000.0097.0002.0345] # GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI; QQCM
+1F7C ; [.12F3.0020.0002.03C9][.0000.0035.0002.0300] # GREEK SMALL LETTER OMEGA WITH VARIA; QQCM
+1FFA ; [.12F3.0020.0008.03A9][.0000.0035.0002.0300] # GREEK CAPITAL LETTER OMEGA WITH VARIA; QQCM
+1FF2 ; [.12F3.0020.0002.03C9][.0000.0035.0002.0300][.0000.0097.0002.0345] # GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI; QQCM
+1FF6 ; [.12F3.0020.0002.03C9][.0000.0045.0002.0342] # GREEK SMALL LETTER OMEGA WITH PERISPOMENI; QQCM
+1FF7 ; [.12F3.0020.0002.03C9][.0000.0045.0002.0342][.0000.0097.0002.0345] # GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI; QQCM
+1FF3 ; [.12F3.0020.0002.03C9][.0000.0097.0002.0345] # GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI; QQCM
+1FFC ; [.12F3.0020.0008.03A9][.0000.0097.0002.0345] # GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI; QQCM
+03E1 ; [.12F4.0020.0002.03E1] # GREEK SMALL LETTER SAMPI
+03E0 ; [.12F4.0020.0008.03E0] # GREEK LETTER SAMPI
+03F8 ; [.12F5.0020.0002.03F8] # GREEK SMALL LETTER SHO
+03F7 ; [.12F5.0020.0008.03F7] # GREEK CAPITAL LETTER SHO
+2C81 ; [.12F6.0020.0002.2C81] # COPTIC SMALL LETTER ALFA
+2C80 ; [.12F6.0020.0008.2C80] # COPTIC CAPITAL LETTER ALFA
+2C83 ; [.12F7.0020.0002.2C83] # COPTIC SMALL LETTER VIDA
+2C82 ; [.12F7.0020.0008.2C82] # COPTIC CAPITAL LETTER VIDA
+2C85 ; [.12F8.0020.0002.2C85] # COPTIC SMALL LETTER GAMMA
+2C84 ; [.12F8.0020.0008.2C84] # COPTIC CAPITAL LETTER GAMMA
+2C87 ; [.12F9.0020.0002.2C87] # COPTIC SMALL LETTER DALDA
+2C86 ; [.12F9.0020.0008.2C86] # COPTIC CAPITAL LETTER DALDA
+2C89 ; [.12FA.0020.0002.2C89] # COPTIC SMALL LETTER EIE
+2C88 ; [.12FA.0020.0008.2C88] # COPTIC CAPITAL LETTER EIE
+2CB7 ; [.12FB.0020.0002.2CB7] # COPTIC SMALL LETTER CRYPTOGRAMMIC EIE
+2CB6 ; [.12FB.0020.0008.2CB6] # COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE
+2C8B ; [.12FC.0020.0002.2C8B] # COPTIC SMALL LETTER SOU
+2C8A ; [.12FC.0020.0008.2C8A] # COPTIC CAPITAL LETTER SOU
+2C8D ; [.12FD.0020.0002.2C8D] # COPTIC SMALL LETTER ZATA
+2C8C ; [.12FD.0020.0008.2C8C] # COPTIC CAPITAL LETTER ZATA
+2C8F ; [.12FE.0020.0002.2C8F] # COPTIC SMALL LETTER HATE
+2C8E ; [.12FE.0020.0008.2C8E] # COPTIC CAPITAL LETTER HATE
+2C91 ; [.12FF.0020.0002.2C91] # COPTIC SMALL LETTER THETHE
+2C90 ; [.12FF.0020.0008.2C90] # COPTIC CAPITAL LETTER THETHE
+2C93 ; [.1300.0020.0002.2C93] # COPTIC SMALL LETTER IAUDA
+2C92 ; [.1300.0020.0008.2C92] # COPTIC CAPITAL LETTER IAUDA
+2C95 ; [.1301.0020.0002.2C95] # COPTIC SMALL LETTER KAPA
+2C94 ; [.1301.0020.0008.2C94] # COPTIC CAPITAL LETTER KAPA
+2CE4 ; [.1301.0020.0004.2CE4][.12F6.0020.0004.2CE4][.1300.0020.001F.2CE4] # COPTIC SYMBOL KAI; QQKN
+2CB9 ; [.1302.0020.0002.2CB9] # COPTIC SMALL LETTER DIALECT-P KAPA
+2CB8 ; [.1302.0020.0008.2CB8] # COPTIC CAPITAL LETTER DIALECT-P KAPA
+2C97 ; [.1303.0020.0002.2C97] # COPTIC SMALL LETTER LAULA
+2C96 ; [.1303.0020.0008.2C96] # COPTIC CAPITAL LETTER LAULA
+2C99 ; [.1304.0020.0002.2C99] # COPTIC SMALL LETTER MI
+2C98 ; [.1304.0020.0008.2C98] # COPTIC CAPITAL LETTER MI
+2C9B ; [.1305.0020.0002.2C9B] # COPTIC SMALL LETTER NI
+2C9A ; [.1305.0020.0008.2C9A] # COPTIC CAPITAL LETTER NI
+2CBB ; [.1306.0020.0002.2CBB] # COPTIC SMALL LETTER DIALECT-P NI
+2CBA ; [.1306.0020.0008.2CBA] # COPTIC CAPITAL LETTER DIALECT-P NI
+2CBD ; [.1307.0020.0002.2CBD] # COPTIC SMALL LETTER CRYPTOGRAMMIC NI
+2CBC ; [.1307.0020.0008.2CBC] # COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI
+2C9D ; [.1308.0020.0002.2C9D] # COPTIC SMALL LETTER KSI
+2C9C ; [.1308.0020.0008.2C9C] # COPTIC CAPITAL LETTER KSI
+2C9F ; [.1309.0020.0002.2C9F] # COPTIC SMALL LETTER O
+2C9E ; [.1309.0020.0008.2C9E] # COPTIC CAPITAL LETTER O
+2CA1 ; [.130A.0020.0002.2CA1] # COPTIC SMALL LETTER PI
+2CA0 ; [.130A.0020.0008.2CA0] # COPTIC CAPITAL LETTER PI
+2CA3 ; [.130B.0020.0002.2CA3] # COPTIC SMALL LETTER RO
+2CA2 ; [.130B.0020.0008.2CA2] # COPTIC CAPITAL LETTER RO
+2CA5 ; [.130C.0020.0002.2CA5] # COPTIC SMALL LETTER SIMA
+2CA4 ; [.130C.0020.0008.2CA4] # COPTIC CAPITAL LETTER SIMA
+2CA7 ; [.130D.0020.0002.2CA7] # COPTIC SMALL LETTER TAU
+2CA6 ; [.130D.0020.0008.2CA6] # COPTIC CAPITAL LETTER TAU
+2CA9 ; [.130E.0020.0002.2CA9] # COPTIC SMALL LETTER UA
+2CA8 ; [.130E.0020.0008.2CA8] # COPTIC CAPITAL LETTER UA
+2CAB ; [.130F.0020.0002.2CAB] # COPTIC SMALL LETTER FI
+2CAA ; [.130F.0020.0008.2CAA] # COPTIC CAPITAL LETTER FI
+2CAD ; [.1310.0020.0002.2CAD] # COPTIC SMALL LETTER KHI
+2CAC ; [.1310.0020.0008.2CAC] # COPTIC CAPITAL LETTER KHI
+2CAF ; [.1311.0020.0002.2CAF] # COPTIC SMALL LETTER PSI
+2CAE ; [.1311.0020.0008.2CAE] # COPTIC CAPITAL LETTER PSI
+2CB1 ; [.1312.0020.0002.2CB1] # COPTIC SMALL LETTER OOU
+2CB0 ; [.1312.0020.0008.2CB0] # COPTIC CAPITAL LETTER OOU
+2CBF ; [.1313.0020.0002.2CBF] # COPTIC SMALL LETTER OLD COPTIC OOU
+2CBE ; [.1313.0020.0008.2CBE] # COPTIC CAPITAL LETTER OLD COPTIC OOU
+2CC1 ; [.1314.0020.0002.2CC1] # COPTIC SMALL LETTER SAMPI
+2CC0 ; [.1314.0020.0008.2CC0] # COPTIC CAPITAL LETTER SAMPI
+03E3 ; [.1315.0020.0002.03E3] # COPTIC SMALL LETTER SHEI
+03E2 ; [.1315.0020.0008.03E2] # COPTIC CAPITAL LETTER SHEI
+2CC3 ; [.1316.0020.0002.2CC3] # COPTIC SMALL LETTER CROSSED SHEI
+2CC2 ; [.1316.0020.0008.2CC2] # COPTIC CAPITAL LETTER CROSSED SHEI
+2CC5 ; [.1317.0020.0002.2CC5] # COPTIC SMALL LETTER OLD COPTIC SHEI
+2CC4 ; [.1317.0020.0008.2CC4] # COPTIC CAPITAL LETTER OLD COPTIC SHEI
+2CC7 ; [.1318.0020.0002.2CC7] # COPTIC SMALL LETTER OLD COPTIC ESH
+2CC6 ; [.1318.0020.0008.2CC6] # COPTIC CAPITAL LETTER OLD COPTIC ESH
+03E5 ; [.1319.0020.0002.03E5] # COPTIC SMALL LETTER FEI
+03E4 ; [.1319.0020.0008.03E4] # COPTIC CAPITAL LETTER FEI
+03E7 ; [.131A.0020.0002.03E7] # COPTIC SMALL LETTER KHEI
+03E6 ; [.131A.0020.0008.03E6] # COPTIC CAPITAL LETTER KHEI
+2CC9 ; [.131B.0020.0002.2CC9] # COPTIC SMALL LETTER AKHMIMIC KHEI
+2CC8 ; [.131B.0020.0008.2CC8] # COPTIC CAPITAL LETTER AKHMIMIC KHEI
+03E9 ; [.131C.0020.0002.03E9] # COPTIC SMALL LETTER HORI
+03E8 ; [.131C.0020.0008.03E8] # COPTIC CAPITAL LETTER HORI
+2CCB ; [.131D.0020.0002.2CCB] # COPTIC SMALL LETTER DIALECT-P HORI
+2CCA ; [.131D.0020.0008.2CCA] # COPTIC CAPITAL LETTER DIALECT-P HORI
+2CCD ; [.131E.0020.0002.2CCD] # COPTIC SMALL LETTER OLD COPTIC HORI
+2CCC ; [.131E.0020.0008.2CCC] # COPTIC CAPITAL LETTER OLD COPTIC HORI
+2CCF ; [.131F.0020.0002.2CCF] # COPTIC SMALL LETTER OLD COPTIC HA
+2CCE ; [.131F.0020.0008.2CCE] # COPTIC CAPITAL LETTER OLD COPTIC HA
+2CD1 ; [.1320.0020.0002.2CD1] # COPTIC SMALL LETTER L-SHAPED HA
+2CD0 ; [.1320.0020.0008.2CD0] # COPTIC CAPITAL LETTER L-SHAPED HA
+2CD3 ; [.1321.0020.0002.2CD3] # COPTIC SMALL LETTER OLD COPTIC HEI
+2CD2 ; [.1321.0020.0008.2CD2] # COPTIC CAPITAL LETTER OLD COPTIC HEI
+2CD5 ; [.1322.0020.0002.2CD5] # COPTIC SMALL LETTER OLD COPTIC HAT
+2CD4 ; [.1322.0020.0008.2CD4] # COPTIC CAPITAL LETTER OLD COPTIC HAT
+03EB ; [.1323.0020.0002.03EB] # COPTIC SMALL LETTER GANGIA
+03EA ; [.1323.0020.0008.03EA] # COPTIC CAPITAL LETTER GANGIA
+2CD7 ; [.1324.0020.0002.2CD7] # COPTIC SMALL LETTER OLD COPTIC GANGIA
+2CD6 ; [.1324.0020.0008.2CD6] # COPTIC CAPITAL LETTER OLD COPTIC GANGIA
+03ED ; [.1325.0020.0002.03ED] # COPTIC SMALL LETTER SHIMA
+03EC ; [.1325.0020.0008.03EC] # COPTIC CAPITAL LETTER SHIMA
+2CD9 ; [.1326.0020.0002.2CD9] # COPTIC SMALL LETTER OLD COPTIC DJA
+2CD8 ; [.1326.0020.0008.2CD8] # COPTIC CAPITAL LETTER OLD COPTIC DJA
+2CDB ; [.1327.0020.0002.2CDB] # COPTIC SMALL LETTER OLD COPTIC SHIMA
+2CDA ; [.1327.0020.0008.2CDA] # COPTIC CAPITAL LETTER OLD COPTIC SHIMA
+2CDD ; [.1328.0020.0002.2CDD] # COPTIC SMALL LETTER OLD NUBIAN SHIMA
+2CDC ; [.1328.0020.0008.2CDC] # COPTIC CAPITAL LETTER OLD NUBIAN SHIMA
+03EF ; [.1329.0020.0002.03EF] # COPTIC SMALL LETTER DEI
+03EE ; [.1329.0020.0008.03EE] # COPTIC CAPITAL LETTER DEI
+2CB3 ; [.132A.0020.0002.2CB3] # COPTIC SMALL LETTER DIALECT-P ALEF
+2CB2 ; [.132A.0020.0008.2CB2] # COPTIC CAPITAL LETTER DIALECT-P ALEF
+2CB5 ; [.132B.0020.0002.2CB5] # COPTIC SMALL LETTER OLD COPTIC AIN
+2CB4 ; [.132B.0020.0008.2CB4] # COPTIC CAPITAL LETTER OLD COPTIC AIN
+2CDF ; [.132C.0020.0002.2CDF] # COPTIC SMALL LETTER OLD NUBIAN NGI
+2CDE ; [.132C.0020.0008.2CDE] # COPTIC CAPITAL LETTER OLD NUBIAN NGI
+2CE1 ; [.132D.0020.0002.2CE1] # COPTIC SMALL LETTER OLD NUBIAN NYI
+2CE0 ; [.132D.0020.0008.2CE0] # COPTIC CAPITAL LETTER OLD NUBIAN NYI
+2CE3 ; [.132E.0020.0002.2CE3] # COPTIC SMALL LETTER OLD NUBIAN WAU
+2CE2 ; [.132E.0020.0008.2CE2] # COPTIC CAPITAL LETTER OLD NUBIAN WAU
+0430 ; [.132F.0020.0002.0430] # CYRILLIC SMALL LETTER A
+0410 ; [.132F.0020.0008.0410] # CYRILLIC CAPITAL LETTER A
+04D1 ; [.1333.0020.0002.04D1] # CYRILLIC SMALL LETTER A WITH BREVE
+0430 0306 ; [.1333.0020.0002.04D1] # CYRILLIC SMALL LETTER A WITH BREVE
+04D0 ; [.1333.0020.0008.04D0] # CYRILLIC CAPITAL LETTER A WITH BREVE
+0410 0306 ; [.1333.0020.0008.04D0] # CYRILLIC CAPITAL LETTER A WITH BREVE
+04D3 ; [.1337.0020.0002.04D3] # CYRILLIC SMALL LETTER A WITH DIAERESIS
+0430 0308 ; [.1337.0020.0002.04D3] # CYRILLIC SMALL LETTER A WITH DIAERESIS
+04D2 ; [.1337.0020.0008.04D2] # CYRILLIC CAPITAL LETTER A WITH DIAERESIS
+0410 0308 ; [.1337.0020.0008.04D2] # CYRILLIC CAPITAL LETTER A WITH DIAERESIS
+04D9 ; [.133B.0020.0002.04D9] # CYRILLIC SMALL LETTER SCHWA
+04D8 ; [.133B.0020.0008.04D8] # CYRILLIC CAPITAL LETTER SCHWA
+04DB ; [.133F.0020.0002.04DB] # CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS
+04D9 0308 ; [.133F.0020.0002.04DB] # CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS
+04DA ; [.133F.0020.0008.04DA] # CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS
+04D8 0308 ; [.133F.0020.0008.04DA] # CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS
+04D5 ; [.1343.0020.0002.04D5] # CYRILLIC SMALL LIGATURE A IE
+04D4 ; [.1343.0020.0008.04D4] # CYRILLIC CAPITAL LIGATURE A IE
+0431 ; [.1347.0020.0002.0431] # CYRILLIC SMALL LETTER BE
+0411 ; [.1347.0020.0008.0411] # CYRILLIC CAPITAL LETTER BE
+0432 ; [.134B.0020.0002.0432] # CYRILLIC SMALL LETTER VE
+0412 ; [.134B.0020.0008.0412] # CYRILLIC CAPITAL LETTER VE
+0433 ; [.134F.0020.0002.0433] # CYRILLIC SMALL LETTER GHE
+0413 ; [.134F.0020.0008.0413] # CYRILLIC CAPITAL LETTER GHE
+0491 ; [.134F.0020.0004.0491][.0000.019A.0004.0491] # CYRILLIC SMALL LETTER GHE WITH UPTURN; QQKN
+0490 ; [.134F.0020.000A.0490][.0000.019A.0004.0490] # CYRILLIC CAPITAL LETTER GHE WITH UPTURN; QQKN
+0493 ; [.1353.0020.0002.0493] # CYRILLIC SMALL LETTER GHE WITH STROKE
+0492 ; [.1353.0020.0008.0492] # CYRILLIC CAPITAL LETTER GHE WITH STROKE
+04FB ; [.1357.0020.0002.04FB] # CYRILLIC SMALL LETTER GHE WITH STROKE AND HOOK
+04FA ; [.1357.0020.0008.04FA] # CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK
+0495 ; [.135B.0020.0002.0495] # CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK
+0494 ; [.135B.0020.0008.0494] # CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK
+04F7 ; [.135F.0020.0002.04F7] # CYRILLIC SMALL LETTER GHE WITH DESCENDER
+04F6 ; [.135F.0020.0008.04F6] # CYRILLIC CAPITAL LETTER GHE WITH DESCENDER
+0434 ; [.1363.0020.0002.0434] # CYRILLIC SMALL LETTER DE
+0414 ; [.1363.0020.0008.0414] # CYRILLIC CAPITAL LETTER DE
+0501 ; [.1367.0020.0002.0501] # CYRILLIC SMALL LETTER KOMI DE
+0500 ; [.1367.0020.0008.0500] # CYRILLIC CAPITAL LETTER KOMI DE
+0452 ; [.1368.0020.0002.0452] # CYRILLIC SMALL LETTER DJE
+0402 ; [.1368.0020.0008.0402] # CYRILLIC CAPITAL LETTER DJE
+0503 ; [.136C.0020.0002.0503] # CYRILLIC SMALL LETTER KOMI DJE
+0502 ; [.136C.0020.0008.0502] # CYRILLIC CAPITAL LETTER KOMI DJE
+0453 ; [.136D.0020.0002.0453] # CYRILLIC SMALL LETTER GJE
+0433 0301 ; [.136D.0020.0002.0453] # CYRILLIC SMALL LETTER GJE
+0433 0341 ; [.136D.0020.0002.0453] # CYRILLIC SMALL LETTER GJE
+0403 ; [.136D.0020.0008.0403] # CYRILLIC CAPITAL LETTER GJE
+0413 0301 ; [.136D.0020.0008.0403] # CYRILLIC CAPITAL LETTER GJE
+0413 0341 ; [.136D.0020.0008.0403] # CYRILLIC CAPITAL LETTER GJE
+0499 ; [.1371.0020.0002.0499] # CYRILLIC SMALL LETTER ZE WITH DESCENDER
+0498 ; [.1371.0020.0008.0498] # CYRILLIC CAPITAL LETTER ZE WITH DESCENDER
+0435 ; [.1375.0020.0002.0435] # CYRILLIC SMALL LETTER IE
+0415 ; [.1375.0020.0008.0415] # CYRILLIC CAPITAL LETTER IE
+0450 ; [.1375.0020.0002.0435][.0000.0035.0002.0300] # CYRILLIC SMALL LETTER IE WITH GRAVE; QQCM
+0400 ; [.1375.0020.0008.0415][.0000.0035.0002.0300] # CYRILLIC CAPITAL LETTER IE WITH GRAVE; QQCM
+0451 ; [.1375.0020.0002.0435][.0000.0047.0002.0308] # CYRILLIC SMALL LETTER IO; QQCM
+0401 ; [.1375.0020.0008.0415][.0000.0047.0002.0308] # CYRILLIC CAPITAL LETTER IO; QQCM
+04D7 ; [.1379.0020.0002.04D7] # CYRILLIC SMALL LETTER IE WITH BREVE
+0435 0306 ; [.1379.0020.0002.04D7] # CYRILLIC SMALL LETTER IE WITH BREVE
+04D6 ; [.1379.0020.0008.04D6] # CYRILLIC CAPITAL LETTER IE WITH BREVE
+0415 0306 ; [.1379.0020.0008.04D6] # CYRILLIC CAPITAL LETTER IE WITH BREVE
+0454 ; [.137D.0020.0002.0454] # CYRILLIC SMALL LETTER UKRAINIAN IE
+0404 ; [.137D.0020.0008.0404] # CYRILLIC CAPITAL LETTER UKRAINIAN IE
+0436 ; [.1381.0020.0002.0436] # CYRILLIC SMALL LETTER ZHE
+0416 ; [.1381.0020.0008.0416] # CYRILLIC CAPITAL LETTER ZHE
+04C2 ; [.1381.0020.0002.0436][.0000.0037.0002.0306] # CYRILLIC SMALL LETTER ZHE WITH BREVE; QQCM
+04C1 ; [.1381.0020.0008.0416][.0000.0037.0002.0306] # CYRILLIC CAPITAL LETTER ZHE WITH BREVE; QQCM
+04DD ; [.1385.0020.0002.04DD] # CYRILLIC SMALL LETTER ZHE WITH DIAERESIS
+0436 0308 ; [.1385.0020.0002.04DD] # CYRILLIC SMALL LETTER ZHE WITH DIAERESIS
+04DC ; [.1385.0020.0008.04DC] # CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS
+0416 0308 ; [.1385.0020.0008.04DC] # CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS
+0497 ; [.1389.0020.0002.0497] # CYRILLIC SMALL LETTER ZHE WITH DESCENDER
+0496 ; [.1389.0020.0008.0496] # CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER
+0437 ; [.138D.0020.0002.0437] # CYRILLIC SMALL LETTER ZE
+0417 ; [.138D.0020.0008.0417] # CYRILLIC CAPITAL LETTER ZE
+0505 ; [.1391.0020.0002.0505] # CYRILLIC SMALL LETTER KOMI ZJE
+0504 ; [.1391.0020.0008.0504] # CYRILLIC CAPITAL LETTER KOMI ZJE
+0511 ; [.1392.0020.0002.0511] # CYRILLIC SMALL LETTER REVERSED ZE
+0510 ; [.1392.0020.0008.0510] # CYRILLIC CAPITAL LETTER REVERSED ZE
+04DF ; [.1393.0020.0002.04DF] # CYRILLIC SMALL LETTER ZE WITH DIAERESIS
+0437 0308 ; [.1393.0020.0002.04DF] # CYRILLIC SMALL LETTER ZE WITH DIAERESIS
+04DE ; [.1393.0020.0008.04DE] # CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS
+0417 0308 ; [.1393.0020.0008.04DE] # CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS
+0455 ; [.1397.0020.0002.0455] # CYRILLIC SMALL LETTER DZE
+0405 ; [.1397.0020.0008.0405] # CYRILLIC CAPITAL LETTER DZE
+04E1 ; [.139B.0020.0002.04E1] # CYRILLIC SMALL LETTER ABKHASIAN DZE
+04E0 ; [.139B.0020.0008.04E0] # CYRILLIC CAPITAL LETTER ABKHASIAN DZE
+0507 ; [.139F.0020.0002.0507] # CYRILLIC SMALL LETTER KOMI DZJE
+0506 ; [.139F.0020.0008.0506] # CYRILLIC CAPITAL LETTER KOMI DZJE
+0438 ; [.13A0.0020.0002.0438] # CYRILLIC SMALL LETTER I
+0418 ; [.13A0.0020.0008.0418] # CYRILLIC CAPITAL LETTER I
+045D ; [.13A0.0020.0002.0438][.0000.0035.0002.0300] # CYRILLIC SMALL LETTER I WITH GRAVE; QQCM
+040D ; [.13A0.0020.0008.0418][.0000.0035.0002.0300] # CYRILLIC CAPITAL LETTER I WITH GRAVE; QQCM
+04E3 ; [.13A0.0020.0002.0438][.0000.005B.0002.0304] # CYRILLIC SMALL LETTER I WITH MACRON; QQCM
+04E2 ; [.13A0.0020.0008.0418][.0000.005B.0002.0304] # CYRILLIC CAPITAL LETTER I WITH MACRON; QQCM
+048B ; [.13A4.0020.0002.048B] # CYRILLIC SMALL LETTER SHORT I WITH TAIL
+048A ; [.13A4.0020.0008.048A] # CYRILLIC CAPITAL LETTER SHORT I WITH TAIL
+04E5 ; [.13A8.0020.0002.04E5] # CYRILLIC SMALL LETTER I WITH DIAERESIS
+0438 0308 ; [.13A8.0020.0002.04E5] # CYRILLIC SMALL LETTER I WITH DIAERESIS
+04E4 ; [.13A8.0020.0008.04E4] # CYRILLIC CAPITAL LETTER I WITH DIAERESIS
+0418 0308 ; [.13A8.0020.0008.04E4] # CYRILLIC CAPITAL LETTER I WITH DIAERESIS
+0456 ; [.13AC.0020.0002.0456] # CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+0406 ; [.13AC.0020.0008.0406] # CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
+0457 ; [.13B0.0020.0002.0457] # CYRILLIC SMALL LETTER YI
+0456 0308 ; [.13B0.0020.0002.0457] # CYRILLIC SMALL LETTER YI
+0407 ; [.13B0.0020.0008.0407] # CYRILLIC CAPITAL LETTER YI
+0406 0308 ; [.13B0.0020.0008.0407] # CYRILLIC CAPITAL LETTER YI
+0439 ; [.13B4.0020.0002.0439] # CYRILLIC SMALL LETTER SHORT I
+0438 0306 ; [.13B4.0020.0002.0439] # CYRILLIC SMALL LETTER SHORT I
+0419 ; [.13B4.0020.0008.0419] # CYRILLIC CAPITAL LETTER SHORT I
+0418 0306 ; [.13B4.0020.0008.0419] # CYRILLIC CAPITAL LETTER SHORT I
+0458 ; [.13B8.0020.0002.0458] # CYRILLIC SMALL LETTER JE
+0408 ; [.13B8.0020.0008.0408] # CYRILLIC CAPITAL LETTER JE
+043A ; [.13BC.0020.0002.043A] # CYRILLIC SMALL LETTER KA
+041A ; [.13BC.0020.0008.041A] # CYRILLIC CAPITAL LETTER KA
+049B ; [.13C0.0020.0002.049B] # CYRILLIC SMALL LETTER KA WITH DESCENDER
+049A ; [.13C0.0020.0008.049A] # CYRILLIC CAPITAL LETTER KA WITH DESCENDER
+04C4 ; [.13C4.0020.0002.04C4] # CYRILLIC SMALL LETTER KA WITH HOOK
+04C3 ; [.13C4.0020.0008.04C3] # CYRILLIC CAPITAL LETTER KA WITH HOOK
+04A1 ; [.13C8.0020.0002.04A1] # CYRILLIC SMALL LETTER BASHKIR KA
+04A0 ; [.13C8.0020.0008.04A0] # CYRILLIC CAPITAL LETTER BASHKIR KA
+049F ; [.13CC.0020.0002.049F] # CYRILLIC SMALL LETTER KA WITH STROKE
+049E ; [.13CC.0020.0008.049E] # CYRILLIC CAPITAL LETTER KA WITH STROKE
+049D ; [.13D0.0020.0002.049D] # CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE
+049C ; [.13D0.0020.0008.049C] # CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE
+043B ; [.13D4.0020.0002.043B] # CYRILLIC SMALL LETTER EL
+041B ; [.13D4.0020.0008.041B] # CYRILLIC CAPITAL LETTER EL
+1D2B ; [.13D8.0020.0002.1D2B] # CYRILLIC LETTER SMALL CAPITAL EL
+04C6 ; [.13D9.0020.0002.04C6] # CYRILLIC SMALL LETTER EL WITH TAIL
+04C5 ; [.13D9.0020.0008.04C5] # CYRILLIC CAPITAL LETTER EL WITH TAIL
+0513 ; [.13DD.0020.0002.0513] # CYRILLIC SMALL LETTER EL WITH HOOK
+0512 ; [.13DD.0020.0008.0512] # CYRILLIC CAPITAL LETTER EL WITH HOOK
+0459 ; [.13DE.0020.0002.0459] # CYRILLIC SMALL LETTER LJE
+0409 ; [.13DE.0020.0008.0409] # CYRILLIC CAPITAL LETTER LJE
+0509 ; [.13E2.0020.0002.0509] # CYRILLIC SMALL LETTER KOMI LJE
+0508 ; [.13E2.0020.0008.0508] # CYRILLIC CAPITAL LETTER KOMI LJE
+043C ; [.13E3.0020.0002.043C] # CYRILLIC SMALL LETTER EM
+041C ; [.13E3.0020.0008.041C] # CYRILLIC CAPITAL LETTER EM
+04CE ; [.13E7.0020.0002.04CE] # CYRILLIC SMALL LETTER EM WITH TAIL
+04CD ; [.13E7.0020.0008.04CD] # CYRILLIC CAPITAL LETTER EM WITH TAIL
+043D ; [.13EB.0020.0002.043D] # CYRILLIC SMALL LETTER EN
+041D ; [.13EB.0020.0008.041D] # CYRILLIC CAPITAL LETTER EN
+1D78 ; [.13EB.0020.0014.1D78] # MODIFIER LETTER CYRILLIC EN; QQK
+04CA ; [.13EF.0020.0002.04CA] # CYRILLIC SMALL LETTER EN WITH TAIL
+04C9 ; [.13EF.0020.0008.04C9] # CYRILLIC CAPITAL LETTER EN WITH TAIL
+04A3 ; [.13F3.0020.0002.04A3] # CYRILLIC SMALL LETTER EN WITH DESCENDER
+04A2 ; [.13F3.0020.0008.04A2] # CYRILLIC CAPITAL LETTER EN WITH DESCENDER
+04C8 ; [.13F7.0020.0002.04C8] # CYRILLIC SMALL LETTER EN WITH HOOK
+04C7 ; [.13F7.0020.0008.04C7] # CYRILLIC CAPITAL LETTER EN WITH HOOK
+04A5 ; [.13FB.0020.0002.04A5] # CYRILLIC SMALL LIGATURE EN GHE
+04A4 ; [.13FB.0020.0008.04A4] # CYRILLIC CAPITAL LIGATURE EN GHE
+045A ; [.13FF.0020.0002.045A] # CYRILLIC SMALL LETTER NJE
+040A ; [.13FF.0020.0008.040A] # CYRILLIC CAPITAL LETTER NJE
+050B ; [.1403.0020.0002.050B] # CYRILLIC SMALL LETTER KOMI NJE
+050A ; [.1403.0020.0008.050A] # CYRILLIC CAPITAL LETTER KOMI NJE
+043E ; [.1404.0020.0002.043E] # CYRILLIC SMALL LETTER O
+041E ; [.1404.0020.0008.041E] # CYRILLIC CAPITAL LETTER O
+04E7 ; [.1408.0020.0002.04E7] # CYRILLIC SMALL LETTER O WITH DIAERESIS
+043E 0308 ; [.1408.0020.0002.04E7] # CYRILLIC SMALL LETTER O WITH DIAERESIS
+04E6 ; [.1408.0020.0008.04E6] # CYRILLIC CAPITAL LETTER O WITH DIAERESIS
+041E 0308 ; [.1408.0020.0008.04E6] # CYRILLIC CAPITAL LETTER O WITH DIAERESIS
+04E9 ; [.140C.0020.0002.04E9] # CYRILLIC SMALL LETTER BARRED O
+04E8 ; [.140C.0020.0008.04E8] # CYRILLIC CAPITAL LETTER BARRED O
+04EB ; [.1410.0020.0002.04EB] # CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS
+04E9 0308 ; [.1410.0020.0002.04EB] # CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS
+04EA ; [.1410.0020.0008.04EA] # CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS
+04E8 0308 ; [.1410.0020.0008.04EA] # CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS
+043F ; [.1414.0020.0002.043F] # CYRILLIC SMALL LETTER PE
+041F ; [.1414.0020.0008.041F] # CYRILLIC CAPITAL LETTER PE
+04A7 ; [.1418.0020.0002.04A7] # CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK
+04A6 ; [.1418.0020.0008.04A6] # CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK
+0481 ; [.141C.0020.0002.0481] # CYRILLIC SMALL LETTER KOPPA
+0480 ; [.141C.0020.0008.0480] # CYRILLIC CAPITAL LETTER KOPPA
+0440 ; [.1420.0020.0002.0440] # CYRILLIC SMALL LETTER ER
+0420 ; [.1420.0020.0008.0420] # CYRILLIC CAPITAL LETTER ER
+048F ; [.1424.0020.0002.048F] # CYRILLIC SMALL LETTER ER WITH TICK
+048E ; [.1424.0020.0008.048E] # CYRILLIC CAPITAL LETTER ER WITH TICK
+0441 ; [.1428.0020.0002.0441] # CYRILLIC SMALL LETTER ES
+0421 ; [.1428.0020.0008.0421] # CYRILLIC CAPITAL LETTER ES
+050D ; [.142C.0020.0002.050D] # CYRILLIC SMALL LETTER KOMI SJE
+050C ; [.142C.0020.0008.050C] # CYRILLIC CAPITAL LETTER KOMI SJE
+04AB ; [.142D.0020.0002.04AB] # CYRILLIC SMALL LETTER ES WITH DESCENDER
+04AA ; [.142D.0020.0008.04AA] # CYRILLIC CAPITAL LETTER ES WITH DESCENDER
+0442 ; [.1431.0020.0002.0442] # CYRILLIC SMALL LETTER TE
+0422 ; [.1431.0020.0008.0422] # CYRILLIC CAPITAL LETTER TE
+050F ; [.1435.0020.0002.050F] # CYRILLIC SMALL LETTER KOMI TJE
+050E ; [.1435.0020.0008.050E] # CYRILLIC CAPITAL LETTER KOMI TJE
+04AD ; [.1436.0020.0002.04AD] # CYRILLIC SMALL LETTER TE WITH DESCENDER
+04AC ; [.1436.0020.0008.04AC] # CYRILLIC CAPITAL LETTER TE WITH DESCENDER
+045B ; [.143A.0020.0002.045B] # CYRILLIC SMALL LETTER TSHE
+040B ; [.143A.0020.0008.040B] # CYRILLIC CAPITAL LETTER TSHE
+045C ; [.143E.0020.0002.045C] # CYRILLIC SMALL LETTER KJE
+043A 0301 ; [.143E.0020.0002.045C] # CYRILLIC SMALL LETTER KJE
+043A 0341 ; [.143E.0020.0002.045C] # CYRILLIC SMALL LETTER KJE
+040C ; [.143E.0020.0008.040C] # CYRILLIC CAPITAL LETTER KJE
+041A 0301 ; [.143E.0020.0008.040C] # CYRILLIC CAPITAL LETTER KJE
+041A 0341 ; [.143E.0020.0008.040C] # CYRILLIC CAPITAL LETTER KJE
+0443 ; [.1442.0020.0002.0443] # CYRILLIC SMALL LETTER U
+0423 ; [.1442.0020.0008.0423] # CYRILLIC CAPITAL LETTER U
+04EF ; [.1442.0020.0002.0443][.0000.005B.0002.0304] # CYRILLIC SMALL LETTER U WITH MACRON; QQCM
+04EE ; [.1442.0020.0008.0423][.0000.005B.0002.0304] # CYRILLIC CAPITAL LETTER U WITH MACRON; QQCM
+045E ; [.1446.0020.0002.045E] # CYRILLIC SMALL LETTER SHORT U
+0443 0306 ; [.1446.0020.0002.045E] # CYRILLIC SMALL LETTER SHORT U
+040E ; [.1446.0020.0008.040E] # CYRILLIC CAPITAL LETTER SHORT U
+0423 0306 ; [.1446.0020.0008.040E] # CYRILLIC CAPITAL LETTER SHORT U
+04F1 ; [.144A.0020.0002.04F1] # CYRILLIC SMALL LETTER U WITH DIAERESIS
+0443 0308 ; [.144A.0020.0002.04F1] # CYRILLIC SMALL LETTER U WITH DIAERESIS
+04F0 ; [.144A.0020.0008.04F0] # CYRILLIC CAPITAL LETTER U WITH DIAERESIS
+0423 0308 ; [.144A.0020.0008.04F0] # CYRILLIC CAPITAL LETTER U WITH DIAERESIS
+04F3 ; [.144E.0020.0002.04F3] # CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE
+0443 030B ; [.144E.0020.0002.04F3] # CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE
+04F2 ; [.144E.0020.0008.04F2] # CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE
+0423 030B ; [.144E.0020.0008.04F2] # CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE
+04AF ; [.1452.0020.0002.04AF] # CYRILLIC SMALL LETTER STRAIGHT U
+04AE ; [.1452.0020.0008.04AE] # CYRILLIC CAPITAL LETTER STRAIGHT U
+04B1 ; [.1456.0020.0002.04B1] # CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE
+04B0 ; [.1456.0020.0008.04B0] # CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE
+0479 ; [.145A.0020.0002.0479] # CYRILLIC SMALL LETTER UK
+0478 ; [.145A.0020.0008.0478] # CYRILLIC CAPITAL LETTER UK
+0444 ; [.145E.0020.0002.0444] # CYRILLIC SMALL LETTER EF
+0424 ; [.145E.0020.0008.0424] # CYRILLIC CAPITAL LETTER EF
+0445 ; [.1462.0020.0002.0445] # CYRILLIC SMALL LETTER HA
+0425 ; [.1462.0020.0008.0425] # CYRILLIC CAPITAL LETTER HA
+04FD ; [.1466.0020.0002.04FD] # CYRILLIC SMALL LETTER HA WITH HOOK
+04FC ; [.1466.0020.0008.04FC] # CYRILLIC CAPITAL LETTER HA WITH HOOK
+04FF ; [.146A.0020.0002.04FF] # CYRILLIC SMALL LETTER HA WITH STROKE
+04FE ; [.146A.0020.0008.04FE] # CYRILLIC CAPITAL LETTER HA WITH STROKE
+04B3 ; [.146E.0020.0002.04B3] # CYRILLIC SMALL LETTER HA WITH DESCENDER
+04B2 ; [.146E.0020.0008.04B2] # CYRILLIC CAPITAL LETTER HA WITH DESCENDER
+04BB ; [.1472.0020.0002.04BB] # CYRILLIC SMALL LETTER SHHA
+04BA ; [.1472.0020.0008.04BA] # CYRILLIC CAPITAL LETTER SHHA
+0461 ; [.1476.0020.0002.0461] # CYRILLIC SMALL LETTER OMEGA
+0460 ; [.1476.0020.0008.0460] # CYRILLIC CAPITAL LETTER OMEGA
+047F ; [.147A.0020.0002.047F] # CYRILLIC SMALL LETTER OT
+047E ; [.147A.0020.0008.047E] # CYRILLIC CAPITAL LETTER OT
+047D ; [.147E.0020.0002.047D] # CYRILLIC SMALL LETTER OMEGA WITH TITLO
+047C ; [.147E.0020.0008.047C] # CYRILLIC CAPITAL LETTER OMEGA WITH TITLO
+047B ; [.1482.0020.0002.047B] # CYRILLIC SMALL LETTER ROUND OMEGA
+047A ; [.1482.0020.0008.047A] # CYRILLIC CAPITAL LETTER ROUND OMEGA
+0446 ; [.1486.0020.0002.0446] # CYRILLIC SMALL LETTER TSE
+0426 ; [.1486.0020.0008.0426] # CYRILLIC CAPITAL LETTER TSE
+04B5 ; [.148A.0020.0002.04B5] # CYRILLIC SMALL LIGATURE TE TSE
+04B4 ; [.148A.0020.0008.04B4] # CYRILLIC CAPITAL LIGATURE TE TSE
+0447 ; [.148E.0020.0002.0447] # CYRILLIC SMALL LETTER CHE
+0427 ; [.148E.0020.0008.0427] # CYRILLIC CAPITAL LETTER CHE
+04F5 ; [.1492.0020.0002.04F5] # CYRILLIC SMALL LETTER CHE WITH DIAERESIS
+0447 0308 ; [.1492.0020.0002.04F5] # CYRILLIC SMALL LETTER CHE WITH DIAERESIS
+04F4 ; [.1492.0020.0008.04F4] # CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS
+0427 0308 ; [.1492.0020.0008.04F4] # CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS
+04B7 ; [.1496.0020.0002.04B7] # CYRILLIC SMALL LETTER CHE WITH DESCENDER
+04B6 ; [.1496.0020.0008.04B6] # CYRILLIC CAPITAL LETTER CHE WITH DESCENDER
+04CC ; [.149A.0020.0002.04CC] # CYRILLIC SMALL LETTER KHAKASSIAN CHE
+04CB ; [.149A.0020.0008.04CB] # CYRILLIC CAPITAL LETTER KHAKASSIAN CHE
+04B9 ; [.149E.0020.0002.04B9] # CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE
+04B8 ; [.149E.0020.0008.04B8] # CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE
+04BD ; [.14A2.0020.0002.04BD] # CYRILLIC SMALL LETTER ABKHASIAN CHE
+04BC ; [.14A2.0020.0008.04BC] # CYRILLIC CAPITAL LETTER ABKHASIAN CHE
+04BF ; [.14A6.0020.0002.04BF] # CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER
+04BE ; [.14A6.0020.0008.04BE] # CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER
+045F ; [.14AA.0020.0002.045F] # CYRILLIC SMALL LETTER DZHE
+040F ; [.14AA.0020.0008.040F] # CYRILLIC CAPITAL LETTER DZHE
+0448 ; [.14AE.0020.0002.0448] # CYRILLIC SMALL LETTER SHA
+0428 ; [.14AE.0020.0008.0428] # CYRILLIC CAPITAL LETTER SHA
+0449 ; [.14B2.0020.0002.0449] # CYRILLIC SMALL LETTER SHCHA
+0429 ; [.14B2.0020.0008.0429] # CYRILLIC CAPITAL LETTER SHCHA
+044A ; [.14B6.0020.0002.044A] # CYRILLIC SMALL LETTER HARD SIGN
+042A ; [.14B6.0020.0008.042A] # CYRILLIC CAPITAL LETTER HARD SIGN
+044B ; [.14BA.0020.0002.044B] # CYRILLIC SMALL LETTER YERU
+042B ; [.14BA.0020.0008.042B] # CYRILLIC CAPITAL LETTER YERU
+04F9 ; [.14BE.0020.0002.04F9] # CYRILLIC SMALL LETTER YERU WITH DIAERESIS
+044B 0308 ; [.14BE.0020.0002.04F9] # CYRILLIC SMALL LETTER YERU WITH DIAERESIS
+04F8 ; [.14BE.0020.0008.04F8] # CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS
+042B 0308 ; [.14BE.0020.0008.04F8] # CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS
+044C ; [.14C2.0020.0002.044C] # CYRILLIC SMALL LETTER SOFT SIGN
+042C ; [.14C2.0020.0008.042C] # CYRILLIC CAPITAL LETTER SOFT SIGN
+048D ; [.14C6.0020.0002.048D] # CYRILLIC SMALL LETTER SEMISOFT SIGN
+048C ; [.14C6.0020.0008.048C] # CYRILLIC CAPITAL LETTER SEMISOFT SIGN
+0463 ; [.14CA.0020.0002.0463] # CYRILLIC SMALL LETTER YAT
+0462 ; [.14CA.0020.0008.0462] # CYRILLIC CAPITAL LETTER YAT
+044D ; [.14CE.0020.0002.044D] # CYRILLIC SMALL LETTER E
+042D ; [.14CE.0020.0008.042D] # CYRILLIC CAPITAL LETTER E
+04ED ; [.14D2.0020.0002.04ED] # CYRILLIC SMALL LETTER E WITH DIAERESIS
+044D 0308 ; [.14D2.0020.0002.04ED] # CYRILLIC SMALL LETTER E WITH DIAERESIS
+04EC ; [.14D2.0020.0008.04EC] # CYRILLIC CAPITAL LETTER E WITH DIAERESIS
+042D 0308 ; [.14D2.0020.0008.04EC] # CYRILLIC CAPITAL LETTER E WITH DIAERESIS
+044E ; [.14D6.0020.0002.044E] # CYRILLIC SMALL LETTER YU
+042E ; [.14D6.0020.0008.042E] # CYRILLIC CAPITAL LETTER YU
+044F ; [.14DA.0020.0002.044F] # CYRILLIC SMALL LETTER YA
+042F ; [.14DA.0020.0008.042F] # CYRILLIC CAPITAL LETTER YA
+0465 ; [.14DE.0020.0002.0465] # CYRILLIC SMALL LETTER IOTIFIED E
+0464 ; [.14DE.0020.0008.0464] # CYRILLIC CAPITAL LETTER IOTIFIED E
+0467 ; [.14E2.0020.0002.0467] # CYRILLIC SMALL LETTER LITTLE YUS
+0466 ; [.14E2.0020.0008.0466] # CYRILLIC CAPITAL LETTER LITTLE YUS
+046B ; [.14E6.0020.0002.046B] # CYRILLIC SMALL LETTER BIG YUS
+046A ; [.14E6.0020.0008.046A] # CYRILLIC CAPITAL LETTER BIG YUS
+0469 ; [.14EA.0020.0002.0469] # CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS
+0468 ; [.14EA.0020.0008.0468] # CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS
+046D ; [.14EE.0020.0002.046D] # CYRILLIC SMALL LETTER IOTIFIED BIG YUS
+046C ; [.14EE.0020.0008.046C] # CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS
+046F ; [.14F2.0020.0002.046F] # CYRILLIC SMALL LETTER KSI
+046E ; [.14F2.0020.0008.046E] # CYRILLIC CAPITAL LETTER KSI
+0471 ; [.14F6.0020.0002.0471] # CYRILLIC SMALL LETTER PSI
+0470 ; [.14F6.0020.0008.0470] # CYRILLIC CAPITAL LETTER PSI
+0473 ; [.14FA.0020.0002.0473] # CYRILLIC SMALL LETTER FITA
+0472 ; [.14FA.0020.0008.0472] # CYRILLIC CAPITAL LETTER FITA
+0475 ; [.14FE.0020.0002.0475] # CYRILLIC SMALL LETTER IZHITSA
+0474 ; [.14FE.0020.0008.0474] # CYRILLIC CAPITAL LETTER IZHITSA
+0477 ; [.1502.0020.0002.0477] # CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT
+0475 030F ; [.1502.0020.0002.0477] # CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT
+0476 ; [.1502.0020.0008.0476] # CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT
+0474 030F ; [.1502.0020.0008.0476] # CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT
+04A9 ; [.1506.0020.0002.04A9] # CYRILLIC SMALL LETTER ABKHASIAN HA
+04A8 ; [.1506.0020.0008.04A8] # CYRILLIC CAPITAL LETTER ABKHASIAN HA
+04CF ; [.150A.0020.0002.04CF] # CYRILLIC SMALL LETTER PALOCHKA
+04C0 ; [.150A.0020.0008.04C0] # CYRILLIC LETTER PALOCHKA
+2C30 ; [.150E.0020.0002.2C30] # GLAGOLITIC SMALL LETTER AZU
+2C00 ; [.150E.0020.0008.2C00] # GLAGOLITIC CAPITAL LETTER AZU
+2C31 ; [.150F.0020.0002.2C31] # GLAGOLITIC SMALL LETTER BUKY
+2C01 ; [.150F.0020.0008.2C01] # GLAGOLITIC CAPITAL LETTER BUKY
+2C32 ; [.1510.0020.0002.2C32] # GLAGOLITIC SMALL LETTER VEDE
+2C02 ; [.1510.0020.0008.2C02] # GLAGOLITIC CAPITAL LETTER VEDE
+2C33 ; [.1511.0020.0002.2C33] # GLAGOLITIC SMALL LETTER GLAGOLI
+2C03 ; [.1511.0020.0008.2C03] # GLAGOLITIC CAPITAL LETTER GLAGOLI
+2C34 ; [.1512.0020.0002.2C34] # GLAGOLITIC SMALL LETTER DOBRO
+2C04 ; [.1512.0020.0008.2C04] # GLAGOLITIC CAPITAL LETTER DOBRO
+2C35 ; [.1513.0020.0002.2C35] # GLAGOLITIC SMALL LETTER YESTU
+2C05 ; [.1513.0020.0008.2C05] # GLAGOLITIC CAPITAL LETTER YESTU
+2C36 ; [.1514.0020.0002.2C36] # GLAGOLITIC SMALL LETTER ZHIVETE
+2C06 ; [.1514.0020.0008.2C06] # GLAGOLITIC CAPITAL LETTER ZHIVETE
+2C37 ; [.1515.0020.0002.2C37] # GLAGOLITIC SMALL LETTER DZELO
+2C07 ; [.1515.0020.0008.2C07] # GLAGOLITIC CAPITAL LETTER DZELO
+2C38 ; [.1516.0020.0002.2C38] # GLAGOLITIC SMALL LETTER ZEMLJA
+2C08 ; [.1516.0020.0008.2C08] # GLAGOLITIC CAPITAL LETTER ZEMLJA
+2C39 ; [.1517.0020.0002.2C39] # GLAGOLITIC SMALL LETTER IZHE
+2C09 ; [.1517.0020.0008.2C09] # GLAGOLITIC CAPITAL LETTER IZHE
+2C3A ; [.1518.0020.0002.2C3A] # GLAGOLITIC SMALL LETTER INITIAL IZHE
+2C0A ; [.1518.0020.0008.2C0A] # GLAGOLITIC CAPITAL LETTER INITIAL IZHE
+2C3B ; [.1519.0020.0002.2C3B] # GLAGOLITIC SMALL LETTER I
+2C0B ; [.1519.0020.0008.2C0B] # GLAGOLITIC CAPITAL LETTER I
+2C3C ; [.151A.0020.0002.2C3C] # GLAGOLITIC SMALL LETTER DJERVI
+2C0C ; [.151A.0020.0008.2C0C] # GLAGOLITIC CAPITAL LETTER DJERVI
+2C3D ; [.151B.0020.0002.2C3D] # GLAGOLITIC SMALL LETTER KAKO
+2C0D ; [.151B.0020.0008.2C0D] # GLAGOLITIC CAPITAL LETTER KAKO
+2C3E ; [.151C.0020.0002.2C3E] # GLAGOLITIC SMALL LETTER LJUDIJE
+2C0E ; [.151C.0020.0008.2C0E] # GLAGOLITIC CAPITAL LETTER LJUDIJE
+2C3F ; [.151D.0020.0002.2C3F] # GLAGOLITIC SMALL LETTER MYSLITE
+2C0F ; [.151D.0020.0008.2C0F] # GLAGOLITIC CAPITAL LETTER MYSLITE
+2C40 ; [.151E.0020.0002.2C40] # GLAGOLITIC SMALL LETTER NASHI
+2C10 ; [.151E.0020.0008.2C10] # GLAGOLITIC CAPITAL LETTER NASHI
+2C41 ; [.151F.0020.0002.2C41] # GLAGOLITIC SMALL LETTER ONU
+2C11 ; [.151F.0020.0008.2C11] # GLAGOLITIC CAPITAL LETTER ONU
+2C42 ; [.1520.0020.0002.2C42] # GLAGOLITIC SMALL LETTER POKOJI
+2C12 ; [.1520.0020.0008.2C12] # GLAGOLITIC CAPITAL LETTER POKOJI
+2C43 ; [.1521.0020.0002.2C43] # GLAGOLITIC SMALL LETTER RITSI
+2C13 ; [.1521.0020.0008.2C13] # GLAGOLITIC CAPITAL LETTER RITSI
+2C44 ; [.1522.0020.0002.2C44] # GLAGOLITIC SMALL LETTER SLOVO
+2C14 ; [.1522.0020.0008.2C14] # GLAGOLITIC CAPITAL LETTER SLOVO
+2C45 ; [.1523.0020.0002.2C45] # GLAGOLITIC SMALL LETTER TVRIDO
+2C15 ; [.1523.0020.0008.2C15] # GLAGOLITIC CAPITAL LETTER TVRIDO
+2C46 ; [.1524.0020.0002.2C46] # GLAGOLITIC SMALL LETTER UKU
+2C16 ; [.1524.0020.0008.2C16] # GLAGOLITIC CAPITAL LETTER UKU
+2C47 ; [.1525.0020.0002.2C47] # GLAGOLITIC SMALL LETTER FRITU
+2C17 ; [.1525.0020.0008.2C17] # GLAGOLITIC CAPITAL LETTER FRITU
+2C48 ; [.1526.0020.0002.2C48] # GLAGOLITIC SMALL LETTER HERU
+2C18 ; [.1526.0020.0008.2C18] # GLAGOLITIC CAPITAL LETTER HERU
+2C49 ; [.1527.0020.0002.2C49] # GLAGOLITIC SMALL LETTER OTU
+2C19 ; [.1527.0020.0008.2C19] # GLAGOLITIC CAPITAL LETTER OTU
+2C4A ; [.1528.0020.0002.2C4A] # GLAGOLITIC SMALL LETTER PE
+2C1A ; [.1528.0020.0008.2C1A] # GLAGOLITIC CAPITAL LETTER PE
+2C4B ; [.1529.0020.0002.2C4B] # GLAGOLITIC SMALL LETTER SHTA
+2C1B ; [.1529.0020.0008.2C1B] # GLAGOLITIC CAPITAL LETTER SHTA
+2C4C ; [.152A.0020.0002.2C4C] # GLAGOLITIC SMALL LETTER TSI
+2C1C ; [.152A.0020.0008.2C1C] # GLAGOLITIC CAPITAL LETTER TSI
+2C4D ; [.152B.0020.0002.2C4D] # GLAGOLITIC SMALL LETTER CHRIVI
+2C1D ; [.152B.0020.0008.2C1D] # GLAGOLITIC CAPITAL LETTER CHRIVI
+2C4E ; [.152C.0020.0002.2C4E] # GLAGOLITIC SMALL LETTER SHA
+2C1E ; [.152C.0020.0008.2C1E] # GLAGOLITIC CAPITAL LETTER SHA
+2C4F ; [.152D.0020.0002.2C4F] # GLAGOLITIC SMALL LETTER YERU
+2C1F ; [.152D.0020.0008.2C1F] # GLAGOLITIC CAPITAL LETTER YERU
+2C50 ; [.152E.0020.0002.2C50] # GLAGOLITIC SMALL LETTER YERI
+2C20 ; [.152E.0020.0008.2C20] # GLAGOLITIC CAPITAL LETTER YERI
+2C51 ; [.152F.0020.0002.2C51] # GLAGOLITIC SMALL LETTER YATI
+2C21 ; [.152F.0020.0008.2C21] # GLAGOLITIC CAPITAL LETTER YATI
+2C52 ; [.1530.0020.0002.2C52] # GLAGOLITIC SMALL LETTER SPIDERY HA
+2C22 ; [.1530.0020.0008.2C22] # GLAGOLITIC CAPITAL LETTER SPIDERY HA
+2C53 ; [.1531.0020.0002.2C53] # GLAGOLITIC SMALL LETTER YU
+2C23 ; [.1531.0020.0008.2C23] # GLAGOLITIC CAPITAL LETTER YU
+2C54 ; [.1532.0020.0002.2C54] # GLAGOLITIC SMALL LETTER SMALL YUS
+2C24 ; [.1532.0020.0008.2C24] # GLAGOLITIC CAPITAL LETTER SMALL YUS
+2C55 ; [.1533.0020.0002.2C55] # GLAGOLITIC SMALL LETTER SMALL YUS WITH TAIL
+2C25 ; [.1533.0020.0008.2C25] # GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL
+2C56 ; [.1534.0020.0002.2C56] # GLAGOLITIC SMALL LETTER YO
+2C26 ; [.1534.0020.0008.2C26] # GLAGOLITIC CAPITAL LETTER YO
+2C57 ; [.1535.0020.0002.2C57] # GLAGOLITIC SMALL LETTER IOTATED SMALL YUS
+2C27 ; [.1535.0020.0008.2C27] # GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS
+2C58 ; [.1536.0020.0002.2C58] # GLAGOLITIC SMALL LETTER BIG YUS
+2C28 ; [.1536.0020.0008.2C28] # GLAGOLITIC CAPITAL LETTER BIG YUS
+2C59 ; [.1537.0020.0002.2C59] # GLAGOLITIC SMALL LETTER IOTATED BIG YUS
+2C29 ; [.1537.0020.0008.2C29] # GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS
+2C5A ; [.1538.0020.0002.2C5A] # GLAGOLITIC SMALL LETTER FITA
+2C2A ; [.1538.0020.0008.2C2A] # GLAGOLITIC CAPITAL LETTER FITA
+2C5B ; [.1539.0020.0002.2C5B] # GLAGOLITIC SMALL LETTER IZHITSA
+2C2B ; [.1539.0020.0008.2C2B] # GLAGOLITIC CAPITAL LETTER IZHITSA
+2C5C ; [.153A.0020.0002.2C5C] # GLAGOLITIC SMALL LETTER SHTAPIC
+2C2C ; [.153A.0020.0008.2C2C] # GLAGOLITIC CAPITAL LETTER SHTAPIC
+2C5D ; [.153B.0020.0002.2C5D] # GLAGOLITIC SMALL LETTER TROKUTASTI A
+2C2D ; [.153B.0020.0008.2C2D] # GLAGOLITIC CAPITAL LETTER TROKUTASTI A
+2C5E ; [.153C.0020.0002.2C5E] # GLAGOLITIC SMALL LETTER LATINATE MYSLITE
+2C2E ; [.153C.0020.0008.2C2E] # GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE
+10D0 ; [.153D.0020.0002.10D0] # GEORGIAN LETTER AN
+2D00 ; [.153E.0020.0002.2D00] # GEORGIAN SMALL LETTER AN
+10A0 ; [.153E.0020.0008.10A0] # GEORGIAN CAPITAL LETTER AN
+10D1 ; [.153F.0020.0002.10D1] # GEORGIAN LETTER BAN
+2D01 ; [.1540.0020.0002.2D01] # GEORGIAN SMALL LETTER BAN
+10A1 ; [.1540.0020.0008.10A1] # GEORGIAN CAPITAL LETTER BAN
+10D2 ; [.1541.0020.0002.10D2] # GEORGIAN LETTER GAN
+2D02 ; [.1542.0020.0002.2D02] # GEORGIAN SMALL LETTER GAN
+10A2 ; [.1542.0020.0008.10A2] # GEORGIAN CAPITAL LETTER GAN
+10D3 ; [.1543.0020.0002.10D3] # GEORGIAN LETTER DON
+2D03 ; [.1544.0020.0002.2D03] # GEORGIAN SMALL LETTER DON
+10A3 ; [.1544.0020.0008.10A3] # GEORGIAN CAPITAL LETTER DON
+10D4 ; [.1545.0020.0002.10D4] # GEORGIAN LETTER EN
+2D04 ; [.1546.0020.0002.2D04] # GEORGIAN SMALL LETTER EN
+10A4 ; [.1546.0020.0008.10A4] # GEORGIAN CAPITAL LETTER EN
+10D5 ; [.1547.0020.0002.10D5] # GEORGIAN LETTER VIN
+2D05 ; [.1548.0020.0002.2D05] # GEORGIAN SMALL LETTER VIN
+10A5 ; [.1548.0020.0008.10A5] # GEORGIAN CAPITAL LETTER VIN
+10D6 ; [.1549.0020.0002.10D6] # GEORGIAN LETTER ZEN
+2D06 ; [.154A.0020.0002.2D06] # GEORGIAN SMALL LETTER ZEN
+10A6 ; [.154A.0020.0008.10A6] # GEORGIAN CAPITAL LETTER ZEN
+10F1 ; [.154B.0020.0002.10F1] # GEORGIAN LETTER HE
+2D21 ; [.154C.0020.0002.2D21] # GEORGIAN SMALL LETTER HE
+10C1 ; [.154C.0020.0008.10C1] # GEORGIAN CAPITAL LETTER HE
+10D7 ; [.154D.0020.0002.10D7] # GEORGIAN LETTER TAN
+2D07 ; [.154E.0020.0002.2D07] # GEORGIAN SMALL LETTER TAN
+10A7 ; [.154E.0020.0008.10A7] # GEORGIAN CAPITAL LETTER TAN
+10D8 ; [.154F.0020.0002.10D8] # GEORGIAN LETTER IN
+2D08 ; [.1550.0020.0002.2D08] # GEORGIAN SMALL LETTER IN
+10A8 ; [.1550.0020.0008.10A8] # GEORGIAN CAPITAL LETTER IN
+10D9 ; [.1551.0020.0002.10D9] # GEORGIAN LETTER KAN
+2D09 ; [.1552.0020.0002.2D09] # GEORGIAN SMALL LETTER KAN
+10A9 ; [.1552.0020.0008.10A9] # GEORGIAN CAPITAL LETTER KAN
+10DA ; [.1553.0020.0002.10DA] # GEORGIAN LETTER LAS
+2D0A ; [.1554.0020.0002.2D0A] # GEORGIAN SMALL LETTER LAS
+10AA ; [.1554.0020.0008.10AA] # GEORGIAN CAPITAL LETTER LAS
+10DB ; [.1555.0020.0002.10DB] # GEORGIAN LETTER MAN
+2D0B ; [.1556.0020.0002.2D0B] # GEORGIAN SMALL LETTER MAN
+10AB ; [.1556.0020.0008.10AB] # GEORGIAN CAPITAL LETTER MAN
+10DC ; [.1557.0020.0002.10DC] # GEORGIAN LETTER NAR
+10FC ; [.1557.0020.0014.10FC] # MODIFIER LETTER GEORGIAN NAR; QQK
+2D0C ; [.1558.0020.0002.2D0C] # GEORGIAN SMALL LETTER NAR
+10AC ; [.1558.0020.0008.10AC] # GEORGIAN CAPITAL LETTER NAR
+10F2 ; [.1559.0020.0002.10F2] # GEORGIAN LETTER HIE
+2D22 ; [.155A.0020.0002.2D22] # GEORGIAN SMALL LETTER HIE
+10C2 ; [.155A.0020.0008.10C2] # GEORGIAN CAPITAL LETTER HIE
+10DD ; [.155B.0020.0002.10DD] # GEORGIAN LETTER ON
+2D0D ; [.155C.0020.0002.2D0D] # GEORGIAN SMALL LETTER ON
+10AD ; [.155C.0020.0008.10AD] # GEORGIAN CAPITAL LETTER ON
+10DE ; [.155D.0020.0002.10DE] # GEORGIAN LETTER PAR
+2D0E ; [.155E.0020.0002.2D0E] # GEORGIAN SMALL LETTER PAR
+10AE ; [.155E.0020.0008.10AE] # GEORGIAN CAPITAL LETTER PAR
+10DF ; [.155F.0020.0002.10DF] # GEORGIAN LETTER ZHAR
+2D0F ; [.1560.0020.0002.2D0F] # GEORGIAN SMALL LETTER ZHAR
+10AF ; [.1560.0020.0008.10AF] # GEORGIAN CAPITAL LETTER ZHAR
+10E0 ; [.1561.0020.0002.10E0] # GEORGIAN LETTER RAE
+2D10 ; [.1562.0020.0002.2D10] # GEORGIAN SMALL LETTER RAE
+10B0 ; [.1562.0020.0008.10B0] # GEORGIAN CAPITAL LETTER RAE
+10E1 ; [.1563.0020.0002.10E1] # GEORGIAN LETTER SAN
+2D11 ; [.1564.0020.0002.2D11] # GEORGIAN SMALL LETTER SAN
+10B1 ; [.1564.0020.0008.10B1] # GEORGIAN CAPITAL LETTER SAN
+10E2 ; [.1565.0020.0002.10E2] # GEORGIAN LETTER TAR
+2D12 ; [.1566.0020.0002.2D12] # GEORGIAN SMALL LETTER TAR
+10B2 ; [.1566.0020.0008.10B2] # GEORGIAN CAPITAL LETTER TAR
+10F3 ; [.1567.0020.0002.10F3] # GEORGIAN LETTER WE
+2D23 ; [.1568.0020.0002.2D23] # GEORGIAN SMALL LETTER WE
+10C3 ; [.1568.0020.0008.10C3] # GEORGIAN CAPITAL LETTER WE
+10E3 ; [.1569.0020.0002.10E3] # GEORGIAN LETTER UN
+2D13 ; [.156A.0020.0002.2D13] # GEORGIAN SMALL LETTER UN
+10B3 ; [.156A.0020.0008.10B3] # GEORGIAN CAPITAL LETTER UN
+10E4 ; [.156B.0020.0002.10E4] # GEORGIAN LETTER PHAR
+2D14 ; [.156C.0020.0002.2D14] # GEORGIAN SMALL LETTER PHAR
+10B4 ; [.156C.0020.0008.10B4] # GEORGIAN CAPITAL LETTER PHAR
+10E5 ; [.156D.0020.0002.10E5] # GEORGIAN LETTER KHAR
+2D15 ; [.156E.0020.0002.2D15] # GEORGIAN SMALL LETTER KHAR
+10B5 ; [.156E.0020.0008.10B5] # GEORGIAN CAPITAL LETTER KHAR
+10E6 ; [.156F.0020.0002.10E6] # GEORGIAN LETTER GHAN
+2D16 ; [.1570.0020.0002.2D16] # GEORGIAN SMALL LETTER GHAN
+10B6 ; [.1570.0020.0008.10B6] # GEORGIAN CAPITAL LETTER GHAN
+10E7 ; [.1571.0020.0002.10E7] # GEORGIAN LETTER QAR
+2D17 ; [.1572.0020.0002.2D17] # GEORGIAN SMALL LETTER QAR
+10B7 ; [.1572.0020.0008.10B7] # GEORGIAN CAPITAL LETTER QAR
+10E8 ; [.1573.0020.0002.10E8] # GEORGIAN LETTER SHIN
+2D18 ; [.1574.0020.0002.2D18] # GEORGIAN SMALL LETTER SHIN
+10B8 ; [.1574.0020.0008.10B8] # GEORGIAN CAPITAL LETTER SHIN
+10E9 ; [.1575.0020.0002.10E9] # GEORGIAN LETTER CHIN
+2D19 ; [.1576.0020.0002.2D19] # GEORGIAN SMALL LETTER CHIN
+10B9 ; [.1576.0020.0008.10B9] # GEORGIAN CAPITAL LETTER CHIN
+10EA ; [.1577.0020.0002.10EA] # GEORGIAN LETTER CAN
+2D1A ; [.1578.0020.0002.2D1A] # GEORGIAN SMALL LETTER CAN
+10BA ; [.1578.0020.0008.10BA] # GEORGIAN CAPITAL LETTER CAN
+10EB ; [.1579.0020.0002.10EB] # GEORGIAN LETTER JIL
+2D1B ; [.157A.0020.0002.2D1B] # GEORGIAN SMALL LETTER JIL
+10BB ; [.157A.0020.0008.10BB] # GEORGIAN CAPITAL LETTER JIL
+10EC ; [.157B.0020.0002.10EC] # GEORGIAN LETTER CIL
+2D1C ; [.157C.0020.0002.2D1C] # GEORGIAN SMALL LETTER CIL
+10BC ; [.157C.0020.0008.10BC] # GEORGIAN CAPITAL LETTER CIL
+10ED ; [.157D.0020.0002.10ED] # GEORGIAN LETTER CHAR
+2D1D ; [.157E.0020.0002.2D1D] # GEORGIAN SMALL LETTER CHAR
+10BD ; [.157E.0020.0008.10BD] # GEORGIAN CAPITAL LETTER CHAR
+10EE ; [.157F.0020.0002.10EE] # GEORGIAN LETTER XAN
+2D1E ; [.1580.0020.0002.2D1E] # GEORGIAN SMALL LETTER XAN
+10BE ; [.1580.0020.0008.10BE] # GEORGIAN CAPITAL LETTER XAN
+10F4 ; [.1581.0020.0002.10F4] # GEORGIAN LETTER HAR
+2D24 ; [.1582.0020.0002.2D24] # GEORGIAN SMALL LETTER HAR
+10C4 ; [.1582.0020.0008.10C4] # GEORGIAN CAPITAL LETTER HAR
+10EF ; [.1583.0020.0002.10EF] # GEORGIAN LETTER JHAN
+2D1F ; [.1584.0020.0002.2D1F] # GEORGIAN SMALL LETTER JHAN
+10BF ; [.1584.0020.0008.10BF] # GEORGIAN CAPITAL LETTER JHAN
+10F0 ; [.1585.0020.0002.10F0] # GEORGIAN LETTER HAE
+2D20 ; [.1586.0020.0002.2D20] # GEORGIAN SMALL LETTER HAE
+10C0 ; [.1586.0020.0008.10C0] # GEORGIAN CAPITAL LETTER HAE
+10F5 ; [.1587.0020.0002.10F5] # GEORGIAN LETTER HOE
+2D25 ; [.1588.0020.0002.2D25] # GEORGIAN SMALL LETTER HOE
+10C5 ; [.1588.0020.0008.10C5] # GEORGIAN CAPITAL LETTER HOE
+10F6 ; [.1589.0020.0002.10F6] # GEORGIAN LETTER FI
+10F7 ; [.158A.0020.0002.10F7] # GEORGIAN LETTER YN
+10F8 ; [.158B.0020.0002.10F8] # GEORGIAN LETTER ELIFI
+10F9 ; [.158C.0020.0002.10F9] # GEORGIAN LETTER TURNED GAN
+10FA ; [.158D.0020.0002.10FA] # GEORGIAN LETTER AIN
+0561 ; [.158E.0020.0002.0561] # ARMENIAN SMALL LETTER AYB
+0531 ; [.158E.0020.0008.0531] # ARMENIAN CAPITAL LETTER AYB
+0562 ; [.158F.0020.0002.0562] # ARMENIAN SMALL LETTER BEN
+0532 ; [.158F.0020.0008.0532] # ARMENIAN CAPITAL LETTER BEN
+0563 ; [.1590.0020.0002.0563] # ARMENIAN SMALL LETTER GIM
+0533 ; [.1590.0020.0008.0533] # ARMENIAN CAPITAL LETTER GIM
+0564 ; [.1591.0020.0002.0564] # ARMENIAN SMALL LETTER DA
+0534 ; [.1591.0020.0008.0534] # ARMENIAN CAPITAL LETTER DA
+0565 ; [.1592.0020.0002.0565] # ARMENIAN SMALL LETTER ECH
+0535 ; [.1592.0020.0008.0535] # ARMENIAN CAPITAL LETTER ECH
+0587 ; [.1592.0020.0004.0587][.15AF.0020.0004.0587] # ARMENIAN SMALL LIGATURE ECH YIWN; QQKN
+0566 ; [.1593.0020.0002.0566] # ARMENIAN SMALL LETTER ZA
+0536 ; [.1593.0020.0008.0536] # ARMENIAN CAPITAL LETTER ZA
+0567 ; [.1594.0020.0002.0567] # ARMENIAN SMALL LETTER EH
+0537 ; [.1594.0020.0008.0537] # ARMENIAN CAPITAL LETTER EH
+0568 ; [.1595.0020.0002.0568] # ARMENIAN SMALL LETTER ET
+0538 ; [.1595.0020.0008.0538] # ARMENIAN CAPITAL LETTER ET
+0569 ; [.1596.0020.0002.0569] # ARMENIAN SMALL LETTER TO
+0539 ; [.1596.0020.0008.0539] # ARMENIAN CAPITAL LETTER TO
+056A ; [.1597.0020.0002.056A] # ARMENIAN SMALL LETTER ZHE
+053A ; [.1597.0020.0008.053A] # ARMENIAN CAPITAL LETTER ZHE
+056B ; [.1598.0020.0002.056B] # ARMENIAN SMALL LETTER INI
+053B ; [.1598.0020.0008.053B] # ARMENIAN CAPITAL LETTER INI
+056C ; [.1599.0020.0002.056C] # ARMENIAN SMALL LETTER LIWN
+053C ; [.1599.0020.0008.053C] # ARMENIAN CAPITAL LETTER LIWN
+056D ; [.159A.0020.0002.056D] # ARMENIAN SMALL LETTER XEH
+053D ; [.159A.0020.0008.053D] # ARMENIAN CAPITAL LETTER XEH
+056E ; [.159B.0020.0002.056E] # ARMENIAN SMALL LETTER CA
+053E ; [.159B.0020.0008.053E] # ARMENIAN CAPITAL LETTER CA
+056F ; [.159C.0020.0002.056F] # ARMENIAN SMALL LETTER KEN
+053F ; [.159C.0020.0008.053F] # ARMENIAN CAPITAL LETTER KEN
+0570 ; [.159D.0020.0002.0570] # ARMENIAN SMALL LETTER HO
+0540 ; [.159D.0020.0008.0540] # ARMENIAN CAPITAL LETTER HO
+0571 ; [.159E.0020.0002.0571] # ARMENIAN SMALL LETTER JA
+0541 ; [.159E.0020.0008.0541] # ARMENIAN CAPITAL LETTER JA
+0572 ; [.159F.0020.0002.0572] # ARMENIAN SMALL LETTER GHAD
+0542 ; [.159F.0020.0008.0542] # ARMENIAN CAPITAL LETTER GHAD
+0573 ; [.15A0.0020.0002.0573] # ARMENIAN SMALL LETTER CHEH
+0543 ; [.15A0.0020.0008.0543] # ARMENIAN CAPITAL LETTER CHEH
+0574 ; [.15A1.0020.0002.0574] # ARMENIAN SMALL LETTER MEN
+0544 ; [.15A1.0020.0008.0544] # ARMENIAN CAPITAL LETTER MEN
+FB14 ; [.15A1.0020.0004.FB14][.1592.0020.0004.FB14] # ARMENIAN SMALL LIGATURE MEN ECH; QQKN
+FB15 ; [.15A1.0020.0004.FB15][.1598.0020.0004.FB15] # ARMENIAN SMALL LIGATURE MEN INI; QQKN
+FB17 ; [.15A1.0020.0004.FB17][.159A.0020.0004.FB17] # ARMENIAN SMALL LIGATURE MEN XEH; QQKN
+FB13 ; [.15A1.0020.0004.FB13][.15A3.0020.0004.FB13] # ARMENIAN SMALL LIGATURE MEN NOW; QQKN
+0575 ; [.15A2.0020.0002.0575] # ARMENIAN SMALL LETTER YI
+0545 ; [.15A2.0020.0008.0545] # ARMENIAN CAPITAL LETTER YI
+0576 ; [.15A3.0020.0002.0576] # ARMENIAN SMALL LETTER NOW
+0546 ; [.15A3.0020.0008.0546] # ARMENIAN CAPITAL LETTER NOW
+0577 ; [.15A4.0020.0002.0577] # ARMENIAN SMALL LETTER SHA
+0547 ; [.15A4.0020.0008.0547] # ARMENIAN CAPITAL LETTER SHA
+0578 ; [.15A5.0020.0002.0578] # ARMENIAN SMALL LETTER VO
+0548 ; [.15A5.0020.0008.0548] # ARMENIAN CAPITAL LETTER VO
+0579 ; [.15A6.0020.0002.0579] # ARMENIAN SMALL LETTER CHA
+0549 ; [.15A6.0020.0008.0549] # ARMENIAN CAPITAL LETTER CHA
+057A ; [.15A7.0020.0002.057A] # ARMENIAN SMALL LETTER PEH
+054A ; [.15A7.0020.0008.054A] # ARMENIAN CAPITAL LETTER PEH
+057B ; [.15A8.0020.0002.057B] # ARMENIAN SMALL LETTER JHEH
+054B ; [.15A8.0020.0008.054B] # ARMENIAN CAPITAL LETTER JHEH
+057C ; [.15A9.0020.0002.057C] # ARMENIAN SMALL LETTER RA
+054C ; [.15A9.0020.0008.054C] # ARMENIAN CAPITAL LETTER RA
+057D ; [.15AA.0020.0002.057D] # ARMENIAN SMALL LETTER SEH
+054D ; [.15AA.0020.0008.054D] # ARMENIAN CAPITAL LETTER SEH
+057E ; [.15AB.0020.0002.057E] # ARMENIAN SMALL LETTER VEW
+054E ; [.15AB.0020.0008.054E] # ARMENIAN CAPITAL LETTER VEW
+FB16 ; [.15AB.0020.0004.FB16][.15A3.0020.0004.FB16] # ARMENIAN SMALL LIGATURE VEW NOW; QQKN
+057F ; [.15AC.0020.0002.057F] # ARMENIAN SMALL LETTER TIWN
+054F ; [.15AC.0020.0008.054F] # ARMENIAN CAPITAL LETTER TIWN
+0580 ; [.15AD.0020.0002.0580] # ARMENIAN SMALL LETTER REH
+0550 ; [.15AD.0020.0008.0550] # ARMENIAN CAPITAL LETTER REH
+0581 ; [.15AE.0020.0002.0581] # ARMENIAN SMALL LETTER CO
+0551 ; [.15AE.0020.0008.0551] # ARMENIAN CAPITAL LETTER CO
+0582 ; [.15AF.0020.0002.0582] # ARMENIAN SMALL LETTER YIWN
+0552 ; [.15AF.0020.0008.0552] # ARMENIAN CAPITAL LETTER YIWN
+0583 ; [.15B0.0020.0002.0583] # ARMENIAN SMALL LETTER PIWR
+0553 ; [.15B0.0020.0008.0553] # ARMENIAN CAPITAL LETTER PIWR
+0584 ; [.15B1.0020.0002.0584] # ARMENIAN SMALL LETTER KEH
+0554 ; [.15B1.0020.0008.0554] # ARMENIAN CAPITAL LETTER KEH
+0585 ; [.15B2.0020.0002.0585] # ARMENIAN SMALL LETTER OH
+0555 ; [.15B2.0020.0008.0555] # ARMENIAN CAPITAL LETTER OH
+0586 ; [.15B3.0020.0002.0586] # ARMENIAN SMALL LETTER FEH
+0556 ; [.15B3.0020.0008.0556] # ARMENIAN CAPITAL LETTER FEH
+0559 ; [.15B4.0020.0002.0559] # ARMENIAN MODIFIER LETTER LEFT HALF RING
+05D0 ; [.15B5.0020.0002.05D0] # HEBREW LETTER ALEF
+2135 ; [.15B5.0020.0004.2135] # ALEF SYMBOL; QQK
+FB21 ; [.15B5.0020.0005.FB21] # HEBREW LETTER WIDE ALEF; QQK
+FB2E ; [.15B5.0020.0002.05D0][.0000.00CC.0002.05B7] # HEBREW LETTER ALEF WITH PATAH; QQCM
+FB2F ; [.15B5.0020.0002.05D0][.0000.00CD.0002.05B8] # HEBREW LETTER ALEF WITH QAMATS; QQCM
+FB30 ; [.15B5.0020.0002.05D0][.0000.00D4.0002.05BC] # HEBREW LETTER ALEF WITH MAPIQ; QQCM
+FB4F ; [.15B5.0020.0004.FB4F][.15C0.0020.0004.FB4F] # HEBREW LIGATURE ALEF LAMED; QQKN
+05D1 ; [.15B6.0020.0002.05D1] # HEBREW LETTER BET
+2136 ; [.15B6.0020.0004.2136] # BET SYMBOL; QQK
+FB31 ; [.15B6.0020.0002.05D1][.0000.00D4.0002.05BC] # HEBREW LETTER BET WITH DAGESH; QQCM
+FB4C ; [.15B6.0020.0002.05D1][.0000.00D7.0002.05BF] # HEBREW LETTER BET WITH RAFE; QQCM
+05D2 ; [.15B7.0020.0002.05D2] # HEBREW LETTER GIMEL
+2137 ; [.15B7.0020.0004.2137] # GIMEL SYMBOL; QQK
+FB32 ; [.15B7.0020.0002.05D2][.0000.00D4.0002.05BC] # HEBREW LETTER GIMEL WITH DAGESH; QQCM
+05D3 ; [.15B8.0020.0002.05D3] # HEBREW LETTER DALET
+2138 ; [.15B8.0020.0004.2138] # DALET SYMBOL; QQK
+FB22 ; [.15B8.0020.0005.FB22] # HEBREW LETTER WIDE DALET; QQK
+FB33 ; [.15B8.0020.0002.05D3][.0000.00D4.0002.05BC] # HEBREW LETTER DALET WITH DAGESH; QQCM
+05D4 ; [.15B9.0020.0002.05D4] # HEBREW LETTER HE
+FB23 ; [.15B9.0020.0005.FB23] # HEBREW LETTER WIDE HE; QQK
+FB34 ; [.15B9.0020.0002.05D4][.0000.00D4.0002.05BC] # HEBREW LETTER HE WITH MAPIQ; QQCM
+05D5 ; [.15BA.0020.0002.05D5] # HEBREW LETTER VAV
+FB4B ; [.15BA.0020.0002.05D5][.0000.00CF.0002.05B9] # HEBREW LETTER VAV WITH HOLAM; QQCM
+FB35 ; [.15BA.0020.0002.05D5][.0000.00D4.0002.05BC] # HEBREW LETTER VAV WITH DAGESH; QQCM
+05F0 ; [.15BA.0020.0004.05F0][.15BA.0020.0004.05F0] # HEBREW LIGATURE YIDDISH DOUBLE VAV; QQKN
+05F1 ; [.15BA.0020.0004.05F1][.15BE.0020.0004.05F1] # HEBREW LIGATURE YIDDISH VAV YOD; QQKN
+05D6 ; [.15BB.0020.0002.05D6] # HEBREW LETTER ZAYIN
+FB36 ; [.15BB.0020.0002.05D6][.0000.00D4.0002.05BC] # HEBREW LETTER ZAYIN WITH DAGESH; QQCM
+05D7 ; [.15BC.0020.0002.05D7] # HEBREW LETTER HET
+05D8 ; [.15BD.0020.0002.05D8] # HEBREW LETTER TET
+FB38 ; [.15BD.0020.0002.05D8][.0000.00D4.0002.05BC] # HEBREW LETTER TET WITH DAGESH; QQCM
+05D9 ; [.15BE.0020.0002.05D9] # HEBREW LETTER YOD
+FB1D ; [.15BE.0020.0002.05D9][.0000.00C9.0002.05B4] # HEBREW LETTER YOD WITH HIRIQ; QQCM
+FB39 ; [.15BE.0020.0002.05D9][.0000.00D4.0002.05BC] # HEBREW LETTER YOD WITH DAGESH; QQCM
+05F2 ; [.15BE.0020.0004.05F2][.15BE.0020.0004.05F2] # HEBREW LIGATURE YIDDISH DOUBLE YOD; QQKN
+FB1F ; [.15BE.0020.0004.FB1F][.15BE.0020.0004.FB1F][.0000.00CC.0002.FB1F] # HEBREW LIGATURE YIDDISH YOD YOD PATAH; QQKN
+05DB ; [.15BF.0020.0002.05DB] # HEBREW LETTER KAF
+FB24 ; [.15BF.0020.0005.FB24] # HEBREW LETTER WIDE KAF; QQK
+05DA ; [.15BF.0020.0019.05DA] # HEBREW LETTER FINAL KAF; QQK
+FB3B ; [.15BF.0020.0002.05DB][.0000.00D4.0002.05BC] # HEBREW LETTER KAF WITH DAGESH; QQCM
+FB3A ; [.15BF.0020.0019.FB3A][.0000.00D4.0002.FB3A] # HEBREW LETTER FINAL KAF WITH DAGESH; QQKN
+FB4D ; [.15BF.0020.0002.05DB][.0000.00D7.0002.05BF] # HEBREW LETTER KAF WITH RAFE; QQCM
+05DC ; [.15C0.0020.0002.05DC] # HEBREW LETTER LAMED
+FB25 ; [.15C0.0020.0005.FB25] # HEBREW LETTER WIDE LAMED; QQK
+FB3C ; [.15C0.0020.0002.05DC][.0000.00D4.0002.05BC] # HEBREW LETTER LAMED WITH DAGESH; QQCM
+05DE ; [.15C1.0020.0002.05DE] # HEBREW LETTER MEM
+FB26 ; [.15C1.0020.0005.FB26] # HEBREW LETTER WIDE FINAL MEM; QQK
+05DD ; [.15C1.0020.0019.05DD] # HEBREW LETTER FINAL MEM; QQK
+FB3E ; [.15C1.0020.0002.05DE][.0000.00D4.0002.05BC] # HEBREW LETTER MEM WITH DAGESH; QQCM
+05E0 ; [.15C2.0020.0002.05E0] # HEBREW LETTER NUN
+05DF ; [.15C2.0020.0019.05DF] # HEBREW LETTER FINAL NUN; QQK
+FB40 ; [.15C2.0020.0002.05E0][.0000.00D4.0002.05BC] # HEBREW LETTER NUN WITH DAGESH; QQCM
+05E1 ; [.15C3.0020.0002.05E1] # HEBREW LETTER SAMEKH
+FB41 ; [.15C3.0020.0002.05E1][.0000.00D4.0002.05BC] # HEBREW LETTER SAMEKH WITH DAGESH; QQCM
+05E2 ; [.15C4.0020.0002.05E2] # HEBREW LETTER AYIN
+FB20 ; [.15C4.0020.0005.FB20] # HEBREW LETTER ALTERNATIVE AYIN; QQK
+05E4 ; [.15C5.0020.0002.05E4] # HEBREW LETTER PE
+05E3 ; [.15C5.0020.0019.05E3] # HEBREW LETTER FINAL PE; QQK
+FB44 ; [.15C5.0020.0002.05E4][.0000.00D4.0002.05BC] # HEBREW LETTER PE WITH DAGESH; QQCM
+FB43 ; [.15C5.0020.0019.FB43][.0000.00D4.0002.FB43] # HEBREW LETTER FINAL PE WITH DAGESH; QQKN
+FB4E ; [.15C5.0020.0002.05E4][.0000.00D7.0002.05BF] # HEBREW LETTER PE WITH RAFE; QQCM
+05E6 ; [.15C6.0020.0002.05E6] # HEBREW LETTER TSADI
+05E5 ; [.15C6.0020.0019.05E5] # HEBREW LETTER FINAL TSADI; QQK
+FB46 ; [.15C6.0020.0002.05E6][.0000.00D4.0002.05BC] # HEBREW LETTER TSADI WITH DAGESH; QQCM
+05E7 ; [.15C7.0020.0002.05E7] # HEBREW LETTER QOF
+FB47 ; [.15C7.0020.0002.05E7][.0000.00D4.0002.05BC] # HEBREW LETTER QOF WITH DAGESH; QQCM
+05E8 ; [.15C8.0020.0002.05E8] # HEBREW LETTER RESH
+FB27 ; [.15C8.0020.0005.FB27] # HEBREW LETTER WIDE RESH; QQK
+FB48 ; [.15C8.0020.0002.05E8][.0000.00D4.0002.05BC] # HEBREW LETTER RESH WITH DAGESH; QQCM
+05E9 ; [.15C9.0020.0002.05E9] # HEBREW LETTER SHIN
+FB2B ; [.15C9.0020.0002.05E9][.0000.00D2.0002.05C2] # HEBREW LETTER SHIN WITH SIN DOT; QQCM
+FB2A ; [.15C9.0020.0002.05E9][.0000.00D3.0002.05C1] # HEBREW LETTER SHIN WITH SHIN DOT; QQCM
+FB49 ; [.15C9.0020.0002.05E9][.0000.00D4.0002.05BC] # HEBREW LETTER SHIN WITH DAGESH; QQCM
+FB2D ; [.15C9.0020.0002.05E9][.0000.00D4.0002.05BC][.0000.00D2.0002.05C2] # HEBREW LETTER SHIN WITH DAGESH AND SIN DOT; QQCM
+FB2C ; [.15C9.0020.0002.05E9][.0000.00D4.0002.05BC][.0000.00D3.0002.05C1] # HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT; QQCM
+05EA ; [.15CA.0020.0002.05EA] # HEBREW LETTER TAV
+FB28 ; [.15CA.0020.0005.FB28] # HEBREW LETTER WIDE TAV; QQK
+FB4A ; [.15CA.0020.0002.05EA][.0000.00D4.0002.05BC] # HEBREW LETTER TAV WITH DAGESH; QQCM
+10900 ; [.15CB.0020.0002.10900] # PHOENICIAN LETTER ALF
+10901 ; [.15CC.0020.0002.10901] # PHOENICIAN LETTER BET
+10902 ; [.15CD.0020.0002.10902] # PHOENICIAN LETTER GAML
+10903 ; [.15CE.0020.0002.10903] # PHOENICIAN LETTER DELT
+10904 ; [.15CF.0020.0002.10904] # PHOENICIAN LETTER HE
+10905 ; [.15D0.0020.0002.10905] # PHOENICIAN LETTER WAU
+10906 ; [.15D1.0020.0002.10906] # PHOENICIAN LETTER ZAI
+10907 ; [.15D2.0020.0002.10907] # PHOENICIAN LETTER HET
+10908 ; [.15D3.0020.0002.10908] # PHOENICIAN LETTER TET
+10909 ; [.15D4.0020.0002.10909] # PHOENICIAN LETTER YOD
+1090A ; [.15D5.0020.0002.1090A] # PHOENICIAN LETTER KAF
+1090B ; [.15D6.0020.0002.1090B] # PHOENICIAN LETTER LAMD
+1090C ; [.15D7.0020.0002.1090C] # PHOENICIAN LETTER MEM
+1090D ; [.15D8.0020.0002.1090D] # PHOENICIAN LETTER NUN
+1090E ; [.15D9.0020.0002.1090E] # PHOENICIAN LETTER SEMK
+1090F ; [.15DA.0020.0002.1090F] # PHOENICIAN LETTER AIN
+10910 ; [.15DB.0020.0002.10910] # PHOENICIAN LETTER PE
+10911 ; [.15DC.0020.0002.10911] # PHOENICIAN LETTER SADE
+10912 ; [.15DD.0020.0002.10912] # PHOENICIAN LETTER QOF
+10913 ; [.15DE.0020.0002.10913] # PHOENICIAN LETTER ROSH
+10914 ; [.15DF.0020.0002.10914] # PHOENICIAN LETTER SHIN
+10915 ; [.15E0.0020.0002.10915] # PHOENICIAN LETTER TAU
+0621 ; [.15E1.0020.0002.0621] # ARABIC LETTER HAMZA
+0674 ; [.15E1.0020.0004.0674] # ARABIC LETTER HIGH HAMZA; QQK
+FE80 ; [.15E1.0020.001A.FE80] # ARABIC LETTER HAMZA ISOLATED FORM; QQK
+06FD ; [.15E1.0020.0004.06FD][.0000.019A.0004.06FD] # ARABIC SIGN SINDHI AMPERSAND; QQKN
+0622 ; [.15E2.0020.0002.0622] # ARABIC LETTER ALEF WITH MADDA ABOVE
+0627 0653 ; [.15E2.0020.0002.0622] # ARABIC LETTER ALEF WITH MADDA ABOVE
+FE82 ; [.15E2.0020.0019.FE82] # ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM; QQK
+FE81 ; [.15E2.0020.001A.FE81] # ARABIC LETTER ALEF WITH MADDA ABOVE ISOLATED FORM; QQK
+0623 ; [.15E3.0020.0002.0623] # ARABIC LETTER ALEF WITH HAMZA ABOVE
+0627 0654 ; [.15E3.0020.0002.0623] # ARABIC LETTER ALEF WITH HAMZA ABOVE
+FE84 ; [.15E3.0020.0019.FE84] # ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM; QQK
+FE83 ; [.15E3.0020.001A.FE83] # ARABIC LETTER ALEF WITH HAMZA ABOVE ISOLATED FORM; QQK
+0672 ; [.15E4.0020.0002.0672] # ARABIC LETTER ALEF WITH WAVY HAMZA ABOVE
+0671 ; [.15E5.0020.0002.0671] # ARABIC LETTER ALEF WASLA
+FB51 ; [.15E5.0020.0019.FB51] # ARABIC LETTER ALEF WASLA FINAL FORM; QQK
+FB50 ; [.15E5.0020.001A.FB50] # ARABIC LETTER ALEF WASLA ISOLATED FORM; QQK
+0624 ; [.15E6.0020.0002.0624] # ARABIC LETTER WAW WITH HAMZA ABOVE
+0648 0654 ; [.15E6.0020.0002.0624] # ARABIC LETTER WAW WITH HAMZA ABOVE
+FE86 ; [.15E6.0020.0019.FE86] # ARABIC LETTER WAW WITH HAMZA ABOVE FINAL FORM; QQK
+FE85 ; [.15E6.0020.001A.FE85] # ARABIC LETTER WAW WITH HAMZA ABOVE ISOLATED FORM; QQK
+0625 ; [.15E7.0020.0002.0625] # ARABIC LETTER ALEF WITH HAMZA BELOW
+0627 0655 ; [.15E7.0020.0002.0625] # ARABIC LETTER ALEF WITH HAMZA BELOW
+FE88 ; [.15E7.0020.0019.FE88] # ARABIC LETTER ALEF WITH HAMZA BELOW FINAL FORM; QQK
+FE87 ; [.15E7.0020.001A.FE87] # ARABIC LETTER ALEF WITH HAMZA BELOW ISOLATED FORM; QQK
+0673 ; [.15E8.0020.0002.0673] # ARABIC LETTER ALEF WITH WAVY HAMZA BELOW
+0626 ; [.15E9.0020.0002.0626] # ARABIC LETTER YEH WITH HAMZA ABOVE
+064A 0654 ; [.15E9.0020.0002.0626] # ARABIC LETTER YEH WITH HAMZA ABOVE
+FE8B ; [.15E9.0020.0017.FE8B] # ARABIC LETTER YEH WITH HAMZA ABOVE INITIAL FORM; QQK
+FE8C ; [.15E9.0020.0018.FE8C] # ARABIC LETTER YEH WITH HAMZA ABOVE MEDIAL FORM; QQK
+FE8A ; [.15E9.0020.0019.FE8A] # ARABIC LETTER YEH WITH HAMZA ABOVE FINAL FORM; QQK
+FE89 ; [.15E9.0020.001A.FE89] # ARABIC LETTER YEH WITH HAMZA ABOVE ISOLATED FORM; QQK
+FBEB ; [.15E9.0020.0019.FBEB][.15EA.0020.0019.FBEB] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF FINAL FORM; QQKN
+FBEA ; [.15E9.0020.001A.FBEA][.15EA.0020.001A.FBEA] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF ISOLATED FORM; QQKN
+FC97 ; [.15E9.0020.0017.FC97][.15FF.0020.0017.FC97] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM INITIAL FORM; QQKN
+FC00 ; [.15E9.0020.001A.FC00][.15FF.0020.001A.FC00] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH JEEM ISOLATED FORM; QQKN
+FC98 ; [.15E9.0020.0017.FC98][.1605.0020.0017.FC98] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH INITIAL FORM; QQKN
+FC01 ; [.15E9.0020.001A.FC01][.1605.0020.001A.FC01] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HAH ISOLATED FORM; QQKN
+FC99 ; [.15E9.0020.0017.FC99][.1606.0020.0017.FC99] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH KHAH INITIAL FORM; QQKN
+FC64 ; [.15E9.0020.0019.FC64][.161A.0020.0019.FC64] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH REH FINAL FORM; QQKN
+FC65 ; [.15E9.0020.0019.FC65][.161B.0020.0019.FC65] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ZAIN FINAL FORM; QQKN
+FC9A ; [.15E9.0020.0017.FC9A][.1663.0020.0017.FC9A] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM INITIAL FORM; QQKN
+FCDF ; [.15E9.0020.0018.FCDF][.1663.0020.0018.FCDF] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM MEDIAL FORM; QQKN
+FC66 ; [.15E9.0020.0019.FC66][.1663.0020.0019.FC66] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM FINAL FORM; QQKN
+FC02 ; [.15E9.0020.001A.FC02][.1663.0020.001A.FC02] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH MEEM ISOLATED FORM; QQKN
+FC67 ; [.15E9.0020.0019.FC67][.1666.0020.0019.FC67] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH NOON FINAL FORM; QQKN
+FC9B ; [.15E9.0020.0017.FC9B][.166F.0020.0017.FC9B] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH INITIAL FORM; QQKN
+FCE0 ; [.15E9.0020.0018.FCE0][.166F.0020.0018.FCE0] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH HEH MEDIAL FORM; QQKN
+FBED ; [.15E9.0020.0019.FBED][.1674.0020.0019.FBED] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE FINAL FORM; QQKN
+FBEC ; [.15E9.0020.001A.FBEC][.1674.0020.001A.FBEC] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH AE ISOLATED FORM; QQKN
+FBEF ; [.15E9.0020.0019.FBEF][.1675.0020.0019.FBEF] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW FINAL FORM; QQKN
+FBEE ; [.15E9.0020.001A.FBEE][.1675.0020.001A.FBEE] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH WAW ISOLATED FORM; QQKN
+FBF3 ; [.15E9.0020.0019.FBF3][.1678.0020.0019.FBF3] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE FINAL FORM; QQKN
+FBF2 ; [.15E9.0020.001A.FBF2][.1678.0020.001A.FBF2] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH OE ISOLATED FORM; QQKN
+FBF1 ; [.15E9.0020.0019.FBF1][.1679.0020.0019.FBF1] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U FINAL FORM; QQKN
+FBF0 ; [.15E9.0020.001A.FBF0][.1679.0020.001A.FBF0] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH U ISOLATED FORM; QQKN
+FBF5 ; [.15E9.0020.0019.FBF5][.167A.0020.0019.FBF5] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU FINAL FORM; QQKN
+FBF4 ; [.15E9.0020.001A.FBF4][.167A.0020.001A.FBF4] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YU ISOLATED FORM; QQKN
+FBFB ; [.15E9.0020.0017.FBFB][.167F.0020.0017.FBFB] # ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA INITIAL FORM; QQKN
+FBFA ; [.15E9.0020.0019.FBFA][.167F.0020.0019.FBFA] # ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM; QQKN
+FC68 ; [.15E9.0020.0019.FC68][.167F.0020.0019.FC68] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA FINAL FORM; QQKN
+FBF9 ; [.15E9.0020.001A.FBF9][.167F.0020.001A.FBF9] # ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FC03 ; [.15E9.0020.001A.FC03][.167F.0020.001A.FC03] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FC69 ; [.15E9.0020.0019.FC69][.1680.0020.0019.FC69] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH FINAL FORM; QQKN
+FC04 ; [.15E9.0020.001A.FC04][.1680.0020.001A.FC04] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH YEH ISOLATED FORM; QQKN
+FBF8 ; [.15E9.0020.0017.FBF8][.1684.0020.0017.FBF8] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E INITIAL FORM; QQKN
+FBF7 ; [.15E9.0020.0019.FBF7][.1684.0020.0019.FBF7] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E FINAL FORM; QQKN
+FBF6 ; [.15E9.0020.001A.FBF6][.1684.0020.001A.FBF6] # ARABIC LIGATURE YEH WITH HAMZA ABOVE WITH E ISOLATED FORM; QQKN
+0627 ; [.15EA.0020.0002.0627] # ARABIC LETTER ALEF
+FE8E ; [.15EA.0020.0019.FE8E] # ARABIC LETTER ALEF FINAL FORM; QQK
+FE8D ; [.15EA.0020.001A.FE8D] # ARABIC LETTER ALEF ISOLATED FORM; QQK
+FD3C ; [.15EA.0020.0019.FD3C][.0000.00D9.0019.FD3C] # ARABIC LIGATURE ALEF WITH FATHATAN FINAL FORM; QQKN
+FD3D ; [.15EA.0020.001A.FD3D][.0000.00D9.001A.FD3D] # ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM; QQKN
+0675 ; [.15EA.0020.0004.0675][.15E1.0020.0004.0675] # ARABIC LETTER HIGH HAMZA ALEF; QQKN
+FDF3 ; [.15EA.0020.001A.FDF3][.164D.0020.001A.FDF3][.15EC.0020.001F.FDF3][.161A.0020.001F.FDF3] # ARABIC LIGATURE AKBAR ISOLATED FORM; QQKN
+FDF2 ; [.15EA.0020.001A.FDF2][.165D.0020.001A.FDF2][.165D.0020.001F.FDF2][.166F.0020.001F.FDF2] # ARABIC LIGATURE ALLAH ISOLATED FORM; QQKN
+066E ; [.15EB.0020.0002.066E] # ARABIC LETTER DOTLESS BEH
+0628 ; [.15EC.0020.0002.0628] # ARABIC LETTER BEH
+FE91 ; [.15EC.0020.0017.FE91] # ARABIC LETTER BEH INITIAL FORM; QQK
+FE92 ; [.15EC.0020.0018.FE92] # ARABIC LETTER BEH MEDIAL FORM; QQK
+FE90 ; [.15EC.0020.0019.FE90] # ARABIC LETTER BEH FINAL FORM; QQK
+FE8F ; [.15EC.0020.001A.FE8F] # ARABIC LETTER BEH ISOLATED FORM; QQK
+FC9C ; [.15EC.0020.0017.FC9C][.15FF.0020.0017.FC9C] # ARABIC LIGATURE BEH WITH JEEM INITIAL FORM; QQKN
+FC05 ; [.15EC.0020.001A.FC05][.15FF.0020.001A.FC05] # ARABIC LIGATURE BEH WITH JEEM ISOLATED FORM; QQKN
+FC9D ; [.15EC.0020.0017.FC9D][.1605.0020.0017.FC9D] # ARABIC LIGATURE BEH WITH HAH INITIAL FORM; QQKN
+FC06 ; [.15EC.0020.001A.FC06][.1605.0020.001A.FC06] # ARABIC LIGATURE BEH WITH HAH ISOLATED FORM; QQKN
+FDC2 ; [.15EC.0020.0019.FDC2][.1605.0020.0019.FDC2][.1680.0020.001F.FDC2] # ARABIC LIGATURE BEH WITH HAH WITH YEH FINAL FORM; QQKN
+FC9E ; [.15EC.0020.0017.FC9E][.1606.0020.0017.FC9E] # ARABIC LIGATURE BEH WITH KHAH INITIAL FORM; QQKN
+FC07 ; [.15EC.0020.001A.FC07][.1606.0020.001A.FC07] # ARABIC LIGATURE BEH WITH KHAH ISOLATED FORM; QQKN
+FD9E ; [.15EC.0020.0019.FD9E][.1606.0020.0019.FD9E][.1680.0020.001F.FD9E] # ARABIC LIGATURE BEH WITH KHAH WITH YEH FINAL FORM; QQKN
+FC6A ; [.15EC.0020.0019.FC6A][.161A.0020.0019.FC6A] # ARABIC LIGATURE BEH WITH REH FINAL FORM; QQKN
+FC6B ; [.15EC.0020.0019.FC6B][.161B.0020.0019.FC6B] # ARABIC LIGATURE BEH WITH ZAIN FINAL FORM; QQKN
+FC9F ; [.15EC.0020.0017.FC9F][.1663.0020.0017.FC9F] # ARABIC LIGATURE BEH WITH MEEM INITIAL FORM; QQKN
+FCE1 ; [.15EC.0020.0018.FCE1][.1663.0020.0018.FCE1] # ARABIC LIGATURE BEH WITH MEEM MEDIAL FORM; QQKN
+FC6C ; [.15EC.0020.0019.FC6C][.1663.0020.0019.FC6C] # ARABIC LIGATURE BEH WITH MEEM FINAL FORM; QQKN
+FC08 ; [.15EC.0020.001A.FC08][.1663.0020.001A.FC08] # ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM; QQKN
+FC6D ; [.15EC.0020.0019.FC6D][.1666.0020.0019.FC6D] # ARABIC LIGATURE BEH WITH NOON FINAL FORM; QQKN
+FCA0 ; [.15EC.0020.0017.FCA0][.166F.0020.0017.FCA0] # ARABIC LIGATURE BEH WITH HEH INITIAL FORM; QQKN
+FCE2 ; [.15EC.0020.0018.FCE2][.166F.0020.0018.FCE2] # ARABIC LIGATURE BEH WITH HEH MEDIAL FORM; QQKN
+FC6E ; [.15EC.0020.0019.FC6E][.167F.0020.0019.FC6E] # ARABIC LIGATURE BEH WITH ALEF MAKSURA FINAL FORM; QQKN
+FC09 ; [.15EC.0020.001A.FC09][.167F.0020.001A.FC09] # ARABIC LIGATURE BEH WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FC6F ; [.15EC.0020.0019.FC6F][.1680.0020.0019.FC6F] # ARABIC LIGATURE BEH WITH YEH FINAL FORM; QQKN
+FC0A ; [.15EC.0020.001A.FC0A][.1680.0020.001A.FC0A] # ARABIC LIGATURE BEH WITH YEH ISOLATED FORM; QQKN
+067B ; [.15ED.0020.0002.067B] # ARABIC LETTER BEEH
+FB54 ; [.15ED.0020.0017.FB54] # ARABIC LETTER BEEH INITIAL FORM; QQK
+FB55 ; [.15ED.0020.0018.FB55] # ARABIC LETTER BEEH MEDIAL FORM; QQK
+FB53 ; [.15ED.0020.0019.FB53] # ARABIC LETTER BEEH FINAL FORM; QQK
+FB52 ; [.15ED.0020.001A.FB52] # ARABIC LETTER BEEH ISOLATED FORM; QQK
+067E ; [.15EE.0020.0002.067E] # ARABIC LETTER PEH
+FB58 ; [.15EE.0020.0017.FB58] # ARABIC LETTER PEH INITIAL FORM; QQK
+FB59 ; [.15EE.0020.0018.FB59] # ARABIC LETTER PEH MEDIAL FORM; QQK
+FB57 ; [.15EE.0020.0019.FB57] # ARABIC LETTER PEH FINAL FORM; QQK
+FB56 ; [.15EE.0020.001A.FB56] # ARABIC LETTER PEH ISOLATED FORM; QQK
+0680 ; [.15EF.0020.0002.0680] # ARABIC LETTER BEHEH
+FB5C ; [.15EF.0020.0017.FB5C] # ARABIC LETTER BEHEH INITIAL FORM; QQK
+FB5D ; [.15EF.0020.0018.FB5D] # ARABIC LETTER BEHEH MEDIAL FORM; QQK
+FB5B ; [.15EF.0020.0019.FB5B] # ARABIC LETTER BEHEH FINAL FORM; QQK
+FB5A ; [.15EF.0020.001A.FB5A] # ARABIC LETTER BEHEH ISOLATED FORM; QQK
+0750 ; [.15F0.0020.0002.0750] # ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW
+0751 ; [.15F1.0020.0002.0751] # ARABIC LETTER BEH WITH DOT BELOW AND THREE DOTS ABOVE
+0752 ; [.15F2.0020.0002.0752] # ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW
+0753 ; [.15F3.0020.0002.0753] # ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW AND TWO DOTS ABOVE
+0754 ; [.15F4.0020.0002.0754] # ARABIC LETTER BEH WITH TWO DOTS BELOW AND DOT ABOVE
+0755 ; [.15F5.0020.0002.0755] # ARABIC LETTER BEH WITH INVERTED SMALL V BELOW
+0756 ; [.15F6.0020.0002.0756] # ARABIC LETTER BEH WITH SMALL V
+0629 ; [.15F7.0020.0002.0629] # ARABIC LETTER TEH MARBUTA
+FE94 ; [.15F7.0020.0019.FE94] # ARABIC LETTER TEH MARBUTA FINAL FORM; QQK
+FE93 ; [.15F7.0020.001A.FE93] # ARABIC LETTER TEH MARBUTA ISOLATED FORM; QQK
+062A ; [.15F8.0020.0002.062A] # ARABIC LETTER TEH
+FE97 ; [.15F8.0020.0017.FE97] # ARABIC LETTER TEH INITIAL FORM; QQK
+FE98 ; [.15F8.0020.0018.FE98] # ARABIC LETTER TEH MEDIAL FORM; QQK
+FE96 ; [.15F8.0020.0019.FE96] # ARABIC LETTER TEH FINAL FORM; QQK
+FE95 ; [.15F8.0020.001A.FE95] # ARABIC LETTER TEH ISOLATED FORM; QQK
+FCA1 ; [.15F8.0020.0017.FCA1][.15FF.0020.0017.FCA1] # ARABIC LIGATURE TEH WITH JEEM INITIAL FORM; QQKN
+FC0B ; [.15F8.0020.001A.FC0B][.15FF.0020.001A.FC0B] # ARABIC LIGATURE TEH WITH JEEM ISOLATED FORM; QQKN
+FD50 ; [.15F8.0020.0017.FD50][.15FF.0020.0017.FD50][.1663.0020.001F.FD50] # ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM; QQKN
+FDA0 ; [.15F8.0020.0019.FDA0][.15FF.0020.0019.FDA0][.167F.0020.001F.FDA0] # ARABIC LIGATURE TEH WITH JEEM WITH ALEF MAKSURA FINAL FORM; QQKN
+FD9F ; [.15F8.0020.0019.FD9F][.15FF.0020.0019.FD9F][.1680.0020.001F.FD9F] # ARABIC LIGATURE TEH WITH JEEM WITH YEH FINAL FORM; QQKN
+FCA2 ; [.15F8.0020.0017.FCA2][.1605.0020.0017.FCA2] # ARABIC LIGATURE TEH WITH HAH INITIAL FORM; QQKN
+FC0C ; [.15F8.0020.001A.FC0C][.1605.0020.001A.FC0C] # ARABIC LIGATURE TEH WITH HAH ISOLATED FORM; QQKN
+FD52 ; [.15F8.0020.0017.FD52][.1605.0020.0017.FD52][.15FF.0020.001F.FD52] # ARABIC LIGATURE TEH WITH HAH WITH JEEM INITIAL FORM; QQKN
+FD51 ; [.15F8.0020.0019.FD51][.1605.0020.0019.FD51][.15FF.0020.001F.FD51] # ARABIC LIGATURE TEH WITH HAH WITH JEEM FINAL FORM; QQKN
+FD53 ; [.15F8.0020.0017.FD53][.1605.0020.0017.FD53][.1663.0020.001F.FD53] # ARABIC LIGATURE TEH WITH HAH WITH MEEM INITIAL FORM; QQKN
+FCA3 ; [.15F8.0020.0017.FCA3][.1606.0020.0017.FCA3] # ARABIC LIGATURE TEH WITH KHAH INITIAL FORM; QQKN
+FC0D ; [.15F8.0020.001A.FC0D][.1606.0020.001A.FC0D] # ARABIC LIGATURE TEH WITH KHAH ISOLATED FORM; QQKN
+FD54 ; [.15F8.0020.0017.FD54][.1606.0020.0017.FD54][.1663.0020.001F.FD54] # ARABIC LIGATURE TEH WITH KHAH WITH MEEM INITIAL FORM; QQKN
+FDA2 ; [.15F8.0020.0019.FDA2][.1606.0020.0019.FDA2][.167F.0020.001F.FDA2] # ARABIC LIGATURE TEH WITH KHAH WITH ALEF MAKSURA FINAL FORM; QQKN
+FDA1 ; [.15F8.0020.0019.FDA1][.1606.0020.0019.FDA1][.1680.0020.001F.FDA1] # ARABIC LIGATURE TEH WITH KHAH WITH YEH FINAL FORM; QQKN
+FC70 ; [.15F8.0020.0019.FC70][.161A.0020.0019.FC70] # ARABIC LIGATURE TEH WITH REH FINAL FORM; QQKN
+FC71 ; [.15F8.0020.0019.FC71][.161B.0020.0019.FC71] # ARABIC LIGATURE TEH WITH ZAIN FINAL FORM; QQKN
+FCA4 ; [.15F8.0020.0017.FCA4][.1663.0020.0017.FCA4] # ARABIC LIGATURE TEH WITH MEEM INITIAL FORM; QQKN
+FCE3 ; [.15F8.0020.0018.FCE3][.1663.0020.0018.FCE3] # ARABIC LIGATURE TEH WITH MEEM MEDIAL FORM; QQKN
+FC72 ; [.15F8.0020.0019.FC72][.1663.0020.0019.FC72] # ARABIC LIGATURE TEH WITH MEEM FINAL FORM; QQKN
+FC0E ; [.15F8.0020.001A.FC0E][.1663.0020.001A.FC0E] # ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM; QQKN
+FD55 ; [.15F8.0020.0017.FD55][.1663.0020.0017.FD55][.15FF.0020.001F.FD55] # ARABIC LIGATURE TEH WITH MEEM WITH JEEM INITIAL FORM; QQKN
+FD56 ; [.15F8.0020.0017.FD56][.1663.0020.0017.FD56][.1605.0020.001F.FD56] # ARABIC LIGATURE TEH WITH MEEM WITH HAH INITIAL FORM; QQKN
+FD57 ; [.15F8.0020.0017.FD57][.1663.0020.0017.FD57][.1606.0020.001F.FD57] # ARABIC LIGATURE TEH WITH MEEM WITH KHAH INITIAL FORM; QQKN
+FDA4 ; [.15F8.0020.0019.FDA4][.1663.0020.0019.FDA4][.167F.0020.001F.FDA4] # ARABIC LIGATURE TEH WITH MEEM WITH ALEF MAKSURA FINAL FORM; QQKN
+FDA3 ; [.15F8.0020.0019.FDA3][.1663.0020.0019.FDA3][.1680.0020.001F.FDA3] # ARABIC LIGATURE TEH WITH MEEM WITH YEH FINAL FORM; QQKN
+FC73 ; [.15F8.0020.0019.FC73][.1666.0020.0019.FC73] # ARABIC LIGATURE TEH WITH NOON FINAL FORM; QQKN
+FCA5 ; [.15F8.0020.0017.FCA5][.166F.0020.0017.FCA5] # ARABIC LIGATURE TEH WITH HEH INITIAL FORM; QQKN
+FCE4 ; [.15F8.0020.0018.FCE4][.166F.0020.0018.FCE4] # ARABIC LIGATURE TEH WITH HEH MEDIAL FORM; QQKN
+FC74 ; [.15F8.0020.0019.FC74][.167F.0020.0019.FC74] # ARABIC LIGATURE TEH WITH ALEF MAKSURA FINAL FORM; QQKN
+FC0F ; [.15F8.0020.001A.FC0F][.167F.0020.001A.FC0F] # ARABIC LIGATURE TEH WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FC75 ; [.15F8.0020.0019.FC75][.1680.0020.0019.FC75] # ARABIC LIGATURE TEH WITH YEH FINAL FORM; QQKN
+FC10 ; [.15F8.0020.001A.FC10][.1680.0020.001A.FC10] # ARABIC LIGATURE TEH WITH YEH ISOLATED FORM; QQKN
+062B ; [.15F9.0020.0002.062B] # ARABIC LETTER THEH
+FE9B ; [.15F9.0020.0017.FE9B] # ARABIC LETTER THEH INITIAL FORM; QQK
+FE9C ; [.15F9.0020.0018.FE9C] # ARABIC LETTER THEH MEDIAL FORM; QQK
+FE9A ; [.15F9.0020.0019.FE9A] # ARABIC LETTER THEH FINAL FORM; QQK
+FE99 ; [.15F9.0020.001A.FE99] # ARABIC LETTER THEH ISOLATED FORM; QQK
+FC11 ; [.15F9.0020.001A.FC11][.15FF.0020.001A.FC11] # ARABIC LIGATURE THEH WITH JEEM ISOLATED FORM; QQKN
+FC76 ; [.15F9.0020.0019.FC76][.161A.0020.0019.FC76] # ARABIC LIGATURE THEH WITH REH FINAL FORM; QQKN
+FC77 ; [.15F9.0020.0019.FC77][.161B.0020.0019.FC77] # ARABIC LIGATURE THEH WITH ZAIN FINAL FORM; QQKN
+FCA6 ; [.15F9.0020.0017.FCA6][.1663.0020.0017.FCA6] # ARABIC LIGATURE THEH WITH MEEM INITIAL FORM; QQKN
+FCE5 ; [.15F9.0020.0018.FCE5][.1663.0020.0018.FCE5] # ARABIC LIGATURE THEH WITH MEEM MEDIAL FORM; QQKN
+FC78 ; [.15F9.0020.0019.FC78][.1663.0020.0019.FC78] # ARABIC LIGATURE THEH WITH MEEM FINAL FORM; QQKN
+FC12 ; [.15F9.0020.001A.FC12][.1663.0020.001A.FC12] # ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM; QQKN
+FC79 ; [.15F9.0020.0019.FC79][.1666.0020.0019.FC79] # ARABIC LIGATURE THEH WITH NOON FINAL FORM; QQKN
+FCE6 ; [.15F9.0020.0018.FCE6][.166F.0020.0018.FCE6] # ARABIC LIGATURE THEH WITH HEH MEDIAL FORM; QQKN
+FC7A ; [.15F9.0020.0019.FC7A][.167F.0020.0019.FC7A] # ARABIC LIGATURE THEH WITH ALEF MAKSURA FINAL FORM; QQKN
+FC13 ; [.15F9.0020.001A.FC13][.167F.0020.001A.FC13] # ARABIC LIGATURE THEH WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FC7B ; [.15F9.0020.0019.FC7B][.1680.0020.0019.FC7B] # ARABIC LIGATURE THEH WITH YEH FINAL FORM; QQKN
+FC14 ; [.15F9.0020.001A.FC14][.1680.0020.001A.FC14] # ARABIC LIGATURE THEH WITH YEH ISOLATED FORM; QQKN
+0679 ; [.15FA.0020.0002.0679] # ARABIC LETTER TTEH
+FB68 ; [.15FA.0020.0017.FB68] # ARABIC LETTER TTEH INITIAL FORM; QQK
+FB69 ; [.15FA.0020.0018.FB69] # ARABIC LETTER TTEH MEDIAL FORM; QQK
+FB67 ; [.15FA.0020.0019.FB67] # ARABIC LETTER TTEH FINAL FORM; QQK
+FB66 ; [.15FA.0020.001A.FB66] # ARABIC LETTER TTEH ISOLATED FORM; QQK
+067A ; [.15FB.0020.0002.067A] # ARABIC LETTER TTEHEH
+FB60 ; [.15FB.0020.0017.FB60] # ARABIC LETTER TTEHEH INITIAL FORM; QQK
+FB61 ; [.15FB.0020.0018.FB61] # ARABIC LETTER TTEHEH MEDIAL FORM; QQK
+FB5F ; [.15FB.0020.0019.FB5F] # ARABIC LETTER TTEHEH FINAL FORM; QQK
+FB5E ; [.15FB.0020.001A.FB5E] # ARABIC LETTER TTEHEH ISOLATED FORM; QQK
+067C ; [.15FC.0020.0002.067C] # ARABIC LETTER TEH WITH RING
+067D ; [.15FD.0020.0002.067D] # ARABIC LETTER TEH WITH THREE DOTS ABOVE DOWNWARDS
+067F ; [.15FE.0020.0002.067F] # ARABIC LETTER TEHEH
+FB64 ; [.15FE.0020.0017.FB64] # ARABIC LETTER TEHEH INITIAL FORM; QQK
+FB65 ; [.15FE.0020.0018.FB65] # ARABIC LETTER TEHEH MEDIAL FORM; QQK
+FB63 ; [.15FE.0020.0019.FB63] # ARABIC LETTER TEHEH FINAL FORM; QQK
+FB62 ; [.15FE.0020.001A.FB62] # ARABIC LETTER TEHEH ISOLATED FORM; QQK
+062C ; [.15FF.0020.0002.062C] # ARABIC LETTER JEEM
+FE9F ; [.15FF.0020.0017.FE9F] # ARABIC LETTER JEEM INITIAL FORM; QQK
+FEA0 ; [.15FF.0020.0018.FEA0] # ARABIC LETTER JEEM MEDIAL FORM; QQK
+FE9E ; [.15FF.0020.0019.FE9E] # ARABIC LETTER JEEM FINAL FORM; QQK
+FE9D ; [.15FF.0020.001A.FE9D] # ARABIC LETTER JEEM ISOLATED FORM; QQK
+FCA7 ; [.15FF.0020.0017.FCA7][.1605.0020.0017.FCA7] # ARABIC LIGATURE JEEM WITH HAH INITIAL FORM; QQKN
+FC15 ; [.15FF.0020.001A.FC15][.1605.0020.001A.FC15] # ARABIC LIGATURE JEEM WITH HAH ISOLATED FORM; QQKN
+FDA6 ; [.15FF.0020.0019.FDA6][.1605.0020.0019.FDA6][.167F.0020.001F.FDA6] # ARABIC LIGATURE JEEM WITH HAH WITH ALEF MAKSURA FINAL FORM; QQKN
+FDBE ; [.15FF.0020.0019.FDBE][.1605.0020.0019.FDBE][.1680.0020.001F.FDBE] # ARABIC LIGATURE JEEM WITH HAH WITH YEH FINAL FORM; QQKN
+FDFB ; [.15FF.0020.001A.FDFB][.165D.0020.001A.FDFB][*0209.0020.001F.FDFB][.15FF.0020.001F.FDFB][.165D.0020.001F.FDFB][.15EA.0020.001F.FDFB][.165D.0020.001F.FDFB][.166F.0020.001F.FDFB] # ARABIC LIGATURE JALLAJALALOUHOU; QQKN
+FCA8 ; [.15FF.0020.0017.FCA8][.1663.0020.0017.FCA8] # ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM; QQKN
+FC16 ; [.15FF.0020.001A.FC16][.1663.0020.001A.FC16] # ARABIC LIGATURE JEEM WITH MEEM ISOLATED FORM; QQKN
+FD59 ; [.15FF.0020.0017.FD59][.1663.0020.0017.FD59][.1605.0020.001F.FD59] # ARABIC LIGATURE JEEM WITH MEEM WITH HAH INITIAL FORM; QQKN
+FD58 ; [.15FF.0020.0019.FD58][.1663.0020.0019.FD58][.1605.0020.001F.FD58] # ARABIC LIGATURE JEEM WITH MEEM WITH HAH FINAL FORM; QQKN
+FDA7 ; [.15FF.0020.0019.FDA7][.1663.0020.0019.FDA7][.167F.0020.001F.FDA7] # ARABIC LIGATURE JEEM WITH MEEM WITH ALEF MAKSURA FINAL FORM; QQKN
+FDA5 ; [.15FF.0020.0019.FDA5][.1663.0020.0019.FDA5][.1680.0020.001F.FDA5] # ARABIC LIGATURE JEEM WITH MEEM WITH YEH FINAL FORM; QQKN
+FD1D ; [.15FF.0020.0019.FD1D][.167F.0020.0019.FD1D] # ARABIC LIGATURE JEEM WITH ALEF MAKSURA FINAL FORM; QQKN
+FD01 ; [.15FF.0020.001A.FD01][.167F.0020.001A.FD01] # ARABIC LIGATURE JEEM WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FD1E ; [.15FF.0020.0019.FD1E][.1680.0020.0019.FD1E] # ARABIC LIGATURE JEEM WITH YEH FINAL FORM; QQKN
+FD02 ; [.15FF.0020.001A.FD02][.1680.0020.001A.FD02] # ARABIC LIGATURE JEEM WITH YEH ISOLATED FORM; QQKN
+0683 ; [.1600.0020.0002.0683] # ARABIC LETTER NYEH
+FB78 ; [.1600.0020.0017.FB78] # ARABIC LETTER NYEH INITIAL FORM; QQK
+FB79 ; [.1600.0020.0018.FB79] # ARABIC LETTER NYEH MEDIAL FORM; QQK
+FB77 ; [.1600.0020.0019.FB77] # ARABIC LETTER NYEH FINAL FORM; QQK
+FB76 ; [.1600.0020.001A.FB76] # ARABIC LETTER NYEH ISOLATED FORM; QQK
+0684 ; [.1601.0020.0002.0684] # ARABIC LETTER DYEH
+FB74 ; [.1601.0020.0017.FB74] # ARABIC LETTER DYEH INITIAL FORM; QQK
+FB75 ; [.1601.0020.0018.FB75] # ARABIC LETTER DYEH MEDIAL FORM; QQK
+FB73 ; [.1601.0020.0019.FB73] # ARABIC LETTER DYEH FINAL FORM; QQK
+FB72 ; [.1601.0020.001A.FB72] # ARABIC LETTER DYEH ISOLATED FORM; QQK
+0686 ; [.1602.0020.0002.0686] # ARABIC LETTER TCHEH
+FB7C ; [.1602.0020.0017.FB7C] # ARABIC LETTER TCHEH INITIAL FORM; QQK
+FB7D ; [.1602.0020.0018.FB7D] # ARABIC LETTER TCHEH MEDIAL FORM; QQK
+FB7B ; [.1602.0020.0019.FB7B] # ARABIC LETTER TCHEH FINAL FORM; QQK
+FB7A ; [.1602.0020.001A.FB7A] # ARABIC LETTER TCHEH ISOLATED FORM; QQK
+06BF ; [.1603.0020.0002.06BF] # ARABIC LETTER TCHEH WITH DOT ABOVE
+0687 ; [.1604.0020.0002.0687] # ARABIC LETTER TCHEHEH
+FB80 ; [.1604.0020.0017.FB80] # ARABIC LETTER TCHEHEH INITIAL FORM; QQK
+FB81 ; [.1604.0020.0018.FB81] # ARABIC LETTER TCHEHEH MEDIAL FORM; QQK
+FB7F ; [.1604.0020.0019.FB7F] # ARABIC LETTER TCHEHEH FINAL FORM; QQK
+FB7E ; [.1604.0020.001A.FB7E] # ARABIC LETTER TCHEHEH ISOLATED FORM; QQK
+062D ; [.1605.0020.0002.062D] # ARABIC LETTER HAH
+FEA3 ; [.1605.0020.0017.FEA3] # ARABIC LETTER HAH INITIAL FORM; QQK
+FEA4 ; [.1605.0020.0018.FEA4] # ARABIC LETTER HAH MEDIAL FORM; QQK
+FEA2 ; [.1605.0020.0019.FEA2] # ARABIC LETTER HAH FINAL FORM; QQK
+FEA1 ; [.1605.0020.001A.FEA1] # ARABIC LETTER HAH ISOLATED FORM; QQK
+FCA9 ; [.1605.0020.0017.FCA9][.15FF.0020.0017.FCA9] # ARABIC LIGATURE HAH WITH JEEM INITIAL FORM; QQKN
+FC17 ; [.1605.0020.001A.FC17][.15FF.0020.001A.FC17] # ARABIC LIGATURE HAH WITH JEEM ISOLATED FORM; QQKN
+FDBF ; [.1605.0020.0019.FDBF][.15FF.0020.0019.FDBF][.1680.0020.001F.FDBF] # ARABIC LIGATURE HAH WITH JEEM WITH YEH FINAL FORM; QQKN
+FCAA ; [.1605.0020.0017.FCAA][.1663.0020.0017.FCAA] # ARABIC LIGATURE HAH WITH MEEM INITIAL FORM; QQKN
+FC18 ; [.1605.0020.001A.FC18][.1663.0020.001A.FC18] # ARABIC LIGATURE HAH WITH MEEM ISOLATED FORM; QQKN
+FD5B ; [.1605.0020.0019.FD5B][.1663.0020.0019.FD5B][.167F.0020.001F.FD5B] # ARABIC LIGATURE HAH WITH MEEM WITH ALEF MAKSURA FINAL FORM; QQKN
+FD5A ; [.1605.0020.0019.FD5A][.1663.0020.0019.FD5A][.1680.0020.001F.FD5A] # ARABIC LIGATURE HAH WITH MEEM WITH YEH FINAL FORM; QQKN
+FD1B ; [.1605.0020.0019.FD1B][.167F.0020.0019.FD1B] # ARABIC LIGATURE HAH WITH ALEF MAKSURA FINAL FORM; QQKN
+FCFF ; [.1605.0020.001A.FCFF][.167F.0020.001A.FCFF] # ARABIC LIGATURE HAH WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FD1C ; [.1605.0020.0019.FD1C][.1680.0020.0019.FD1C] # ARABIC LIGATURE HAH WITH YEH FINAL FORM; QQKN
+FD00 ; [.1605.0020.001A.FD00][.1680.0020.001A.FD00] # ARABIC LIGATURE HAH WITH YEH ISOLATED FORM; QQKN
+062E ; [.1606.0020.0002.062E] # ARABIC LETTER KHAH
+FEA7 ; [.1606.0020.0017.FEA7] # ARABIC LETTER KHAH INITIAL FORM; QQK
+FEA8 ; [.1606.0020.0018.FEA8] # ARABIC LETTER KHAH MEDIAL FORM; QQK
+FEA6 ; [.1606.0020.0019.FEA6] # ARABIC LETTER KHAH FINAL FORM; QQK
+FEA5 ; [.1606.0020.001A.FEA5] # ARABIC LETTER KHAH ISOLATED FORM; QQK
+FCAB ; [.1606.0020.0017.FCAB][.15FF.0020.0017.FCAB] # ARABIC LIGATURE KHAH WITH JEEM INITIAL FORM; QQKN
+FC19 ; [.1606.0020.001A.FC19][.15FF.0020.001A.FC19] # ARABIC LIGATURE KHAH WITH JEEM ISOLATED FORM; QQKN
+FC1A ; [.1606.0020.001A.FC1A][.1605.0020.001A.FC1A] # ARABIC LIGATURE KHAH WITH HAH ISOLATED FORM; QQKN
+FCAC ; [.1606.0020.0017.FCAC][.1663.0020.0017.FCAC] # ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM; QQKN
+FC1B ; [.1606.0020.001A.FC1B][.1663.0020.001A.FC1B] # ARABIC LIGATURE KHAH WITH MEEM ISOLATED FORM; QQKN
+FD1F ; [.1606.0020.0019.FD1F][.167F.0020.0019.FD1F] # ARABIC LIGATURE KHAH WITH ALEF MAKSURA FINAL FORM; QQKN
+FD03 ; [.1606.0020.001A.FD03][.167F.0020.001A.FD03] # ARABIC LIGATURE KHAH WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FD20 ; [.1606.0020.0019.FD20][.1680.0020.0019.FD20] # ARABIC LIGATURE KHAH WITH YEH FINAL FORM; QQKN
+FD04 ; [.1606.0020.001A.FD04][.1680.0020.001A.FD04] # ARABIC LIGATURE KHAH WITH YEH ISOLATED FORM; QQKN
+0681 ; [.1607.0020.0002.0681] # ARABIC LETTER HAH WITH HAMZA ABOVE
+0682 ; [.1608.0020.0002.0682] # ARABIC LETTER HAH WITH TWO DOTS VERTICAL ABOVE
+0685 ; [.1609.0020.0002.0685] # ARABIC LETTER HAH WITH THREE DOTS ABOVE
+0757 ; [.160A.0020.0002.0757] # ARABIC LETTER HAH WITH TWO DOTS ABOVE
+0758 ; [.160B.0020.0002.0758] # ARABIC LETTER HAH WITH THREE DOTS POINTING UPWARDS BELOW
+062F ; [.160C.0020.0002.062F] # ARABIC LETTER DAL
+FEAA ; [.160C.0020.0019.FEAA] # ARABIC LETTER DAL FINAL FORM; QQK
+FEA9 ; [.160C.0020.001A.FEA9] # ARABIC LETTER DAL ISOLATED FORM; QQK
+0630 ; [.160D.0020.0002.0630] # ARABIC LETTER THAL
+FEAC ; [.160D.0020.0019.FEAC] # ARABIC LETTER THAL FINAL FORM; QQK
+FEAB ; [.160D.0020.001A.FEAB] # ARABIC LETTER THAL ISOLATED FORM; QQK
+FC5B ; [.160D.0020.001A.FC5B][.0000.00F3.001A.FC5B] # ARABIC LIGATURE THAL WITH SUPERSCRIPT ALEF ISOLATED FORM; QQKN
+0688 ; [.160E.0020.0002.0688] # ARABIC LETTER DDAL
+FB89 ; [.160E.0020.0019.FB89] # ARABIC LETTER DDAL FINAL FORM; QQK
+FB88 ; [.160E.0020.001A.FB88] # ARABIC LETTER DDAL ISOLATED FORM; QQK
+0689 ; [.160F.0020.0002.0689] # ARABIC LETTER DAL WITH RING
+068A ; [.1610.0020.0002.068A] # ARABIC LETTER DAL WITH DOT BELOW
+068B ; [.1611.0020.0002.068B] # ARABIC LETTER DAL WITH DOT BELOW AND SMALL TAH
+068C ; [.1612.0020.0002.068C] # ARABIC LETTER DAHAL
+FB85 ; [.1612.0020.0019.FB85] # ARABIC LETTER DAHAL FINAL FORM; QQK
+FB84 ; [.1612.0020.001A.FB84] # ARABIC LETTER DAHAL ISOLATED FORM; QQK
+068D ; [.1613.0020.0002.068D] # ARABIC LETTER DDAHAL
+FB83 ; [.1613.0020.0019.FB83] # ARABIC LETTER DDAHAL FINAL FORM; QQK
+FB82 ; [.1613.0020.001A.FB82] # ARABIC LETTER DDAHAL ISOLATED FORM; QQK
+068E ; [.1614.0020.0002.068E] # ARABIC LETTER DUL
+FB87 ; [.1614.0020.0019.FB87] # ARABIC LETTER DUL FINAL FORM; QQK
+FB86 ; [.1614.0020.001A.FB86] # ARABIC LETTER DUL ISOLATED FORM; QQK
+068F ; [.1615.0020.0002.068F] # ARABIC LETTER DAL WITH THREE DOTS ABOVE DOWNWARDS
+0690 ; [.1616.0020.0002.0690] # ARABIC LETTER DAL WITH FOUR DOTS ABOVE
+06EE ; [.1617.0020.0002.06EE] # ARABIC LETTER DAL WITH INVERTED V
+0759 ; [.1618.0020.0002.0759] # ARABIC LETTER DAL WITH TWO DOTS VERTICALLY BELOW AND SMALL TAH
+075A ; [.1619.0020.0002.075A] # ARABIC LETTER DAL WITH INVERTED SMALL V BELOW
+0631 ; [.161A.0020.0002.0631] # ARABIC LETTER REH
+FEAE ; [.161A.0020.0019.FEAE] # ARABIC LETTER REH FINAL FORM; QQK
+FEAD ; [.161A.0020.001A.FEAD] # ARABIC LETTER REH ISOLATED FORM; QQK
+FC5C ; [.161A.0020.001A.FC5C][.0000.00F3.001A.FC5C] # ARABIC LIGATURE REH WITH SUPERSCRIPT ALEF ISOLATED FORM; QQKN
+FDF6 ; [.161A.0020.001A.FDF6][.1629.0020.001A.FDF6][.1675.0020.001F.FDF6][.165D.0020.001F.FDF6] # ARABIC LIGATURE RASOUL ISOLATED FORM; QQKN
+FDFC ; [.161A.0020.001A.FDFC][.1681.0020.001A.FDFC][.15EA.0020.001F.FDFC][.165D.0020.001F.FDFC] # RIAL SIGN; QQKN
+0632 ; [.161B.0020.0002.0632] # ARABIC LETTER ZAIN
+FEB0 ; [.161B.0020.0019.FEB0] # ARABIC LETTER ZAIN FINAL FORM; QQK
+FEAF ; [.161B.0020.001A.FEAF] # ARABIC LETTER ZAIN ISOLATED FORM; QQK
+0691 ; [.161C.0020.0002.0691] # ARABIC LETTER RREH
+FB8D ; [.161C.0020.0019.FB8D] # ARABIC LETTER RREH FINAL FORM; QQK
+FB8C ; [.161C.0020.001A.FB8C] # ARABIC LETTER RREH ISOLATED FORM; QQK
+0692 ; [.161D.0020.0002.0692] # ARABIC LETTER REH WITH SMALL V
+0693 ; [.161E.0020.0002.0693] # ARABIC LETTER REH WITH RING
+0694 ; [.161F.0020.0002.0694] # ARABIC LETTER REH WITH DOT BELOW
+0695 ; [.1620.0020.0002.0695] # ARABIC LETTER REH WITH SMALL V BELOW
+0696 ; [.1621.0020.0002.0696] # ARABIC LETTER REH WITH DOT BELOW AND DOT ABOVE
+0697 ; [.1622.0020.0002.0697] # ARABIC LETTER REH WITH TWO DOTS ABOVE
+0698 ; [.1623.0020.0002.0698] # ARABIC LETTER JEH
+FB8B ; [.1623.0020.0019.FB8B] # ARABIC LETTER JEH FINAL FORM; QQK
+FB8A ; [.1623.0020.001A.FB8A] # ARABIC LETTER JEH ISOLATED FORM; QQK
+0699 ; [.1624.0020.0002.0699] # ARABIC LETTER REH WITH FOUR DOTS ABOVE
+06EF ; [.1625.0020.0002.06EF] # ARABIC LETTER REH WITH INVERTED V
+075B ; [.1626.0020.0002.075B] # ARABIC LETTER REH WITH STROKE
+076B ; [.1627.0020.0002.076B] # ARABIC LETTER REH WITH TWO DOTS VERTICALLY ABOVE
+076C ; [.1628.0020.0002.076C] # ARABIC LETTER REH WITH HAMZA ABOVE
+0633 ; [.1629.0020.0002.0633] # ARABIC LETTER SEEN
+FEB3 ; [.1629.0020.0017.FEB3] # ARABIC LETTER SEEN INITIAL FORM; QQK
+FEB4 ; [.1629.0020.0018.FEB4] # ARABIC LETTER SEEN MEDIAL FORM; QQK
+FEB2 ; [.1629.0020.0019.FEB2] # ARABIC LETTER SEEN FINAL FORM; QQK
+FEB1 ; [.1629.0020.001A.FEB1] # ARABIC LETTER SEEN ISOLATED FORM; QQK
+FCAD ; [.1629.0020.0017.FCAD][.15FF.0020.0017.FCAD] # ARABIC LIGATURE SEEN WITH JEEM INITIAL FORM; QQKN
+FD34 ; [.1629.0020.0018.FD34][.15FF.0020.0018.FD34] # ARABIC LIGATURE SEEN WITH JEEM MEDIAL FORM; QQKN
+FC1C ; [.1629.0020.001A.FC1C][.15FF.0020.001A.FC1C] # ARABIC LIGATURE SEEN WITH JEEM ISOLATED FORM; QQKN
+FD5D ; [.1629.0020.0017.FD5D][.15FF.0020.0017.FD5D][.1605.0020.001F.FD5D] # ARABIC LIGATURE SEEN WITH JEEM WITH HAH INITIAL FORM; QQKN
+FD5E ; [.1629.0020.0019.FD5E][.15FF.0020.0019.FD5E][.167F.0020.001F.FD5E] # ARABIC LIGATURE SEEN WITH JEEM WITH ALEF MAKSURA FINAL FORM; QQKN
+FCAE ; [.1629.0020.0017.FCAE][.1605.0020.0017.FCAE] # ARABIC LIGATURE SEEN WITH HAH INITIAL FORM; QQKN
+FD35 ; [.1629.0020.0018.FD35][.1605.0020.0018.FD35] # ARABIC LIGATURE SEEN WITH HAH MEDIAL FORM; QQKN
+FC1D ; [.1629.0020.001A.FC1D][.1605.0020.001A.FC1D] # ARABIC LIGATURE SEEN WITH HAH ISOLATED FORM; QQKN
+FD5C ; [.1629.0020.0017.FD5C][.1605.0020.0017.FD5C][.15FF.0020.001F.FD5C] # ARABIC LIGATURE SEEN WITH HAH WITH JEEM INITIAL FORM; QQKN
+FCAF ; [.1629.0020.0017.FCAF][.1606.0020.0017.FCAF] # ARABIC LIGATURE SEEN WITH KHAH INITIAL FORM; QQKN
+FD36 ; [.1629.0020.0018.FD36][.1606.0020.0018.FD36] # ARABIC LIGATURE SEEN WITH KHAH MEDIAL FORM; QQKN
+FC1E ; [.1629.0020.001A.FC1E][.1606.0020.001A.FC1E] # ARABIC LIGATURE SEEN WITH KHAH ISOLATED FORM; QQKN
+FDA8 ; [.1629.0020.0019.FDA8][.1606.0020.0019.FDA8][.167F.0020.001F.FDA8] # ARABIC LIGATURE SEEN WITH KHAH WITH ALEF MAKSURA FINAL FORM; QQKN
+FDC6 ; [.1629.0020.0019.FDC6][.1606.0020.0019.FDC6][.1680.0020.001F.FDC6] # ARABIC LIGATURE SEEN WITH KHAH WITH YEH FINAL FORM; QQKN
+FD2A ; [.1629.0020.0019.FD2A][.161A.0020.0019.FD2A] # ARABIC LIGATURE SEEN WITH REH FINAL FORM; QQKN
+FD0E ; [.1629.0020.001A.FD0E][.161A.0020.001A.FD0E] # ARABIC LIGATURE SEEN WITH REH ISOLATED FORM; QQKN
+FCB0 ; [.1629.0020.0017.FCB0][.1663.0020.0017.FCB0] # ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM; QQKN
+FCE7 ; [.1629.0020.0018.FCE7][.1663.0020.0018.FCE7] # ARABIC LIGATURE SEEN WITH MEEM MEDIAL FORM; QQKN
+FC1F ; [.1629.0020.001A.FC1F][.1663.0020.001A.FC1F] # ARABIC LIGATURE SEEN WITH MEEM ISOLATED FORM; QQKN
+FD61 ; [.1629.0020.0017.FD61][.1663.0020.0017.FD61][.15FF.0020.001F.FD61] # ARABIC LIGATURE SEEN WITH MEEM WITH JEEM INITIAL FORM; QQKN
+FD60 ; [.1629.0020.0017.FD60][.1663.0020.0017.FD60][.1605.0020.001F.FD60] # ARABIC LIGATURE SEEN WITH MEEM WITH HAH INITIAL FORM; QQKN
+FD5F ; [.1629.0020.0019.FD5F][.1663.0020.0019.FD5F][.1605.0020.001F.FD5F] # ARABIC LIGATURE SEEN WITH MEEM WITH HAH FINAL FORM; QQKN
+FD63 ; [.1629.0020.0017.FD63][.1663.0020.0017.FD63][.1663.0020.001F.FD63] # ARABIC LIGATURE SEEN WITH MEEM WITH MEEM INITIAL FORM; QQKN
+FD62 ; [.1629.0020.0019.FD62][.1663.0020.0019.FD62][.1663.0020.001F.FD62] # ARABIC LIGATURE SEEN WITH MEEM WITH MEEM FINAL FORM; QQKN
+FD31 ; [.1629.0020.0017.FD31][.166F.0020.0017.FD31] # ARABIC LIGATURE SEEN WITH HEH INITIAL FORM; QQKN
+FCE8 ; [.1629.0020.0018.FCE8][.166F.0020.0018.FCE8] # ARABIC LIGATURE SEEN WITH HEH MEDIAL FORM; QQKN
+FD17 ; [.1629.0020.0019.FD17][.167F.0020.0019.FD17] # ARABIC LIGATURE SEEN WITH ALEF MAKSURA FINAL FORM; QQKN
+FCFB ; [.1629.0020.001A.FCFB][.167F.0020.001A.FCFB] # ARABIC LIGATURE SEEN WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FD18 ; [.1629.0020.0019.FD18][.1680.0020.0019.FD18] # ARABIC LIGATURE SEEN WITH YEH FINAL FORM; QQKN
+FCFC ; [.1629.0020.001A.FCFC][.1680.0020.001A.FCFC] # ARABIC LIGATURE SEEN WITH YEH ISOLATED FORM; QQKN
+0634 ; [.162A.0020.0002.0634] # ARABIC LETTER SHEEN
+FEB7 ; [.162A.0020.0017.FEB7] # ARABIC LETTER SHEEN INITIAL FORM; QQK
+FEB8 ; [.162A.0020.0018.FEB8] # ARABIC LETTER SHEEN MEDIAL FORM; QQK
+FEB6 ; [.162A.0020.0019.FEB6] # ARABIC LETTER SHEEN FINAL FORM; QQK
+FEB5 ; [.162A.0020.001A.FEB5] # ARABIC LETTER SHEEN ISOLATED FORM; QQK
+FD2D ; [.162A.0020.0017.FD2D][.15FF.0020.0017.FD2D] # ARABIC LIGATURE SHEEN WITH JEEM INITIAL FORM; QQKN
+FD37 ; [.162A.0020.0018.FD37][.15FF.0020.0018.FD37] # ARABIC LIGATURE SHEEN WITH JEEM MEDIAL FORM; QQKN
+FD25 ; [.162A.0020.0019.FD25][.15FF.0020.0019.FD25] # ARABIC LIGATURE SHEEN WITH JEEM FINAL FORM; QQKN
+FD09 ; [.162A.0020.001A.FD09][.15FF.0020.001A.FD09] # ARABIC LIGATURE SHEEN WITH JEEM ISOLATED FORM; QQKN
+FD69 ; [.162A.0020.0019.FD69][.15FF.0020.0019.FD69][.1680.0020.001F.FD69] # ARABIC LIGATURE SHEEN WITH JEEM WITH YEH FINAL FORM; QQKN
+FD2E ; [.162A.0020.0017.FD2E][.1605.0020.0017.FD2E] # ARABIC LIGATURE SHEEN WITH HAH INITIAL FORM; QQKN
+FD38 ; [.162A.0020.0018.FD38][.1605.0020.0018.FD38] # ARABIC LIGATURE SHEEN WITH HAH MEDIAL FORM; QQKN
+FD26 ; [.162A.0020.0019.FD26][.1605.0020.0019.FD26] # ARABIC LIGATURE SHEEN WITH HAH FINAL FORM; QQKN
+FD0A ; [.162A.0020.001A.FD0A][.1605.0020.001A.FD0A] # ARABIC LIGATURE SHEEN WITH HAH ISOLATED FORM; QQKN
+FD68 ; [.162A.0020.0017.FD68][.1605.0020.0017.FD68][.1663.0020.001F.FD68] # ARABIC LIGATURE SHEEN WITH HAH WITH MEEM INITIAL FORM; QQKN
+FD67 ; [.162A.0020.0019.FD67][.1605.0020.0019.FD67][.1663.0020.001F.FD67] # ARABIC LIGATURE SHEEN WITH HAH WITH MEEM FINAL FORM; QQKN
+FDAA ; [.162A.0020.0019.FDAA][.1605.0020.0019.FDAA][.1680.0020.001F.FDAA] # ARABIC LIGATURE SHEEN WITH HAH WITH YEH FINAL FORM; QQKN
+FD2F ; [.162A.0020.0017.FD2F][.1606.0020.0017.FD2F] # ARABIC LIGATURE SHEEN WITH KHAH INITIAL FORM; QQKN
+FD39 ; [.162A.0020.0018.FD39][.1606.0020.0018.FD39] # ARABIC LIGATURE SHEEN WITH KHAH MEDIAL FORM; QQKN
+FD27 ; [.162A.0020.0019.FD27][.1606.0020.0019.FD27] # ARABIC LIGATURE SHEEN WITH KHAH FINAL FORM; QQKN
+FD0B ; [.162A.0020.001A.FD0B][.1606.0020.001A.FD0B] # ARABIC LIGATURE SHEEN WITH KHAH ISOLATED FORM; QQKN
+FD29 ; [.162A.0020.0019.FD29][.161A.0020.0019.FD29] # ARABIC LIGATURE SHEEN WITH REH FINAL FORM; QQKN
+FD0D ; [.162A.0020.001A.FD0D][.161A.0020.001A.FD0D] # ARABIC LIGATURE SHEEN WITH REH ISOLATED FORM; QQKN
+FD30 ; [.162A.0020.0017.FD30][.1663.0020.0017.FD30] # ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM; QQKN
+FCE9 ; [.162A.0020.0018.FCE9][.1663.0020.0018.FCE9] # ARABIC LIGATURE SHEEN WITH MEEM MEDIAL FORM; QQKN
+FD28 ; [.162A.0020.0019.FD28][.1663.0020.0019.FD28] # ARABIC LIGATURE SHEEN WITH MEEM FINAL FORM; QQKN
+FD0C ; [.162A.0020.001A.FD0C][.1663.0020.001A.FD0C] # ARABIC LIGATURE SHEEN WITH MEEM ISOLATED FORM; QQKN
+FD6B ; [.162A.0020.0017.FD6B][.1663.0020.0017.FD6B][.1606.0020.001F.FD6B] # ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH INITIAL FORM; QQKN
+FD6A ; [.162A.0020.0019.FD6A][.1663.0020.0019.FD6A][.1606.0020.001F.FD6A] # ARABIC LIGATURE SHEEN WITH MEEM WITH KHAH FINAL FORM; QQKN
+FD6D ; [.162A.0020.0017.FD6D][.1663.0020.0017.FD6D][.1663.0020.001F.FD6D] # ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM INITIAL FORM; QQKN
+FD6C ; [.162A.0020.0019.FD6C][.1663.0020.0019.FD6C][.1663.0020.001F.FD6C] # ARABIC LIGATURE SHEEN WITH MEEM WITH MEEM FINAL FORM; QQKN
+FD32 ; [.162A.0020.0017.FD32][.166F.0020.0017.FD32] # ARABIC LIGATURE SHEEN WITH HEH INITIAL FORM; QQKN
+FCEA ; [.162A.0020.0018.FCEA][.166F.0020.0018.FCEA] # ARABIC LIGATURE SHEEN WITH HEH MEDIAL FORM; QQKN
+FD19 ; [.162A.0020.0019.FD19][.167F.0020.0019.FD19] # ARABIC LIGATURE SHEEN WITH ALEF MAKSURA FINAL FORM; QQKN
+FCFD ; [.162A.0020.001A.FCFD][.167F.0020.001A.FCFD] # ARABIC LIGATURE SHEEN WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FD1A ; [.162A.0020.0019.FD1A][.1680.0020.0019.FD1A] # ARABIC LIGATURE SHEEN WITH YEH FINAL FORM; QQKN
+FCFE ; [.162A.0020.001A.FCFE][.1680.0020.001A.FCFE] # ARABIC LIGATURE SHEEN WITH YEH ISOLATED FORM; QQKN
+069A ; [.162B.0020.0002.069A] # ARABIC LETTER SEEN WITH DOT BELOW AND DOT ABOVE
+069B ; [.162C.0020.0002.069B] # ARABIC LETTER SEEN WITH THREE DOTS BELOW
+069C ; [.162D.0020.0002.069C] # ARABIC LETTER SEEN WITH THREE DOTS BELOW AND THREE DOTS ABOVE
+06FA ; [.162E.0020.0002.06FA] # ARABIC LETTER SHEEN WITH DOT BELOW
+075C ; [.162F.0020.0002.075C] # ARABIC LETTER SEEN WITH FOUR DOTS ABOVE
+076D ; [.1630.0020.0002.076D] # ARABIC LETTER SEEN WITH TWO DOTS VERTICALLY ABOVE
+0635 ; [.1631.0020.0002.0635] # ARABIC LETTER SAD
+FEBB ; [.1631.0020.0017.FEBB] # ARABIC LETTER SAD INITIAL FORM; QQK
+FEBC ; [.1631.0020.0018.FEBC] # ARABIC LETTER SAD MEDIAL FORM; QQK
+FEBA ; [.1631.0020.0019.FEBA] # ARABIC LETTER SAD FINAL FORM; QQK
+FEB9 ; [.1631.0020.001A.FEB9] # ARABIC LETTER SAD ISOLATED FORM; QQK
+FCB1 ; [.1631.0020.0017.FCB1][.1605.0020.0017.FCB1] # ARABIC LIGATURE SAD WITH HAH INITIAL FORM; QQKN
+FC20 ; [.1631.0020.001A.FC20][.1605.0020.001A.FC20] # ARABIC LIGATURE SAD WITH HAH ISOLATED FORM; QQKN
+FD65 ; [.1631.0020.0017.FD65][.1605.0020.0017.FD65][.1605.0020.001F.FD65] # ARABIC LIGATURE SAD WITH HAH WITH HAH INITIAL FORM; QQKN
+FD64 ; [.1631.0020.0019.FD64][.1605.0020.0019.FD64][.1605.0020.001F.FD64] # ARABIC LIGATURE SAD WITH HAH WITH HAH FINAL FORM; QQKN
+FDA9 ; [.1631.0020.0019.FDA9][.1605.0020.0019.FDA9][.1680.0020.001F.FDA9] # ARABIC LIGATURE SAD WITH HAH WITH YEH FINAL FORM; QQKN
+FCB2 ; [.1631.0020.0017.FCB2][.1606.0020.0017.FCB2] # ARABIC LIGATURE SAD WITH KHAH INITIAL FORM; QQKN
+FD2B ; [.1631.0020.0019.FD2B][.161A.0020.0019.FD2B] # ARABIC LIGATURE SAD WITH REH FINAL FORM; QQKN
+FD0F ; [.1631.0020.001A.FD0F][.161A.0020.001A.FD0F] # ARABIC LIGATURE SAD WITH REH ISOLATED FORM; QQKN
+FDF5 ; [.1631.0020.001A.FDF5][.165D.0020.001A.FDF5][.1639.0020.001F.FDF5][.1663.0020.001F.FDF5] # ARABIC LIGATURE SALAM ISOLATED FORM; QQKN
+FDF9 ; [.1631.0020.001A.FDF9][.165D.0020.001A.FDF9][.167F.0020.001F.FDF9] # ARABIC LIGATURE SALLA ISOLATED FORM; QQKN
+FDFA ; [.1631.0020.001A.FDFA][.165D.0020.001A.FDFA][.167F.0020.001F.FDFA][*0209.0020.001F.FDFA][.15EA.0020.001F.FDFA][.165D.0020.001F.FDFA][.165D.0020.001F.FDFA][.166F.0020.001F.FDFA][*0209.0020.001F.FDFA][.1639.0020.001F.FDFA][.165D.0020.001F.FDFA][.1680.0020.001F.FDFA][.166F.0020.001F.FDFA][*0209.0020.001F.FDFA][.1675.0020.001F.FDFA][.1629.0020.001F.FDFA][.165D.0020.001F.FDFA][.1663.0020.001F.FDFA] # ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM; QQKN
+FDF0 ; [.1631.0020.001A.FDF0][.165D.0020.001A.FDF0][.1686.0020.001F.FDF0] # ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM; QQKN
+FCB3 ; [.1631.0020.0017.FCB3][.1663.0020.0017.FCB3] # ARABIC LIGATURE SAD WITH MEEM INITIAL FORM; QQKN
+FC21 ; [.1631.0020.001A.FC21][.1663.0020.001A.FC21] # ARABIC LIGATURE SAD WITH MEEM ISOLATED FORM; QQKN
+FDC5 ; [.1631.0020.0017.FDC5][.1663.0020.0017.FDC5][.1663.0020.001F.FDC5] # ARABIC LIGATURE SAD WITH MEEM WITH MEEM INITIAL FORM; QQKN
+FD66 ; [.1631.0020.0019.FD66][.1663.0020.0019.FD66][.1663.0020.001F.FD66] # ARABIC LIGATURE SAD WITH MEEM WITH MEEM FINAL FORM; QQKN
+FD21 ; [.1631.0020.0019.FD21][.167F.0020.0019.FD21] # ARABIC LIGATURE SAD WITH ALEF MAKSURA FINAL FORM; QQKN
+FD05 ; [.1631.0020.001A.FD05][.167F.0020.001A.FD05] # ARABIC LIGATURE SAD WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FD22 ; [.1631.0020.0019.FD22][.1680.0020.0019.FD22] # ARABIC LIGATURE SAD WITH YEH FINAL FORM; QQKN
+FD06 ; [.1631.0020.001A.FD06][.1680.0020.001A.FD06] # ARABIC LIGATURE SAD WITH YEH ISOLATED FORM; QQKN
+0636 ; [.1632.0020.0002.0636] # ARABIC LETTER DAD
+FEBF ; [.1632.0020.0017.FEBF] # ARABIC LETTER DAD INITIAL FORM; QQK
+FEC0 ; [.1632.0020.0018.FEC0] # ARABIC LETTER DAD MEDIAL FORM; QQK
+FEBE ; [.1632.0020.0019.FEBE] # ARABIC LETTER DAD FINAL FORM; QQK
+FEBD ; [.1632.0020.001A.FEBD] # ARABIC LETTER DAD ISOLATED FORM; QQK
+FCB4 ; [.1632.0020.0017.FCB4][.15FF.0020.0017.FCB4] # ARABIC LIGATURE DAD WITH JEEM INITIAL FORM; QQKN
+FC22 ; [.1632.0020.001A.FC22][.15FF.0020.001A.FC22] # ARABIC LIGATURE DAD WITH JEEM ISOLATED FORM; QQKN
+FCB5 ; [.1632.0020.0017.FCB5][.1605.0020.0017.FCB5] # ARABIC LIGATURE DAD WITH HAH INITIAL FORM; QQKN
+FC23 ; [.1632.0020.001A.FC23][.1605.0020.001A.FC23] # ARABIC LIGATURE DAD WITH HAH ISOLATED FORM; QQKN
+FD6E ; [.1632.0020.0019.FD6E][.1605.0020.0019.FD6E][.167F.0020.001F.FD6E] # ARABIC LIGATURE DAD WITH HAH WITH ALEF MAKSURA FINAL FORM; QQKN
+FDAB ; [.1632.0020.0019.FDAB][.1605.0020.0019.FDAB][.1680.0020.001F.FDAB] # ARABIC LIGATURE DAD WITH HAH WITH YEH FINAL FORM; QQKN
+FCB6 ; [.1632.0020.0017.FCB6][.1606.0020.0017.FCB6] # ARABIC LIGATURE DAD WITH KHAH INITIAL FORM; QQKN
+FC24 ; [.1632.0020.001A.FC24][.1606.0020.001A.FC24] # ARABIC LIGATURE DAD WITH KHAH ISOLATED FORM; QQKN
+FD70 ; [.1632.0020.0017.FD70][.1606.0020.0017.FD70][.1663.0020.001F.FD70] # ARABIC LIGATURE DAD WITH KHAH WITH MEEM INITIAL FORM; QQKN
+FD6F ; [.1632.0020.0019.FD6F][.1606.0020.0019.FD6F][.1663.0020.001F.FD6F] # ARABIC LIGATURE DAD WITH KHAH WITH MEEM FINAL FORM; QQKN
+FD2C ; [.1632.0020.0019.FD2C][.161A.0020.0019.FD2C] # ARABIC LIGATURE DAD WITH REH FINAL FORM; QQKN
+FD10 ; [.1632.0020.001A.FD10][.161A.0020.001A.FD10] # ARABIC LIGATURE DAD WITH REH ISOLATED FORM; QQKN
+FCB7 ; [.1632.0020.0017.FCB7][.1663.0020.0017.FCB7] # ARABIC LIGATURE DAD WITH MEEM INITIAL FORM; QQKN
+FC25 ; [.1632.0020.001A.FC25][.1663.0020.001A.FC25] # ARABIC LIGATURE DAD WITH MEEM ISOLATED FORM; QQKN
+FD23 ; [.1632.0020.0019.FD23][.167F.0020.0019.FD23] # ARABIC LIGATURE DAD WITH ALEF MAKSURA FINAL FORM; QQKN
+FD07 ; [.1632.0020.001A.FD07][.167F.0020.001A.FD07] # ARABIC LIGATURE DAD WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FD24 ; [.1632.0020.0019.FD24][.1680.0020.0019.FD24] # ARABIC LIGATURE DAD WITH YEH FINAL FORM; QQKN
+FD08 ; [.1632.0020.001A.FD08][.1680.0020.001A.FD08] # ARABIC LIGATURE DAD WITH YEH ISOLATED FORM; QQKN
+069D ; [.1633.0020.0002.069D] # ARABIC LETTER SAD WITH TWO DOTS BELOW
+069E ; [.1634.0020.0002.069E] # ARABIC LETTER SAD WITH THREE DOTS ABOVE
+06FB ; [.1635.0020.0002.06FB] # ARABIC LETTER DAD WITH DOT BELOW
+0637 ; [.1636.0020.0002.0637] # ARABIC LETTER TAH
+FEC3 ; [.1636.0020.0017.FEC3] # ARABIC LETTER TAH INITIAL FORM; QQK
+FEC4 ; [.1636.0020.0018.FEC4] # ARABIC LETTER TAH MEDIAL FORM; QQK
+FEC2 ; [.1636.0020.0019.FEC2] # ARABIC LETTER TAH FINAL FORM; QQK
+FEC1 ; [.1636.0020.001A.FEC1] # ARABIC LETTER TAH ISOLATED FORM; QQK
+FCB8 ; [.1636.0020.0017.FCB8][.1605.0020.0017.FCB8] # ARABIC LIGATURE TAH WITH HAH INITIAL FORM; QQKN
+FC26 ; [.1636.0020.001A.FC26][.1605.0020.001A.FC26] # ARABIC LIGATURE TAH WITH HAH ISOLATED FORM; QQKN
+FD33 ; [.1636.0020.0017.FD33][.1663.0020.0017.FD33] # ARABIC LIGATURE TAH WITH MEEM INITIAL FORM; QQKN
+FD3A ; [.1636.0020.0018.FD3A][.1663.0020.0018.FD3A] # ARABIC LIGATURE TAH WITH MEEM MEDIAL FORM; QQKN
+FC27 ; [.1636.0020.001A.FC27][.1663.0020.001A.FC27] # ARABIC LIGATURE TAH WITH MEEM ISOLATED FORM; QQKN
+FD72 ; [.1636.0020.0017.FD72][.1663.0020.0017.FD72][.1605.0020.001F.FD72] # ARABIC LIGATURE TAH WITH MEEM WITH HAH INITIAL FORM; QQKN
+FD71 ; [.1636.0020.0019.FD71][.1663.0020.0019.FD71][.1605.0020.001F.FD71] # ARABIC LIGATURE TAH WITH MEEM WITH HAH FINAL FORM; QQKN
+FD73 ; [.1636.0020.0017.FD73][.1663.0020.0017.FD73][.1663.0020.001F.FD73] # ARABIC LIGATURE TAH WITH MEEM WITH MEEM INITIAL FORM; QQKN
+FD74 ; [.1636.0020.0019.FD74][.1663.0020.0019.FD74][.1680.0020.001F.FD74] # ARABIC LIGATURE TAH WITH MEEM WITH YEH FINAL FORM; QQKN
+FD11 ; [.1636.0020.0019.FD11][.167F.0020.0019.FD11] # ARABIC LIGATURE TAH WITH ALEF MAKSURA FINAL FORM; QQKN
+FCF5 ; [.1636.0020.001A.FCF5][.167F.0020.001A.FCF5] # ARABIC LIGATURE TAH WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FD12 ; [.1636.0020.0019.FD12][.1680.0020.0019.FD12] # ARABIC LIGATURE TAH WITH YEH FINAL FORM; QQKN
+FCF6 ; [.1636.0020.001A.FCF6][.1680.0020.001A.FCF6] # ARABIC LIGATURE TAH WITH YEH ISOLATED FORM; QQKN
+0638 ; [.1637.0020.0002.0638] # ARABIC LETTER ZAH
+FEC7 ; [.1637.0020.0017.FEC7] # ARABIC LETTER ZAH INITIAL FORM; QQK
+FEC8 ; [.1637.0020.0018.FEC8] # ARABIC LETTER ZAH MEDIAL FORM; QQK
+FEC6 ; [.1637.0020.0019.FEC6] # ARABIC LETTER ZAH FINAL FORM; QQK
+FEC5 ; [.1637.0020.001A.FEC5] # ARABIC LETTER ZAH ISOLATED FORM; QQK
+FCB9 ; [.1637.0020.0017.FCB9][.1663.0020.0017.FCB9] # ARABIC LIGATURE ZAH WITH MEEM INITIAL FORM; QQKN
+FD3B ; [.1637.0020.0018.FD3B][.1663.0020.0018.FD3B] # ARABIC LIGATURE ZAH WITH MEEM MEDIAL FORM; QQKN
+FC28 ; [.1637.0020.001A.FC28][.1663.0020.001A.FC28] # ARABIC LIGATURE ZAH WITH MEEM ISOLATED FORM; QQKN
+069F ; [.1638.0020.0002.069F] # ARABIC LETTER TAH WITH THREE DOTS ABOVE
+0639 ; [.1639.0020.0002.0639] # ARABIC LETTER AIN
+FECB ; [.1639.0020.0017.FECB] # ARABIC LETTER AIN INITIAL FORM; QQK
+FECC ; [.1639.0020.0018.FECC] # ARABIC LETTER AIN MEDIAL FORM; QQK
+FECA ; [.1639.0020.0019.FECA] # ARABIC LETTER AIN FINAL FORM; QQK
+FEC9 ; [.1639.0020.001A.FEC9] # ARABIC LETTER AIN ISOLATED FORM; QQK
+FCBA ; [.1639.0020.0017.FCBA][.15FF.0020.0017.FCBA] # ARABIC LIGATURE AIN WITH JEEM INITIAL FORM; QQKN
+FC29 ; [.1639.0020.001A.FC29][.15FF.0020.001A.FC29] # ARABIC LIGATURE AIN WITH JEEM ISOLATED FORM; QQKN
+FDC4 ; [.1639.0020.0017.FDC4][.15FF.0020.0017.FDC4][.1663.0020.001F.FDC4] # ARABIC LIGATURE AIN WITH JEEM WITH MEEM INITIAL FORM; QQKN
+FD75 ; [.1639.0020.0019.FD75][.15FF.0020.0019.FD75][.1663.0020.001F.FD75] # ARABIC LIGATURE AIN WITH JEEM WITH MEEM FINAL FORM; QQKN
+FDF7 ; [.1639.0020.001A.FDF7][.165D.0020.001A.FDF7][.1680.0020.001F.FDF7][.166F.0020.001F.FDF7] # ARABIC LIGATURE ALAYHE ISOLATED FORM; QQKN
+FCBB ; [.1639.0020.0017.FCBB][.1663.0020.0017.FCBB] # ARABIC LIGATURE AIN WITH MEEM INITIAL FORM; QQKN
+FC2A ; [.1639.0020.001A.FC2A][.1663.0020.001A.FC2A] # ARABIC LIGATURE AIN WITH MEEM ISOLATED FORM; QQKN
+FD77 ; [.1639.0020.0017.FD77][.1663.0020.0017.FD77][.1663.0020.001F.FD77] # ARABIC LIGATURE AIN WITH MEEM WITH MEEM INITIAL FORM; QQKN
+FD76 ; [.1639.0020.0019.FD76][.1663.0020.0019.FD76][.1663.0020.001F.FD76] # ARABIC LIGATURE AIN WITH MEEM WITH MEEM FINAL FORM; QQKN
+FD78 ; [.1639.0020.0019.FD78][.1663.0020.0019.FD78][.167F.0020.001F.FD78] # ARABIC LIGATURE AIN WITH MEEM WITH ALEF MAKSURA FINAL FORM; QQKN
+FDB6 ; [.1639.0020.0019.FDB6][.1663.0020.0019.FDB6][.1680.0020.001F.FDB6] # ARABIC LIGATURE AIN WITH MEEM WITH YEH FINAL FORM; QQKN
+FD13 ; [.1639.0020.0019.FD13][.167F.0020.0019.FD13] # ARABIC LIGATURE AIN WITH ALEF MAKSURA FINAL FORM; QQKN
+FCF7 ; [.1639.0020.001A.FCF7][.167F.0020.001A.FCF7] # ARABIC LIGATURE AIN WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FD14 ; [.1639.0020.0019.FD14][.1680.0020.0019.FD14] # ARABIC LIGATURE AIN WITH YEH FINAL FORM; QQKN
+FCF8 ; [.1639.0020.001A.FCF8][.1680.0020.001A.FCF8] # ARABIC LIGATURE AIN WITH YEH ISOLATED FORM; QQKN
+063A ; [.163A.0020.0002.063A] # ARABIC LETTER GHAIN
+FECF ; [.163A.0020.0017.FECF] # ARABIC LETTER GHAIN INITIAL FORM; QQK
+FED0 ; [.163A.0020.0018.FED0] # ARABIC LETTER GHAIN MEDIAL FORM; QQK
+FECE ; [.163A.0020.0019.FECE] # ARABIC LETTER GHAIN FINAL FORM; QQK
+FECD ; [.163A.0020.001A.FECD] # ARABIC LETTER GHAIN ISOLATED FORM; QQK
+FCBC ; [.163A.0020.0017.FCBC][.15FF.0020.0017.FCBC] # ARABIC LIGATURE GHAIN WITH JEEM INITIAL FORM; QQKN
+FC2B ; [.163A.0020.001A.FC2B][.15FF.0020.001A.FC2B] # ARABIC LIGATURE GHAIN WITH JEEM ISOLATED FORM; QQKN
+FCBD ; [.163A.0020.0017.FCBD][.1663.0020.0017.FCBD] # ARABIC LIGATURE GHAIN WITH MEEM INITIAL FORM; QQKN
+FC2C ; [.163A.0020.001A.FC2C][.1663.0020.001A.FC2C] # ARABIC LIGATURE GHAIN WITH MEEM ISOLATED FORM; QQKN
+FD79 ; [.163A.0020.0019.FD79][.1663.0020.0019.FD79][.1663.0020.001F.FD79] # ARABIC LIGATURE GHAIN WITH MEEM WITH MEEM FINAL FORM; QQKN
+FD7B ; [.163A.0020.0019.FD7B][.1663.0020.0019.FD7B][.167F.0020.001F.FD7B] # ARABIC LIGATURE GHAIN WITH MEEM WITH ALEF MAKSURA FINAL FORM; QQKN
+FD7A ; [.163A.0020.0019.FD7A][.1663.0020.0019.FD7A][.1680.0020.001F.FD7A] # ARABIC LIGATURE GHAIN WITH MEEM WITH YEH FINAL FORM; QQKN
+FD15 ; [.163A.0020.0019.FD15][.167F.0020.0019.FD15] # ARABIC LIGATURE GHAIN WITH ALEF MAKSURA FINAL FORM; QQKN
+FCF9 ; [.163A.0020.001A.FCF9][.167F.0020.001A.FCF9] # ARABIC LIGATURE GHAIN WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FD16 ; [.163A.0020.0019.FD16][.1680.0020.0019.FD16] # ARABIC LIGATURE GHAIN WITH YEH FINAL FORM; QQKN
+FCFA ; [.163A.0020.001A.FCFA][.1680.0020.001A.FCFA] # ARABIC LIGATURE GHAIN WITH YEH ISOLATED FORM; QQKN
+06A0 ; [.163B.0020.0002.06A0] # ARABIC LETTER AIN WITH THREE DOTS ABOVE
+06FC ; [.163C.0020.0002.06FC] # ARABIC LETTER GHAIN WITH DOT BELOW
+075D ; [.163D.0020.0002.075D] # ARABIC LETTER AIN WITH TWO DOTS ABOVE
+075E ; [.163E.0020.0002.075E] # ARABIC LETTER AIN WITH THREE DOTS POINTING DOWNWARDS ABOVE
+075F ; [.163F.0020.0002.075F] # ARABIC LETTER AIN WITH TWO DOTS VERTICALLY ABOVE
+0641 ; [.1640.0020.0002.0641] # ARABIC LETTER FEH
+FED3 ; [.1640.0020.0017.FED3] # ARABIC LETTER FEH INITIAL FORM; QQK
+FED4 ; [.1640.0020.0018.FED4] # ARABIC LETTER FEH MEDIAL FORM; QQK
+FED2 ; [.1640.0020.0019.FED2] # ARABIC LETTER FEH FINAL FORM; QQK
+FED1 ; [.1640.0020.001A.FED1] # ARABIC LETTER FEH ISOLATED FORM; QQK
+FCBE ; [.1640.0020.0017.FCBE][.15FF.0020.0017.FCBE] # ARABIC LIGATURE FEH WITH JEEM INITIAL FORM; QQKN
+FC2D ; [.1640.0020.001A.FC2D][.15FF.0020.001A.FC2D] # ARABIC LIGATURE FEH WITH JEEM ISOLATED FORM; QQKN
+FCBF ; [.1640.0020.0017.FCBF][.1605.0020.0017.FCBF] # ARABIC LIGATURE FEH WITH HAH INITIAL FORM; QQKN
+FC2E ; [.1640.0020.001A.FC2E][.1605.0020.001A.FC2E] # ARABIC LIGATURE FEH WITH HAH ISOLATED FORM; QQKN
+FCC0 ; [.1640.0020.0017.FCC0][.1606.0020.0017.FCC0] # ARABIC LIGATURE FEH WITH KHAH INITIAL FORM; QQKN
+FC2F ; [.1640.0020.001A.FC2F][.1606.0020.001A.FC2F] # ARABIC LIGATURE FEH WITH KHAH ISOLATED FORM; QQKN
+FD7D ; [.1640.0020.0017.FD7D][.1606.0020.0017.FD7D][.1663.0020.001F.FD7D] # ARABIC LIGATURE FEH WITH KHAH WITH MEEM INITIAL FORM; QQKN
+FD7C ; [.1640.0020.0019.FD7C][.1606.0020.0019.FD7C][.1663.0020.001F.FD7C] # ARABIC LIGATURE FEH WITH KHAH WITH MEEM FINAL FORM; QQKN
+FCC1 ; [.1640.0020.0017.FCC1][.1663.0020.0017.FCC1] # ARABIC LIGATURE FEH WITH MEEM INITIAL FORM; QQKN
+FC30 ; [.1640.0020.001A.FC30][.1663.0020.001A.FC30] # ARABIC LIGATURE FEH WITH MEEM ISOLATED FORM; QQKN
+FDC1 ; [.1640.0020.0019.FDC1][.1663.0020.0019.FDC1][.1680.0020.001F.FDC1] # ARABIC LIGATURE FEH WITH MEEM WITH YEH FINAL FORM; QQKN
+FC7C ; [.1640.0020.0019.FC7C][.167F.0020.0019.FC7C] # ARABIC LIGATURE FEH WITH ALEF MAKSURA FINAL FORM; QQKN
+FC31 ; [.1640.0020.001A.FC31][.167F.0020.001A.FC31] # ARABIC LIGATURE FEH WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FC7D ; [.1640.0020.0019.FC7D][.1680.0020.0019.FC7D] # ARABIC LIGATURE FEH WITH YEH FINAL FORM; QQKN
+FC32 ; [.1640.0020.001A.FC32][.1680.0020.001A.FC32] # ARABIC LIGATURE FEH WITH YEH ISOLATED FORM; QQKN
+06A1 ; [.1641.0020.0002.06A1] # ARABIC LETTER DOTLESS FEH
+06A2 ; [.1642.0020.0002.06A2] # ARABIC LETTER FEH WITH DOT MOVED BELOW
+06A3 ; [.1643.0020.0002.06A3] # ARABIC LETTER FEH WITH DOT BELOW
+06A4 ; [.1644.0020.0002.06A4] # ARABIC LETTER VEH
+FB6C ; [.1644.0020.0017.FB6C] # ARABIC LETTER VEH INITIAL FORM; QQK
+FB6D ; [.1644.0020.0018.FB6D] # ARABIC LETTER VEH MEDIAL FORM; QQK
+FB6B ; [.1644.0020.0019.FB6B] # ARABIC LETTER VEH FINAL FORM; QQK
+FB6A ; [.1644.0020.001A.FB6A] # ARABIC LETTER VEH ISOLATED FORM; QQK
+06A5 ; [.1645.0020.0002.06A5] # ARABIC LETTER FEH WITH THREE DOTS BELOW
+06A6 ; [.1646.0020.0002.06A6] # ARABIC LETTER PEHEH
+FB70 ; [.1646.0020.0017.FB70] # ARABIC LETTER PEHEH INITIAL FORM; QQK
+FB71 ; [.1646.0020.0018.FB71] # ARABIC LETTER PEHEH MEDIAL FORM; QQK
+FB6F ; [.1646.0020.0019.FB6F] # ARABIC LETTER PEHEH FINAL FORM; QQK
+FB6E ; [.1646.0020.001A.FB6E] # ARABIC LETTER PEHEH ISOLATED FORM; QQK
+0760 ; [.1647.0020.0002.0760] # ARABIC LETTER FEH WITH TWO DOTS BELOW
+0761 ; [.1648.0020.0002.0761] # ARABIC LETTER FEH WITH THREE DOTS POINTING UPWARDS BELOW
+066F ; [.1649.0020.0002.066F] # ARABIC LETTER DOTLESS QAF
+0642 ; [.164A.0020.0002.0642] # ARABIC LETTER QAF
+FED7 ; [.164A.0020.0017.FED7] # ARABIC LETTER QAF INITIAL FORM; QQK
+FED8 ; [.164A.0020.0018.FED8] # ARABIC LETTER QAF MEDIAL FORM; QQK
+FED6 ; [.164A.0020.0019.FED6] # ARABIC LETTER QAF FINAL FORM; QQK
+FED5 ; [.164A.0020.001A.FED5] # ARABIC LETTER QAF ISOLATED FORM; QQK
+FCC2 ; [.164A.0020.0017.FCC2][.1605.0020.0017.FCC2] # ARABIC LIGATURE QAF WITH HAH INITIAL FORM; QQKN
+FC33 ; [.164A.0020.001A.FC33][.1605.0020.001A.FC33] # ARABIC LIGATURE QAF WITH HAH ISOLATED FORM; QQKN
+FDF1 ; [.164A.0020.001A.FDF1][.165D.0020.001A.FDF1][.1686.0020.001F.FDF1] # ARABIC LIGATURE QALA USED AS KORANIC STOP SIGN ISOLATED FORM; QQKN
+FCC3 ; [.164A.0020.0017.FCC3][.1663.0020.0017.FCC3] # ARABIC LIGATURE QAF WITH MEEM INITIAL FORM; QQKN
+FC34 ; [.164A.0020.001A.FC34][.1663.0020.001A.FC34] # ARABIC LIGATURE QAF WITH MEEM ISOLATED FORM; QQKN
+FDB4 ; [.164A.0020.0017.FDB4][.1663.0020.0017.FDB4][.1605.0020.001F.FDB4] # ARABIC LIGATURE QAF WITH MEEM WITH HAH INITIAL FORM; QQKN
+FD7E ; [.164A.0020.0019.FD7E][.1663.0020.0019.FD7E][.1605.0020.001F.FD7E] # ARABIC LIGATURE QAF WITH MEEM WITH HAH FINAL FORM; QQKN
+FD7F ; [.164A.0020.0019.FD7F][.1663.0020.0019.FD7F][.1663.0020.001F.FD7F] # ARABIC LIGATURE QAF WITH MEEM WITH MEEM FINAL FORM; QQKN
+FDB2 ; [.164A.0020.0019.FDB2][.1663.0020.0019.FDB2][.1680.0020.001F.FDB2] # ARABIC LIGATURE QAF WITH MEEM WITH YEH FINAL FORM; QQKN
+FC7E ; [.164A.0020.0019.FC7E][.167F.0020.0019.FC7E] # ARABIC LIGATURE QAF WITH ALEF MAKSURA FINAL FORM; QQKN
+FC35 ; [.164A.0020.001A.FC35][.167F.0020.001A.FC35] # ARABIC LIGATURE QAF WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FC7F ; [.164A.0020.0019.FC7F][.1680.0020.0019.FC7F] # ARABIC LIGATURE QAF WITH YEH FINAL FORM; QQKN
+FC36 ; [.164A.0020.001A.FC36][.1680.0020.001A.FC36] # ARABIC LIGATURE QAF WITH YEH ISOLATED FORM; QQKN
+06A7 ; [.164B.0020.0002.06A7] # ARABIC LETTER QAF WITH DOT ABOVE
+06A8 ; [.164C.0020.0002.06A8] # ARABIC LETTER QAF WITH THREE DOTS ABOVE
+0643 ; [.164D.0020.0002.0643] # ARABIC LETTER KAF
+FEDB ; [.164D.0020.0017.FEDB] # ARABIC LETTER KAF INITIAL FORM; QQK
+FEDC ; [.164D.0020.0018.FEDC] # ARABIC LETTER KAF MEDIAL FORM; QQK
+FEDA ; [.164D.0020.0019.FEDA] # ARABIC LETTER KAF FINAL FORM; QQK
+FED9 ; [.164D.0020.001A.FED9] # ARABIC LETTER KAF ISOLATED FORM; QQK
+FC80 ; [.164D.0020.0019.FC80][.15EA.0020.0019.FC80] # ARABIC LIGATURE KAF WITH ALEF FINAL FORM; QQKN
+FC37 ; [.164D.0020.001A.FC37][.15EA.0020.001A.FC37] # ARABIC LIGATURE KAF WITH ALEF ISOLATED FORM; QQKN
+FCC4 ; [.164D.0020.0017.FCC4][.15FF.0020.0017.FCC4] # ARABIC LIGATURE KAF WITH JEEM INITIAL FORM; QQKN
+FC38 ; [.164D.0020.001A.FC38][.15FF.0020.001A.FC38] # ARABIC LIGATURE KAF WITH JEEM ISOLATED FORM; QQKN
+FCC5 ; [.164D.0020.0017.FCC5][.1605.0020.0017.FCC5] # ARABIC LIGATURE KAF WITH HAH INITIAL FORM; QQKN
+FC39 ; [.164D.0020.001A.FC39][.1605.0020.001A.FC39] # ARABIC LIGATURE KAF WITH HAH ISOLATED FORM; QQKN
+FCC6 ; [.164D.0020.0017.FCC6][.1606.0020.0017.FCC6] # ARABIC LIGATURE KAF WITH KHAH INITIAL FORM; QQKN
+FC3A ; [.164D.0020.001A.FC3A][.1606.0020.001A.FC3A] # ARABIC LIGATURE KAF WITH KHAH ISOLATED FORM; QQKN
+FCC7 ; [.164D.0020.0017.FCC7][.165D.0020.0017.FCC7] # ARABIC LIGATURE KAF WITH LAM INITIAL FORM; QQKN
+FCEB ; [.164D.0020.0018.FCEB][.165D.0020.0018.FCEB] # ARABIC LIGATURE KAF WITH LAM MEDIAL FORM; QQKN
+FC81 ; [.164D.0020.0019.FC81][.165D.0020.0019.FC81] # ARABIC LIGATURE KAF WITH LAM FINAL FORM; QQKN
+FC3B ; [.164D.0020.001A.FC3B][.165D.0020.001A.FC3B] # ARABIC LIGATURE KAF WITH LAM ISOLATED FORM; QQKN
+FCC8 ; [.164D.0020.0017.FCC8][.1663.0020.0017.FCC8] # ARABIC LIGATURE KAF WITH MEEM INITIAL FORM; QQKN
+FCEC ; [.164D.0020.0018.FCEC][.1663.0020.0018.FCEC] # ARABIC LIGATURE KAF WITH MEEM MEDIAL FORM; QQKN
+FC82 ; [.164D.0020.0019.FC82][.1663.0020.0019.FC82] # ARABIC LIGATURE KAF WITH MEEM FINAL FORM; QQKN
+FC3C ; [.164D.0020.001A.FC3C][.1663.0020.001A.FC3C] # ARABIC LIGATURE KAF WITH MEEM ISOLATED FORM; QQKN
+FDC3 ; [.164D.0020.0017.FDC3][.1663.0020.0017.FDC3][.1663.0020.001F.FDC3] # ARABIC LIGATURE KAF WITH MEEM WITH MEEM INITIAL FORM; QQKN
+FDBB ; [.164D.0020.0019.FDBB][.1663.0020.0019.FDBB][.1663.0020.001F.FDBB] # ARABIC LIGATURE KAF WITH MEEM WITH MEEM FINAL FORM; QQKN
+FDB7 ; [.164D.0020.0019.FDB7][.1663.0020.0019.FDB7][.1680.0020.001F.FDB7] # ARABIC LIGATURE KAF WITH MEEM WITH YEH FINAL FORM; QQKN
+FC83 ; [.164D.0020.0019.FC83][.167F.0020.0019.FC83] # ARABIC LIGATURE KAF WITH ALEF MAKSURA FINAL FORM; QQKN
+FC3D ; [.164D.0020.001A.FC3D][.167F.0020.001A.FC3D] # ARABIC LIGATURE KAF WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FC84 ; [.164D.0020.0019.FC84][.1680.0020.0019.FC84] # ARABIC LIGATURE KAF WITH YEH FINAL FORM; QQKN
+FC3E ; [.164D.0020.001A.FC3E][.1680.0020.001A.FC3E] # ARABIC LIGATURE KAF WITH YEH ISOLATED FORM; QQKN
+06A9 ; [.164E.0020.0002.06A9] # ARABIC LETTER KEHEH
+FB90 ; [.164E.0020.0017.FB90] # ARABIC LETTER KEHEH INITIAL FORM; QQK
+FB91 ; [.164E.0020.0018.FB91] # ARABIC LETTER KEHEH MEDIAL FORM; QQK
+FB8F ; [.164E.0020.0019.FB8F] # ARABIC LETTER KEHEH FINAL FORM; QQK
+FB8E ; [.164E.0020.001A.FB8E] # ARABIC LETTER KEHEH ISOLATED FORM; QQK
+06AA ; [.164F.0020.0002.06AA] # ARABIC LETTER SWASH KAF
+06AB ; [.1650.0020.0002.06AB] # ARABIC LETTER KAF WITH RING
+06AC ; [.1651.0020.0002.06AC] # ARABIC LETTER KAF WITH DOT ABOVE
+06AD ; [.1652.0020.0002.06AD] # ARABIC LETTER NG
+FBD5 ; [.1652.0020.0017.FBD5] # ARABIC LETTER NG INITIAL FORM; QQK
+FBD6 ; [.1652.0020.0018.FBD6] # ARABIC LETTER NG MEDIAL FORM; QQK
+FBD4 ; [.1652.0020.0019.FBD4] # ARABIC LETTER NG FINAL FORM; QQK
+FBD3 ; [.1652.0020.001A.FBD3] # ARABIC LETTER NG ISOLATED FORM; QQK
+06AE ; [.1653.0020.0002.06AE] # ARABIC LETTER KAF WITH THREE DOTS BELOW
+06AF ; [.1654.0020.0002.06AF] # ARABIC LETTER GAF
+FB94 ; [.1654.0020.0017.FB94] # ARABIC LETTER GAF INITIAL FORM; QQK
+FB95 ; [.1654.0020.0018.FB95] # ARABIC LETTER GAF MEDIAL FORM; QQK
+FB93 ; [.1654.0020.0019.FB93] # ARABIC LETTER GAF FINAL FORM; QQK
+FB92 ; [.1654.0020.001A.FB92] # ARABIC LETTER GAF ISOLATED FORM; QQK
+06B0 ; [.1655.0020.0002.06B0] # ARABIC LETTER GAF WITH RING
+06B1 ; [.1656.0020.0002.06B1] # ARABIC LETTER NGOEH
+FB9C ; [.1656.0020.0017.FB9C] # ARABIC LETTER NGOEH INITIAL FORM; QQK
+FB9D ; [.1656.0020.0018.FB9D] # ARABIC LETTER NGOEH MEDIAL FORM; QQK
+FB9B ; [.1656.0020.0019.FB9B] # ARABIC LETTER NGOEH FINAL FORM; QQK
+FB9A ; [.1656.0020.001A.FB9A] # ARABIC LETTER NGOEH ISOLATED FORM; QQK
+06B2 ; [.1657.0020.0002.06B2] # ARABIC LETTER GAF WITH TWO DOTS BELOW
+06B3 ; [.1658.0020.0002.06B3] # ARABIC LETTER GUEH
+FB98 ; [.1658.0020.0017.FB98] # ARABIC LETTER GUEH INITIAL FORM; QQK
+FB99 ; [.1658.0020.0018.FB99] # ARABIC LETTER GUEH MEDIAL FORM; QQK
+FB97 ; [.1658.0020.0019.FB97] # ARABIC LETTER GUEH FINAL FORM; QQK
+FB96 ; [.1658.0020.001A.FB96] # ARABIC LETTER GUEH ISOLATED FORM; QQK
+06B4 ; [.1659.0020.0002.06B4] # ARABIC LETTER GAF WITH THREE DOTS ABOVE
+0762 ; [.165A.0020.0002.0762] # ARABIC LETTER KEHEH WITH DOT ABOVE
+0763 ; [.165B.0020.0002.0763] # ARABIC LETTER KEHEH WITH THREE DOTS ABOVE
+0764 ; [.165C.0020.0002.0764] # ARABIC LETTER KEHEH WITH THREE DOTS POINTING UPWARDS BELOW
+0644 ; [.165D.0020.0002.0644] # ARABIC LETTER LAM
+FEDF ; [.165D.0020.0017.FEDF] # ARABIC LETTER LAM INITIAL FORM; QQK
+FEE0 ; [.165D.0020.0018.FEE0] # ARABIC LETTER LAM MEDIAL FORM; QQK
+FEDE ; [.165D.0020.0019.FEDE] # ARABIC LETTER LAM FINAL FORM; QQK
+FEDD ; [.165D.0020.001A.FEDD] # ARABIC LETTER LAM ISOLATED FORM; QQK
+FEF6 ; [.165D.0020.0019.FEF6][.15E2.0020.0019.FEF6] # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM; QQKN
+FEF5 ; [.165D.0020.001A.FEF5][.15E2.0020.001A.FEF5] # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM; QQKN
+FEF8 ; [.165D.0020.0019.FEF8][.15E3.0020.0019.FEF8] # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM; QQKN
+FEF7 ; [.165D.0020.001A.FEF7][.15E3.0020.001A.FEF7] # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM; QQKN
+FEFA ; [.165D.0020.0019.FEFA][.15E7.0020.0019.FEFA] # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM; QQKN
+FEF9 ; [.165D.0020.001A.FEF9][.15E7.0020.001A.FEF9] # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM; QQKN
+FEFC ; [.165D.0020.0019.FEFC][.15EA.0020.0019.FEFC] # ARABIC LIGATURE LAM WITH ALEF FINAL FORM; QQKN
+FEFB ; [.165D.0020.001A.FEFB][.15EA.0020.001A.FEFB] # ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM; QQKN
+FCC9 ; [.165D.0020.0017.FCC9][.15FF.0020.0017.FCC9] # ARABIC LIGATURE LAM WITH JEEM INITIAL FORM; QQKN
+FC3F ; [.165D.0020.001A.FC3F][.15FF.0020.001A.FC3F] # ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM; QQKN
+FD83 ; [.165D.0020.0017.FD83][.15FF.0020.0017.FD83][.15FF.0020.001F.FD83] # ARABIC LIGATURE LAM WITH JEEM WITH JEEM INITIAL FORM; QQKN
+FD84 ; [.165D.0020.0019.FD84][.15FF.0020.0019.FD84][.15FF.0020.001F.FD84] # ARABIC LIGATURE LAM WITH JEEM WITH JEEM FINAL FORM; QQKN
+FDBA ; [.165D.0020.0017.FDBA][.15FF.0020.0017.FDBA][.1663.0020.001F.FDBA] # ARABIC LIGATURE LAM WITH JEEM WITH MEEM INITIAL FORM; QQKN
+FDBC ; [.165D.0020.0019.FDBC][.15FF.0020.0019.FDBC][.1663.0020.001F.FDBC] # ARABIC LIGATURE LAM WITH JEEM WITH MEEM FINAL FORM; QQKN
+FDAC ; [.165D.0020.0019.FDAC][.15FF.0020.0019.FDAC][.1680.0020.001F.FDAC] # ARABIC LIGATURE LAM WITH JEEM WITH YEH FINAL FORM; QQKN
+FCCA ; [.165D.0020.0017.FCCA][.1605.0020.0017.FCCA] # ARABIC LIGATURE LAM WITH HAH INITIAL FORM; QQKN
+FC40 ; [.165D.0020.001A.FC40][.1605.0020.001A.FC40] # ARABIC LIGATURE LAM WITH HAH ISOLATED FORM; QQKN
+FDB5 ; [.165D.0020.0017.FDB5][.1605.0020.0017.FDB5][.1663.0020.001F.FDB5] # ARABIC LIGATURE LAM WITH HAH WITH MEEM INITIAL FORM; QQKN
+FD80 ; [.165D.0020.0019.FD80][.1605.0020.0019.FD80][.1663.0020.001F.FD80] # ARABIC LIGATURE LAM WITH HAH WITH MEEM FINAL FORM; QQKN
+FD82 ; [.165D.0020.0019.FD82][.1605.0020.0019.FD82][.167F.0020.001F.FD82] # ARABIC LIGATURE LAM WITH HAH WITH ALEF MAKSURA FINAL FORM; QQKN
+FD81 ; [.165D.0020.0019.FD81][.1605.0020.0019.FD81][.1680.0020.001F.FD81] # ARABIC LIGATURE LAM WITH HAH WITH YEH FINAL FORM; QQKN
+FCCB ; [.165D.0020.0017.FCCB][.1606.0020.0017.FCCB] # ARABIC LIGATURE LAM WITH KHAH INITIAL FORM; QQKN
+FC41 ; [.165D.0020.001A.FC41][.1606.0020.001A.FC41] # ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM; QQKN
+FD86 ; [.165D.0020.0017.FD86][.1606.0020.0017.FD86][.1663.0020.001F.FD86] # ARABIC LIGATURE LAM WITH KHAH WITH MEEM INITIAL FORM; QQKN
+FD85 ; [.165D.0020.0019.FD85][.1606.0020.0019.FD85][.1663.0020.001F.FD85] # ARABIC LIGATURE LAM WITH KHAH WITH MEEM FINAL FORM; QQKN
+FCCC ; [.165D.0020.0017.FCCC][.1663.0020.0017.FCCC] # ARABIC LIGATURE LAM WITH MEEM INITIAL FORM; QQKN
+FCED ; [.165D.0020.0018.FCED][.1663.0020.0018.FCED] # ARABIC LIGATURE LAM WITH MEEM MEDIAL FORM; QQKN
+FC85 ; [.165D.0020.0019.FC85][.1663.0020.0019.FC85] # ARABIC LIGATURE LAM WITH MEEM FINAL FORM; QQKN
+FC42 ; [.165D.0020.001A.FC42][.1663.0020.001A.FC42] # ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM; QQKN
+FD88 ; [.165D.0020.0017.FD88][.1663.0020.0017.FD88][.1605.0020.001F.FD88] # ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM; QQKN
+FD87 ; [.165D.0020.0019.FD87][.1663.0020.0019.FD87][.1605.0020.001F.FD87] # ARABIC LIGATURE LAM WITH MEEM WITH HAH FINAL FORM; QQKN
+FDAD ; [.165D.0020.0019.FDAD][.1663.0020.0019.FDAD][.1680.0020.001F.FDAD] # ARABIC LIGATURE LAM WITH MEEM WITH YEH FINAL FORM; QQKN
+FCCD ; [.165D.0020.0017.FCCD][.166F.0020.0017.FCCD] # ARABIC LIGATURE LAM WITH HEH INITIAL FORM; QQKN
+FC86 ; [.165D.0020.0019.FC86][.167F.0020.0019.FC86] # ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM; QQKN
+FC43 ; [.165D.0020.001A.FC43][.167F.0020.001A.FC43] # ARABIC LIGATURE LAM WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FC87 ; [.165D.0020.0019.FC87][.1680.0020.0019.FC87] # ARABIC LIGATURE LAM WITH YEH FINAL FORM; QQKN
+FC44 ; [.165D.0020.001A.FC44][.1680.0020.001A.FC44] # ARABIC LIGATURE LAM WITH YEH ISOLATED FORM; QQKN
+06B5 ; [.165E.0020.0002.06B5] # ARABIC LETTER LAM WITH SMALL V
+06B6 ; [.165F.0020.0002.06B6] # ARABIC LETTER LAM WITH DOT ABOVE
+06B7 ; [.1660.0020.0002.06B7] # ARABIC LETTER LAM WITH THREE DOTS ABOVE
+06B8 ; [.1661.0020.0002.06B8] # ARABIC LETTER LAM WITH THREE DOTS BELOW
+076A ; [.1662.0020.0002.076A] # ARABIC LETTER LAM WITH BAR
+0645 ; [.1663.0020.0002.0645] # ARABIC LETTER MEEM
+FEE3 ; [.1663.0020.0017.FEE3] # ARABIC LETTER MEEM INITIAL FORM; QQK
+FEE4 ; [.1663.0020.0018.FEE4] # ARABIC LETTER MEEM MEDIAL FORM; QQK
+FEE2 ; [.1663.0020.0019.FEE2] # ARABIC LETTER MEEM FINAL FORM; QQK
+FEE1 ; [.1663.0020.001A.FEE1] # ARABIC LETTER MEEM ISOLATED FORM; QQK
+06FE ; [.1663.0020.0004.06FE][.0000.019A.0004.06FE] # ARABIC SIGN SINDHI POSTPOSITION MEN; QQKN
+FC88 ; [.1663.0020.0019.FC88][.15EA.0020.0019.FC88] # ARABIC LIGATURE MEEM WITH ALEF FINAL FORM; QQKN
+FCCE ; [.1663.0020.0017.FCCE][.15FF.0020.0017.FCCE] # ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM; QQKN
+FC45 ; [.1663.0020.001A.FC45][.15FF.0020.001A.FC45] # ARABIC LIGATURE MEEM WITH JEEM ISOLATED FORM; QQKN
+FD8C ; [.1663.0020.0017.FD8C][.15FF.0020.0017.FD8C][.1605.0020.001F.FD8C] # ARABIC LIGATURE MEEM WITH JEEM WITH HAH INITIAL FORM; QQKN
+FD92 ; [.1663.0020.0017.FD92][.15FF.0020.0017.FD92][.1606.0020.001F.FD92] # ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM; QQKN
+FD8D ; [.1663.0020.0017.FD8D][.15FF.0020.0017.FD8D][.1663.0020.001F.FD8D] # ARABIC LIGATURE MEEM WITH JEEM WITH MEEM INITIAL FORM; QQKN
+FDC0 ; [.1663.0020.0019.FDC0][.15FF.0020.0019.FDC0][.1680.0020.001F.FDC0] # ARABIC LIGATURE MEEM WITH JEEM WITH YEH FINAL FORM; QQKN
+FCCF ; [.1663.0020.0017.FCCF][.1605.0020.0017.FCCF] # ARABIC LIGATURE MEEM WITH HAH INITIAL FORM; QQKN
+FC46 ; [.1663.0020.001A.FC46][.1605.0020.001A.FC46] # ARABIC LIGATURE MEEM WITH HAH ISOLATED FORM; QQKN
+FD89 ; [.1663.0020.0017.FD89][.1605.0020.0017.FD89][.15FF.0020.001F.FD89] # ARABIC LIGATURE MEEM WITH HAH WITH JEEM INITIAL FORM; QQKN
+FD8A ; [.1663.0020.0017.FD8A][.1605.0020.0017.FD8A][.1663.0020.001F.FD8A] # ARABIC LIGATURE MEEM WITH HAH WITH MEEM INITIAL FORM; QQKN
+FDF4 ; [.1663.0020.001A.FDF4][.1605.0020.001A.FDF4][.1663.0020.001F.FDF4][.160C.0020.001F.FDF4] # ARABIC LIGATURE MOHAMMAD ISOLATED FORM; QQKN
+FD8B ; [.1663.0020.0019.FD8B][.1605.0020.0019.FD8B][.1680.0020.001F.FD8B] # ARABIC LIGATURE MEEM WITH HAH WITH YEH FINAL FORM; QQKN
+FCD0 ; [.1663.0020.0017.FCD0][.1606.0020.0017.FCD0] # ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM; QQKN
+FC47 ; [.1663.0020.001A.FC47][.1606.0020.001A.FC47] # ARABIC LIGATURE MEEM WITH KHAH ISOLATED FORM; QQKN
+FD8E ; [.1663.0020.0017.FD8E][.1606.0020.0017.FD8E][.15FF.0020.001F.FD8E] # ARABIC LIGATURE MEEM WITH KHAH WITH JEEM INITIAL FORM; QQKN
+FD8F ; [.1663.0020.0017.FD8F][.1606.0020.0017.FD8F][.1663.0020.001F.FD8F] # ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM; QQKN
+FDB9 ; [.1663.0020.0019.FDB9][.1606.0020.0019.FDB9][.1680.0020.001F.FDB9] # ARABIC LIGATURE MEEM WITH KHAH WITH YEH FINAL FORM; QQKN
+FCD1 ; [.1663.0020.0017.FCD1][.1663.0020.0017.FCD1] # ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM; QQKN
+FC89 ; [.1663.0020.0019.FC89][.1663.0020.0019.FC89] # ARABIC LIGATURE MEEM WITH MEEM FINAL FORM; QQKN
+FC48 ; [.1663.0020.001A.FC48][.1663.0020.001A.FC48] # ARABIC LIGATURE MEEM WITH MEEM ISOLATED FORM; QQKN
+FDB1 ; [.1663.0020.0019.FDB1][.1663.0020.0019.FDB1][.1680.0020.001F.FDB1] # ARABIC LIGATURE MEEM WITH MEEM WITH YEH FINAL FORM; QQKN
+FC49 ; [.1663.0020.001A.FC49][.167F.0020.001A.FC49] # ARABIC LIGATURE MEEM WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FC4A ; [.1663.0020.001A.FC4A][.1680.0020.001A.FC4A] # ARABIC LIGATURE MEEM WITH YEH ISOLATED FORM; QQKN
+0765 ; [.1664.0020.0002.0765] # ARABIC LETTER MEEM WITH DOT ABOVE
+0766 ; [.1665.0020.0002.0766] # ARABIC LETTER MEEM WITH DOT BELOW
+0646 ; [.1666.0020.0002.0646] # ARABIC LETTER NOON
+FEE7 ; [.1666.0020.0017.FEE7] # ARABIC LETTER NOON INITIAL FORM; QQK
+FEE8 ; [.1666.0020.0018.FEE8] # ARABIC LETTER NOON MEDIAL FORM; QQK
+FEE6 ; [.1666.0020.0019.FEE6] # ARABIC LETTER NOON FINAL FORM; QQK
+FEE5 ; [.1666.0020.001A.FEE5] # ARABIC LETTER NOON ISOLATED FORM; QQK
+FCD2 ; [.1666.0020.0017.FCD2][.15FF.0020.0017.FCD2] # ARABIC LIGATURE NOON WITH JEEM INITIAL FORM; QQKN
+FC4B ; [.1666.0020.001A.FC4B][.15FF.0020.001A.FC4B] # ARABIC LIGATURE NOON WITH JEEM ISOLATED FORM; QQKN
+FDB8 ; [.1666.0020.0017.FDB8][.15FF.0020.0017.FDB8][.1605.0020.001F.FDB8] # ARABIC LIGATURE NOON WITH JEEM WITH HAH INITIAL FORM; QQKN
+FDBD ; [.1666.0020.0019.FDBD][.15FF.0020.0019.FDBD][.1605.0020.001F.FDBD] # ARABIC LIGATURE NOON WITH JEEM WITH HAH FINAL FORM; QQKN
+FD98 ; [.1666.0020.0017.FD98][.15FF.0020.0017.FD98][.1663.0020.001F.FD98] # ARABIC LIGATURE NOON WITH JEEM WITH MEEM INITIAL FORM; QQKN
+FD97 ; [.1666.0020.0019.FD97][.15FF.0020.0019.FD97][.1663.0020.001F.FD97] # ARABIC LIGATURE NOON WITH JEEM WITH MEEM FINAL FORM; QQKN
+FD99 ; [.1666.0020.0019.FD99][.15FF.0020.0019.FD99][.167F.0020.001F.FD99] # ARABIC LIGATURE NOON WITH JEEM WITH ALEF MAKSURA FINAL FORM; QQKN
+FDC7 ; [.1666.0020.0019.FDC7][.15FF.0020.0019.FDC7][.1680.0020.001F.FDC7] # ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM; QQKN
+FCD3 ; [.1666.0020.0017.FCD3][.1605.0020.0017.FCD3] # ARABIC LIGATURE NOON WITH HAH INITIAL FORM; QQKN
+FC4C ; [.1666.0020.001A.FC4C][.1605.0020.001A.FC4C] # ARABIC LIGATURE NOON WITH HAH ISOLATED FORM; QQKN
+FD95 ; [.1666.0020.0017.FD95][.1605.0020.0017.FD95][.1663.0020.001F.FD95] # ARABIC LIGATURE NOON WITH HAH WITH MEEM INITIAL FORM; QQKN
+FD96 ; [.1666.0020.0019.FD96][.1605.0020.0019.FD96][.167F.0020.001F.FD96] # ARABIC LIGATURE NOON WITH HAH WITH ALEF MAKSURA FINAL FORM; QQKN
+FDB3 ; [.1666.0020.0019.FDB3][.1605.0020.0019.FDB3][.1680.0020.001F.FDB3] # ARABIC LIGATURE NOON WITH HAH WITH YEH FINAL FORM; QQKN
+FCD4 ; [.1666.0020.0017.FCD4][.1606.0020.0017.FCD4] # ARABIC LIGATURE NOON WITH KHAH INITIAL FORM; QQKN
+FC4D ; [.1666.0020.001A.FC4D][.1606.0020.001A.FC4D] # ARABIC LIGATURE NOON WITH KHAH ISOLATED FORM; QQKN
+FC8A ; [.1666.0020.0019.FC8A][.161A.0020.0019.FC8A] # ARABIC LIGATURE NOON WITH REH FINAL FORM; QQKN
+FC8B ; [.1666.0020.0019.FC8B][.161B.0020.0019.FC8B] # ARABIC LIGATURE NOON WITH ZAIN FINAL FORM; QQKN
+FCD5 ; [.1666.0020.0017.FCD5][.1663.0020.0017.FCD5] # ARABIC LIGATURE NOON WITH MEEM INITIAL FORM; QQKN
+FCEE ; [.1666.0020.0018.FCEE][.1663.0020.0018.FCEE] # ARABIC LIGATURE NOON WITH MEEM MEDIAL FORM; QQKN
+FC8C ; [.1666.0020.0019.FC8C][.1663.0020.0019.FC8C] # ARABIC LIGATURE NOON WITH MEEM FINAL FORM; QQKN
+FC4E ; [.1666.0020.001A.FC4E][.1663.0020.001A.FC4E] # ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM; QQKN
+FD9B ; [.1666.0020.0019.FD9B][.1663.0020.0019.FD9B][.167F.0020.001F.FD9B] # ARABIC LIGATURE NOON WITH MEEM WITH ALEF MAKSURA FINAL FORM; QQKN
+FD9A ; [.1666.0020.0019.FD9A][.1663.0020.0019.FD9A][.1680.0020.001F.FD9A] # ARABIC LIGATURE NOON WITH MEEM WITH YEH FINAL FORM; QQKN
+FC8D ; [.1666.0020.0019.FC8D][.1666.0020.0019.FC8D] # ARABIC LIGATURE NOON WITH NOON FINAL FORM; QQKN
+FCD6 ; [.1666.0020.0017.FCD6][.166F.0020.0017.FCD6] # ARABIC LIGATURE NOON WITH HEH INITIAL FORM; QQKN
+FCEF ; [.1666.0020.0018.FCEF][.166F.0020.0018.FCEF] # ARABIC LIGATURE NOON WITH HEH MEDIAL FORM; QQKN
+FC8E ; [.1666.0020.0019.FC8E][.167F.0020.0019.FC8E] # ARABIC LIGATURE NOON WITH ALEF MAKSURA FINAL FORM; QQKN
+FC4F ; [.1666.0020.001A.FC4F][.167F.0020.001A.FC4F] # ARABIC LIGATURE NOON WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FC8F ; [.1666.0020.0019.FC8F][.1680.0020.0019.FC8F] # ARABIC LIGATURE NOON WITH YEH FINAL FORM; QQKN
+FC50 ; [.1666.0020.001A.FC50][.1680.0020.001A.FC50] # ARABIC LIGATURE NOON WITH YEH ISOLATED FORM; QQKN
+06BA ; [.1667.0020.0002.06BA] # ARABIC LETTER NOON GHUNNA
+FB9F ; [.1667.0020.0019.FB9F] # ARABIC LETTER NOON GHUNNA FINAL FORM; QQK
+FB9E ; [.1667.0020.001A.FB9E] # ARABIC LETTER NOON GHUNNA ISOLATED FORM; QQK
+06BB ; [.1668.0020.0002.06BB] # ARABIC LETTER RNOON
+FBA2 ; [.1668.0020.0017.FBA2] # ARABIC LETTER RNOON INITIAL FORM; QQK
+FBA3 ; [.1668.0020.0018.FBA3] # ARABIC LETTER RNOON MEDIAL FORM; QQK
+FBA1 ; [.1668.0020.0019.FBA1] # ARABIC LETTER RNOON FINAL FORM; QQK
+FBA0 ; [.1668.0020.001A.FBA0] # ARABIC LETTER RNOON ISOLATED FORM; QQK
+06BC ; [.1669.0020.0002.06BC] # ARABIC LETTER NOON WITH RING
+06BD ; [.166A.0020.0002.06BD] # ARABIC LETTER NOON WITH THREE DOTS ABOVE
+06B9 ; [.166B.0020.0002.06B9] # ARABIC LETTER NOON WITH DOT BELOW
+0767 ; [.166C.0020.0002.0767] # ARABIC LETTER NOON WITH TWO DOTS BELOW
+0768 ; [.166D.0020.0002.0768] # ARABIC LETTER NOON WITH SMALL TAH
+0769 ; [.166E.0020.0002.0769] # ARABIC LETTER NOON WITH SMALL V
+0647 ; [.166F.0020.0002.0647] # ARABIC LETTER HEH
+FEEB ; [.166F.0020.0017.FEEB] # ARABIC LETTER HEH INITIAL FORM; QQK
+FEEC ; [.166F.0020.0018.FEEC] # ARABIC LETTER HEH MEDIAL FORM; QQK
+FEEA ; [.166F.0020.0019.FEEA] # ARABIC LETTER HEH FINAL FORM; QQK
+FEE9 ; [.166F.0020.001A.FEE9] # ARABIC LETTER HEH ISOLATED FORM; QQK
+FCD9 ; [.166F.0020.0017.FCD9][.0000.00F3.0017.FCD9] # ARABIC LIGATURE HEH WITH SUPERSCRIPT ALEF INITIAL FORM; QQKN
+FCD7 ; [.166F.0020.0017.FCD7][.15FF.0020.0017.FCD7] # ARABIC LIGATURE HEH WITH JEEM INITIAL FORM; QQKN
+FC51 ; [.166F.0020.001A.FC51][.15FF.0020.001A.FC51] # ARABIC LIGATURE HEH WITH JEEM ISOLATED FORM; QQKN
+FCD8 ; [.166F.0020.0017.FCD8][.1663.0020.0017.FCD8] # ARABIC LIGATURE HEH WITH MEEM INITIAL FORM; QQKN
+FC52 ; [.166F.0020.001A.FC52][.1663.0020.001A.FC52] # ARABIC LIGATURE HEH WITH MEEM ISOLATED FORM; QQKN
+FD93 ; [.166F.0020.0017.FD93][.1663.0020.0017.FD93][.15FF.0020.001F.FD93] # ARABIC LIGATURE HEH WITH MEEM WITH JEEM INITIAL FORM; QQKN
+FD94 ; [.166F.0020.0017.FD94][.1663.0020.0017.FD94][.1663.0020.001F.FD94] # ARABIC LIGATURE HEH WITH MEEM WITH MEEM INITIAL FORM; QQKN
+FC53 ; [.166F.0020.001A.FC53][.167F.0020.001A.FC53] # ARABIC LIGATURE HEH WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FC54 ; [.166F.0020.001A.FC54][.1680.0020.001A.FC54] # ARABIC LIGATURE HEH WITH YEH ISOLATED FORM; QQKN
+06BE ; [.1670.0020.0002.06BE] # ARABIC LETTER HEH DOACHASHMEE
+FBAC ; [.1670.0020.0017.FBAC] # ARABIC LETTER HEH DOACHASHMEE INITIAL FORM; QQK
+FBAD ; [.1670.0020.0018.FBAD] # ARABIC LETTER HEH DOACHASHMEE MEDIAL FORM; QQK
+FBAB ; [.1670.0020.0019.FBAB] # ARABIC LETTER HEH DOACHASHMEE FINAL FORM; QQK
+FBAA ; [.1670.0020.001A.FBAA] # ARABIC LETTER HEH DOACHASHMEE ISOLATED FORM; QQK
+06C1 ; [.1671.0020.0002.06C1] # ARABIC LETTER HEH GOAL
+FBA8 ; [.1671.0020.0017.FBA8] # ARABIC LETTER HEH GOAL INITIAL FORM; QQK
+FBA9 ; [.1671.0020.0018.FBA9] # ARABIC LETTER HEH GOAL MEDIAL FORM; QQK
+FBA7 ; [.1671.0020.0019.FBA7] # ARABIC LETTER HEH GOAL FINAL FORM; QQK
+FBA6 ; [.1671.0020.001A.FBA6] # ARABIC LETTER HEH GOAL ISOLATED FORM; QQK
+06C2 ; [.1671.0020.0002.06C1][.0000.00E8.0002.0654] # ARABIC LETTER HEH GOAL WITH HAMZA ABOVE; QQCM
+06C3 ; [.1672.0020.0002.06C3] # ARABIC LETTER TEH MARBUTA GOAL
+06FF ; [.1673.0020.0002.06FF] # ARABIC LETTER HEH WITH INVERTED V
+06D5 ; [.1674.0020.0002.06D5] # ARABIC LETTER AE
+06C0 ; [.1674.0020.0002.06D5][.0000.00E8.0002.0654] # ARABIC LETTER HEH WITH YEH ABOVE; QQCM
+FBA5 ; [.1674.0020.0019.FBA5][.0000.00E8.0019.FBA5] # ARABIC LETTER HEH WITH YEH ABOVE FINAL FORM; QQKN
+FBA4 ; [.1674.0020.001A.FBA4][.0000.00E8.001A.FBA4] # ARABIC LETTER HEH WITH YEH ABOVE ISOLATED FORM; QQKN
+0648 ; [.1675.0020.0002.0648] # ARABIC LETTER WAW
+06E5 ; [.1675.0020.0004.06E5] # ARABIC SMALL WAW; QQK
+FEEE ; [.1675.0020.0019.FEEE] # ARABIC LETTER WAW FINAL FORM; QQK
+FEED ; [.1675.0020.001A.FEED] # ARABIC LETTER WAW ISOLATED FORM; QQK
+0676 ; [.1675.0020.0004.0676][.15E1.0020.0004.0676] # ARABIC LETTER HIGH HAMZA WAW; QQKN
+FDF8 ; [.1675.0020.001A.FDF8][.1629.0020.001A.FDF8][.165D.0020.001F.FDF8][.1663.0020.001F.FDF8] # ARABIC LIGATURE WASALLAM ISOLATED FORM; QQKN
+06C4 ; [.1676.0020.0002.06C4] # ARABIC LETTER WAW WITH RING
+06C5 ; [.1677.0020.0002.06C5] # ARABIC LETTER KIRGHIZ OE
+FBE1 ; [.1677.0020.0019.FBE1] # ARABIC LETTER KIRGHIZ OE FINAL FORM; QQK
+FBE0 ; [.1677.0020.001A.FBE0] # ARABIC LETTER KIRGHIZ OE ISOLATED FORM; QQK
+06C6 ; [.1678.0020.0002.06C6] # ARABIC LETTER OE
+FBDA ; [.1678.0020.0019.FBDA] # ARABIC LETTER OE FINAL FORM; QQK
+FBD9 ; [.1678.0020.001A.FBD9] # ARABIC LETTER OE ISOLATED FORM; QQK
+06C7 ; [.1679.0020.0002.06C7] # ARABIC LETTER U
+FBD8 ; [.1679.0020.0019.FBD8] # ARABIC LETTER U FINAL FORM; QQK
+FBD7 ; [.1679.0020.001A.FBD7] # ARABIC LETTER U ISOLATED FORM; QQK
+0677 ; [.1679.0020.0004.0677][.15E1.0020.0004.0677] # ARABIC LETTER U WITH HAMZA ABOVE; QQKN
+FBDD ; [.1679.0020.001A.FBDD][.15E1.0020.001A.FBDD] # ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM; QQKN
+06C8 ; [.167A.0020.0002.06C8] # ARABIC LETTER YU
+FBDC ; [.167A.0020.0019.FBDC] # ARABIC LETTER YU FINAL FORM; QQK
+FBDB ; [.167A.0020.001A.FBDB] # ARABIC LETTER YU ISOLATED FORM; QQK
+06C9 ; [.167B.0020.0002.06C9] # ARABIC LETTER KIRGHIZ YU
+FBE3 ; [.167B.0020.0019.FBE3] # ARABIC LETTER KIRGHIZ YU FINAL FORM; QQK
+FBE2 ; [.167B.0020.001A.FBE2] # ARABIC LETTER KIRGHIZ YU ISOLATED FORM; QQK
+06CA ; [.167C.0020.0002.06CA] # ARABIC LETTER WAW WITH TWO DOTS ABOVE
+06CB ; [.167D.0020.0002.06CB] # ARABIC LETTER VE
+FBDF ; [.167D.0020.0019.FBDF] # ARABIC LETTER VE FINAL FORM; QQK
+FBDE ; [.167D.0020.001A.FBDE] # ARABIC LETTER VE ISOLATED FORM; QQK
+06CF ; [.167E.0020.0002.06CF] # ARABIC LETTER WAW WITH DOT ABOVE
+0649 ; [.167F.0020.0002.0649] # ARABIC LETTER ALEF MAKSURA
+FBE8 ; [.167F.0020.0017.FBE8] # ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA INITIAL FORM; QQK
+FBE9 ; [.167F.0020.0018.FBE9] # ARABIC LETTER UIGHUR KAZAKH KIRGHIZ ALEF MAKSURA MEDIAL FORM; QQK
+FEF0 ; [.167F.0020.0019.FEF0] # ARABIC LETTER ALEF MAKSURA FINAL FORM; QQK
+FEEF ; [.167F.0020.001A.FEEF] # ARABIC LETTER ALEF MAKSURA ISOLATED FORM; QQK
+FC90 ; [.167F.0020.0019.FC90][.0000.00F3.0019.FC90] # ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF FINAL FORM; QQKN
+FC5D ; [.167F.0020.001A.FC5D][.0000.00F3.001A.FC5D] # ARABIC LIGATURE ALEF MAKSURA WITH SUPERSCRIPT ALEF ISOLATED FORM; QQKN
+064A ; [.1680.0020.0002.064A] # ARABIC LETTER YEH
+06E6 ; [.1680.0020.0004.06E6] # ARABIC SMALL YEH; QQK
+FEF3 ; [.1680.0020.0017.FEF3] # ARABIC LETTER YEH INITIAL FORM; QQK
+FEF4 ; [.1680.0020.0018.FEF4] # ARABIC LETTER YEH MEDIAL FORM; QQK
+FEF2 ; [.1680.0020.0019.FEF2] # ARABIC LETTER YEH FINAL FORM; QQK
+FEF1 ; [.1680.0020.001A.FEF1] # ARABIC LETTER YEH ISOLATED FORM; QQK
+0678 ; [.1680.0020.0004.0678][.15E1.0020.0004.0678] # ARABIC LETTER HIGH HAMZA YEH; QQKN
+FCDA ; [.1680.0020.0017.FCDA][.15FF.0020.0017.FCDA] # ARABIC LIGATURE YEH WITH JEEM INITIAL FORM; QQKN
+FC55 ; [.1680.0020.001A.FC55][.15FF.0020.001A.FC55] # ARABIC LIGATURE YEH WITH JEEM ISOLATED FORM; QQKN
+FDAF ; [.1680.0020.0019.FDAF][.15FF.0020.0019.FDAF][.1680.0020.001F.FDAF] # ARABIC LIGATURE YEH WITH JEEM WITH YEH FINAL FORM; QQKN
+FCDB ; [.1680.0020.0017.FCDB][.1605.0020.0017.FCDB] # ARABIC LIGATURE YEH WITH HAH INITIAL FORM; QQKN
+FC56 ; [.1680.0020.001A.FC56][.1605.0020.001A.FC56] # ARABIC LIGATURE YEH WITH HAH ISOLATED FORM; QQKN
+FDAE ; [.1680.0020.0019.FDAE][.1605.0020.0019.FDAE][.1680.0020.001F.FDAE] # ARABIC LIGATURE YEH WITH HAH WITH YEH FINAL FORM; QQKN
+FCDC ; [.1680.0020.0017.FCDC][.1606.0020.0017.FCDC] # ARABIC LIGATURE YEH WITH KHAH INITIAL FORM; QQKN
+FC57 ; [.1680.0020.001A.FC57][.1606.0020.001A.FC57] # ARABIC LIGATURE YEH WITH KHAH ISOLATED FORM; QQKN
+FC91 ; [.1680.0020.0019.FC91][.161A.0020.0019.FC91] # ARABIC LIGATURE YEH WITH REH FINAL FORM; QQKN
+FC92 ; [.1680.0020.0019.FC92][.161B.0020.0019.FC92] # ARABIC LIGATURE YEH WITH ZAIN FINAL FORM; QQKN
+FCDD ; [.1680.0020.0017.FCDD][.1663.0020.0017.FCDD] # ARABIC LIGATURE YEH WITH MEEM INITIAL FORM; QQKN
+FCF0 ; [.1680.0020.0018.FCF0][.1663.0020.0018.FCF0] # ARABIC LIGATURE YEH WITH MEEM MEDIAL FORM; QQKN
+FC93 ; [.1680.0020.0019.FC93][.1663.0020.0019.FC93] # ARABIC LIGATURE YEH WITH MEEM FINAL FORM; QQKN
+FC58 ; [.1680.0020.001A.FC58][.1663.0020.001A.FC58] # ARABIC LIGATURE YEH WITH MEEM ISOLATED FORM; QQKN
+FD9D ; [.1680.0020.0017.FD9D][.1663.0020.0017.FD9D][.1663.0020.001F.FD9D] # ARABIC LIGATURE YEH WITH MEEM WITH MEEM INITIAL FORM; QQKN
+FD9C ; [.1680.0020.0019.FD9C][.1663.0020.0019.FD9C][.1663.0020.001F.FD9C] # ARABIC LIGATURE YEH WITH MEEM WITH MEEM FINAL FORM; QQKN
+FDB0 ; [.1680.0020.0019.FDB0][.1663.0020.0019.FDB0][.1680.0020.001F.FDB0] # ARABIC LIGATURE YEH WITH MEEM WITH YEH FINAL FORM; QQKN
+FC94 ; [.1680.0020.0019.FC94][.1666.0020.0019.FC94] # ARABIC LIGATURE YEH WITH NOON FINAL FORM; QQKN
+FCDE ; [.1680.0020.0017.FCDE][.166F.0020.0017.FCDE] # ARABIC LIGATURE YEH WITH HEH INITIAL FORM; QQKN
+FCF1 ; [.1680.0020.0018.FCF1][.166F.0020.0018.FCF1] # ARABIC LIGATURE YEH WITH HEH MEDIAL FORM; QQKN
+FC95 ; [.1680.0020.0019.FC95][.167F.0020.0019.FC95] # ARABIC LIGATURE YEH WITH ALEF MAKSURA FINAL FORM; QQKN
+FC59 ; [.1680.0020.001A.FC59][.167F.0020.001A.FC59] # ARABIC LIGATURE YEH WITH ALEF MAKSURA ISOLATED FORM; QQKN
+FC96 ; [.1680.0020.0019.FC96][.1680.0020.0019.FC96] # ARABIC LIGATURE YEH WITH YEH FINAL FORM; QQKN
+FC5A ; [.1680.0020.001A.FC5A][.1680.0020.001A.FC5A] # ARABIC LIGATURE YEH WITH YEH ISOLATED FORM; QQKN
+06CC ; [.1681.0020.0002.06CC] # ARABIC LETTER FARSI YEH
+FBFE ; [.1681.0020.0017.FBFE] # ARABIC LETTER FARSI YEH INITIAL FORM; QQK
+FBFF ; [.1681.0020.0018.FBFF] # ARABIC LETTER FARSI YEH MEDIAL FORM; QQK
+FBFD ; [.1681.0020.0019.FBFD] # ARABIC LETTER FARSI YEH FINAL FORM; QQK
+FBFC ; [.1681.0020.001A.FBFC] # ARABIC LETTER FARSI YEH ISOLATED FORM; QQK
+06CD ; [.1682.0020.0002.06CD] # ARABIC LETTER YEH WITH TAIL
+06CE ; [.1683.0020.0002.06CE] # ARABIC LETTER YEH WITH SMALL V
+06D0 ; [.1684.0020.0002.06D0] # ARABIC LETTER E
+FBE6 ; [.1684.0020.0017.FBE6] # ARABIC LETTER E INITIAL FORM; QQK
+FBE7 ; [.1684.0020.0018.FBE7] # ARABIC LETTER E MEDIAL FORM; QQK
+FBE5 ; [.1684.0020.0019.FBE5] # ARABIC LETTER E FINAL FORM; QQK
+FBE4 ; [.1684.0020.001A.FBE4] # ARABIC LETTER E ISOLATED FORM; QQK
+06D1 ; [.1685.0020.0002.06D1] # ARABIC LETTER YEH WITH THREE DOTS BELOW
+06D2 ; [.1686.0020.0002.06D2] # ARABIC LETTER YEH BARREE
+FBAF ; [.1686.0020.0019.FBAF] # ARABIC LETTER YEH BARREE FINAL FORM; QQK
+FBAE ; [.1686.0020.001A.FBAE] # ARABIC LETTER YEH BARREE ISOLATED FORM; QQK
+06D3 ; [.1686.0020.0002.06D2][.0000.00E8.0002.0654] # ARABIC LETTER YEH BARREE WITH HAMZA ABOVE; QQCM
+FBB1 ; [.1686.0020.0019.FBB1][.0000.00E8.0019.FBB1] # ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM; QQKN
+FBB0 ; [.1686.0020.001A.FBB0][.0000.00E8.001A.FBB0] # ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM; QQKN
+0710 ; [.1687.0020.0002.0710] # SYRIAC LETTER ALAPH
+0712 ; [.1688.0020.0002.0712] # SYRIAC LETTER BETH
+072D ; [.1688.0020.0004.072D][.0000.019C.0004.072D] # SYRIAC LETTER PERSIAN BHETH; QQKN
+0713 ; [.1689.0020.0002.0713] # SYRIAC LETTER GAMAL
+0714 ; [.1689.0020.0004.0714][.0000.019A.0004.0714] # SYRIAC LETTER GAMAL GARSHUNI; QQKN
+072E ; [.1689.0020.0004.072E][.0000.019C.0004.072E] # SYRIAC LETTER PERSIAN GHAMAL; QQKN
+0716 ; [.168A.0020.0002.0716] # SYRIAC LETTER DOTLESS DALATH RISH
+0715 ; [.168B.0020.0002.0715] # SYRIAC LETTER DALATH
+072F ; [.168B.0020.0004.072F][.0000.019C.0004.072F] # SYRIAC LETTER PERSIAN DHALATH; QQKN
+0717 ; [.168C.0020.0002.0717] # SYRIAC LETTER HE
+0718 ; [.168D.0020.0002.0718] # SYRIAC LETTER WAW
+0719 ; [.168E.0020.0002.0719] # SYRIAC LETTER ZAIN
+074D ; [.168F.0020.0002.074D] # SYRIAC LETTER SOGDIAN ZHAIN
+071A ; [.1690.0020.0002.071A] # SYRIAC LETTER HETH
+071B ; [.1691.0020.0002.071B] # SYRIAC LETTER TETH
+071C ; [.1691.0020.0004.071C][.0000.019A.0004.071C] # SYRIAC LETTER TETH GARSHUNI; QQKN
+071D ; [.1692.0020.0002.071D] # SYRIAC LETTER YUDH
+071E ; [.1693.0020.0002.071E] # SYRIAC LETTER YUDH HE
+071F ; [.1694.0020.0002.071F] # SYRIAC LETTER KAPH
+074E ; [.1695.0020.0002.074E] # SYRIAC LETTER SOGDIAN KHAPH
+0720 ; [.1696.0020.0002.0720] # SYRIAC LETTER LAMADH
+0721 ; [.1697.0020.0002.0721] # SYRIAC LETTER MIM
+0722 ; [.1698.0020.0002.0722] # SYRIAC LETTER NUN
+0723 ; [.1699.0020.0002.0723] # SYRIAC LETTER SEMKATH
+0724 ; [.1699.0020.0019.0724] # SYRIAC LETTER FINAL SEMKATH; QQK
+0725 ; [.169A.0020.0002.0725] # SYRIAC LETTER E
+0726 ; [.169B.0020.0002.0726] # SYRIAC LETTER PE
+0727 ; [.169B.0020.0004.0727][.0000.019A.0004.0727] # SYRIAC LETTER REVERSED PE; QQKN
+074F ; [.169C.0020.0002.074F] # SYRIAC LETTER SOGDIAN FE
+0728 ; [.169D.0020.0002.0728] # SYRIAC LETTER SADHE
+0729 ; [.169E.0020.0002.0729] # SYRIAC LETTER QAPH
+072A ; [.169F.0020.0002.072A] # SYRIAC LETTER RISH
+072B ; [.16A0.0020.0002.072B] # SYRIAC LETTER SHIN
+072C ; [.16A1.0020.0002.072C] # SYRIAC LETTER TAW
+0780 ; [.16A2.0020.0002.0780] # THAANA LETTER HAA
+0799 ; [.16A3.0020.0002.0799] # THAANA LETTER HHAA
+079A ; [.16A4.0020.0002.079A] # THAANA LETTER KHAA
+0781 ; [.16A5.0020.0002.0781] # THAANA LETTER SHAVIYANI
+0782 ; [.16A6.0020.0002.0782] # THAANA LETTER NOONU
+0783 ; [.16A7.0020.0002.0783] # THAANA LETTER RAA
+079C ; [.16A8.0020.0002.079C] # THAANA LETTER ZAA
+0784 ; [.16A9.0020.0002.0784] # THAANA LETTER BAA
+0785 ; [.16AA.0020.0002.0785] # THAANA LETTER LHAVIYANI
+0786 ; [.16AB.0020.0002.0786] # THAANA LETTER KAAFU
+0787 ; [.16AC.0020.0002.0787] # THAANA LETTER ALIFU
+07A2 ; [.16AD.0020.0002.07A2] # THAANA LETTER AINU
+07A3 ; [.16AE.0020.0002.07A3] # THAANA LETTER GHAINU
+0788 ; [.16AF.0020.0002.0788] # THAANA LETTER VAAVU
+07A5 ; [.16B0.0020.0002.07A5] # THAANA LETTER WAAVU
+0789 ; [.16B1.0020.0002.0789] # THAANA LETTER MEEMU
+078A ; [.16B2.0020.0002.078A] # THAANA LETTER FAAFU
+078B ; [.16B3.0020.0002.078B] # THAANA LETTER DHAALU
+079B ; [.16B4.0020.0002.079B] # THAANA LETTER THAALU
+078C ; [.16B5.0020.0002.078C] # THAANA LETTER THAA
+0798 ; [.16B6.0020.0002.0798] # THAANA LETTER TTAA
+07A0 ; [.16B7.0020.0002.07A0] # THAANA LETTER TO
+07A1 ; [.16B8.0020.0002.07A1] # THAANA LETTER ZO
+078D ; [.16B9.0020.0002.078D] # THAANA LETTER LAAMU
+078E ; [.16BA.0020.0002.078E] # THAANA LETTER GAAFU
+07A4 ; [.16BB.0020.0002.07A4] # THAANA LETTER QAAFU
+078F ; [.16BC.0020.0002.078F] # THAANA LETTER GNAVIYANI
+0790 ; [.16BD.0020.0002.0790] # THAANA LETTER SEENU
+079D ; [.16BE.0020.0002.079D] # THAANA LETTER SHEENU
+079E ; [.16BF.0020.0002.079E] # THAANA LETTER SAADHU
+079F ; [.16C0.0020.0002.079F] # THAANA LETTER DAADHU
+0791 ; [.16C1.0020.0002.0791] # THAANA LETTER DAVIYANI
+0792 ; [.16C2.0020.0002.0792] # THAANA LETTER ZAVIYANI
+0793 ; [.16C3.0020.0002.0793] # THAANA LETTER TAVIYANI
+0794 ; [.16C4.0020.0002.0794] # THAANA LETTER YAA
+0795 ; [.16C5.0020.0002.0795] # THAANA LETTER PAVIYANI
+0796 ; [.16C6.0020.0002.0796] # THAANA LETTER JAVIYANI
+0797 ; [.16C7.0020.0002.0797] # THAANA LETTER CHAVIYANI
+07B1 ; [.16C8.0020.0002.07B1] # THAANA LETTER NAA
+07A6 ; [.16C9.0020.0002.07A6] # THAANA ABAFILI
+07A7 ; [.16CA.0020.0002.07A7] # THAANA AABAAFILI
+07A8 ; [.16CB.0020.0002.07A8] # THAANA IBIFILI
+07A9 ; [.16CC.0020.0002.07A9] # THAANA EEBEEFILI
+07AA ; [.16CD.0020.0002.07AA] # THAANA UBUFILI
+07AB ; [.16CE.0020.0002.07AB] # THAANA OOBOOFILI
+07AC ; [.16CF.0020.0002.07AC] # THAANA EBEFILI
+07AD ; [.16D0.0020.0002.07AD] # THAANA EYBEYFILI
+07AE ; [.16D1.0020.0002.07AE] # THAANA OBOFILI
+07AF ; [.16D2.0020.0002.07AF] # THAANA OABOAFILI
+07B0 ; [.16D3.0020.0002.07B0] # THAANA SUKUN
+07CA ; [.16D4.0020.0002.07CA] # NKO LETTER A
+07CB ; [.16D5.0020.0002.07CB] # NKO LETTER EE
+07CC ; [.16D6.0020.0002.07CC] # NKO LETTER I
+07CD ; [.16D7.0020.0002.07CD] # NKO LETTER E
+07CE ; [.16D8.0020.0002.07CE] # NKO LETTER U
+07CF ; [.16D9.0020.0002.07CF] # NKO LETTER OO
+07D0 ; [.16DA.0020.0002.07D0] # NKO LETTER O
+07D1 ; [.16DB.0020.0002.07D1] # NKO LETTER DAGBASINNA
+07D2 ; [.16DC.0020.0002.07D2] # NKO LETTER N
+07D3 ; [.16DD.0020.0002.07D3] # NKO LETTER BA
+07D4 ; [.16DE.0020.0002.07D4] # NKO LETTER PA
+07D5 ; [.16DF.0020.0002.07D5] # NKO LETTER TA
+07D6 ; [.16E0.0020.0002.07D6] # NKO LETTER JA
+07E8 ; [.16E0.0020.0004.07E8][.0000.0199.0004.07E8] # NKO LETTER JONA JA; QQKN
+07D7 ; [.16E1.0020.0002.07D7] # NKO LETTER CHA
+07E9 ; [.16E1.0020.0004.07E9][.0000.0199.0004.07E9] # NKO LETTER JONA CHA; QQKN
+07D8 ; [.16E2.0020.0002.07D8] # NKO LETTER DA
+07D9 ; [.16E3.0020.0002.07D9] # NKO LETTER RA
+07EA ; [.16E3.0020.0004.07EA][.0000.0199.0004.07EA] # NKO LETTER JONA RA; QQKN
+07DA ; [.16E4.0020.0002.07DA] # NKO LETTER RRA
+07DB ; [.16E5.0020.0002.07DB] # NKO LETTER SA
+07DC ; [.16E6.0020.0002.07DC] # NKO LETTER GBA
+07DD ; [.16E7.0020.0002.07DD] # NKO LETTER FA
+07DE ; [.16E8.0020.0002.07DE] # NKO LETTER KA
+07DF ; [.16E9.0020.0002.07DF] # NKO LETTER LA
+07E0 ; [.16EA.0020.0002.07E0] # NKO LETTER NA WOLOSO
+07E1 ; [.16EB.0020.0002.07E1] # NKO LETTER MA
+07E2 ; [.16EC.0020.0002.07E2] # NKO LETTER NYA
+07E3 ; [.16ED.0020.0002.07E3] # NKO LETTER NA
+07E4 ; [.16EE.0020.0002.07E4] # NKO LETTER HA
+07E5 ; [.16EF.0020.0002.07E5] # NKO LETTER WA
+07E6 ; [.16F0.0020.0002.07E6] # NKO LETTER YA
+07E7 ; [.16F1.0020.0002.07E7] # NKO LETTER NYA WOLOSO
+07F4 ; [.16F2.0020.0002.07F4] # NKO HIGH TONE APOSTROPHE
+07F5 ; [.16F3.0020.0002.07F5] # NKO LOW TONE APOSTROPHE
+2D30 ; [.16F4.0020.0002.2D30] # TIFINAGH LETTER YA
+2D31 ; [.16F5.0020.0002.2D31] # TIFINAGH LETTER YAB
+2D32 ; [.16F6.0020.0002.2D32] # TIFINAGH LETTER YABH
+2D33 ; [.16F7.0020.0002.2D33] # TIFINAGH LETTER YAG
+2D34 ; [.16F8.0020.0002.2D34] # TIFINAGH LETTER YAGHH
+2D35 ; [.16F9.0020.0002.2D35] # TIFINAGH LETTER BERBER ACADEMY YAJ
+2D36 ; [.16FA.0020.0002.2D36] # TIFINAGH LETTER YAJ
+2D37 ; [.16FB.0020.0002.2D37] # TIFINAGH LETTER YAD
+2D38 ; [.16FC.0020.0002.2D38] # TIFINAGH LETTER YADH
+2D39 ; [.16FD.0020.0002.2D39] # TIFINAGH LETTER YADD
+2D3A ; [.16FE.0020.0002.2D3A] # TIFINAGH LETTER YADDH
+2D3B ; [.16FF.0020.0002.2D3B] # TIFINAGH LETTER YEY
+2D3C ; [.1700.0020.0002.2D3C] # TIFINAGH LETTER YAF
+2D3D ; [.1701.0020.0002.2D3D] # TIFINAGH LETTER YAK
+2D3E ; [.1702.0020.0002.2D3E] # TIFINAGH LETTER TUAREG YAK
+2D3F ; [.1703.0020.0002.2D3F] # TIFINAGH LETTER YAKHH
+2D40 ; [.1704.0020.0002.2D40] # TIFINAGH LETTER YAH
+2D41 ; [.1705.0020.0002.2D41] # TIFINAGH LETTER BERBER ACADEMY YAH
+2D42 ; [.1706.0020.0002.2D42] # TIFINAGH LETTER TUAREG YAH
+2D43 ; [.1707.0020.0002.2D43] # TIFINAGH LETTER YAHH
+2D44 ; [.1708.0020.0002.2D44] # TIFINAGH LETTER YAA
+2D45 ; [.1709.0020.0002.2D45] # TIFINAGH LETTER YAKH
+2D46 ; [.170A.0020.0002.2D46] # TIFINAGH LETTER TUAREG YAKH
+2D47 ; [.170B.0020.0002.2D47] # TIFINAGH LETTER YAQ
+2D48 ; [.170C.0020.0002.2D48] # TIFINAGH LETTER TUAREG YAQ
+2D49 ; [.170D.0020.0002.2D49] # TIFINAGH LETTER YI
+2D4A ; [.170E.0020.0002.2D4A] # TIFINAGH LETTER YAZH
+2D4B ; [.170F.0020.0002.2D4B] # TIFINAGH LETTER AHAGGAR YAZH
+2D4C ; [.1710.0020.0002.2D4C] # TIFINAGH LETTER TUAREG YAZH
+2D4D ; [.1711.0020.0002.2D4D] # TIFINAGH LETTER YAL
+2D4E ; [.1712.0020.0002.2D4E] # TIFINAGH LETTER YAM
+2D4F ; [.1713.0020.0002.2D4F] # TIFINAGH LETTER YAN
+2D50 ; [.1714.0020.0002.2D50] # TIFINAGH LETTER TUAREG YAGN
+2D51 ; [.1715.0020.0002.2D51] # TIFINAGH LETTER TUAREG YANG
+2D52 ; [.1716.0020.0002.2D52] # TIFINAGH LETTER YAP
+2D53 ; [.1717.0020.0002.2D53] # TIFINAGH LETTER YU
+2D54 ; [.1718.0020.0002.2D54] # TIFINAGH LETTER YAR
+2D55 ; [.1719.0020.0002.2D55] # TIFINAGH LETTER YARR
+2D56 ; [.171A.0020.0002.2D56] # TIFINAGH LETTER YAGH
+2D57 ; [.171B.0020.0002.2D57] # TIFINAGH LETTER TUAREG YAGH
+2D58 ; [.171C.0020.0002.2D58] # TIFINAGH LETTER AYER YAGH
+2D59 ; [.171D.0020.0002.2D59] # TIFINAGH LETTER YAS
+2D5A ; [.171E.0020.0002.2D5A] # TIFINAGH LETTER YASS
+2D5B ; [.171F.0020.0002.2D5B] # TIFINAGH LETTER YASH
+2D5C ; [.1720.0020.0002.2D5C] # TIFINAGH LETTER YAT
+2D5D ; [.1721.0020.0002.2D5D] # TIFINAGH LETTER YATH
+2D5E ; [.1722.0020.0002.2D5E] # TIFINAGH LETTER YACH
+2D5F ; [.1723.0020.0002.2D5F] # TIFINAGH LETTER YATT
+2D60 ; [.1724.0020.0002.2D60] # TIFINAGH LETTER YAV
+2D61 ; [.1725.0020.0002.2D61] # TIFINAGH LETTER YAW
+2D62 ; [.1726.0020.0002.2D62] # TIFINAGH LETTER YAY
+2D63 ; [.1727.0020.0002.2D63] # TIFINAGH LETTER YAZ
+2D64 ; [.1728.0020.0002.2D64] # TIFINAGH LETTER TAWELLEMET YAZ
+2D65 ; [.1729.0020.0002.2D65] # TIFINAGH LETTER YAZZ
+2D6F ; [.172A.0020.0002.2D6F] # TIFINAGH MODIFIER LETTER LABIALIZATION MARK
+1200 ; [.172B.0020.0002.1200] # ETHIOPIC SYLLABLE HA
+1201 ; [.172C.0020.0002.1201] # ETHIOPIC SYLLABLE HU
+1202 ; [.172D.0020.0002.1202] # ETHIOPIC SYLLABLE HI
+1203 ; [.172E.0020.0002.1203] # ETHIOPIC SYLLABLE HAA
+1204 ; [.172F.0020.0002.1204] # ETHIOPIC SYLLABLE HEE
+1205 ; [.1730.0020.0002.1205] # ETHIOPIC SYLLABLE HE
+1206 ; [.1731.0020.0002.1206] # ETHIOPIC SYLLABLE HO
+1207 ; [.1732.0020.0002.1207] # ETHIOPIC SYLLABLE HOA
+1208 ; [.1733.0020.0002.1208] # ETHIOPIC SYLLABLE LA
+1209 ; [.1734.0020.0002.1209] # ETHIOPIC SYLLABLE LU
+120A ; [.1735.0020.0002.120A] # ETHIOPIC SYLLABLE LI
+120B ; [.1736.0020.0002.120B] # ETHIOPIC SYLLABLE LAA
+120C ; [.1737.0020.0002.120C] # ETHIOPIC SYLLABLE LEE
+120D ; [.1738.0020.0002.120D] # ETHIOPIC SYLLABLE LE
+120E ; [.1739.0020.0002.120E] # ETHIOPIC SYLLABLE LO
+120F ; [.173A.0020.0002.120F] # ETHIOPIC SYLLABLE LWA
+2D80 ; [.173B.0020.0002.2D80] # ETHIOPIC SYLLABLE LOA
+1210 ; [.173C.0020.0002.1210] # ETHIOPIC SYLLABLE HHA
+1211 ; [.173D.0020.0002.1211] # ETHIOPIC SYLLABLE HHU
+1212 ; [.173E.0020.0002.1212] # ETHIOPIC SYLLABLE HHI
+1213 ; [.173F.0020.0002.1213] # ETHIOPIC SYLLABLE HHAA
+1214 ; [.1740.0020.0002.1214] # ETHIOPIC SYLLABLE HHEE
+1215 ; [.1741.0020.0002.1215] # ETHIOPIC SYLLABLE HHE
+1216 ; [.1742.0020.0002.1216] # ETHIOPIC SYLLABLE HHO
+1217 ; [.1743.0020.0002.1217] # ETHIOPIC SYLLABLE HHWA
+1218 ; [.1744.0020.0002.1218] # ETHIOPIC SYLLABLE MA
+1219 ; [.1745.0020.0002.1219] # ETHIOPIC SYLLABLE MU
+121A ; [.1746.0020.0002.121A] # ETHIOPIC SYLLABLE MI
+121B ; [.1747.0020.0002.121B] # ETHIOPIC SYLLABLE MAA
+121C ; [.1748.0020.0002.121C] # ETHIOPIC SYLLABLE MEE
+121D ; [.1749.0020.0002.121D] # ETHIOPIC SYLLABLE ME
+121E ; [.174A.0020.0002.121E] # ETHIOPIC SYLLABLE MO
+121F ; [.174B.0020.0002.121F] # ETHIOPIC SYLLABLE MWA
+1380 ; [.174C.0020.0002.1380] # ETHIOPIC SYLLABLE SEBATBEIT MWA
+1381 ; [.174D.0020.0002.1381] # ETHIOPIC SYLLABLE MWI
+1382 ; [.174E.0020.0002.1382] # ETHIOPIC SYLLABLE MWEE
+1383 ; [.174F.0020.0002.1383] # ETHIOPIC SYLLABLE MWE
+2D81 ; [.1750.0020.0002.2D81] # ETHIOPIC SYLLABLE MOA
+1220 ; [.1751.0020.0002.1220] # ETHIOPIC SYLLABLE SZA
+1221 ; [.1752.0020.0002.1221] # ETHIOPIC SYLLABLE SZU
+1222 ; [.1753.0020.0002.1222] # ETHIOPIC SYLLABLE SZI
+1223 ; [.1754.0020.0002.1223] # ETHIOPIC SYLLABLE SZAA
+1224 ; [.1755.0020.0002.1224] # ETHIOPIC SYLLABLE SZEE
+1225 ; [.1756.0020.0002.1225] # ETHIOPIC SYLLABLE SZE
+1226 ; [.1757.0020.0002.1226] # ETHIOPIC SYLLABLE SZO
+1227 ; [.1758.0020.0002.1227] # ETHIOPIC SYLLABLE SZWA
+1228 ; [.1759.0020.0002.1228] # ETHIOPIC SYLLABLE RA
+1229 ; [.175A.0020.0002.1229] # ETHIOPIC SYLLABLE RU
+122A ; [.175B.0020.0002.122A] # ETHIOPIC SYLLABLE RI
+122B ; [.175C.0020.0002.122B] # ETHIOPIC SYLLABLE RAA
+122C ; [.175D.0020.0002.122C] # ETHIOPIC SYLLABLE REE
+122D ; [.175E.0020.0002.122D] # ETHIOPIC SYLLABLE RE
+122E ; [.175F.0020.0002.122E] # ETHIOPIC SYLLABLE RO
+122F ; [.1760.0020.0002.122F] # ETHIOPIC SYLLABLE RWA
+2D82 ; [.1761.0020.0002.2D82] # ETHIOPIC SYLLABLE ROA
+1230 ; [.1762.0020.0002.1230] # ETHIOPIC SYLLABLE SA
+1231 ; [.1763.0020.0002.1231] # ETHIOPIC SYLLABLE SU
+1232 ; [.1764.0020.0002.1232] # ETHIOPIC SYLLABLE SI
+1233 ; [.1765.0020.0002.1233] # ETHIOPIC SYLLABLE SAA
+1234 ; [.1766.0020.0002.1234] # ETHIOPIC SYLLABLE SEE
+1235 ; [.1767.0020.0002.1235] # ETHIOPIC SYLLABLE SE
+1236 ; [.1768.0020.0002.1236] # ETHIOPIC SYLLABLE SO
+1237 ; [.1769.0020.0002.1237] # ETHIOPIC SYLLABLE SWA
+2D83 ; [.176A.0020.0002.2D83] # ETHIOPIC SYLLABLE SOA
+1238 ; [.176B.0020.0002.1238] # ETHIOPIC SYLLABLE SHA
+1239 ; [.176C.0020.0002.1239] # ETHIOPIC SYLLABLE SHU
+123A ; [.176D.0020.0002.123A] # ETHIOPIC SYLLABLE SHI
+123B ; [.176E.0020.0002.123B] # ETHIOPIC SYLLABLE SHAA
+123C ; [.176F.0020.0002.123C] # ETHIOPIC SYLLABLE SHEE
+123D ; [.1770.0020.0002.123D] # ETHIOPIC SYLLABLE SHE
+123E ; [.1771.0020.0002.123E] # ETHIOPIC SYLLABLE SHO
+123F ; [.1772.0020.0002.123F] # ETHIOPIC SYLLABLE SHWA
+2D84 ; [.1773.0020.0002.2D84] # ETHIOPIC SYLLABLE SHOA
+1240 ; [.1774.0020.0002.1240] # ETHIOPIC SYLLABLE QA
+1241 ; [.1775.0020.0002.1241] # ETHIOPIC SYLLABLE QU
+1242 ; [.1776.0020.0002.1242] # ETHIOPIC SYLLABLE QI
+1243 ; [.1777.0020.0002.1243] # ETHIOPIC SYLLABLE QAA
+1244 ; [.1778.0020.0002.1244] # ETHIOPIC SYLLABLE QEE
+1245 ; [.1779.0020.0002.1245] # ETHIOPIC SYLLABLE QE
+1246 ; [.177A.0020.0002.1246] # ETHIOPIC SYLLABLE QO
+1247 ; [.177B.0020.0002.1247] # ETHIOPIC SYLLABLE QOA
+1248 ; [.177C.0020.0002.1248] # ETHIOPIC SYLLABLE QWA
+124A ; [.177D.0020.0002.124A] # ETHIOPIC SYLLABLE QWI
+124B ; [.177E.0020.0002.124B] # ETHIOPIC SYLLABLE QWAA
+124C ; [.177F.0020.0002.124C] # ETHIOPIC SYLLABLE QWEE
+124D ; [.1780.0020.0002.124D] # ETHIOPIC SYLLABLE QWE
+1250 ; [.1781.0020.0002.1250] # ETHIOPIC SYLLABLE QHA
+1251 ; [.1782.0020.0002.1251] # ETHIOPIC SYLLABLE QHU
+1252 ; [.1783.0020.0002.1252] # ETHIOPIC SYLLABLE QHI
+1253 ; [.1784.0020.0002.1253] # ETHIOPIC SYLLABLE QHAA
+1254 ; [.1785.0020.0002.1254] # ETHIOPIC SYLLABLE QHEE
+1255 ; [.1786.0020.0002.1255] # ETHIOPIC SYLLABLE QHE
+1256 ; [.1787.0020.0002.1256] # ETHIOPIC SYLLABLE QHO
+1258 ; [.1788.0020.0002.1258] # ETHIOPIC SYLLABLE QHWA
+125A ; [.1789.0020.0002.125A] # ETHIOPIC SYLLABLE QHWI
+125B ; [.178A.0020.0002.125B] # ETHIOPIC SYLLABLE QHWAA
+125C ; [.178B.0020.0002.125C] # ETHIOPIC SYLLABLE QHWEE
+125D ; [.178C.0020.0002.125D] # ETHIOPIC SYLLABLE QHWE
+1260 ; [.178D.0020.0002.1260] # ETHIOPIC SYLLABLE BA
+1261 ; [.178E.0020.0002.1261] # ETHIOPIC SYLLABLE BU
+1262 ; [.178F.0020.0002.1262] # ETHIOPIC SYLLABLE BI
+1263 ; [.1790.0020.0002.1263] # ETHIOPIC SYLLABLE BAA
+1264 ; [.1791.0020.0002.1264] # ETHIOPIC SYLLABLE BEE
+1265 ; [.1792.0020.0002.1265] # ETHIOPIC SYLLABLE BE
+1266 ; [.1793.0020.0002.1266] # ETHIOPIC SYLLABLE BO
+1267 ; [.1794.0020.0002.1267] # ETHIOPIC SYLLABLE BWA
+1384 ; [.1795.0020.0002.1384] # ETHIOPIC SYLLABLE SEBATBEIT BWA
+1385 ; [.1796.0020.0002.1385] # ETHIOPIC SYLLABLE BWI
+1386 ; [.1797.0020.0002.1386] # ETHIOPIC SYLLABLE BWEE
+1387 ; [.1798.0020.0002.1387] # ETHIOPIC SYLLABLE BWE
+2D85 ; [.1799.0020.0002.2D85] # ETHIOPIC SYLLABLE BOA
+1268 ; [.179A.0020.0002.1268] # ETHIOPIC SYLLABLE VA
+1269 ; [.179B.0020.0002.1269] # ETHIOPIC SYLLABLE VU
+126A ; [.179C.0020.0002.126A] # ETHIOPIC SYLLABLE VI
+126B ; [.179D.0020.0002.126B] # ETHIOPIC SYLLABLE VAA
+126C ; [.179E.0020.0002.126C] # ETHIOPIC SYLLABLE VEE
+126D ; [.179F.0020.0002.126D] # ETHIOPIC SYLLABLE VE
+126E ; [.17A0.0020.0002.126E] # ETHIOPIC SYLLABLE VO
+126F ; [.17A1.0020.0002.126F] # ETHIOPIC SYLLABLE VWA
+1270 ; [.17A2.0020.0002.1270] # ETHIOPIC SYLLABLE TA
+1271 ; [.17A3.0020.0002.1271] # ETHIOPIC SYLLABLE TU
+1272 ; [.17A4.0020.0002.1272] # ETHIOPIC SYLLABLE TI
+1273 ; [.17A5.0020.0002.1273] # ETHIOPIC SYLLABLE TAA
+1274 ; [.17A6.0020.0002.1274] # ETHIOPIC SYLLABLE TEE
+1275 ; [.17A7.0020.0002.1275] # ETHIOPIC SYLLABLE TE
+1276 ; [.17A8.0020.0002.1276] # ETHIOPIC SYLLABLE TO
+1277 ; [.17A9.0020.0002.1277] # ETHIOPIC SYLLABLE TWA
+2D86 ; [.17AA.0020.0002.2D86] # ETHIOPIC SYLLABLE TOA
+1278 ; [.17AB.0020.0002.1278] # ETHIOPIC SYLLABLE CA
+1279 ; [.17AC.0020.0002.1279] # ETHIOPIC SYLLABLE CU
+127A ; [.17AD.0020.0002.127A] # ETHIOPIC SYLLABLE CI
+127B ; [.17AE.0020.0002.127B] # ETHIOPIC SYLLABLE CAA
+127C ; [.17AF.0020.0002.127C] # ETHIOPIC SYLLABLE CEE
+127D ; [.17B0.0020.0002.127D] # ETHIOPIC SYLLABLE CE
+127E ; [.17B1.0020.0002.127E] # ETHIOPIC SYLLABLE CO
+127F ; [.17B2.0020.0002.127F] # ETHIOPIC SYLLABLE CWA
+2D87 ; [.17B3.0020.0002.2D87] # ETHIOPIC SYLLABLE COA
+1280 ; [.17B4.0020.0002.1280] # ETHIOPIC SYLLABLE XA
+1281 ; [.17B5.0020.0002.1281] # ETHIOPIC SYLLABLE XU
+1282 ; [.17B6.0020.0002.1282] # ETHIOPIC SYLLABLE XI
+1283 ; [.17B7.0020.0002.1283] # ETHIOPIC SYLLABLE XAA
+1284 ; [.17B8.0020.0002.1284] # ETHIOPIC SYLLABLE XEE
+1285 ; [.17B9.0020.0002.1285] # ETHIOPIC SYLLABLE XE
+1286 ; [.17BA.0020.0002.1286] # ETHIOPIC SYLLABLE XO
+1287 ; [.17BB.0020.0002.1287] # ETHIOPIC SYLLABLE XOA
+1288 ; [.17BC.0020.0002.1288] # ETHIOPIC SYLLABLE XWA
+128A ; [.17BD.0020.0002.128A] # ETHIOPIC SYLLABLE XWI
+128B ; [.17BE.0020.0002.128B] # ETHIOPIC SYLLABLE XWAA
+128C ; [.17BF.0020.0002.128C] # ETHIOPIC SYLLABLE XWEE
+128D ; [.17C0.0020.0002.128D] # ETHIOPIC SYLLABLE XWE
+1290 ; [.17C1.0020.0002.1290] # ETHIOPIC SYLLABLE NA
+1291 ; [.17C2.0020.0002.1291] # ETHIOPIC SYLLABLE NU
+1292 ; [.17C3.0020.0002.1292] # ETHIOPIC SYLLABLE NI
+1293 ; [.17C4.0020.0002.1293] # ETHIOPIC SYLLABLE NAA
+1294 ; [.17C5.0020.0002.1294] # ETHIOPIC SYLLABLE NEE
+1295 ; [.17C6.0020.0002.1295] # ETHIOPIC SYLLABLE NE
+1296 ; [.17C7.0020.0002.1296] # ETHIOPIC SYLLABLE NO
+1297 ; [.17C8.0020.0002.1297] # ETHIOPIC SYLLABLE NWA
+2D88 ; [.17C9.0020.0002.2D88] # ETHIOPIC SYLLABLE NOA
+1298 ; [.17CA.0020.0002.1298] # ETHIOPIC SYLLABLE NYA
+1299 ; [.17CB.0020.0002.1299] # ETHIOPIC SYLLABLE NYU
+129A ; [.17CC.0020.0002.129A] # ETHIOPIC SYLLABLE NYI
+129B ; [.17CD.0020.0002.129B] # ETHIOPIC SYLLABLE NYAA
+129C ; [.17CE.0020.0002.129C] # ETHIOPIC SYLLABLE NYEE
+129D ; [.17CF.0020.0002.129D] # ETHIOPIC SYLLABLE NYE
+129E ; [.17D0.0020.0002.129E] # ETHIOPIC SYLLABLE NYO
+129F ; [.17D1.0020.0002.129F] # ETHIOPIC SYLLABLE NYWA
+2D89 ; [.17D2.0020.0002.2D89] # ETHIOPIC SYLLABLE NYOA
+12A0 ; [.17D3.0020.0002.12A0] # ETHIOPIC SYLLABLE GLOTTAL A
+12A1 ; [.17D4.0020.0002.12A1] # ETHIOPIC SYLLABLE GLOTTAL U
+12A2 ; [.17D5.0020.0002.12A2] # ETHIOPIC SYLLABLE GLOTTAL I
+12A3 ; [.17D6.0020.0002.12A3] # ETHIOPIC SYLLABLE GLOTTAL AA
+12A4 ; [.17D7.0020.0002.12A4] # ETHIOPIC SYLLABLE GLOTTAL EE
+12A5 ; [.17D8.0020.0002.12A5] # ETHIOPIC SYLLABLE GLOTTAL E
+12A6 ; [.17D9.0020.0002.12A6] # ETHIOPIC SYLLABLE GLOTTAL O
+12A7 ; [.17DA.0020.0002.12A7] # ETHIOPIC SYLLABLE GLOTTAL WA
+2D8A ; [.17DB.0020.0002.2D8A] # ETHIOPIC SYLLABLE GLOTTAL OA
+12A8 ; [.17DC.0020.0002.12A8] # ETHIOPIC SYLLABLE KA
+12A9 ; [.17DD.0020.0002.12A9] # ETHIOPIC SYLLABLE KU
+12AA ; [.17DE.0020.0002.12AA] # ETHIOPIC SYLLABLE KI
+12AB ; [.17DF.0020.0002.12AB] # ETHIOPIC SYLLABLE KAA
+12AC ; [.17E0.0020.0002.12AC] # ETHIOPIC SYLLABLE KEE
+12AD ; [.17E1.0020.0002.12AD] # ETHIOPIC SYLLABLE KE
+12AE ; [.17E2.0020.0002.12AE] # ETHIOPIC SYLLABLE KO
+12AF ; [.17E3.0020.0002.12AF] # ETHIOPIC SYLLABLE KOA
+12B0 ; [.17E4.0020.0002.12B0] # ETHIOPIC SYLLABLE KWA
+12B2 ; [.17E5.0020.0002.12B2] # ETHIOPIC SYLLABLE KWI
+12B3 ; [.17E6.0020.0002.12B3] # ETHIOPIC SYLLABLE KWAA
+12B4 ; [.17E7.0020.0002.12B4] # ETHIOPIC SYLLABLE KWEE
+12B5 ; [.17E8.0020.0002.12B5] # ETHIOPIC SYLLABLE KWE
+12B8 ; [.17E9.0020.0002.12B8] # ETHIOPIC SYLLABLE KXA
+12B9 ; [.17EA.0020.0002.12B9] # ETHIOPIC SYLLABLE KXU
+12BA ; [.17EB.0020.0002.12BA] # ETHIOPIC SYLLABLE KXI
+12BB ; [.17EC.0020.0002.12BB] # ETHIOPIC SYLLABLE KXAA
+12BC ; [.17ED.0020.0002.12BC] # ETHIOPIC SYLLABLE KXEE
+12BD ; [.17EE.0020.0002.12BD] # ETHIOPIC SYLLABLE KXE
+12BE ; [.17EF.0020.0002.12BE] # ETHIOPIC SYLLABLE KXO
+12C0 ; [.17F0.0020.0002.12C0] # ETHIOPIC SYLLABLE KXWA
+12C2 ; [.17F1.0020.0002.12C2] # ETHIOPIC SYLLABLE KXWI
+12C3 ; [.17F2.0020.0002.12C3] # ETHIOPIC SYLLABLE KXWAA
+12C4 ; [.17F3.0020.0002.12C4] # ETHIOPIC SYLLABLE KXWEE
+12C5 ; [.17F4.0020.0002.12C5] # ETHIOPIC SYLLABLE KXWE
+12C8 ; [.17F5.0020.0002.12C8] # ETHIOPIC SYLLABLE WA
+12C9 ; [.17F6.0020.0002.12C9] # ETHIOPIC SYLLABLE WU
+12CA ; [.17F7.0020.0002.12CA] # ETHIOPIC SYLLABLE WI
+12CB ; [.17F8.0020.0002.12CB] # ETHIOPIC SYLLABLE WAA
+12CC ; [.17F9.0020.0002.12CC] # ETHIOPIC SYLLABLE WEE
+12CD ; [.17FA.0020.0002.12CD] # ETHIOPIC SYLLABLE WE
+12CE ; [.17FB.0020.0002.12CE] # ETHIOPIC SYLLABLE WO
+12CF ; [.17FC.0020.0002.12CF] # ETHIOPIC SYLLABLE WOA
+12D0 ; [.17FD.0020.0002.12D0] # ETHIOPIC SYLLABLE PHARYNGEAL A
+12D1 ; [.17FE.0020.0002.12D1] # ETHIOPIC SYLLABLE PHARYNGEAL U
+12D2 ; [.17FF.0020.0002.12D2] # ETHIOPIC SYLLABLE PHARYNGEAL I
+12D3 ; [.1800.0020.0002.12D3] # ETHIOPIC SYLLABLE PHARYNGEAL AA
+12D4 ; [.1801.0020.0002.12D4] # ETHIOPIC SYLLABLE PHARYNGEAL EE
+12D5 ; [.1802.0020.0002.12D5] # ETHIOPIC SYLLABLE PHARYNGEAL E
+12D6 ; [.1803.0020.0002.12D6] # ETHIOPIC SYLLABLE PHARYNGEAL O
+12D8 ; [.1804.0020.0002.12D8] # ETHIOPIC SYLLABLE ZA
+12D9 ; [.1805.0020.0002.12D9] # ETHIOPIC SYLLABLE ZU
+12DA ; [.1806.0020.0002.12DA] # ETHIOPIC SYLLABLE ZI
+12DB ; [.1807.0020.0002.12DB] # ETHIOPIC SYLLABLE ZAA
+12DC ; [.1808.0020.0002.12DC] # ETHIOPIC SYLLABLE ZEE
+12DD ; [.1809.0020.0002.12DD] # ETHIOPIC SYLLABLE ZE
+12DE ; [.180A.0020.0002.12DE] # ETHIOPIC SYLLABLE ZO
+12DF ; [.180B.0020.0002.12DF] # ETHIOPIC SYLLABLE ZWA
+2D8B ; [.180C.0020.0002.2D8B] # ETHIOPIC SYLLABLE ZOA
+12E0 ; [.180D.0020.0002.12E0] # ETHIOPIC SYLLABLE ZHA
+12E1 ; [.180E.0020.0002.12E1] # ETHIOPIC SYLLABLE ZHU
+12E2 ; [.180F.0020.0002.12E2] # ETHIOPIC SYLLABLE ZHI
+12E3 ; [.1810.0020.0002.12E3] # ETHIOPIC SYLLABLE ZHAA
+12E4 ; [.1811.0020.0002.12E4] # ETHIOPIC SYLLABLE ZHEE
+12E5 ; [.1812.0020.0002.12E5] # ETHIOPIC SYLLABLE ZHE
+12E6 ; [.1813.0020.0002.12E6] # ETHIOPIC SYLLABLE ZHO
+12E7 ; [.1814.0020.0002.12E7] # ETHIOPIC SYLLABLE ZHWA
+12E8 ; [.1815.0020.0002.12E8] # ETHIOPIC SYLLABLE YA
+12E9 ; [.1816.0020.0002.12E9] # ETHIOPIC SYLLABLE YU
+12EA ; [.1817.0020.0002.12EA] # ETHIOPIC SYLLABLE YI
+12EB ; [.1818.0020.0002.12EB] # ETHIOPIC SYLLABLE YAA
+12EC ; [.1819.0020.0002.12EC] # ETHIOPIC SYLLABLE YEE
+12ED ; [.181A.0020.0002.12ED] # ETHIOPIC SYLLABLE YE
+12EE ; [.181B.0020.0002.12EE] # ETHIOPIC SYLLABLE YO
+12EF ; [.181C.0020.0002.12EF] # ETHIOPIC SYLLABLE YOA
+12F0 ; [.181D.0020.0002.12F0] # ETHIOPIC SYLLABLE DA
+12F1 ; [.181E.0020.0002.12F1] # ETHIOPIC SYLLABLE DU
+12F2 ; [.181F.0020.0002.12F2] # ETHIOPIC SYLLABLE DI
+12F3 ; [.1820.0020.0002.12F3] # ETHIOPIC SYLLABLE DAA
+12F4 ; [.1821.0020.0002.12F4] # ETHIOPIC SYLLABLE DEE
+12F5 ; [.1822.0020.0002.12F5] # ETHIOPIC SYLLABLE DE
+12F6 ; [.1823.0020.0002.12F6] # ETHIOPIC SYLLABLE DO
+12F7 ; [.1824.0020.0002.12F7] # ETHIOPIC SYLLABLE DWA
+2D8C ; [.1825.0020.0002.2D8C] # ETHIOPIC SYLLABLE DOA
+12F8 ; [.1826.0020.0002.12F8] # ETHIOPIC SYLLABLE DDA
+12F9 ; [.1827.0020.0002.12F9] # ETHIOPIC SYLLABLE DDU
+12FA ; [.1828.0020.0002.12FA] # ETHIOPIC SYLLABLE DDI
+12FB ; [.1829.0020.0002.12FB] # ETHIOPIC SYLLABLE DDAA
+12FC ; [.182A.0020.0002.12FC] # ETHIOPIC SYLLABLE DDEE
+12FD ; [.182B.0020.0002.12FD] # ETHIOPIC SYLLABLE DDE
+12FE ; [.182C.0020.0002.12FE] # ETHIOPIC SYLLABLE DDO
+12FF ; [.182D.0020.0002.12FF] # ETHIOPIC SYLLABLE DDWA
+2D8D ; [.182E.0020.0002.2D8D] # ETHIOPIC SYLLABLE DDOA
+1300 ; [.182F.0020.0002.1300] # ETHIOPIC SYLLABLE JA
+1301 ; [.1830.0020.0002.1301] # ETHIOPIC SYLLABLE JU
+1302 ; [.1831.0020.0002.1302] # ETHIOPIC SYLLABLE JI
+1303 ; [.1832.0020.0002.1303] # ETHIOPIC SYLLABLE JAA
+1304 ; [.1833.0020.0002.1304] # ETHIOPIC SYLLABLE JEE
+1305 ; [.1834.0020.0002.1305] # ETHIOPIC SYLLABLE JE
+1306 ; [.1835.0020.0002.1306] # ETHIOPIC SYLLABLE JO
+1307 ; [.1836.0020.0002.1307] # ETHIOPIC SYLLABLE JWA
+2D8E ; [.1837.0020.0002.2D8E] # ETHIOPIC SYLLABLE JOA
+1308 ; [.1838.0020.0002.1308] # ETHIOPIC SYLLABLE GA
+1309 ; [.1839.0020.0002.1309] # ETHIOPIC SYLLABLE GU
+130A ; [.183A.0020.0002.130A] # ETHIOPIC SYLLABLE GI
+130B ; [.183B.0020.0002.130B] # ETHIOPIC SYLLABLE GAA
+130C ; [.183C.0020.0002.130C] # ETHIOPIC SYLLABLE GEE
+130D ; [.183D.0020.0002.130D] # ETHIOPIC SYLLABLE GE
+130E ; [.183E.0020.0002.130E] # ETHIOPIC SYLLABLE GO
+130F ; [.183F.0020.0002.130F] # ETHIOPIC SYLLABLE GOA
+1310 ; [.1840.0020.0002.1310] # ETHIOPIC SYLLABLE GWA
+1312 ; [.1841.0020.0002.1312] # ETHIOPIC SYLLABLE GWI
+1313 ; [.1842.0020.0002.1313] # ETHIOPIC SYLLABLE GWAA
+1314 ; [.1843.0020.0002.1314] # ETHIOPIC SYLLABLE GWEE
+1315 ; [.1844.0020.0002.1315] # ETHIOPIC SYLLABLE GWE
+1318 ; [.1845.0020.0002.1318] # ETHIOPIC SYLLABLE GGA
+1319 ; [.1846.0020.0002.1319] # ETHIOPIC SYLLABLE GGU
+131A ; [.1847.0020.0002.131A] # ETHIOPIC SYLLABLE GGI
+131B ; [.1848.0020.0002.131B] # ETHIOPIC SYLLABLE GGAA
+131C ; [.1849.0020.0002.131C] # ETHIOPIC SYLLABLE GGEE
+131D ; [.184A.0020.0002.131D] # ETHIOPIC SYLLABLE GGE
+131E ; [.184B.0020.0002.131E] # ETHIOPIC SYLLABLE GGO
+131F ; [.184C.0020.0002.131F] # ETHIOPIC SYLLABLE GGWAA
+2D93 ; [.184D.0020.0002.2D93] # ETHIOPIC SYLLABLE GGWA
+2D94 ; [.184E.0020.0002.2D94] # ETHIOPIC SYLLABLE GGWI
+2D95 ; [.184F.0020.0002.2D95] # ETHIOPIC SYLLABLE GGWEE
+2D96 ; [.1850.0020.0002.2D96] # ETHIOPIC SYLLABLE GGWE
+1320 ; [.1851.0020.0002.1320] # ETHIOPIC SYLLABLE THA
+1321 ; [.1852.0020.0002.1321] # ETHIOPIC SYLLABLE THU
+1322 ; [.1853.0020.0002.1322] # ETHIOPIC SYLLABLE THI
+1323 ; [.1854.0020.0002.1323] # ETHIOPIC SYLLABLE THAA
+1324 ; [.1855.0020.0002.1324] # ETHIOPIC SYLLABLE THEE
+1325 ; [.1856.0020.0002.1325] # ETHIOPIC SYLLABLE THE
+1326 ; [.1857.0020.0002.1326] # ETHIOPIC SYLLABLE THO
+1327 ; [.1858.0020.0002.1327] # ETHIOPIC SYLLABLE THWA
+2D8F ; [.1859.0020.0002.2D8F] # ETHIOPIC SYLLABLE THOA
+1328 ; [.185A.0020.0002.1328] # ETHIOPIC SYLLABLE CHA
+1329 ; [.185B.0020.0002.1329] # ETHIOPIC SYLLABLE CHU
+132A ; [.185C.0020.0002.132A] # ETHIOPIC SYLLABLE CHI
+132B ; [.185D.0020.0002.132B] # ETHIOPIC SYLLABLE CHAA
+132C ; [.185E.0020.0002.132C] # ETHIOPIC SYLLABLE CHEE
+132D ; [.185F.0020.0002.132D] # ETHIOPIC SYLLABLE CHE
+132E ; [.1860.0020.0002.132E] # ETHIOPIC SYLLABLE CHO
+132F ; [.1861.0020.0002.132F] # ETHIOPIC SYLLABLE CHWA
+2D90 ; [.1862.0020.0002.2D90] # ETHIOPIC SYLLABLE CHOA
+1330 ; [.1863.0020.0002.1330] # ETHIOPIC SYLLABLE PHA
+1331 ; [.1864.0020.0002.1331] # ETHIOPIC SYLLABLE PHU
+1332 ; [.1865.0020.0002.1332] # ETHIOPIC SYLLABLE PHI
+1333 ; [.1866.0020.0002.1333] # ETHIOPIC SYLLABLE PHAA
+1334 ; [.1867.0020.0002.1334] # ETHIOPIC SYLLABLE PHEE
+1335 ; [.1868.0020.0002.1335] # ETHIOPIC SYLLABLE PHE
+1336 ; [.1869.0020.0002.1336] # ETHIOPIC SYLLABLE PHO
+1337 ; [.186A.0020.0002.1337] # ETHIOPIC SYLLABLE PHWA
+2D91 ; [.186B.0020.0002.2D91] # ETHIOPIC SYLLABLE PHOA
+1338 ; [.186C.0020.0002.1338] # ETHIOPIC SYLLABLE TSA
+1339 ; [.186D.0020.0002.1339] # ETHIOPIC SYLLABLE TSU
+133A ; [.186E.0020.0002.133A] # ETHIOPIC SYLLABLE TSI
+133B ; [.186F.0020.0002.133B] # ETHIOPIC SYLLABLE TSAA
+133C ; [.1870.0020.0002.133C] # ETHIOPIC SYLLABLE TSEE
+133D ; [.1871.0020.0002.133D] # ETHIOPIC SYLLABLE TSE
+133E ; [.1872.0020.0002.133E] # ETHIOPIC SYLLABLE TSO
+133F ; [.1873.0020.0002.133F] # ETHIOPIC SYLLABLE TSWA
+1340 ; [.1874.0020.0002.1340] # ETHIOPIC SYLLABLE TZA
+1341 ; [.1875.0020.0002.1341] # ETHIOPIC SYLLABLE TZU
+1342 ; [.1876.0020.0002.1342] # ETHIOPIC SYLLABLE TZI
+1343 ; [.1877.0020.0002.1343] # ETHIOPIC SYLLABLE TZAA
+1344 ; [.1878.0020.0002.1344] # ETHIOPIC SYLLABLE TZEE
+1345 ; [.1879.0020.0002.1345] # ETHIOPIC SYLLABLE TZE
+1346 ; [.187A.0020.0002.1346] # ETHIOPIC SYLLABLE TZO
+1347 ; [.187B.0020.0002.1347] # ETHIOPIC SYLLABLE TZOA
+1348 ; [.187C.0020.0002.1348] # ETHIOPIC SYLLABLE FA
+1349 ; [.187D.0020.0002.1349] # ETHIOPIC SYLLABLE FU
+134A ; [.187E.0020.0002.134A] # ETHIOPIC SYLLABLE FI
+134B ; [.187F.0020.0002.134B] # ETHIOPIC SYLLABLE FAA
+134C ; [.1880.0020.0002.134C] # ETHIOPIC SYLLABLE FEE
+134D ; [.1881.0020.0002.134D] # ETHIOPIC SYLLABLE FE
+134E ; [.1882.0020.0002.134E] # ETHIOPIC SYLLABLE FO
+134F ; [.1883.0020.0002.134F] # ETHIOPIC SYLLABLE FWA
+1388 ; [.1884.0020.0002.1388] # ETHIOPIC SYLLABLE SEBATBEIT FWA
+1389 ; [.1885.0020.0002.1389] # ETHIOPIC SYLLABLE FWI
+138A ; [.1886.0020.0002.138A] # ETHIOPIC SYLLABLE FWEE
+138B ; [.1887.0020.0002.138B] # ETHIOPIC SYLLABLE FWE
+1350 ; [.1888.0020.0002.1350] # ETHIOPIC SYLLABLE PA
+1351 ; [.1889.0020.0002.1351] # ETHIOPIC SYLLABLE PU
+1352 ; [.188A.0020.0002.1352] # ETHIOPIC SYLLABLE PI
+1353 ; [.188B.0020.0002.1353] # ETHIOPIC SYLLABLE PAA
+1354 ; [.188C.0020.0002.1354] # ETHIOPIC SYLLABLE PEE
+1355 ; [.188D.0020.0002.1355] # ETHIOPIC SYLLABLE PE
+1356 ; [.188E.0020.0002.1356] # ETHIOPIC SYLLABLE PO
+1357 ; [.188F.0020.0002.1357] # ETHIOPIC SYLLABLE PWA
+138C ; [.1890.0020.0002.138C] # ETHIOPIC SYLLABLE SEBATBEIT PWA
+138D ; [.1891.0020.0002.138D] # ETHIOPIC SYLLABLE PWI
+138E ; [.1892.0020.0002.138E] # ETHIOPIC SYLLABLE PWEE
+138F ; [.1893.0020.0002.138F] # ETHIOPIC SYLLABLE PWE
+2D92 ; [.1894.0020.0002.2D92] # ETHIOPIC SYLLABLE POA
+1358 ; [.1895.0020.0002.1358] # ETHIOPIC SYLLABLE RYA
+1359 ; [.1896.0020.0002.1359] # ETHIOPIC SYLLABLE MYA
+135A ; [.1897.0020.0002.135A] # ETHIOPIC SYLLABLE FYA
+2DA0 ; [.1898.0020.0002.2DA0] # ETHIOPIC SYLLABLE SSA
+2DA1 ; [.1899.0020.0002.2DA1] # ETHIOPIC SYLLABLE SSU
+2DA2 ; [.189A.0020.0002.2DA2] # ETHIOPIC SYLLABLE SSI
+2DA3 ; [.189B.0020.0002.2DA3] # ETHIOPIC SYLLABLE SSAA
+2DA4 ; [.189C.0020.0002.2DA4] # ETHIOPIC SYLLABLE SSEE
+2DA5 ; [.189D.0020.0002.2DA5] # ETHIOPIC SYLLABLE SSE
+2DA6 ; [.189E.0020.0002.2DA6] # ETHIOPIC SYLLABLE SSO
+2DA8 ; [.189F.0020.0002.2DA8] # ETHIOPIC SYLLABLE CCA
+2DA9 ; [.18A0.0020.0002.2DA9] # ETHIOPIC SYLLABLE CCU
+2DAA ; [.18A1.0020.0002.2DAA] # ETHIOPIC SYLLABLE CCI
+2DAB ; [.18A2.0020.0002.2DAB] # ETHIOPIC SYLLABLE CCAA
+2DAC ; [.18A3.0020.0002.2DAC] # ETHIOPIC SYLLABLE CCEE
+2DAD ; [.18A4.0020.0002.2DAD] # ETHIOPIC SYLLABLE CCE
+2DAE ; [.18A5.0020.0002.2DAE] # ETHIOPIC SYLLABLE CCO
+2DB0 ; [.18A6.0020.0002.2DB0] # ETHIOPIC SYLLABLE ZZA
+2DB1 ; [.18A7.0020.0002.2DB1] # ETHIOPIC SYLLABLE ZZU
+2DB2 ; [.18A8.0020.0002.2DB2] # ETHIOPIC SYLLABLE ZZI
+2DB3 ; [.18A9.0020.0002.2DB3] # ETHIOPIC SYLLABLE ZZAA
+2DB4 ; [.18AA.0020.0002.2DB4] # ETHIOPIC SYLLABLE ZZEE
+2DB5 ; [.18AB.0020.0002.2DB5] # ETHIOPIC SYLLABLE ZZE
+2DB6 ; [.18AC.0020.0002.2DB6] # ETHIOPIC SYLLABLE ZZO
+2DB8 ; [.18AD.0020.0002.2DB8] # ETHIOPIC SYLLABLE CCHA
+2DB9 ; [.18AE.0020.0002.2DB9] # ETHIOPIC SYLLABLE CCHU
+2DBA ; [.18AF.0020.0002.2DBA] # ETHIOPIC SYLLABLE CCHI
+2DBB ; [.18B0.0020.0002.2DBB] # ETHIOPIC SYLLABLE CCHAA
+2DBC ; [.18B1.0020.0002.2DBC] # ETHIOPIC SYLLABLE CCHEE
+2DBD ; [.18B2.0020.0002.2DBD] # ETHIOPIC SYLLABLE CCHE
+2DBE ; [.18B3.0020.0002.2DBE] # ETHIOPIC SYLLABLE CCHO
+2DC0 ; [.18B4.0020.0002.2DC0] # ETHIOPIC SYLLABLE QYA
+2DC1 ; [.18B5.0020.0002.2DC1] # ETHIOPIC SYLLABLE QYU
+2DC2 ; [.18B6.0020.0002.2DC2] # ETHIOPIC SYLLABLE QYI
+2DC3 ; [.18B7.0020.0002.2DC3] # ETHIOPIC SYLLABLE QYAA
+2DC4 ; [.18B8.0020.0002.2DC4] # ETHIOPIC SYLLABLE QYEE
+2DC5 ; [.18B9.0020.0002.2DC5] # ETHIOPIC SYLLABLE QYE
+2DC6 ; [.18BA.0020.0002.2DC6] # ETHIOPIC SYLLABLE QYO
+2DC8 ; [.18BB.0020.0002.2DC8] # ETHIOPIC SYLLABLE KYA
+2DC9 ; [.18BC.0020.0002.2DC9] # ETHIOPIC SYLLABLE KYU
+2DCA ; [.18BD.0020.0002.2DCA] # ETHIOPIC SYLLABLE KYI
+2DCB ; [.18BE.0020.0002.2DCB] # ETHIOPIC SYLLABLE KYAA
+2DCC ; [.18BF.0020.0002.2DCC] # ETHIOPIC SYLLABLE KYEE
+2DCD ; [.18C0.0020.0002.2DCD] # ETHIOPIC SYLLABLE KYE
+2DCE ; [.18C1.0020.0002.2DCE] # ETHIOPIC SYLLABLE KYO
+2DD0 ; [.18C2.0020.0002.2DD0] # ETHIOPIC SYLLABLE XYA
+2DD1 ; [.18C3.0020.0002.2DD1] # ETHIOPIC SYLLABLE XYU
+2DD2 ; [.18C4.0020.0002.2DD2] # ETHIOPIC SYLLABLE XYI
+2DD3 ; [.18C5.0020.0002.2DD3] # ETHIOPIC SYLLABLE XYAA
+2DD4 ; [.18C6.0020.0002.2DD4] # ETHIOPIC SYLLABLE XYEE
+2DD5 ; [.18C7.0020.0002.2DD5] # ETHIOPIC SYLLABLE XYE
+2DD6 ; [.18C8.0020.0002.2DD6] # ETHIOPIC SYLLABLE XYO
+2DD8 ; [.18C9.0020.0002.2DD8] # ETHIOPIC SYLLABLE GYA
+2DD9 ; [.18CA.0020.0002.2DD9] # ETHIOPIC SYLLABLE GYU
+2DDA ; [.18CB.0020.0002.2DDA] # ETHIOPIC SYLLABLE GYI
+2DDB ; [.18CC.0020.0002.2DDB] # ETHIOPIC SYLLABLE GYAA
+2DDC ; [.18CD.0020.0002.2DDC] # ETHIOPIC SYLLABLE GYEE
+2DDD ; [.18CE.0020.0002.2DDD] # ETHIOPIC SYLLABLE GYE
+2DDE ; [.18CF.0020.0002.2DDE] # ETHIOPIC SYLLABLE GYO
+0950 ; [.18D0.0020.0002.0950] # DEVANAGARI OM
+0904 ; [.18D1.0020.0002.0904] # DEVANAGARI LETTER SHORT A
+0905 ; [.18D2.0020.0002.0905] # DEVANAGARI LETTER A
+0906 ; [.18D3.0020.0002.0906] # DEVANAGARI LETTER AA
+0907 ; [.18D4.0020.0002.0907] # DEVANAGARI LETTER I
+0908 ; [.18D5.0020.0002.0908] # DEVANAGARI LETTER II
+0909 ; [.18D6.0020.0002.0909] # DEVANAGARI LETTER U
+090A ; [.18D7.0020.0002.090A] # DEVANAGARI LETTER UU
+090B ; [.18D8.0020.0002.090B] # DEVANAGARI LETTER VOCALIC R
+0960 ; [.18D9.0020.0002.0960] # DEVANAGARI LETTER VOCALIC RR
+090C ; [.18DA.0020.0002.090C] # DEVANAGARI LETTER VOCALIC L
+0961 ; [.18DB.0020.0002.0961] # DEVANAGARI LETTER VOCALIC LL
+090D ; [.18DC.0020.0002.090D] # DEVANAGARI LETTER CANDRA E
+090E ; [.18DD.0020.0002.090E] # DEVANAGARI LETTER SHORT E
+090F ; [.18DE.0020.0002.090F] # DEVANAGARI LETTER E
+0910 ; [.18DF.0020.0002.0910] # DEVANAGARI LETTER AI
+0911 ; [.18E0.0020.0002.0911] # DEVANAGARI LETTER CANDRA O
+0912 ; [.18E1.0020.0002.0912] # DEVANAGARI LETTER SHORT O
+0913 ; [.18E2.0020.0002.0913] # DEVANAGARI LETTER O
+0914 ; [.18E3.0020.0002.0914] # DEVANAGARI LETTER AU
+0915 ; [.18E4.0020.0002.0915] # DEVANAGARI LETTER KA
+0958 ; [.18E4.0020.0002.0915][.0000.0119.0002.093C] # DEVANAGARI LETTER QA; QQCM
+0916 ; [.18E5.0020.0002.0916] # DEVANAGARI LETTER KHA
+0959 ; [.18E5.0020.0002.0916][.0000.0119.0002.093C] # DEVANAGARI LETTER KHHA; QQCM
+0917 ; [.18E6.0020.0002.0917] # DEVANAGARI LETTER GA
+095A ; [.18E6.0020.0002.0917][.0000.0119.0002.093C] # DEVANAGARI LETTER GHHA; QQCM
+097B ; [.18E7.0020.0002.097B] # DEVANAGARI LETTER GGA
+0918 ; [.18E8.0020.0002.0918] # DEVANAGARI LETTER GHA
+0919 ; [.18E9.0020.0002.0919] # DEVANAGARI LETTER NGA
+091A ; [.18EA.0020.0002.091A] # DEVANAGARI LETTER CA
+091B ; [.18EB.0020.0002.091B] # DEVANAGARI LETTER CHA
+091C ; [.18EC.0020.0002.091C] # DEVANAGARI LETTER JA
+095B ; [.18EC.0020.0002.091C][.0000.0119.0002.093C] # DEVANAGARI LETTER ZA; QQCM
+097C ; [.18ED.0020.0002.097C] # DEVANAGARI LETTER JJA
+091D ; [.18EE.0020.0002.091D] # DEVANAGARI LETTER JHA
+091E ; [.18EF.0020.0002.091E] # DEVANAGARI LETTER NYA
+091F ; [.18F0.0020.0002.091F] # DEVANAGARI LETTER TTA
+0920 ; [.18F1.0020.0002.0920] # DEVANAGARI LETTER TTHA
+0921 ; [.18F2.0020.0002.0921] # DEVANAGARI LETTER DDA
+095C ; [.18F2.0020.0002.0921][.0000.0119.0002.093C] # DEVANAGARI LETTER DDDHA; QQCM
+097E ; [.18F3.0020.0002.097E] # DEVANAGARI LETTER DDDA
+0922 ; [.18F4.0020.0002.0922] # DEVANAGARI LETTER DDHA
+095D ; [.18F4.0020.0002.0922][.0000.0119.0002.093C] # DEVANAGARI LETTER RHA; QQCM
+0923 ; [.18F5.0020.0002.0923] # DEVANAGARI LETTER NNA
+0924 ; [.18F6.0020.0002.0924] # DEVANAGARI LETTER TA
+0925 ; [.18F7.0020.0002.0925] # DEVANAGARI LETTER THA
+0926 ; [.18F8.0020.0002.0926] # DEVANAGARI LETTER DA
+0927 ; [.18F9.0020.0002.0927] # DEVANAGARI LETTER DHA
+0928 ; [.18FA.0020.0002.0928] # DEVANAGARI LETTER NA
+0929 ; [.18FA.0020.0002.0928][.0000.0119.0002.093C] # DEVANAGARI LETTER NNNA; QQCM
+092A ; [.18FB.0020.0002.092A] # DEVANAGARI LETTER PA
+092B ; [.18FC.0020.0002.092B] # DEVANAGARI LETTER PHA
+095E ; [.18FC.0020.0002.092B][.0000.0119.0002.093C] # DEVANAGARI LETTER FA; QQCM
+092C ; [.18FD.0020.0002.092C] # DEVANAGARI LETTER BA
+097F ; [.18FE.0020.0002.097F] # DEVANAGARI LETTER BBA
+092D ; [.18FF.0020.0002.092D] # DEVANAGARI LETTER BHA
+092E ; [.1900.0020.0002.092E] # DEVANAGARI LETTER MA
+092F ; [.1901.0020.0002.092F] # DEVANAGARI LETTER YA
+095F ; [.1901.0020.0002.092F][.0000.0119.0002.093C] # DEVANAGARI LETTER YYA; QQCM
+0930 ; [.1902.0020.0002.0930] # DEVANAGARI LETTER RA
+0931 ; [.1902.0020.0002.0930][.0000.0119.0002.093C] # DEVANAGARI LETTER RRA; QQCM
+0932 ; [.1903.0020.0002.0932] # DEVANAGARI LETTER LA
+0933 ; [.1904.0020.0002.0933] # DEVANAGARI LETTER LLA
+0934 ; [.1904.0020.0002.0933][.0000.0119.0002.093C] # DEVANAGARI LETTER LLLA; QQCM
+0935 ; [.1905.0020.0002.0935] # DEVANAGARI LETTER VA
+0936 ; [.1906.0020.0002.0936] # DEVANAGARI LETTER SHA
+0937 ; [.1907.0020.0002.0937] # DEVANAGARI LETTER SSA
+0938 ; [.1908.0020.0002.0938] # DEVANAGARI LETTER SA
+0939 ; [.1909.0020.0002.0939] # DEVANAGARI LETTER HA
+093D ; [.190A.0020.0002.093D] # DEVANAGARI SIGN AVAGRAHA
+097D ; [.190B.0020.0002.097D] # DEVANAGARI LETTER GLOTTAL STOP
+093E ; [.190C.0020.0002.093E] # DEVANAGARI VOWEL SIGN AA
+093F ; [.190D.0020.0002.093F] # DEVANAGARI VOWEL SIGN I
+0940 ; [.190E.0020.0002.0940] # DEVANAGARI VOWEL SIGN II
+0941 ; [.190F.0020.0002.0941] # DEVANAGARI VOWEL SIGN U
+0942 ; [.1910.0020.0002.0942] # DEVANAGARI VOWEL SIGN UU
+0943 ; [.1911.0020.0002.0943] # DEVANAGARI VOWEL SIGN VOCALIC R
+0944 ; [.1912.0020.0002.0944] # DEVANAGARI VOWEL SIGN VOCALIC RR
+0962 ; [.1913.0020.0002.0962] # DEVANAGARI VOWEL SIGN VOCALIC L
+0963 ; [.1914.0020.0002.0963] # DEVANAGARI VOWEL SIGN VOCALIC LL
+0945 ; [.1915.0020.0002.0945] # DEVANAGARI VOWEL SIGN CANDRA E
+0946 ; [.1916.0020.0002.0946] # DEVANAGARI VOWEL SIGN SHORT E
+0947 ; [.1917.0020.0002.0947] # DEVANAGARI VOWEL SIGN E
+0948 ; [.1918.0020.0002.0948] # DEVANAGARI VOWEL SIGN AI
+0949 ; [.1919.0020.0002.0949] # DEVANAGARI VOWEL SIGN CANDRA O
+094A ; [.191A.0020.0002.094A] # DEVANAGARI VOWEL SIGN SHORT O
+094B ; [.191B.0020.0002.094B] # DEVANAGARI VOWEL SIGN O
+094C ; [.191C.0020.0002.094C] # DEVANAGARI VOWEL SIGN AU
+094D ; [.191D.0020.0002.094D] # DEVANAGARI SIGN VIRAMA
+0985 ; [.191E.0020.0002.0985] # BENGALI LETTER A
+0986 ; [.191F.0020.0002.0986] # BENGALI LETTER AA
+0987 ; [.1920.0020.0002.0987] # BENGALI LETTER I
+0988 ; [.1921.0020.0002.0988] # BENGALI LETTER II
+0989 ; [.1922.0020.0002.0989] # BENGALI LETTER U
+098A ; [.1923.0020.0002.098A] # BENGALI LETTER UU
+098B ; [.1924.0020.0002.098B] # BENGALI LETTER VOCALIC R
+09E0 ; [.1925.0020.0002.09E0] # BENGALI LETTER VOCALIC RR
+098C ; [.1926.0020.0002.098C] # BENGALI LETTER VOCALIC L
+09E1 ; [.1927.0020.0002.09E1] # BENGALI LETTER VOCALIC LL
+098F ; [.1928.0020.0002.098F] # BENGALI LETTER E
+0990 ; [.1929.0020.0002.0990] # BENGALI LETTER AI
+0993 ; [.192A.0020.0002.0993] # BENGALI LETTER O
+0994 ; [.192B.0020.0002.0994] # BENGALI LETTER AU
+0995 ; [.192C.0020.0002.0995] # BENGALI LETTER KA
+0996 ; [.192D.0020.0002.0996] # BENGALI LETTER KHA
+0997 ; [.192E.0020.0002.0997] # BENGALI LETTER GA
+0998 ; [.192F.0020.0002.0998] # BENGALI LETTER GHA
+0999 ; [.1930.0020.0002.0999] # BENGALI LETTER NGA
+099A ; [.1931.0020.0002.099A] # BENGALI LETTER CA
+099B ; [.1932.0020.0002.099B] # BENGALI LETTER CHA
+099C ; [.1933.0020.0002.099C] # BENGALI LETTER JA
+099D ; [.1934.0020.0002.099D] # BENGALI LETTER JHA
+099E ; [.1935.0020.0002.099E] # BENGALI LETTER NYA
+099F ; [.1936.0020.0002.099F] # BENGALI LETTER TTA
+09A0 ; [.1937.0020.0002.09A0] # BENGALI LETTER TTHA
+09A1 ; [.1938.0020.0002.09A1] # BENGALI LETTER DDA
+09DC ; [.1938.0020.0002.09A1][.0000.0121.0002.09BC] # BENGALI LETTER RRA; QQCM
+09A2 ; [.1939.0020.0002.09A2] # BENGALI LETTER DDHA
+09DD ; [.1939.0020.0002.09A2][.0000.0121.0002.09BC] # BENGALI LETTER RHA; QQCM
+09A3 ; [.193A.0020.0002.09A3] # BENGALI LETTER NNA
+09A4 ; [.193B.0020.0002.09A4] # BENGALI LETTER TA
+09CE ; [.193B.0020.0004.09CE][.195C.0020.0004.09CE] # BENGALI LETTER KHANDA TA; QQKN
+09A5 ; [.193C.0020.0002.09A5] # BENGALI LETTER THA
+09A6 ; [.193D.0020.0002.09A6] # BENGALI LETTER DA
+09A7 ; [.193E.0020.0002.09A7] # BENGALI LETTER DHA
+09A8 ; [.193F.0020.0002.09A8] # BENGALI LETTER NA
+09AA ; [.1940.0020.0002.09AA] # BENGALI LETTER PA
+09AB ; [.1941.0020.0002.09AB] # BENGALI LETTER PHA
+09AC ; [.1942.0020.0002.09AC] # BENGALI LETTER BA
+09AD ; [.1943.0020.0002.09AD] # BENGALI LETTER BHA
+09AE ; [.1944.0020.0002.09AE] # BENGALI LETTER MA
+09AF ; [.1945.0020.0002.09AF] # BENGALI LETTER YA
+09DF ; [.1945.0020.0002.09AF][.0000.0121.0002.09BC] # BENGALI LETTER YYA; QQCM
+09B0 ; [.1946.0020.0002.09B0] # BENGALI LETTER RA
+09F0 ; [.1947.0020.0002.09F0] # BENGALI LETTER RA WITH MIDDLE DIAGONAL
+09B2 ; [.1948.0020.0002.09B2] # BENGALI LETTER LA
+09F1 ; [.1949.0020.0002.09F1] # BENGALI LETTER RA WITH LOWER DIAGONAL
+09B6 ; [.194A.0020.0002.09B6] # BENGALI LETTER SHA
+09B7 ; [.194B.0020.0002.09B7] # BENGALI LETTER SSA
+09B8 ; [.194C.0020.0002.09B8] # BENGALI LETTER SA
+09B9 ; [.194D.0020.0002.09B9] # BENGALI LETTER HA
+09BD ; [.194E.0020.0002.09BD] # BENGALI SIGN AVAGRAHA
+09BE ; [.194F.0020.0002.09BE] # BENGALI VOWEL SIGN AA
+09BF ; [.1950.0020.0002.09BF] # BENGALI VOWEL SIGN I
+09C0 ; [.1951.0020.0002.09C0] # BENGALI VOWEL SIGN II
+09C1 ; [.1952.0020.0002.09C1] # BENGALI VOWEL SIGN U
+09C2 ; [.1953.0020.0002.09C2] # BENGALI VOWEL SIGN UU
+09C3 ; [.1954.0020.0002.09C3] # BENGALI VOWEL SIGN VOCALIC R
+09C4 ; [.1955.0020.0002.09C4] # BENGALI VOWEL SIGN VOCALIC RR
+09E2 ; [.1956.0020.0002.09E2] # BENGALI VOWEL SIGN VOCALIC L
+09E3 ; [.1957.0020.0002.09E3] # BENGALI VOWEL SIGN VOCALIC LL
+09C7 ; [.1958.0020.0002.09C7] # BENGALI VOWEL SIGN E
+09C8 ; [.1959.0020.0002.09C8] # BENGALI VOWEL SIGN AI
+09CB ; [.195A.0020.0002.09CB] # BENGALI VOWEL SIGN O
+09C7 09BE ; [.195A.0020.0002.09CB] # BENGALI VOWEL SIGN O
+09CC ; [.195B.0020.0002.09CC] # BENGALI VOWEL SIGN AU
+09C7 09D7 ; [.195B.0020.0002.09CC] # BENGALI VOWEL SIGN AU
+09CD ; [.195C.0020.0002.09CD] # BENGALI SIGN VIRAMA
+09D7 ; [.195D.0020.0002.09D7] # BENGALI AU LENGTH MARK
+0A74 ; [.195E.0020.0002.0A74] # GURMUKHI EK ONKAR
+0A73 ; [.195F.0020.0002.0A73] # GURMUKHI URA
+0A09 ; [.1960.0020.0002.0A09] # GURMUKHI LETTER U
+0A0A ; [.1961.0020.0002.0A0A] # GURMUKHI LETTER UU
+0A13 ; [.1962.0020.0002.0A13] # GURMUKHI LETTER OO
+0A05 ; [.1963.0020.0002.0A05] # GURMUKHI LETTER A
+0A06 ; [.1964.0020.0002.0A06] # GURMUKHI LETTER AA
+0A10 ; [.1965.0020.0002.0A10] # GURMUKHI LETTER AI
+0A14 ; [.1966.0020.0002.0A14] # GURMUKHI LETTER AU
+0A72 ; [.1967.0020.0002.0A72] # GURMUKHI IRI
+0A07 ; [.1968.0020.0002.0A07] # GURMUKHI LETTER I
+0A08 ; [.1969.0020.0002.0A08] # GURMUKHI LETTER II
+0A0F ; [.196A.0020.0002.0A0F] # GURMUKHI LETTER EE
+0A38 ; [.196B.0020.0002.0A38] # GURMUKHI LETTER SA
+0A36 ; [.196B.0020.0002.0A38][.0000.0125.0002.0A3C] # GURMUKHI LETTER SHA; QQCM
+0A39 ; [.196C.0020.0002.0A39] # GURMUKHI LETTER HA
+0A15 ; [.196D.0020.0002.0A15] # GURMUKHI LETTER KA
+0A16 ; [.196E.0020.0002.0A16] # GURMUKHI LETTER KHA
+0A59 ; [.196E.0020.0002.0A16][.0000.0125.0002.0A3C] # GURMUKHI LETTER KHHA; QQCM
+0A17 ; [.196F.0020.0002.0A17] # GURMUKHI LETTER GA
+0A5A ; [.196F.0020.0002.0A17][.0000.0125.0002.0A3C] # GURMUKHI LETTER GHHA; QQCM
+0A18 ; [.1970.0020.0002.0A18] # GURMUKHI LETTER GHA
+0A19 ; [.1971.0020.0002.0A19] # GURMUKHI LETTER NGA
+0A1A ; [.1972.0020.0002.0A1A] # GURMUKHI LETTER CA
+0A1B ; [.1973.0020.0002.0A1B] # GURMUKHI LETTER CHA
+0A1C ; [.1974.0020.0002.0A1C] # GURMUKHI LETTER JA
+0A5B ; [.1974.0020.0002.0A1C][.0000.0125.0002.0A3C] # GURMUKHI LETTER ZA; QQCM
+0A1D ; [.1975.0020.0002.0A1D] # GURMUKHI LETTER JHA
+0A1E ; [.1976.0020.0002.0A1E] # GURMUKHI LETTER NYA
+0A1F ; [.1977.0020.0002.0A1F] # GURMUKHI LETTER TTA
+0A20 ; [.1978.0020.0002.0A20] # GURMUKHI LETTER TTHA
+0A21 ; [.1979.0020.0002.0A21] # GURMUKHI LETTER DDA
+0A22 ; [.197A.0020.0002.0A22] # GURMUKHI LETTER DDHA
+0A23 ; [.197B.0020.0002.0A23] # GURMUKHI LETTER NNA
+0A24 ; [.197C.0020.0002.0A24] # GURMUKHI LETTER TA
+0A25 ; [.197D.0020.0002.0A25] # GURMUKHI LETTER THA
+0A26 ; [.197E.0020.0002.0A26] # GURMUKHI LETTER DA
+0A27 ; [.197F.0020.0002.0A27] # GURMUKHI LETTER DHA
+0A28 ; [.1980.0020.0002.0A28] # GURMUKHI LETTER NA
+0A2A ; [.1981.0020.0002.0A2A] # GURMUKHI LETTER PA
+0A2B ; [.1982.0020.0002.0A2B] # GURMUKHI LETTER PHA
+0A5E ; [.1982.0020.0002.0A2B][.0000.0125.0002.0A3C] # GURMUKHI LETTER FA; QQCM
+0A2C ; [.1983.0020.0002.0A2C] # GURMUKHI LETTER BA
+0A2D ; [.1984.0020.0002.0A2D] # GURMUKHI LETTER BHA
+0A2E ; [.1985.0020.0002.0A2E] # GURMUKHI LETTER MA
+0A2F ; [.1986.0020.0002.0A2F] # GURMUKHI LETTER YA
+0A30 ; [.1987.0020.0002.0A30] # GURMUKHI LETTER RA
+0A32 ; [.1988.0020.0002.0A32] # GURMUKHI LETTER LA
+0A33 ; [.1988.0020.0002.0A32][.0000.0125.0002.0A3C] # GURMUKHI LETTER LLA; QQCM
+0A35 ; [.1989.0020.0002.0A35] # GURMUKHI LETTER VA
+0A5C ; [.198A.0020.0002.0A5C] # GURMUKHI LETTER RRA
+0A3E ; [.198B.0020.0002.0A3E] # GURMUKHI VOWEL SIGN AA
+0A3F ; [.198C.0020.0002.0A3F] # GURMUKHI VOWEL SIGN I
+0A40 ; [.198D.0020.0002.0A40] # GURMUKHI VOWEL SIGN II
+0A41 ; [.198E.0020.0002.0A41] # GURMUKHI VOWEL SIGN U
+0A42 ; [.198F.0020.0002.0A42] # GURMUKHI VOWEL SIGN UU
+0A47 ; [.1990.0020.0002.0A47] # GURMUKHI VOWEL SIGN EE
+0A48 ; [.1991.0020.0002.0A48] # GURMUKHI VOWEL SIGN AI
+0A4B ; [.1992.0020.0002.0A4B] # GURMUKHI VOWEL SIGN OO
+0A4C ; [.1993.0020.0002.0A4C] # GURMUKHI VOWEL SIGN AU
+0A4D ; [.1994.0020.0002.0A4D] # GURMUKHI SIGN VIRAMA
+0AD0 ; [.1995.0020.0002.0AD0] # GUJARATI OM
+0A85 ; [.1996.0020.0002.0A85] # GUJARATI LETTER A
+0A86 ; [.1997.0020.0002.0A86] # GUJARATI LETTER AA
+0A87 ; [.1998.0020.0002.0A87] # GUJARATI LETTER I
+0A88 ; [.1999.0020.0002.0A88] # GUJARATI LETTER II
+0A89 ; [.199A.0020.0002.0A89] # GUJARATI LETTER U
+0A8A ; [.199B.0020.0002.0A8A] # GUJARATI LETTER UU
+0A8B ; [.199C.0020.0002.0A8B] # GUJARATI LETTER VOCALIC R
+0AE0 ; [.199D.0020.0002.0AE0] # GUJARATI LETTER VOCALIC RR
+0A8C ; [.199E.0020.0002.0A8C] # GUJARATI LETTER VOCALIC L
+0AE1 ; [.199F.0020.0002.0AE1] # GUJARATI LETTER VOCALIC LL
+0A8D ; [.19A0.0020.0002.0A8D] # GUJARATI VOWEL CANDRA E
+0A8F ; [.19A1.0020.0002.0A8F] # GUJARATI LETTER E
+0A90 ; [.19A2.0020.0002.0A90] # GUJARATI LETTER AI
+0A91 ; [.19A3.0020.0002.0A91] # GUJARATI VOWEL CANDRA O
+0A93 ; [.19A4.0020.0002.0A93] # GUJARATI LETTER O
+0A94 ; [.19A5.0020.0002.0A94] # GUJARATI LETTER AU
+0A95 ; [.19A6.0020.0002.0A95] # GUJARATI LETTER KA
+0A96 ; [.19A7.0020.0002.0A96] # GUJARATI LETTER KHA
+0A97 ; [.19A8.0020.0002.0A97] # GUJARATI LETTER GA
+0A98 ; [.19A9.0020.0002.0A98] # GUJARATI LETTER GHA
+0A99 ; [.19AA.0020.0002.0A99] # GUJARATI LETTER NGA
+0A9A ; [.19AB.0020.0002.0A9A] # GUJARATI LETTER CA
+0A9B ; [.19AC.0020.0002.0A9B] # GUJARATI LETTER CHA
+0A9C ; [.19AD.0020.0002.0A9C] # GUJARATI LETTER JA
+0A9D ; [.19AE.0020.0002.0A9D] # GUJARATI LETTER JHA
+0A9E ; [.19AF.0020.0002.0A9E] # GUJARATI LETTER NYA
+0A9F ; [.19B0.0020.0002.0A9F] # GUJARATI LETTER TTA
+0AA0 ; [.19B1.0020.0002.0AA0] # GUJARATI LETTER TTHA
+0AA1 ; [.19B2.0020.0002.0AA1] # GUJARATI LETTER DDA
+0AA2 ; [.19B3.0020.0002.0AA2] # GUJARATI LETTER DDHA
+0AA3 ; [.19B4.0020.0002.0AA3] # GUJARATI LETTER NNA
+0AA4 ; [.19B5.0020.0002.0AA4] # GUJARATI LETTER TA
+0AA5 ; [.19B6.0020.0002.0AA5] # GUJARATI LETTER THA
+0AA6 ; [.19B7.0020.0002.0AA6] # GUJARATI LETTER DA
+0AA7 ; [.19B8.0020.0002.0AA7] # GUJARATI LETTER DHA
+0AA8 ; [.19B9.0020.0002.0AA8] # GUJARATI LETTER NA
+0AAA ; [.19BA.0020.0002.0AAA] # GUJARATI LETTER PA
+0AAB ; [.19BB.0020.0002.0AAB] # GUJARATI LETTER PHA
+0AAC ; [.19BC.0020.0002.0AAC] # GUJARATI LETTER BA
+0AAD ; [.19BD.0020.0002.0AAD] # GUJARATI LETTER BHA
+0AAE ; [.19BE.0020.0002.0AAE] # GUJARATI LETTER MA
+0AAF ; [.19BF.0020.0002.0AAF] # GUJARATI LETTER YA
+0AB0 ; [.19C0.0020.0002.0AB0] # GUJARATI LETTER RA
+0AB2 ; [.19C1.0020.0002.0AB2] # GUJARATI LETTER LA
+0AB3 ; [.19C2.0020.0002.0AB3] # GUJARATI LETTER LLA
+0AB5 ; [.19C3.0020.0002.0AB5] # GUJARATI LETTER VA
+0AB6 ; [.19C4.0020.0002.0AB6] # GUJARATI LETTER SHA
+0AB7 ; [.19C5.0020.0002.0AB7] # GUJARATI LETTER SSA
+0AB8 ; [.19C6.0020.0002.0AB8] # GUJARATI LETTER SA
+0AB9 ; [.19C7.0020.0002.0AB9] # GUJARATI LETTER HA
+0ABD ; [.19C8.0020.0002.0ABD] # GUJARATI SIGN AVAGRAHA
+0ABE ; [.19C9.0020.0002.0ABE] # GUJARATI VOWEL SIGN AA
+0ABF ; [.19CA.0020.0002.0ABF] # GUJARATI VOWEL SIGN I
+0AC0 ; [.19CB.0020.0002.0AC0] # GUJARATI VOWEL SIGN II
+0AC1 ; [.19CC.0020.0002.0AC1] # GUJARATI VOWEL SIGN U
+0AC2 ; [.19CD.0020.0002.0AC2] # GUJARATI VOWEL SIGN UU
+0AC3 ; [.19CE.0020.0002.0AC3] # GUJARATI VOWEL SIGN VOCALIC R
+0AC4 ; [.19CF.0020.0002.0AC4] # GUJARATI VOWEL SIGN VOCALIC RR
+0AE2 ; [.19D0.0020.0002.0AE2] # GUJARATI VOWEL SIGN VOCALIC L
+0AE3 ; [.19D1.0020.0002.0AE3] # GUJARATI VOWEL SIGN VOCALIC LL
+0AC5 ; [.19D2.0020.0002.0AC5] # GUJARATI VOWEL SIGN CANDRA E
+0AC7 ; [.19D3.0020.0002.0AC7] # GUJARATI VOWEL SIGN E
+0AC8 ; [.19D4.0020.0002.0AC8] # GUJARATI VOWEL SIGN AI
+0AC9 ; [.19D5.0020.0002.0AC9] # GUJARATI VOWEL SIGN CANDRA O
+0ACB ; [.19D6.0020.0002.0ACB] # GUJARATI VOWEL SIGN O
+0ACC ; [.19D7.0020.0002.0ACC] # GUJARATI VOWEL SIGN AU
+0ACD ; [.19D8.0020.0002.0ACD] # GUJARATI SIGN VIRAMA
+0B05 ; [.19D9.0020.0002.0B05] # ORIYA LETTER A
+0B06 ; [.19DA.0020.0002.0B06] # ORIYA LETTER AA
+0B07 ; [.19DB.0020.0002.0B07] # ORIYA LETTER I
+0B08 ; [.19DC.0020.0002.0B08] # ORIYA LETTER II
+0B09 ; [.19DD.0020.0002.0B09] # ORIYA LETTER U
+0B0A ; [.19DE.0020.0002.0B0A] # ORIYA LETTER UU
+0B0B ; [.19DF.0020.0002.0B0B] # ORIYA LETTER VOCALIC R
+0B60 ; [.19E0.0020.0002.0B60] # ORIYA LETTER VOCALIC RR
+0B0C ; [.19E1.0020.0002.0B0C] # ORIYA LETTER VOCALIC L
+0B61 ; [.19E2.0020.0002.0B61] # ORIYA LETTER VOCALIC LL
+0B0F ; [.19E3.0020.0002.0B0F] # ORIYA LETTER E
+0B10 ; [.19E4.0020.0002.0B10] # ORIYA LETTER AI
+0B13 ; [.19E5.0020.0002.0B13] # ORIYA LETTER O
+0B14 ; [.19E6.0020.0002.0B14] # ORIYA LETTER AU
+0B15 ; [.19E7.0020.0002.0B15] # ORIYA LETTER KA
+0B16 ; [.19E8.0020.0002.0B16] # ORIYA LETTER KHA
+0B17 ; [.19E9.0020.0002.0B17] # ORIYA LETTER GA
+0B18 ; [.19EA.0020.0002.0B18] # ORIYA LETTER GHA
+0B19 ; [.19EB.0020.0002.0B19] # ORIYA LETTER NGA
+0B1A ; [.19EC.0020.0002.0B1A] # ORIYA LETTER CA
+0B1B ; [.19ED.0020.0002.0B1B] # ORIYA LETTER CHA
+0B1C ; [.19EE.0020.0002.0B1C] # ORIYA LETTER JA
+0B1D ; [.19EF.0020.0002.0B1D] # ORIYA LETTER JHA
+0B1E ; [.19F0.0020.0002.0B1E] # ORIYA LETTER NYA
+0B1F ; [.19F1.0020.0002.0B1F] # ORIYA LETTER TTA
+0B20 ; [.19F2.0020.0002.0B20] # ORIYA LETTER TTHA
+0B21 ; [.19F3.0020.0002.0B21] # ORIYA LETTER DDA
+0B5C ; [.19F3.0020.0002.0B21][.0000.012F.0002.0B3C] # ORIYA LETTER RRA; QQCM
+0B22 ; [.19F4.0020.0002.0B22] # ORIYA LETTER DDHA
+0B5D ; [.19F4.0020.0002.0B22][.0000.012F.0002.0B3C] # ORIYA LETTER RHA; QQCM
+0B23 ; [.19F5.0020.0002.0B23] # ORIYA LETTER NNA
+0B24 ; [.19F6.0020.0002.0B24] # ORIYA LETTER TA
+0B25 ; [.19F7.0020.0002.0B25] # ORIYA LETTER THA
+0B26 ; [.19F8.0020.0002.0B26] # ORIYA LETTER DA
+0B27 ; [.19F9.0020.0002.0B27] # ORIYA LETTER DHA
+0B28 ; [.19FA.0020.0002.0B28] # ORIYA LETTER NA
+0B2A ; [.19FB.0020.0002.0B2A] # ORIYA LETTER PA
+0B2B ; [.19FC.0020.0002.0B2B] # ORIYA LETTER PHA
+0B2C ; [.19FD.0020.0002.0B2C] # ORIYA LETTER BA
+0B2D ; [.19FE.0020.0002.0B2D] # ORIYA LETTER BHA
+0B2E ; [.19FF.0020.0002.0B2E] # ORIYA LETTER MA
+0B2F ; [.1A00.0020.0002.0B2F] # ORIYA LETTER YA
+0B5F ; [.1A01.0020.0002.0B5F] # ORIYA LETTER YYA
+0B30 ; [.1A02.0020.0002.0B30] # ORIYA LETTER RA
+0B32 ; [.1A03.0020.0002.0B32] # ORIYA LETTER LA
+0B33 ; [.1A04.0020.0002.0B33] # ORIYA LETTER LLA
+0B35 ; [.1A05.0020.0002.0B35] # ORIYA LETTER VA
+0B71 ; [.1A06.0020.0002.0B71] # ORIYA LETTER WA
+0B36 ; [.1A07.0020.0002.0B36] # ORIYA LETTER SHA
+0B37 ; [.1A08.0020.0002.0B37] # ORIYA LETTER SSA
+0B38 ; [.1A09.0020.0002.0B38] # ORIYA LETTER SA
+0B39 ; [.1A0A.0020.0002.0B39] # ORIYA LETTER HA
+0B3D ; [.1A0B.0020.0002.0B3D] # ORIYA SIGN AVAGRAHA
+0B3E ; [.1A0C.0020.0002.0B3E] # ORIYA VOWEL SIGN AA
+0B3F ; [.1A0D.0020.0002.0B3F] # ORIYA VOWEL SIGN I
+0B40 ; [.1A0E.0020.0002.0B40] # ORIYA VOWEL SIGN II
+0B41 ; [.1A0F.0020.0002.0B41] # ORIYA VOWEL SIGN U
+0B42 ; [.1A10.0020.0002.0B42] # ORIYA VOWEL SIGN UU
+0B43 ; [.1A11.0020.0002.0B43] # ORIYA VOWEL SIGN VOCALIC R
+0B47 ; [.1A12.0020.0002.0B47] # ORIYA VOWEL SIGN E
+0B48 ; [.1A13.0020.0002.0B48] # ORIYA VOWEL SIGN AI
+0B47 0B56 ; [.1A13.0020.0002.0B48] # ORIYA VOWEL SIGN AI
+0B4B ; [.1A14.0020.0002.0B4B] # ORIYA VOWEL SIGN O
+0B47 0B3E ; [.1A14.0020.0002.0B4B] # ORIYA VOWEL SIGN O
+0B4C ; [.1A15.0020.0002.0B4C] # ORIYA VOWEL SIGN AU
+0B47 0B57 ; [.1A15.0020.0002.0B4C] # ORIYA VOWEL SIGN AU
+0B4D ; [.1A16.0020.0002.0B4D] # ORIYA SIGN VIRAMA
+0B56 ; [.1A17.0020.0002.0B56] # ORIYA AI LENGTH MARK
+0B57 ; [.1A18.0020.0002.0B57] # ORIYA AU LENGTH MARK
+0B83 ; [.1A19.0020.0002.0B83] # TAMIL SIGN VISARGA
+0B85 ; [.1A1A.0020.0002.0B85] # TAMIL LETTER A
+0B86 ; [.1A1B.0020.0002.0B86] # TAMIL LETTER AA
+0B87 ; [.1A1C.0020.0002.0B87] # TAMIL LETTER I
+0B88 ; [.1A1D.0020.0002.0B88] # TAMIL LETTER II
+0B89 ; [.1A1E.0020.0002.0B89] # TAMIL LETTER U
+0B8A ; [.1A1F.0020.0002.0B8A] # TAMIL LETTER UU
+0B8E ; [.1A20.0020.0002.0B8E] # TAMIL LETTER E
+0B8F ; [.1A21.0020.0002.0B8F] # TAMIL LETTER EE
+0B90 ; [.1A22.0020.0002.0B90] # TAMIL LETTER AI
+0B92 ; [.1A23.0020.0002.0B92] # TAMIL LETTER O
+0B93 ; [.1A24.0020.0002.0B93] # TAMIL LETTER OO
+0B94 ; [.1A25.0020.0002.0B94] # TAMIL LETTER AU
+0B92 0BD7 ; [.1A25.0020.0002.0B94] # TAMIL LETTER AU
+0B95 ; [.1A26.0020.0002.0B95] # TAMIL LETTER KA
+0B99 ; [.1A27.0020.0002.0B99] # TAMIL LETTER NGA
+0B9A ; [.1A28.0020.0002.0B9A] # TAMIL LETTER CA
+0B9C ; [.1A29.0020.0002.0B9C] # TAMIL LETTER JA
+0B9E ; [.1A2A.0020.0002.0B9E] # TAMIL LETTER NYA
+0B9F ; [.1A2B.0020.0002.0B9F] # TAMIL LETTER TTA
+0BA3 ; [.1A2C.0020.0002.0BA3] # TAMIL LETTER NNA
+0BA4 ; [.1A2D.0020.0002.0BA4] # TAMIL LETTER TA
+0BA8 ; [.1A2E.0020.0002.0BA8] # TAMIL LETTER NA
+0BA9 ; [.1A2F.0020.0002.0BA9] # TAMIL LETTER NNNA
+0BAA ; [.1A30.0020.0002.0BAA] # TAMIL LETTER PA
+0BAE ; [.1A31.0020.0002.0BAE] # TAMIL LETTER MA
+0BAF ; [.1A32.0020.0002.0BAF] # TAMIL LETTER YA
+0BB0 ; [.1A33.0020.0002.0BB0] # TAMIL LETTER RA
+0BB1 ; [.1A34.0020.0002.0BB1] # TAMIL LETTER RRA
+0BB2 ; [.1A35.0020.0002.0BB2] # TAMIL LETTER LA
+0BB3 ; [.1A36.0020.0002.0BB3] # TAMIL LETTER LLA
+0BB4 ; [.1A37.0020.0002.0BB4] # TAMIL LETTER LLLA
+0BB5 ; [.1A38.0020.0002.0BB5] # TAMIL LETTER VA
+0BB6 ; [.1A39.0020.0002.0BB6] # TAMIL LETTER SHA
+0BB7 ; [.1A3A.0020.0002.0BB7] # TAMIL LETTER SSA
+0BB8 ; [.1A3B.0020.0002.0BB8] # TAMIL LETTER SA
+0BB9 ; [.1A3C.0020.0002.0BB9] # TAMIL LETTER HA
+0BBE ; [.1A3D.0020.0002.0BBE] # TAMIL VOWEL SIGN AA
+0BBF ; [.1A3E.0020.0002.0BBF] # TAMIL VOWEL SIGN I
+0BC0 ; [.1A3F.0020.0002.0BC0] # TAMIL VOWEL SIGN II
+0BC1 ; [.1A40.0020.0002.0BC1] # TAMIL VOWEL SIGN U
+0BC2 ; [.1A41.0020.0002.0BC2] # TAMIL VOWEL SIGN UU
+0BC6 ; [.1A42.0020.0002.0BC6] # TAMIL VOWEL SIGN E
+0BC7 ; [.1A43.0020.0002.0BC7] # TAMIL VOWEL SIGN EE
+0BC8 ; [.1A44.0020.0002.0BC8] # TAMIL VOWEL SIGN AI
+0BCA ; [.1A45.0020.0002.0BCA] # TAMIL VOWEL SIGN O
+0BC6 0BBE ; [.1A45.0020.0002.0BCA] # TAMIL VOWEL SIGN O
+0BCB ; [.1A46.0020.0002.0BCB] # TAMIL VOWEL SIGN OO
+0BC7 0BBE ; [.1A46.0020.0002.0BCB] # TAMIL VOWEL SIGN OO
+0BCC ; [.1A47.0020.0002.0BCC] # TAMIL VOWEL SIGN AU
+0BC6 0BD7 ; [.1A47.0020.0002.0BCC] # TAMIL VOWEL SIGN AU
+0BCD ; [.1A48.0020.0002.0BCD] # TAMIL SIGN VIRAMA
+0BD7 ; [.1A49.0020.0002.0BD7] # TAMIL AU LENGTH MARK
+0C05 ; [.1A4A.0020.0002.0C05] # TELUGU LETTER A
+0C06 ; [.1A4B.0020.0002.0C06] # TELUGU LETTER AA
+0C07 ; [.1A4C.0020.0002.0C07] # TELUGU LETTER I
+0C08 ; [.1A4D.0020.0002.0C08] # TELUGU LETTER II
+0C09 ; [.1A4E.0020.0002.0C09] # TELUGU LETTER U
+0C0A ; [.1A4F.0020.0002.0C0A] # TELUGU LETTER UU
+0C0B ; [.1A50.0020.0002.0C0B] # TELUGU LETTER VOCALIC R
+0C60 ; [.1A51.0020.0002.0C60] # TELUGU LETTER VOCALIC RR
+0C0C ; [.1A52.0020.0002.0C0C] # TELUGU LETTER VOCALIC L
+0C61 ; [.1A53.0020.0002.0C61] # TELUGU LETTER VOCALIC LL
+0C0E ; [.1A54.0020.0002.0C0E] # TELUGU LETTER E
+0C0F ; [.1A55.0020.0002.0C0F] # TELUGU LETTER EE
+0C10 ; [.1A56.0020.0002.0C10] # TELUGU LETTER AI
+0C12 ; [.1A57.0020.0002.0C12] # TELUGU LETTER O
+0C13 ; [.1A58.0020.0002.0C13] # TELUGU LETTER OO
+0C14 ; [.1A59.0020.0002.0C14] # TELUGU LETTER AU
+0C15 ; [.1A5A.0020.0002.0C15] # TELUGU LETTER KA
+0C16 ; [.1A5B.0020.0002.0C16] # TELUGU LETTER KHA
+0C17 ; [.1A5C.0020.0002.0C17] # TELUGU LETTER GA
+0C18 ; [.1A5D.0020.0002.0C18] # TELUGU LETTER GHA
+0C19 ; [.1A5E.0020.0002.0C19] # TELUGU LETTER NGA
+0C1A ; [.1A5F.0020.0002.0C1A] # TELUGU LETTER CA
+0C1B ; [.1A60.0020.0002.0C1B] # TELUGU LETTER CHA
+0C1C ; [.1A61.0020.0002.0C1C] # TELUGU LETTER JA
+0C1D ; [.1A62.0020.0002.0C1D] # TELUGU LETTER JHA
+0C1E ; [.1A63.0020.0002.0C1E] # TELUGU LETTER NYA
+0C1F ; [.1A64.0020.0002.0C1F] # TELUGU LETTER TTA
+0C20 ; [.1A65.0020.0002.0C20] # TELUGU LETTER TTHA
+0C21 ; [.1A66.0020.0002.0C21] # TELUGU LETTER DDA
+0C22 ; [.1A67.0020.0002.0C22] # TELUGU LETTER DDHA
+0C23 ; [.1A68.0020.0002.0C23] # TELUGU LETTER NNA
+0C24 ; [.1A69.0020.0002.0C24] # TELUGU LETTER TA
+0C25 ; [.1A6A.0020.0002.0C25] # TELUGU LETTER THA
+0C26 ; [.1A6B.0020.0002.0C26] # TELUGU LETTER DA
+0C27 ; [.1A6C.0020.0002.0C27] # TELUGU LETTER DHA
+0C28 ; [.1A6D.0020.0002.0C28] # TELUGU LETTER NA
+0C2A ; [.1A6E.0020.0002.0C2A] # TELUGU LETTER PA
+0C2B ; [.1A6F.0020.0002.0C2B] # TELUGU LETTER PHA
+0C2C ; [.1A70.0020.0002.0C2C] # TELUGU LETTER BA
+0C2D ; [.1A71.0020.0002.0C2D] # TELUGU LETTER BHA
+0C2E ; [.1A72.0020.0002.0C2E] # TELUGU LETTER MA
+0C2F ; [.1A73.0020.0002.0C2F] # TELUGU LETTER YA
+0C30 ; [.1A74.0020.0002.0C30] # TELUGU LETTER RA
+0C31 ; [.1A75.0020.0002.0C31] # TELUGU LETTER RRA
+0C32 ; [.1A76.0020.0002.0C32] # TELUGU LETTER LA
+0C33 ; [.1A77.0020.0002.0C33] # TELUGU LETTER LLA
+0C35 ; [.1A78.0020.0002.0C35] # TELUGU LETTER VA
+0C36 ; [.1A79.0020.0002.0C36] # TELUGU LETTER SHA
+0C37 ; [.1A7A.0020.0002.0C37] # TELUGU LETTER SSA
+0C38 ; [.1A7B.0020.0002.0C38] # TELUGU LETTER SA
+0C39 ; [.1A7C.0020.0002.0C39] # TELUGU LETTER HA
+0C3E ; [.1A7D.0020.0002.0C3E] # TELUGU VOWEL SIGN AA
+0C3F ; [.1A7E.0020.0002.0C3F] # TELUGU VOWEL SIGN I
+0C40 ; [.1A7F.0020.0002.0C40] # TELUGU VOWEL SIGN II
+0C41 ; [.1A80.0020.0002.0C41] # TELUGU VOWEL SIGN U
+0C42 ; [.1A81.0020.0002.0C42] # TELUGU VOWEL SIGN UU
+0C43 ; [.1A82.0020.0002.0C43] # TELUGU VOWEL SIGN VOCALIC R
+0C44 ; [.1A83.0020.0002.0C44] # TELUGU VOWEL SIGN VOCALIC RR
+0C46 ; [.1A84.0020.0002.0C46] # TELUGU VOWEL SIGN E
+0C47 ; [.1A85.0020.0002.0C47] # TELUGU VOWEL SIGN EE
+0C48 ; [.1A86.0020.0002.0C48] # TELUGU VOWEL SIGN AI
+0C46 0C56 ; [.1A86.0020.0002.0C48] # TELUGU VOWEL SIGN AI
+0C4A ; [.1A87.0020.0002.0C4A] # TELUGU VOWEL SIGN O
+0C4B ; [.1A88.0020.0002.0C4B] # TELUGU VOWEL SIGN OO
+0C4C ; [.1A89.0020.0002.0C4C] # TELUGU VOWEL SIGN AU
+0C4D ; [.1A8A.0020.0002.0C4D] # TELUGU SIGN VIRAMA
+0C55 ; [.1A8B.0020.0002.0C55] # TELUGU LENGTH MARK
+0C56 ; [.1A8C.0020.0002.0C56] # TELUGU AI LENGTH MARK
+0C85 ; [.1A8D.0020.0002.0C85] # KANNADA LETTER A
+0C86 ; [.1A8E.0020.0002.0C86] # KANNADA LETTER AA
+0C87 ; [.1A8F.0020.0002.0C87] # KANNADA LETTER I
+0C88 ; [.1A90.0020.0002.0C88] # KANNADA LETTER II
+0C89 ; [.1A91.0020.0002.0C89] # KANNADA LETTER U
+0C8A ; [.1A92.0020.0002.0C8A] # KANNADA LETTER UU
+0C8B ; [.1A93.0020.0002.0C8B] # KANNADA LETTER VOCALIC R
+0CE0 ; [.1A94.0020.0002.0CE0] # KANNADA LETTER VOCALIC RR
+0C8C ; [.1A95.0020.0002.0C8C] # KANNADA LETTER VOCALIC L
+0CE1 ; [.1A96.0020.0002.0CE1] # KANNADA LETTER VOCALIC LL
+0C8E ; [.1A97.0020.0002.0C8E] # KANNADA LETTER E
+0C8F ; [.1A98.0020.0002.0C8F] # KANNADA LETTER EE
+0C90 ; [.1A99.0020.0002.0C90] # KANNADA LETTER AI
+0C92 ; [.1A9A.0020.0002.0C92] # KANNADA LETTER O
+0C93 ; [.1A9B.0020.0002.0C93] # KANNADA LETTER OO
+0C94 ; [.1A9C.0020.0002.0C94] # KANNADA LETTER AU
+0C95 ; [.1A9D.0020.0002.0C95] # KANNADA LETTER KA
+0C96 ; [.1A9E.0020.0002.0C96] # KANNADA LETTER KHA
+0C97 ; [.1A9F.0020.0002.0C97] # KANNADA LETTER GA
+0C98 ; [.1AA0.0020.0002.0C98] # KANNADA LETTER GHA
+0C99 ; [.1AA1.0020.0002.0C99] # KANNADA LETTER NGA
+0C9A ; [.1AA2.0020.0002.0C9A] # KANNADA LETTER CA
+0C9B ; [.1AA3.0020.0002.0C9B] # KANNADA LETTER CHA
+0C9C ; [.1AA4.0020.0002.0C9C] # KANNADA LETTER JA
+0C9D ; [.1AA5.0020.0002.0C9D] # KANNADA LETTER JHA
+0C9E ; [.1AA6.0020.0002.0C9E] # KANNADA LETTER NYA
+0C9F ; [.1AA7.0020.0002.0C9F] # KANNADA LETTER TTA
+0CA0 ; [.1AA8.0020.0002.0CA0] # KANNADA LETTER TTHA
+0CA1 ; [.1AA9.0020.0002.0CA1] # KANNADA LETTER DDA
+0CA2 ; [.1AAA.0020.0002.0CA2] # KANNADA LETTER DDHA
+0CA3 ; [.1AAB.0020.0002.0CA3] # KANNADA LETTER NNA
+0CA4 ; [.1AAC.0020.0002.0CA4] # KANNADA LETTER TA
+0CA5 ; [.1AAD.0020.0002.0CA5] # KANNADA LETTER THA
+0CA6 ; [.1AAE.0020.0002.0CA6] # KANNADA LETTER DA
+0CA7 ; [.1AAF.0020.0002.0CA7] # KANNADA LETTER DHA
+0CA8 ; [.1AB0.0020.0002.0CA8] # KANNADA LETTER NA
+0CAA ; [.1AB1.0020.0002.0CAA] # KANNADA LETTER PA
+0CAB ; [.1AB2.0020.0002.0CAB] # KANNADA LETTER PHA
+0CAC ; [.1AB3.0020.0002.0CAC] # KANNADA LETTER BA
+0CAD ; [.1AB4.0020.0002.0CAD] # KANNADA LETTER BHA
+0CAE ; [.1AB5.0020.0002.0CAE] # KANNADA LETTER MA
+0CAF ; [.1AB6.0020.0002.0CAF] # KANNADA LETTER YA
+0CB0 ; [.1AB7.0020.0002.0CB0] # KANNADA LETTER RA
+0CB1 ; [.1AB8.0020.0002.0CB1] # KANNADA LETTER RRA
+0CB2 ; [.1AB9.0020.0002.0CB2] # KANNADA LETTER LA
+0CB5 ; [.1ABA.0020.0002.0CB5] # KANNADA LETTER VA
+0CB6 ; [.1ABB.0020.0002.0CB6] # KANNADA LETTER SHA
+0CB7 ; [.1ABC.0020.0002.0CB7] # KANNADA LETTER SSA
+0CB8 ; [.1ABD.0020.0002.0CB8] # KANNADA LETTER SA
+0CB9 ; [.1ABE.0020.0002.0CB9] # KANNADA LETTER HA
+0CB3 ; [.1ABF.0020.0002.0CB3] # KANNADA LETTER LLA
+0CDE ; [.1AC0.0020.0002.0CDE] # KANNADA LETTER FA
+0CBD ; [.1AC1.0020.0002.0CBD] # KANNADA SIGN AVAGRAHA
+0CBE ; [.1AC2.0020.0002.0CBE] # KANNADA VOWEL SIGN AA
+0CBF ; [.1AC3.0020.0002.0CBF] # KANNADA VOWEL SIGN I
+0CC0 ; [.1AC4.0020.0002.0CC0] # KANNADA VOWEL SIGN II
+0CBF 0CD5 ; [.1AC4.0020.0002.0CC0] # KANNADA VOWEL SIGN II
+0CC1 ; [.1AC5.0020.0002.0CC1] # KANNADA VOWEL SIGN U
+0CC2 ; [.1AC6.0020.0002.0CC2] # KANNADA VOWEL SIGN UU
+0CC3 ; [.1AC7.0020.0002.0CC3] # KANNADA VOWEL SIGN VOCALIC R
+0CC4 ; [.1AC8.0020.0002.0CC4] # KANNADA VOWEL SIGN VOCALIC RR
+0CE2 ; [.1AC9.0020.0002.0CE2] # KANNADA VOWEL SIGN VOCALIC L
+0CE3 ; [.1ACA.0020.0002.0CE3] # KANNADA VOWEL SIGN VOCALIC LL
+0CC6 ; [.1ACB.0020.0002.0CC6] # KANNADA VOWEL SIGN E
+0CC7 ; [.1ACC.0020.0002.0CC7] # KANNADA VOWEL SIGN EE
+0CC6 0CD5 ; [.1ACC.0020.0002.0CC7] # KANNADA VOWEL SIGN EE
+0CC8 ; [.1ACD.0020.0002.0CC8] # KANNADA VOWEL SIGN AI
+0CC6 0CD6 ; [.1ACD.0020.0002.0CC8] # KANNADA VOWEL SIGN AI
+0CCA ; [.1ACE.0020.0002.0CCA] # KANNADA VOWEL SIGN O
+0CC6 0CC2 ; [.1ACE.0020.0002.0CCA] # KANNADA VOWEL SIGN O
+0CCB ; [.1ACF.0020.0002.0CCB] # KANNADA VOWEL SIGN OO
+0CC6 0CC2 0CD5 ; [.1ACF.0020.0002.0CCB] # KANNADA VOWEL SIGN OO
+0CCA 0CD5 ; [.1ACF.0020.0002.0CCB] # KANNADA VOWEL SIGN OO
+0CCC ; [.1AD0.0020.0002.0CCC] # KANNADA VOWEL SIGN AU
+0CCD ; [.1AD1.0020.0002.0CCD] # KANNADA SIGN VIRAMA
+0CD5 ; [.1AD2.0020.0002.0CD5] # KANNADA LENGTH MARK
+0CD6 ; [.1AD3.0020.0002.0CD6] # KANNADA AI LENGTH MARK
+0D05 ; [.1AD4.0020.0002.0D05] # MALAYALAM LETTER A
+0D06 ; [.1AD5.0020.0002.0D06] # MALAYALAM LETTER AA
+0D07 ; [.1AD6.0020.0002.0D07] # MALAYALAM LETTER I
+0D08 ; [.1AD7.0020.0002.0D08] # MALAYALAM LETTER II
+0D09 ; [.1AD8.0020.0002.0D09] # MALAYALAM LETTER U
+0D0A ; [.1AD9.0020.0002.0D0A] # MALAYALAM LETTER UU
+0D0B ; [.1ADA.0020.0002.0D0B] # MALAYALAM LETTER VOCALIC R
+0D60 ; [.1ADB.0020.0002.0D60] # MALAYALAM LETTER VOCALIC RR
+0D0C ; [.1ADC.0020.0002.0D0C] # MALAYALAM LETTER VOCALIC L
+0D61 ; [.1ADD.0020.0002.0D61] # MALAYALAM LETTER VOCALIC LL
+0D0E ; [.1ADE.0020.0002.0D0E] # MALAYALAM LETTER E
+0D0F ; [.1ADF.0020.0002.0D0F] # MALAYALAM LETTER EE
+0D10 ; [.1AE0.0020.0002.0D10] # MALAYALAM LETTER AI
+0D12 ; [.1AE1.0020.0002.0D12] # MALAYALAM LETTER O
+0D13 ; [.1AE2.0020.0002.0D13] # MALAYALAM LETTER OO
+0D14 ; [.1AE3.0020.0002.0D14] # MALAYALAM LETTER AU
+0D15 ; [.1AE4.0020.0002.0D15] # MALAYALAM LETTER KA
+0D16 ; [.1AE5.0020.0002.0D16] # MALAYALAM LETTER KHA
+0D17 ; [.1AE6.0020.0002.0D17] # MALAYALAM LETTER GA
+0D18 ; [.1AE7.0020.0002.0D18] # MALAYALAM LETTER GHA
+0D19 ; [.1AE8.0020.0002.0D19] # MALAYALAM LETTER NGA
+0D1A ; [.1AE9.0020.0002.0D1A] # MALAYALAM LETTER CA
+0D1B ; [.1AEA.0020.0002.0D1B] # MALAYALAM LETTER CHA
+0D1C ; [.1AEB.0020.0002.0D1C] # MALAYALAM LETTER JA
+0D1D ; [.1AEC.0020.0002.0D1D] # MALAYALAM LETTER JHA
+0D1E ; [.1AED.0020.0002.0D1E] # MALAYALAM LETTER NYA
+0D1F ; [.1AEE.0020.0002.0D1F] # MALAYALAM LETTER TTA
+0D20 ; [.1AEF.0020.0002.0D20] # MALAYALAM LETTER TTHA
+0D21 ; [.1AF0.0020.0002.0D21] # MALAYALAM LETTER DDA
+0D22 ; [.1AF1.0020.0002.0D22] # MALAYALAM LETTER DDHA
+0D23 ; [.1AF2.0020.0002.0D23] # MALAYALAM LETTER NNA
+0D24 ; [.1AF3.0020.0002.0D24] # MALAYALAM LETTER TA
+0D25 ; [.1AF4.0020.0002.0D25] # MALAYALAM LETTER THA
+0D26 ; [.1AF5.0020.0002.0D26] # MALAYALAM LETTER DA
+0D27 ; [.1AF6.0020.0002.0D27] # MALAYALAM LETTER DHA
+0D28 ; [.1AF7.0020.0002.0D28] # MALAYALAM LETTER NA
+0D2A ; [.1AF8.0020.0002.0D2A] # MALAYALAM LETTER PA
+0D2B ; [.1AF9.0020.0002.0D2B] # MALAYALAM LETTER PHA
+0D2C ; [.1AFA.0020.0002.0D2C] # MALAYALAM LETTER BA
+0D2D ; [.1AFB.0020.0002.0D2D] # MALAYALAM LETTER BHA
+0D2E ; [.1AFC.0020.0002.0D2E] # MALAYALAM LETTER MA
+0D2F ; [.1AFD.0020.0002.0D2F] # MALAYALAM LETTER YA
+0D30 ; [.1AFE.0020.0002.0D30] # MALAYALAM LETTER RA
+0D31 ; [.1AFF.0020.0002.0D31] # MALAYALAM LETTER RRA
+0D32 ; [.1B00.0020.0002.0D32] # MALAYALAM LETTER LA
+0D33 ; [.1B01.0020.0002.0D33] # MALAYALAM LETTER LLA
+0D34 ; [.1B02.0020.0002.0D34] # MALAYALAM LETTER LLLA
+0D35 ; [.1B03.0020.0002.0D35] # MALAYALAM LETTER VA
+0D36 ; [.1B04.0020.0002.0D36] # MALAYALAM LETTER SHA
+0D37 ; [.1B05.0020.0002.0D37] # MALAYALAM LETTER SSA
+0D38 ; [.1B06.0020.0002.0D38] # MALAYALAM LETTER SA
+0D39 ; [.1B07.0020.0002.0D39] # MALAYALAM LETTER HA
+0D3E ; [.1B08.0020.0002.0D3E] # MALAYALAM VOWEL SIGN AA
+0D3F ; [.1B09.0020.0002.0D3F] # MALAYALAM VOWEL SIGN I
+0D40 ; [.1B0A.0020.0002.0D40] # MALAYALAM VOWEL SIGN II
+0D41 ; [.1B0B.0020.0002.0D41] # MALAYALAM VOWEL SIGN U
+0D42 ; [.1B0C.0020.0002.0D42] # MALAYALAM VOWEL SIGN UU
+0D43 ; [.1B0D.0020.0002.0D43] # MALAYALAM VOWEL SIGN VOCALIC R
+0D46 ; [.1B0E.0020.0002.0D46] # MALAYALAM VOWEL SIGN E
+0D47 ; [.1B0F.0020.0002.0D47] # MALAYALAM VOWEL SIGN EE
+0D48 ; [.1B10.0020.0002.0D48] # MALAYALAM VOWEL SIGN AI
+0D4A ; [.1B11.0020.0002.0D4A] # MALAYALAM VOWEL SIGN O
+0D46 0D3E ; [.1B11.0020.0002.0D4A] # MALAYALAM VOWEL SIGN O
+0D4B ; [.1B12.0020.0002.0D4B] # MALAYALAM VOWEL SIGN OO
+0D47 0D3E ; [.1B12.0020.0002.0D4B] # MALAYALAM VOWEL SIGN OO
+0D4C ; [.1B13.0020.0002.0D4C] # MALAYALAM VOWEL SIGN AU
+0D46 0D57 ; [.1B13.0020.0002.0D4C] # MALAYALAM VOWEL SIGN AU
+0D57 ; [.1B14.0020.0002.0D57] # MALAYALAM AU LENGTH MARK
+0D4D ; [.1B15.0020.0002.0D4D] # MALAYALAM SIGN VIRAMA
+0D85 ; [.1B16.0020.0002.0D85] # SINHALA LETTER AYANNA
+0D86 ; [.1B17.0020.0002.0D86] # SINHALA LETTER AAYANNA
+0D87 ; [.1B18.0020.0002.0D87] # SINHALA LETTER AEYANNA
+0D88 ; [.1B19.0020.0002.0D88] # SINHALA LETTER AEEYANNA
+0D89 ; [.1B1A.0020.0002.0D89] # SINHALA LETTER IYANNA
+0D8A ; [.1B1B.0020.0002.0D8A] # SINHALA LETTER IIYANNA
+0D8B ; [.1B1C.0020.0002.0D8B] # SINHALA LETTER UYANNA
+0D8C ; [.1B1D.0020.0002.0D8C] # SINHALA LETTER UUYANNA
+0D8D ; [.1B1E.0020.0002.0D8D] # SINHALA LETTER IRUYANNA
+0D8E ; [.1B1F.0020.0002.0D8E] # SINHALA LETTER IRUUYANNA
+0D8F ; [.1B20.0020.0002.0D8F] # SINHALA LETTER ILUYANNA
+0D90 ; [.1B21.0020.0002.0D90] # SINHALA LETTER ILUUYANNA
+0D91 ; [.1B22.0020.0002.0D91] # SINHALA LETTER EYANNA
+0D92 ; [.1B23.0020.0002.0D92] # SINHALA LETTER EEYANNA
+0D93 ; [.1B24.0020.0002.0D93] # SINHALA LETTER AIYANNA
+0D94 ; [.1B25.0020.0002.0D94] # SINHALA LETTER OYANNA
+0D95 ; [.1B26.0020.0002.0D95] # SINHALA LETTER OOYANNA
+0D96 ; [.1B27.0020.0002.0D96] # SINHALA LETTER AUYANNA
+0D9A ; [.1B28.0020.0002.0D9A] # SINHALA LETTER ALPAPRAANA KAYANNA
+0D9B ; [.1B29.0020.0002.0D9B] # SINHALA LETTER MAHAAPRAANA KAYANNA
+0D9C ; [.1B2A.0020.0002.0D9C] # SINHALA LETTER ALPAPRAANA GAYANNA
+0D9D ; [.1B2B.0020.0002.0D9D] # SINHALA LETTER MAHAAPRAANA GAYANNA
+0D9E ; [.1B2C.0020.0002.0D9E] # SINHALA LETTER KANTAJA NAASIKYAYA
+0D9F ; [.1B2D.0020.0002.0D9F] # SINHALA LETTER SANYAKA GAYANNA
+0DA0 ; [.1B2E.0020.0002.0DA0] # SINHALA LETTER ALPAPRAANA CAYANNA
+0DA1 ; [.1B2F.0020.0002.0DA1] # SINHALA LETTER MAHAAPRAANA CAYANNA
+0DA2 ; [.1B30.0020.0002.0DA2] # SINHALA LETTER ALPAPRAANA JAYANNA
+0DA3 ; [.1B31.0020.0002.0DA3] # SINHALA LETTER MAHAAPRAANA JAYANNA
+0DA4 ; [.1B32.0020.0002.0DA4] # SINHALA LETTER TAALUJA NAASIKYAYA
+0DA5 ; [.1B33.0020.0002.0DA5] # SINHALA LETTER TAALUJA SANYOOGA NAAKSIKYAYA
+0DA6 ; [.1B34.0020.0002.0DA6] # SINHALA LETTER SANYAKA JAYANNA
+0DA7 ; [.1B35.0020.0002.0DA7] # SINHALA LETTER ALPAPRAANA TTAYANNA
+0DA8 ; [.1B36.0020.0002.0DA8] # SINHALA LETTER MAHAAPRAANA TTAYANNA
+0DA9 ; [.1B37.0020.0002.0DA9] # SINHALA LETTER ALPAPRAANA DDAYANNA
+0DAA ; [.1B38.0020.0002.0DAA] # SINHALA LETTER MAHAAPRAANA DDAYANNA
+0DAB ; [.1B39.0020.0002.0DAB] # SINHALA LETTER MUURDHAJA NAYANNA
+0DAC ; [.1B3A.0020.0002.0DAC] # SINHALA LETTER SANYAKA DDAYANNA
+0DAD ; [.1B3B.0020.0002.0DAD] # SINHALA LETTER ALPAPRAANA TAYANNA
+0DAE ; [.1B3C.0020.0002.0DAE] # SINHALA LETTER MAHAAPRAANA TAYANNA
+0DAF ; [.1B3D.0020.0002.0DAF] # SINHALA LETTER ALPAPRAANA DAYANNA
+0DB0 ; [.1B3E.0020.0002.0DB0] # SINHALA LETTER MAHAAPRAANA DAYANNA
+0DB1 ; [.1B3F.0020.0002.0DB1] # SINHALA LETTER DANTAJA NAYANNA
+0DB3 ; [.1B40.0020.0002.0DB3] # SINHALA LETTER SANYAKA DAYANNA
+0DB4 ; [.1B41.0020.0002.0DB4] # SINHALA LETTER ALPAPRAANA PAYANNA
+0DB5 ; [.1B42.0020.0002.0DB5] # SINHALA LETTER MAHAAPRAANA PAYANNA
+0DB6 ; [.1B43.0020.0002.0DB6] # SINHALA LETTER ALPAPRAANA BAYANNA
+0DB7 ; [.1B44.0020.0002.0DB7] # SINHALA LETTER MAHAAPRAANA BAYANNA
+0DB8 ; [.1B45.0020.0002.0DB8] # SINHALA LETTER MAYANNA
+0DB9 ; [.1B46.0020.0002.0DB9] # SINHALA LETTER AMBA BAYANNA
+0DBA ; [.1B47.0020.0002.0DBA] # SINHALA LETTER YAYANNA
+0DBB ; [.1B48.0020.0002.0DBB] # SINHALA LETTER RAYANNA
+0DBD ; [.1B49.0020.0002.0DBD] # SINHALA LETTER DANTAJA LAYANNA
+0DC0 ; [.1B4A.0020.0002.0DC0] # SINHALA LETTER VAYANNA
+0DC1 ; [.1B4B.0020.0002.0DC1] # SINHALA LETTER TAALUJA SAYANNA
+0DC2 ; [.1B4C.0020.0002.0DC2] # SINHALA LETTER MUURDHAJA SAYANNA
+0DC3 ; [.1B4D.0020.0002.0DC3] # SINHALA LETTER DANTAJA SAYANNA
+0DC4 ; [.1B4E.0020.0002.0DC4] # SINHALA LETTER HAYANNA
+0DC5 ; [.1B4F.0020.0002.0DC5] # SINHALA LETTER MUURDHAJA LAYANNA
+0DC6 ; [.1B50.0020.0002.0DC6] # SINHALA LETTER FAYANNA
+0DCA ; [.1B51.0020.0002.0DCA] # SINHALA SIGN AL-LAKUNA
+0DCF ; [.1B52.0020.0002.0DCF] # SINHALA VOWEL SIGN AELA-PILLA
+0DD0 ; [.1B53.0020.0002.0DD0] # SINHALA VOWEL SIGN KETTI AEDA-PILLA
+0DD1 ; [.1B54.0020.0002.0DD1] # SINHALA VOWEL SIGN DIGA AEDA-PILLA
+0DD2 ; [.1B55.0020.0002.0DD2] # SINHALA VOWEL SIGN KETTI IS-PILLA
+0DD3 ; [.1B56.0020.0002.0DD3] # SINHALA VOWEL SIGN DIGA IS-PILLA
+0DD4 ; [.1B57.0020.0002.0DD4] # SINHALA VOWEL SIGN KETTI PAA-PILLA
+0DD6 ; [.1B58.0020.0002.0DD6] # SINHALA VOWEL SIGN DIGA PAA-PILLA
+0DD8 ; [.1B59.0020.0002.0DD8] # SINHALA VOWEL SIGN GAETTA-PILLA
+0DD9 ; [.1B5A.0020.0002.0DD9] # SINHALA VOWEL SIGN KOMBUVA
+0DDA ; [.1B5B.0020.0002.0DDA] # SINHALA VOWEL SIGN DIGA KOMBUVA
+0DD9 0DCA ; [.1B5B.0020.0002.0DDA] # SINHALA VOWEL SIGN DIGA KOMBUVA
+0DDB ; [.1B5C.0020.0002.0DDB] # SINHALA VOWEL SIGN KOMBU DEKA
+0DDC ; [.1B5D.0020.0002.0DDC] # SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA
+0DD9 0DCF ; [.1B5D.0020.0002.0DDC] # SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA
+0DDD ; [.1B5E.0020.0002.0DDD] # SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA
+0DD9 0DCF 0DCA ; [.1B5E.0020.0002.0DDD] # SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA
+0DDC 0DCA ; [.1B5E.0020.0002.0DDD] # SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA
+0DDE ; [.1B5F.0020.0002.0DDE] # SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA
+0DD9 0DDF ; [.1B5F.0020.0002.0DDE] # SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA
+0DDF ; [.1B60.0020.0002.0DDF] # SINHALA VOWEL SIGN GAYANUKITTA
+0DF2 ; [.1B61.0020.0002.0DF2] # SINHALA VOWEL SIGN DIGA GAETTA-PILLA
+0DF3 ; [.1B62.0020.0002.0DF3] # SINHALA VOWEL SIGN DIGA GAYANUKITTA
+A800 ; [.1B63.0020.0002.A800] # SYLOTI NAGRI LETTER A
+A801 ; [.1B64.0020.0002.A801] # SYLOTI NAGRI LETTER I
+A802 ; [.1B65.0020.0002.A802] # SYLOTI NAGRI SIGN DVISVARA
+A803 ; [.1B66.0020.0002.A803] # SYLOTI NAGRI LETTER U
+A804 ; [.1B67.0020.0002.A804] # SYLOTI NAGRI LETTER E
+A805 ; [.1B68.0020.0002.A805] # SYLOTI NAGRI LETTER O
+A806 ; [.1B69.0020.0002.A806] # SYLOTI NAGRI SIGN HASANTA
+A807 ; [.1B6A.0020.0002.A807] # SYLOTI NAGRI LETTER KO
+A808 ; [.1B6B.0020.0002.A808] # SYLOTI NAGRI LETTER KHO
+A809 ; [.1B6C.0020.0002.A809] # SYLOTI NAGRI LETTER GO
+A80A ; [.1B6D.0020.0002.A80A] # SYLOTI NAGRI LETTER GHO
+A80C ; [.1B6E.0020.0002.A80C] # SYLOTI NAGRI LETTER CO
+A80D ; [.1B6F.0020.0002.A80D] # SYLOTI NAGRI LETTER CHO
+A80E ; [.1B70.0020.0002.A80E] # SYLOTI NAGRI LETTER JO
+A80F ; [.1B71.0020.0002.A80F] # SYLOTI NAGRI LETTER JHO
+A810 ; [.1B72.0020.0002.A810] # SYLOTI NAGRI LETTER TTO
+A811 ; [.1B73.0020.0002.A811] # SYLOTI NAGRI LETTER TTHO
+A812 ; [.1B74.0020.0002.A812] # SYLOTI NAGRI LETTER DDO
+A813 ; [.1B75.0020.0002.A813] # SYLOTI NAGRI LETTER DDHO
+A814 ; [.1B76.0020.0002.A814] # SYLOTI NAGRI LETTER TO
+A815 ; [.1B77.0020.0002.A815] # SYLOTI NAGRI LETTER THO
+A816 ; [.1B78.0020.0002.A816] # SYLOTI NAGRI LETTER DO
+A817 ; [.1B79.0020.0002.A817] # SYLOTI NAGRI LETTER DHO
+A818 ; [.1B7A.0020.0002.A818] # SYLOTI NAGRI LETTER NO
+A819 ; [.1B7B.0020.0002.A819] # SYLOTI NAGRI LETTER PO
+A81A ; [.1B7C.0020.0002.A81A] # SYLOTI NAGRI LETTER PHO
+A81B ; [.1B7D.0020.0002.A81B] # SYLOTI NAGRI LETTER BO
+A81C ; [.1B7E.0020.0002.A81C] # SYLOTI NAGRI LETTER BHO
+A81D ; [.1B7F.0020.0002.A81D] # SYLOTI NAGRI LETTER MO
+A81E ; [.1B80.0020.0002.A81E] # SYLOTI NAGRI LETTER RO
+A81F ; [.1B81.0020.0002.A81F] # SYLOTI NAGRI LETTER LO
+A820 ; [.1B82.0020.0002.A820] # SYLOTI NAGRI LETTER RRO
+A821 ; [.1B83.0020.0002.A821] # SYLOTI NAGRI LETTER SO
+A822 ; [.1B84.0020.0002.A822] # SYLOTI NAGRI LETTER HO
+A823 ; [.1B85.0020.0002.A823] # SYLOTI NAGRI VOWEL SIGN A
+A824 ; [.1B86.0020.0002.A824] # SYLOTI NAGRI VOWEL SIGN I
+A825 ; [.1B87.0020.0002.A825] # SYLOTI NAGRI VOWEL SIGN U
+A826 ; [.1B88.0020.0002.A826] # SYLOTI NAGRI VOWEL SIGN E
+A827 ; [.1B89.0020.0002.A827] # SYLOTI NAGRI VOWEL SIGN OO
+10A00 ; [.1B8A.0020.0002.10A00] # KHAROSHTHI LETTER A
+10A01 ; [.1B8B.0020.0002.10A01] # KHAROSHTHI VOWEL SIGN I
+10A02 ; [.1B8C.0020.0002.10A02] # KHAROSHTHI VOWEL SIGN U
+10A03 ; [.1B8D.0020.0002.10A03] # KHAROSHTHI VOWEL SIGN VOCALIC R
+10A05 ; [.1B8E.0020.0002.10A05] # KHAROSHTHI VOWEL SIGN E
+10A06 ; [.1B8F.0020.0002.10A06] # KHAROSHTHI VOWEL SIGN O
+10A0C ; [.1B90.0020.0002.10A0C] # KHAROSHTHI VOWEL LENGTH MARK
+10A10 ; [.1B91.0020.0002.10A10] # KHAROSHTHI LETTER KA
+10A11 ; [.1B92.0020.0002.10A11] # KHAROSHTHI LETTER KHA
+10A12 ; [.1B93.0020.0002.10A12] # KHAROSHTHI LETTER GA
+10A13 ; [.1B94.0020.0002.10A13] # KHAROSHTHI LETTER GHA
+10A15 ; [.1B95.0020.0002.10A15] # KHAROSHTHI LETTER CA
+10A16 ; [.1B96.0020.0002.10A16] # KHAROSHTHI LETTER CHA
+10A17 ; [.1B97.0020.0002.10A17] # KHAROSHTHI LETTER JA
+10A19 ; [.1B98.0020.0002.10A19] # KHAROSHTHI LETTER NYA
+10A1A ; [.1B99.0020.0002.10A1A] # KHAROSHTHI LETTER TTA
+10A1B ; [.1B9A.0020.0002.10A1B] # KHAROSHTHI LETTER TTHA
+10A1C ; [.1B9B.0020.0002.10A1C] # KHAROSHTHI LETTER DDA
+10A1D ; [.1B9C.0020.0002.10A1D] # KHAROSHTHI LETTER DDHA
+10A1E ; [.1B9D.0020.0002.10A1E] # KHAROSHTHI LETTER NNA
+10A1F ; [.1B9E.0020.0002.10A1F] # KHAROSHTHI LETTER TA
+10A20 ; [.1B9F.0020.0002.10A20] # KHAROSHTHI LETTER THA
+10A21 ; [.1BA0.0020.0002.10A21] # KHAROSHTHI LETTER DA
+10A22 ; [.1BA1.0020.0002.10A22] # KHAROSHTHI LETTER DHA
+10A23 ; [.1BA2.0020.0002.10A23] # KHAROSHTHI LETTER NA
+10A24 ; [.1BA3.0020.0002.10A24] # KHAROSHTHI LETTER PA
+10A25 ; [.1BA4.0020.0002.10A25] # KHAROSHTHI LETTER PHA
+10A26 ; [.1BA5.0020.0002.10A26] # KHAROSHTHI LETTER BA
+10A27 ; [.1BA6.0020.0002.10A27] # KHAROSHTHI LETTER BHA
+10A28 ; [.1BA7.0020.0002.10A28] # KHAROSHTHI LETTER MA
+10A29 ; [.1BA8.0020.0002.10A29] # KHAROSHTHI LETTER YA
+10A2A ; [.1BA9.0020.0002.10A2A] # KHAROSHTHI LETTER RA
+10A2B ; [.1BAA.0020.0002.10A2B] # KHAROSHTHI LETTER LA
+10A2C ; [.1BAB.0020.0002.10A2C] # KHAROSHTHI LETTER VA
+10A2D ; [.1BAC.0020.0002.10A2D] # KHAROSHTHI LETTER SHA
+10A2E ; [.1BAD.0020.0002.10A2E] # KHAROSHTHI LETTER SSA
+10A2F ; [.1BAE.0020.0002.10A2F] # KHAROSHTHI LETTER SA
+10A30 ; [.1BAF.0020.0002.10A30] # KHAROSHTHI LETTER ZA
+10A31 ; [.1BB0.0020.0002.10A31] # KHAROSHTHI LETTER HA
+10A32 ; [.1BB1.0020.0002.10A32] # KHAROSHTHI LETTER KKA
+10A33 ; [.1BB2.0020.0002.10A33] # KHAROSHTHI LETTER TTTHA
+10A3F ; [.1BB3.0020.0002.10A3F] # KHAROSHTHI VIRAMA
+0E01 ; [.1BB4.0020.0002.0E01] # THAI CHARACTER KO KAI
+0E40 0E01 ; [.1BB4.0020.0002.0E01][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER KO KAI>
+0E41 0E01 ; [.1BB4.0020.0002.0E01][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER KO KAI>
+0E42 0E01 ; [.1BB4.0020.0002.0E01][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER KO KAI>
+0E43 0E01 ; [.1BB4.0020.0002.0E01][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER KO KAI>
+0E44 0E01 ; [.1BB4.0020.0002.0E01][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER KO KAI>
+0E02 ; [.1BB5.0020.0002.0E02] # THAI CHARACTER KHO KHAI
+0E40 0E02 ; [.1BB5.0020.0002.0E02][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER KHO KHAI>
+0E41 0E02 ; [.1BB5.0020.0002.0E02][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER KHO KHAI>
+0E42 0E02 ; [.1BB5.0020.0002.0E02][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER KHO KHAI>
+0E43 0E02 ; [.1BB5.0020.0002.0E02][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER KHO KHAI>
+0E44 0E02 ; [.1BB5.0020.0002.0E02][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER KHO KHAI>
+0E03 ; [.1BB6.0020.0002.0E03] # THAI CHARACTER KHO KHUAT
+0E40 0E03 ; [.1BB6.0020.0002.0E03][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER KHO KHUAT>
+0E41 0E03 ; [.1BB6.0020.0002.0E03][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER KHO KHUAT>
+0E42 0E03 ; [.1BB6.0020.0002.0E03][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER KHO KHUAT>
+0E43 0E03 ; [.1BB6.0020.0002.0E03][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER KHO KHUAT>
+0E44 0E03 ; [.1BB6.0020.0002.0E03][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER KHO KHUAT>
+0E04 ; [.1BB7.0020.0002.0E04] # THAI CHARACTER KHO KHWAI
+0E40 0E04 ; [.1BB7.0020.0002.0E04][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER KHO KHWAI>
+0E41 0E04 ; [.1BB7.0020.0002.0E04][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER KHO KHWAI>
+0E42 0E04 ; [.1BB7.0020.0002.0E04][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER KHO KHWAI>
+0E43 0E04 ; [.1BB7.0020.0002.0E04][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER KHO KHWAI>
+0E44 0E04 ; [.1BB7.0020.0002.0E04][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER KHO KHWAI>
+0E05 ; [.1BB8.0020.0002.0E05] # THAI CHARACTER KHO KHON
+0E40 0E05 ; [.1BB8.0020.0002.0E05][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER KHO KHON>
+0E41 0E05 ; [.1BB8.0020.0002.0E05][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER KHO KHON>
+0E42 0E05 ; [.1BB8.0020.0002.0E05][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER KHO KHON>
+0E43 0E05 ; [.1BB8.0020.0002.0E05][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER KHO KHON>
+0E44 0E05 ; [.1BB8.0020.0002.0E05][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER KHO KHON>
+0E06 ; [.1BB9.0020.0002.0E06] # THAI CHARACTER KHO RAKHANG
+0E40 0E06 ; [.1BB9.0020.0002.0E06][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER KHO RAKHANG>
+0E41 0E06 ; [.1BB9.0020.0002.0E06][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER KHO RAKHANG>
+0E42 0E06 ; [.1BB9.0020.0002.0E06][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER KHO RAKHANG>
+0E43 0E06 ; [.1BB9.0020.0002.0E06][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER KHO RAKHANG>
+0E44 0E06 ; [.1BB9.0020.0002.0E06][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER KHO RAKHANG>
+0E07 ; [.1BBA.0020.0002.0E07] # THAI CHARACTER NGO NGU
+0E40 0E07 ; [.1BBA.0020.0002.0E07][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER NGO NGU>
+0E41 0E07 ; [.1BBA.0020.0002.0E07][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER NGO NGU>
+0E42 0E07 ; [.1BBA.0020.0002.0E07][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER NGO NGU>
+0E43 0E07 ; [.1BBA.0020.0002.0E07][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER NGO NGU>
+0E44 0E07 ; [.1BBA.0020.0002.0E07][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER NGO NGU>
+0E08 ; [.1BBB.0020.0002.0E08] # THAI CHARACTER CHO CHAN
+0E40 0E08 ; [.1BBB.0020.0002.0E08][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER CHO CHAN>
+0E41 0E08 ; [.1BBB.0020.0002.0E08][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER CHO CHAN>
+0E42 0E08 ; [.1BBB.0020.0002.0E08][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER CHO CHAN>
+0E43 0E08 ; [.1BBB.0020.0002.0E08][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER CHO CHAN>
+0E44 0E08 ; [.1BBB.0020.0002.0E08][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER CHO CHAN>
+0E09 ; [.1BBC.0020.0002.0E09] # THAI CHARACTER CHO CHING
+0E40 0E09 ; [.1BBC.0020.0002.0E09][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER CHO CHING>
+0E41 0E09 ; [.1BBC.0020.0002.0E09][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER CHO CHING>
+0E42 0E09 ; [.1BBC.0020.0002.0E09][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER CHO CHING>
+0E43 0E09 ; [.1BBC.0020.0002.0E09][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER CHO CHING>
+0E44 0E09 ; [.1BBC.0020.0002.0E09][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER CHO CHING>
+0E0A ; [.1BBD.0020.0002.0E0A] # THAI CHARACTER CHO CHANG
+0E40 0E0A ; [.1BBD.0020.0002.0E0A][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER CHO CHANG>
+0E41 0E0A ; [.1BBD.0020.0002.0E0A][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER CHO CHANG>
+0E42 0E0A ; [.1BBD.0020.0002.0E0A][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER CHO CHANG>
+0E43 0E0A ; [.1BBD.0020.0002.0E0A][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER CHO CHANG>
+0E44 0E0A ; [.1BBD.0020.0002.0E0A][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER CHO CHANG>
+0E0B ; [.1BBE.0020.0002.0E0B] # THAI CHARACTER SO SO
+0E40 0E0B ; [.1BBE.0020.0002.0E0B][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER SO SO>
+0E41 0E0B ; [.1BBE.0020.0002.0E0B][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER SO SO>
+0E42 0E0B ; [.1BBE.0020.0002.0E0B][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER SO SO>
+0E43 0E0B ; [.1BBE.0020.0002.0E0B][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER SO SO>
+0E44 0E0B ; [.1BBE.0020.0002.0E0B][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER SO SO>
+0E0C ; [.1BBF.0020.0002.0E0C] # THAI CHARACTER CHO CHOE
+0E40 0E0C ; [.1BBF.0020.0002.0E0C][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER CHO CHOE>
+0E41 0E0C ; [.1BBF.0020.0002.0E0C][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER CHO CHOE>
+0E42 0E0C ; [.1BBF.0020.0002.0E0C][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER CHO CHOE>
+0E43 0E0C ; [.1BBF.0020.0002.0E0C][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER CHO CHOE>
+0E44 0E0C ; [.1BBF.0020.0002.0E0C][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER CHO CHOE>
+0E0D ; [.1BC0.0020.0002.0E0D] # THAI CHARACTER YO YING
+0E40 0E0D ; [.1BC0.0020.0002.0E0D][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER YO YING>
+0E41 0E0D ; [.1BC0.0020.0002.0E0D][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER YO YING>
+0E42 0E0D ; [.1BC0.0020.0002.0E0D][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER YO YING>
+0E43 0E0D ; [.1BC0.0020.0002.0E0D][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER YO YING>
+0E44 0E0D ; [.1BC0.0020.0002.0E0D][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER YO YING>
+0E0E ; [.1BC1.0020.0002.0E0E] # THAI CHARACTER DO CHADA
+0E40 0E0E ; [.1BC1.0020.0002.0E0E][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER DO CHADA>
+0E41 0E0E ; [.1BC1.0020.0002.0E0E][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER DO CHADA>
+0E42 0E0E ; [.1BC1.0020.0002.0E0E][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER DO CHADA>
+0E43 0E0E ; [.1BC1.0020.0002.0E0E][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER DO CHADA>
+0E44 0E0E ; [.1BC1.0020.0002.0E0E][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER DO CHADA>
+0E0F ; [.1BC2.0020.0002.0E0F] # THAI CHARACTER TO PATAK
+0E40 0E0F ; [.1BC2.0020.0002.0E0F][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER TO PATAK>
+0E41 0E0F ; [.1BC2.0020.0002.0E0F][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER TO PATAK>
+0E42 0E0F ; [.1BC2.0020.0002.0E0F][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER TO PATAK>
+0E43 0E0F ; [.1BC2.0020.0002.0E0F][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER TO PATAK>
+0E44 0E0F ; [.1BC2.0020.0002.0E0F][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER TO PATAK>
+0E10 ; [.1BC3.0020.0002.0E10] # THAI CHARACTER THO THAN
+0E40 0E10 ; [.1BC3.0020.0002.0E10][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER THO THAN>
+0E41 0E10 ; [.1BC3.0020.0002.0E10][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER THO THAN>
+0E42 0E10 ; [.1BC3.0020.0002.0E10][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER THO THAN>
+0E43 0E10 ; [.1BC3.0020.0002.0E10][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER THO THAN>
+0E44 0E10 ; [.1BC3.0020.0002.0E10][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER THO THAN>
+0E11 ; [.1BC4.0020.0002.0E11] # THAI CHARACTER THO NANGMONTHO
+0E40 0E11 ; [.1BC4.0020.0002.0E11][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER THO NANGMONTHO>
+0E41 0E11 ; [.1BC4.0020.0002.0E11][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER THO NANGMONTHO>
+0E42 0E11 ; [.1BC4.0020.0002.0E11][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER THO NANGMONTHO>
+0E43 0E11 ; [.1BC4.0020.0002.0E11][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER THO NANGMONTHO>
+0E44 0E11 ; [.1BC4.0020.0002.0E11][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER THO NANGMONTHO>
+0E12 ; [.1BC5.0020.0002.0E12] # THAI CHARACTER THO PHUTHAO
+0E40 0E12 ; [.1BC5.0020.0002.0E12][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER THO PHUTHAO>
+0E41 0E12 ; [.1BC5.0020.0002.0E12][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER THO PHUTHAO>
+0E42 0E12 ; [.1BC5.0020.0002.0E12][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER THO PHUTHAO>
+0E43 0E12 ; [.1BC5.0020.0002.0E12][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER THO PHUTHAO>
+0E44 0E12 ; [.1BC5.0020.0002.0E12][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER THO PHUTHAO>
+0E13 ; [.1BC6.0020.0002.0E13] # THAI CHARACTER NO NEN
+0E40 0E13 ; [.1BC6.0020.0002.0E13][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER NO NEN>
+0E41 0E13 ; [.1BC6.0020.0002.0E13][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER NO NEN>
+0E42 0E13 ; [.1BC6.0020.0002.0E13][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER NO NEN>
+0E43 0E13 ; [.1BC6.0020.0002.0E13][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER NO NEN>
+0E44 0E13 ; [.1BC6.0020.0002.0E13][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER NO NEN>
+0E14 ; [.1BC7.0020.0002.0E14] # THAI CHARACTER DO DEK
+0E40 0E14 ; [.1BC7.0020.0002.0E14][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER DO DEK>
+0E41 0E14 ; [.1BC7.0020.0002.0E14][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER DO DEK>
+0E42 0E14 ; [.1BC7.0020.0002.0E14][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER DO DEK>
+0E43 0E14 ; [.1BC7.0020.0002.0E14][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER DO DEK>
+0E44 0E14 ; [.1BC7.0020.0002.0E14][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER DO DEK>
+0E15 ; [.1BC8.0020.0002.0E15] # THAI CHARACTER TO TAO
+0E40 0E15 ; [.1BC8.0020.0002.0E15][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER TO TAO>
+0E41 0E15 ; [.1BC8.0020.0002.0E15][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER TO TAO>
+0E42 0E15 ; [.1BC8.0020.0002.0E15][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER TO TAO>
+0E43 0E15 ; [.1BC8.0020.0002.0E15][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER TO TAO>
+0E44 0E15 ; [.1BC8.0020.0002.0E15][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER TO TAO>
+0E16 ; [.1BC9.0020.0002.0E16] # THAI CHARACTER THO THUNG
+0E40 0E16 ; [.1BC9.0020.0002.0E16][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER THO THUNG>
+0E41 0E16 ; [.1BC9.0020.0002.0E16][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER THO THUNG>
+0E42 0E16 ; [.1BC9.0020.0002.0E16][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER THO THUNG>
+0E43 0E16 ; [.1BC9.0020.0002.0E16][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER THO THUNG>
+0E44 0E16 ; [.1BC9.0020.0002.0E16][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER THO THUNG>
+0E17 ; [.1BCA.0020.0002.0E17] # THAI CHARACTER THO THAHAN
+0E40 0E17 ; [.1BCA.0020.0002.0E17][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER THO THAHAN>
+0E41 0E17 ; [.1BCA.0020.0002.0E17][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER THO THAHAN>
+0E42 0E17 ; [.1BCA.0020.0002.0E17][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER THO THAHAN>
+0E43 0E17 ; [.1BCA.0020.0002.0E17][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER THO THAHAN>
+0E44 0E17 ; [.1BCA.0020.0002.0E17][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER THO THAHAN>
+0E18 ; [.1BCB.0020.0002.0E18] # THAI CHARACTER THO THONG
+0E40 0E18 ; [.1BCB.0020.0002.0E18][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER THO THONG>
+0E41 0E18 ; [.1BCB.0020.0002.0E18][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER THO THONG>
+0E42 0E18 ; [.1BCB.0020.0002.0E18][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER THO THONG>
+0E43 0E18 ; [.1BCB.0020.0002.0E18][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER THO THONG>
+0E44 0E18 ; [.1BCB.0020.0002.0E18][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER THO THONG>
+0E19 ; [.1BCC.0020.0002.0E19] # THAI CHARACTER NO NU
+0E40 0E19 ; [.1BCC.0020.0002.0E19][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER NO NU>
+0E41 0E19 ; [.1BCC.0020.0002.0E19][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER NO NU>
+0E42 0E19 ; [.1BCC.0020.0002.0E19][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER NO NU>
+0E43 0E19 ; [.1BCC.0020.0002.0E19][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER NO NU>
+0E44 0E19 ; [.1BCC.0020.0002.0E19][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER NO NU>
+0E1A ; [.1BCD.0020.0002.0E1A] # THAI CHARACTER BO BAIMAI
+0E40 0E1A ; [.1BCD.0020.0002.0E1A][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER BO BAIMAI>
+0E41 0E1A ; [.1BCD.0020.0002.0E1A][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER BO BAIMAI>
+0E42 0E1A ; [.1BCD.0020.0002.0E1A][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER BO BAIMAI>
+0E43 0E1A ; [.1BCD.0020.0002.0E1A][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER BO BAIMAI>
+0E44 0E1A ; [.1BCD.0020.0002.0E1A][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER BO BAIMAI>
+0E1B ; [.1BCE.0020.0002.0E1B] # THAI CHARACTER PO PLA
+0E40 0E1B ; [.1BCE.0020.0002.0E1B][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER PO PLA>
+0E41 0E1B ; [.1BCE.0020.0002.0E1B][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER PO PLA>
+0E42 0E1B ; [.1BCE.0020.0002.0E1B][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER PO PLA>
+0E43 0E1B ; [.1BCE.0020.0002.0E1B][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER PO PLA>
+0E44 0E1B ; [.1BCE.0020.0002.0E1B][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER PO PLA>
+0E1C ; [.1BCF.0020.0002.0E1C] # THAI CHARACTER PHO PHUNG
+0E40 0E1C ; [.1BCF.0020.0002.0E1C][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER PHO PHUNG>
+0E41 0E1C ; [.1BCF.0020.0002.0E1C][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER PHO PHUNG>
+0E42 0E1C ; [.1BCF.0020.0002.0E1C][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER PHO PHUNG>
+0E43 0E1C ; [.1BCF.0020.0002.0E1C][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER PHO PHUNG>
+0E44 0E1C ; [.1BCF.0020.0002.0E1C][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER PHO PHUNG>
+0E1D ; [.1BD0.0020.0002.0E1D] # THAI CHARACTER FO FA
+0E40 0E1D ; [.1BD0.0020.0002.0E1D][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER FO FA>
+0E41 0E1D ; [.1BD0.0020.0002.0E1D][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER FO FA>
+0E42 0E1D ; [.1BD0.0020.0002.0E1D][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER FO FA>
+0E43 0E1D ; [.1BD0.0020.0002.0E1D][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER FO FA>
+0E44 0E1D ; [.1BD0.0020.0002.0E1D][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER FO FA>
+0E1E ; [.1BD1.0020.0002.0E1E] # THAI CHARACTER PHO PHAN
+0E40 0E1E ; [.1BD1.0020.0002.0E1E][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER PHO PHAN>
+0E41 0E1E ; [.1BD1.0020.0002.0E1E][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER PHO PHAN>
+0E42 0E1E ; [.1BD1.0020.0002.0E1E][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER PHO PHAN>
+0E43 0E1E ; [.1BD1.0020.0002.0E1E][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER PHO PHAN>
+0E44 0E1E ; [.1BD1.0020.0002.0E1E][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER PHO PHAN>
+0E1F ; [.1BD2.0020.0002.0E1F] # THAI CHARACTER FO FAN
+0E40 0E1F ; [.1BD2.0020.0002.0E1F][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER FO FAN>
+0E41 0E1F ; [.1BD2.0020.0002.0E1F][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER FO FAN>
+0E42 0E1F ; [.1BD2.0020.0002.0E1F][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER FO FAN>
+0E43 0E1F ; [.1BD2.0020.0002.0E1F][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER FO FAN>
+0E44 0E1F ; [.1BD2.0020.0002.0E1F][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER FO FAN>
+0E20 ; [.1BD3.0020.0002.0E20] # THAI CHARACTER PHO SAMPHAO
+0E40 0E20 ; [.1BD3.0020.0002.0E20][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER PHO SAMPHAO>
+0E41 0E20 ; [.1BD3.0020.0002.0E20][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER PHO SAMPHAO>
+0E42 0E20 ; [.1BD3.0020.0002.0E20][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER PHO SAMPHAO>
+0E43 0E20 ; [.1BD3.0020.0002.0E20][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER PHO SAMPHAO>
+0E44 0E20 ; [.1BD3.0020.0002.0E20][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER PHO SAMPHAO>
+0E21 ; [.1BD4.0020.0002.0E21] # THAI CHARACTER MO MA
+0E40 0E21 ; [.1BD4.0020.0002.0E21][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER MO MA>
+0E41 0E21 ; [.1BD4.0020.0002.0E21][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER MO MA>
+0E42 0E21 ; [.1BD4.0020.0002.0E21][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER MO MA>
+0E43 0E21 ; [.1BD4.0020.0002.0E21][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER MO MA>
+0E44 0E21 ; [.1BD4.0020.0002.0E21][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER MO MA>
+0E22 ; [.1BD5.0020.0002.0E22] # THAI CHARACTER YO YAK
+0E40 0E22 ; [.1BD5.0020.0002.0E22][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER YO YAK>
+0E41 0E22 ; [.1BD5.0020.0002.0E22][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER YO YAK>
+0E42 0E22 ; [.1BD5.0020.0002.0E22][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER YO YAK>
+0E43 0E22 ; [.1BD5.0020.0002.0E22][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER YO YAK>
+0E44 0E22 ; [.1BD5.0020.0002.0E22][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER YO YAK>
+0E23 ; [.1BD6.0020.0002.0E23] # THAI CHARACTER RO RUA
+0E40 0E23 ; [.1BD6.0020.0002.0E23][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER RO RUA>
+0E41 0E23 ; [.1BD6.0020.0002.0E23][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER RO RUA>
+0E42 0E23 ; [.1BD6.0020.0002.0E23][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER RO RUA>
+0E43 0E23 ; [.1BD6.0020.0002.0E23][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER RO RUA>
+0E44 0E23 ; [.1BD6.0020.0002.0E23][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER RO RUA>
+0E24 ; [.1BD7.0020.0002.0E24] # THAI CHARACTER RU
+0E40 0E24 ; [.1BD7.0020.0002.0E24][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER RU>
+0E41 0E24 ; [.1BD7.0020.0002.0E24][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER RU>
+0E42 0E24 ; [.1BD7.0020.0002.0E24][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER RU>
+0E43 0E24 ; [.1BD7.0020.0002.0E24][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER RU>
+0E44 0E24 ; [.1BD7.0020.0002.0E24][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER RU>
+0E25 ; [.1BD8.0020.0002.0E25] # THAI CHARACTER LO LING
+0E40 0E25 ; [.1BD8.0020.0002.0E25][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER LO LING>
+0E41 0E25 ; [.1BD8.0020.0002.0E25][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER LO LING>
+0E42 0E25 ; [.1BD8.0020.0002.0E25][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER LO LING>
+0E43 0E25 ; [.1BD8.0020.0002.0E25][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER LO LING>
+0E44 0E25 ; [.1BD8.0020.0002.0E25][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER LO LING>
+0E26 ; [.1BD9.0020.0002.0E26] # THAI CHARACTER LU
+0E40 0E26 ; [.1BD9.0020.0002.0E26][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER LU>
+0E41 0E26 ; [.1BD9.0020.0002.0E26][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER LU>
+0E42 0E26 ; [.1BD9.0020.0002.0E26][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER LU>
+0E43 0E26 ; [.1BD9.0020.0002.0E26][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER LU>
+0E44 0E26 ; [.1BD9.0020.0002.0E26][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER LU>
+0E27 ; [.1BDA.0020.0002.0E27] # THAI CHARACTER WO WAEN
+0E40 0E27 ; [.1BDA.0020.0002.0E27][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER WO WAEN>
+0E41 0E27 ; [.1BDA.0020.0002.0E27][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER WO WAEN>
+0E42 0E27 ; [.1BDA.0020.0002.0E27][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER WO WAEN>
+0E43 0E27 ; [.1BDA.0020.0002.0E27][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER WO WAEN>
+0E44 0E27 ; [.1BDA.0020.0002.0E27][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER WO WAEN>
+0E28 ; [.1BDB.0020.0002.0E28] # THAI CHARACTER SO SALA
+0E40 0E28 ; [.1BDB.0020.0002.0E28][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER SO SALA>
+0E41 0E28 ; [.1BDB.0020.0002.0E28][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER SO SALA>
+0E42 0E28 ; [.1BDB.0020.0002.0E28][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER SO SALA>
+0E43 0E28 ; [.1BDB.0020.0002.0E28][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER SO SALA>
+0E44 0E28 ; [.1BDB.0020.0002.0E28][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER SO SALA>
+0E29 ; [.1BDC.0020.0002.0E29] # THAI CHARACTER SO RUSI
+0E40 0E29 ; [.1BDC.0020.0002.0E29][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER SO RUSI>
+0E41 0E29 ; [.1BDC.0020.0002.0E29][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER SO RUSI>
+0E42 0E29 ; [.1BDC.0020.0002.0E29][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER SO RUSI>
+0E43 0E29 ; [.1BDC.0020.0002.0E29][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER SO RUSI>
+0E44 0E29 ; [.1BDC.0020.0002.0E29][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER SO RUSI>
+0E2A ; [.1BDD.0020.0002.0E2A] # THAI CHARACTER SO SUA
+0E40 0E2A ; [.1BDD.0020.0002.0E2A][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER SO SUA>
+0E41 0E2A ; [.1BDD.0020.0002.0E2A][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER SO SUA>
+0E42 0E2A ; [.1BDD.0020.0002.0E2A][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER SO SUA>
+0E43 0E2A ; [.1BDD.0020.0002.0E2A][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER SO SUA>
+0E44 0E2A ; [.1BDD.0020.0002.0E2A][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER SO SUA>
+0E2B ; [.1BDE.0020.0002.0E2B] # THAI CHARACTER HO HIP
+0E40 0E2B ; [.1BDE.0020.0002.0E2B][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER HO HIP>
+0E41 0E2B ; [.1BDE.0020.0002.0E2B][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER HO HIP>
+0E42 0E2B ; [.1BDE.0020.0002.0E2B][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER HO HIP>
+0E43 0E2B ; [.1BDE.0020.0002.0E2B][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER HO HIP>
+0E44 0E2B ; [.1BDE.0020.0002.0E2B][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER HO HIP>
+0E2C ; [.1BDF.0020.0002.0E2C] # THAI CHARACTER LO CHULA
+0E40 0E2C ; [.1BDF.0020.0002.0E2C][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER LO CHULA>
+0E41 0E2C ; [.1BDF.0020.0002.0E2C][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER LO CHULA>
+0E42 0E2C ; [.1BDF.0020.0002.0E2C][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER LO CHULA>
+0E43 0E2C ; [.1BDF.0020.0002.0E2C][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER LO CHULA>
+0E44 0E2C ; [.1BDF.0020.0002.0E2C][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER LO CHULA>
+0E2D ; [.1BE0.0020.0002.0E2D] # THAI CHARACTER O ANG
+0E40 0E2D ; [.1BE0.0020.0002.0E2D][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER O ANG>
+0E41 0E2D ; [.1BE0.0020.0002.0E2D][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER O ANG>
+0E42 0E2D ; [.1BE0.0020.0002.0E2D][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER O ANG>
+0E43 0E2D ; [.1BE0.0020.0002.0E2D][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER O ANG>
+0E44 0E2D ; [.1BE0.0020.0002.0E2D][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER O ANG>
+0E2E ; [.1BE1.0020.0002.0E2E] # THAI CHARACTER HO NOKHUK
+0E40 0E2E ; [.1BE1.0020.0002.0E2E][.1BEE.0020.001F.0E40] # <THAI CHARACTER SARA E, THAI CHARACTER HO NOKHUK>
+0E41 0E2E ; [.1BE1.0020.0002.0E2E][.1BEF.0020.001F.0E41] # <THAI CHARACTER SARA AE, THAI CHARACTER HO NOKHUK>
+0E42 0E2E ; [.1BE1.0020.0002.0E2E][.1BF0.0020.001F.0E42] # <THAI CHARACTER SARA O, THAI CHARACTER HO NOKHUK>
+0E43 0E2E ; [.1BE1.0020.0002.0E2E][.1BF1.0020.001F.0E43] # <THAI CHARACTER SARA AI MAIMUAN, THAI CHARACTER HO NOKHUK>
+0E44 0E2E ; [.1BE1.0020.0002.0E2E][.1BF2.0020.001F.0E44] # <THAI CHARACTER SARA AI MAIMALAI, THAI CHARACTER HO NOKHUK>
+0E2F ; [.1BE2.0020.0002.0E2F] # THAI CHARACTER PAIYANNOI
+0E30 ; [.1BE3.0020.0002.0E30] # THAI CHARACTER SARA A
+0E31 ; [.1BE4.0020.0002.0E31] # THAI CHARACTER MAI HAN-AKAT
+0E32 ; [.1BE5.0020.0002.0E32] # THAI CHARACTER SARA AA
+0E33 ; [.1BE6.0020.0002.0E33] # THAI CHARACTER SARA AM
+0E4D 0E32 ; [.1BE6.0020.0002.0E33] # THAI CHARACTER SARA AM
+0E34 ; [.1BE7.0020.0002.0E34] # THAI CHARACTER SARA I
+0E35 ; [.1BE8.0020.0002.0E35] # THAI CHARACTER SARA II
+0E36 ; [.1BE9.0020.0002.0E36] # THAI CHARACTER SARA UE
+0E37 ; [.1BEA.0020.0002.0E37] # THAI CHARACTER SARA UEE
+0E38 ; [.1BEB.0020.0002.0E38] # THAI CHARACTER SARA U
+0E39 ; [.1BEC.0020.0002.0E39] # THAI CHARACTER SARA UU
+0E3A ; [.1BED.0020.0002.0E3A] # THAI CHARACTER PHINTHU
+0E40 ; [.1BEE.0020.0002.0E40] # THAI CHARACTER SARA E
+0E41 ; [.1BEF.0020.0002.0E41] # THAI CHARACTER SARA AE
+0E42 ; [.1BF0.0020.0002.0E42] # THAI CHARACTER SARA O
+0E43 ; [.1BF1.0020.0002.0E43] # THAI CHARACTER SARA AI MAIMUAN
+0E44 ; [.1BF2.0020.0002.0E44] # THAI CHARACTER SARA AI MAIMALAI
+0E45 ; [.1BF3.0020.0002.0E45] # THAI CHARACTER LAKKHANGYAO
+0E81 ; [.1BF4.0020.0002.0E81] # LAO LETTER KO
+0EC0 0E81 ; [.1BF4.0020.0002.0E81][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER KO>
+0EC1 0E81 ; [.1BF4.0020.0002.0E81][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER KO>
+0EC2 0E81 ; [.1BF4.0020.0002.0E81][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER KO>
+0EC3 0E81 ; [.1BF4.0020.0002.0E81][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER KO>
+0EC4 0E81 ; [.1BF4.0020.0002.0E81][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER KO>
+0E82 ; [.1BF5.0020.0002.0E82] # LAO LETTER KHO SUNG
+0EC0 0E82 ; [.1BF5.0020.0002.0E82][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER KHO SUNG>
+0EC1 0E82 ; [.1BF5.0020.0002.0E82][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER KHO SUNG>
+0EC2 0E82 ; [.1BF5.0020.0002.0E82][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER KHO SUNG>
+0EC3 0E82 ; [.1BF5.0020.0002.0E82][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER KHO SUNG>
+0EC4 0E82 ; [.1BF5.0020.0002.0E82][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER KHO SUNG>
+0E84 ; [.1BF6.0020.0002.0E84] # LAO LETTER KHO TAM
+0EC0 0E84 ; [.1BF6.0020.0002.0E84][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER KHO TAM>
+0EC1 0E84 ; [.1BF6.0020.0002.0E84][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER KHO TAM>
+0EC2 0E84 ; [.1BF6.0020.0002.0E84][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER KHO TAM>
+0EC3 0E84 ; [.1BF6.0020.0002.0E84][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER KHO TAM>
+0EC4 0E84 ; [.1BF6.0020.0002.0E84][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER KHO TAM>
+0E87 ; [.1BF7.0020.0002.0E87] # LAO LETTER NGO
+0EC0 0E87 ; [.1BF7.0020.0002.0E87][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER NGO>
+0EC1 0E87 ; [.1BF7.0020.0002.0E87][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER NGO>
+0EC2 0E87 ; [.1BF7.0020.0002.0E87][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER NGO>
+0EC3 0E87 ; [.1BF7.0020.0002.0E87][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER NGO>
+0EC4 0E87 ; [.1BF7.0020.0002.0E87][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER NGO>
+0E88 ; [.1BF8.0020.0002.0E88] # LAO LETTER CO
+0EC0 0E88 ; [.1BF8.0020.0002.0E88][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER CO>
+0EC1 0E88 ; [.1BF8.0020.0002.0E88][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER CO>
+0EC2 0E88 ; [.1BF8.0020.0002.0E88][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER CO>
+0EC3 0E88 ; [.1BF8.0020.0002.0E88][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER CO>
+0EC4 0E88 ; [.1BF8.0020.0002.0E88][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER CO>
+0E8A ; [.1BF9.0020.0002.0E8A] # LAO LETTER SO TAM
+0EC0 0E8A ; [.1BF9.0020.0002.0E8A][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER SO TAM>
+0EC1 0E8A ; [.1BF9.0020.0002.0E8A][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER SO TAM>
+0EC2 0E8A ; [.1BF9.0020.0002.0E8A][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER SO TAM>
+0EC3 0E8A ; [.1BF9.0020.0002.0E8A][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER SO TAM>
+0EC4 0E8A ; [.1BF9.0020.0002.0E8A][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER SO TAM>
+0E8D ; [.1BFA.0020.0002.0E8D] # LAO LETTER NYO
+0EC0 0E8D ; [.1BFA.0020.0002.0E8D][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER NYO>
+0EC1 0E8D ; [.1BFA.0020.0002.0E8D][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER NYO>
+0EC2 0E8D ; [.1BFA.0020.0002.0E8D][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER NYO>
+0EC3 0E8D ; [.1BFA.0020.0002.0E8D][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER NYO>
+0EC4 0E8D ; [.1BFA.0020.0002.0E8D][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER NYO>
+0E94 ; [.1BFB.0020.0002.0E94] # LAO LETTER DO
+0EC0 0E94 ; [.1BFB.0020.0002.0E94][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER DO>
+0EC1 0E94 ; [.1BFB.0020.0002.0E94][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER DO>
+0EC2 0E94 ; [.1BFB.0020.0002.0E94][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER DO>
+0EC3 0E94 ; [.1BFB.0020.0002.0E94][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER DO>
+0EC4 0E94 ; [.1BFB.0020.0002.0E94][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER DO>
+0E95 ; [.1BFC.0020.0002.0E95] # LAO LETTER TO
+0EC0 0E95 ; [.1BFC.0020.0002.0E95][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER TO>
+0EC1 0E95 ; [.1BFC.0020.0002.0E95][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER TO>
+0EC2 0E95 ; [.1BFC.0020.0002.0E95][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER TO>
+0EC3 0E95 ; [.1BFC.0020.0002.0E95][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER TO>
+0EC4 0E95 ; [.1BFC.0020.0002.0E95][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER TO>
+0E96 ; [.1BFD.0020.0002.0E96] # LAO LETTER THO SUNG
+0EC0 0E96 ; [.1BFD.0020.0002.0E96][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER THO SUNG>
+0EC1 0E96 ; [.1BFD.0020.0002.0E96][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER THO SUNG>
+0EC2 0E96 ; [.1BFD.0020.0002.0E96][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER THO SUNG>
+0EC3 0E96 ; [.1BFD.0020.0002.0E96][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER THO SUNG>
+0EC4 0E96 ; [.1BFD.0020.0002.0E96][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER THO SUNG>
+0E97 ; [.1BFE.0020.0002.0E97] # LAO LETTER THO TAM
+0EC0 0E97 ; [.1BFE.0020.0002.0E97][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER THO TAM>
+0EC1 0E97 ; [.1BFE.0020.0002.0E97][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER THO TAM>
+0EC2 0E97 ; [.1BFE.0020.0002.0E97][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER THO TAM>
+0EC3 0E97 ; [.1BFE.0020.0002.0E97][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER THO TAM>
+0EC4 0E97 ; [.1BFE.0020.0002.0E97][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER THO TAM>
+0E99 ; [.1BFF.0020.0002.0E99] # LAO LETTER NO
+0EC0 0E99 ; [.1BFF.0020.0002.0E99][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER NO>
+0EC1 0E99 ; [.1BFF.0020.0002.0E99][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER NO>
+0EC2 0E99 ; [.1BFF.0020.0002.0E99][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER NO>
+0EC3 0E99 ; [.1BFF.0020.0002.0E99][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER NO>
+0EC4 0E99 ; [.1BFF.0020.0002.0E99][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER NO>
+0E9A ; [.1C00.0020.0002.0E9A] # LAO LETTER BO
+0EC0 0E9A ; [.1C00.0020.0002.0E9A][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER BO>
+0EC1 0E9A ; [.1C00.0020.0002.0E9A][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER BO>
+0EC2 0E9A ; [.1C00.0020.0002.0E9A][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER BO>
+0EC3 0E9A ; [.1C00.0020.0002.0E9A][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER BO>
+0EC4 0E9A ; [.1C00.0020.0002.0E9A][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER BO>
+0E9B ; [.1C01.0020.0002.0E9B] # LAO LETTER PO
+0EC0 0E9B ; [.1C01.0020.0002.0E9B][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER PO>
+0EC1 0E9B ; [.1C01.0020.0002.0E9B][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER PO>
+0EC2 0E9B ; [.1C01.0020.0002.0E9B][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER PO>
+0EC3 0E9B ; [.1C01.0020.0002.0E9B][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER PO>
+0EC4 0E9B ; [.1C01.0020.0002.0E9B][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER PO>
+0E9C ; [.1C02.0020.0002.0E9C] # LAO LETTER PHO SUNG
+0EC0 0E9C ; [.1C02.0020.0002.0E9C][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER PHO SUNG>
+0EC1 0E9C ; [.1C02.0020.0002.0E9C][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER PHO SUNG>
+0EC2 0E9C ; [.1C02.0020.0002.0E9C][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER PHO SUNG>
+0EC3 0E9C ; [.1C02.0020.0002.0E9C][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER PHO SUNG>
+0EC4 0E9C ; [.1C02.0020.0002.0E9C][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER PHO SUNG>
+0E9D ; [.1C03.0020.0002.0E9D] # LAO LETTER FO TAM
+0EC0 0E9D ; [.1C03.0020.0002.0E9D][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER FO TAM>
+0EC1 0E9D ; [.1C03.0020.0002.0E9D][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER FO TAM>
+0EC2 0E9D ; [.1C03.0020.0002.0E9D][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER FO TAM>
+0EC3 0E9D ; [.1C03.0020.0002.0E9D][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER FO TAM>
+0EC4 0E9D ; [.1C03.0020.0002.0E9D][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER FO TAM>
+0E9E ; [.1C04.0020.0002.0E9E] # LAO LETTER PHO TAM
+0EC0 0E9E ; [.1C04.0020.0002.0E9E][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER PHO TAM>
+0EC1 0E9E ; [.1C04.0020.0002.0E9E][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER PHO TAM>
+0EC2 0E9E ; [.1C04.0020.0002.0E9E][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER PHO TAM>
+0EC3 0E9E ; [.1C04.0020.0002.0E9E][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER PHO TAM>
+0EC4 0E9E ; [.1C04.0020.0002.0E9E][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER PHO TAM>
+0E9F ; [.1C05.0020.0002.0E9F] # LAO LETTER FO SUNG
+0EC0 0E9F ; [.1C05.0020.0002.0E9F][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER FO SUNG>
+0EC1 0E9F ; [.1C05.0020.0002.0E9F][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER FO SUNG>
+0EC2 0E9F ; [.1C05.0020.0002.0E9F][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER FO SUNG>
+0EC3 0E9F ; [.1C05.0020.0002.0E9F][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER FO SUNG>
+0EC4 0E9F ; [.1C05.0020.0002.0E9F][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER FO SUNG>
+0EA1 ; [.1C06.0020.0002.0EA1] # LAO LETTER MO
+0EC0 0EA1 ; [.1C06.0020.0002.0EA1][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER MO>
+0EC1 0EA1 ; [.1C06.0020.0002.0EA1][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER MO>
+0EC2 0EA1 ; [.1C06.0020.0002.0EA1][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER MO>
+0EC3 0EA1 ; [.1C06.0020.0002.0EA1][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER MO>
+0EC4 0EA1 ; [.1C06.0020.0002.0EA1][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER MO>
+0EA2 ; [.1C07.0020.0002.0EA2] # LAO LETTER YO
+0EC0 0EA2 ; [.1C07.0020.0002.0EA2][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER YO>
+0EC1 0EA2 ; [.1C07.0020.0002.0EA2][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER YO>
+0EC2 0EA2 ; [.1C07.0020.0002.0EA2][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER YO>
+0EC3 0EA2 ; [.1C07.0020.0002.0EA2][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER YO>
+0EC4 0EA2 ; [.1C07.0020.0002.0EA2][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER YO>
+0EA3 ; [.1C08.0020.0002.0EA3] # LAO LETTER LO LING
+0EC0 0EA3 ; [.1C08.0020.0002.0EA3][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER LO LING>
+0EC1 0EA3 ; [.1C08.0020.0002.0EA3][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER LO LING>
+0EC2 0EA3 ; [.1C08.0020.0002.0EA3][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER LO LING>
+0EC3 0EA3 ; [.1C08.0020.0002.0EA3][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER LO LING>
+0EC4 0EA3 ; [.1C08.0020.0002.0EA3][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER LO LING>
+0EA5 ; [.1C09.0020.0002.0EA5] # LAO LETTER LO LOOT
+0EC0 0EA5 ; [.1C09.0020.0002.0EA5][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER LO LOOT>
+0EC1 0EA5 ; [.1C09.0020.0002.0EA5][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER LO LOOT>
+0EC2 0EA5 ; [.1C09.0020.0002.0EA5][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER LO LOOT>
+0EC3 0EA5 ; [.1C09.0020.0002.0EA5][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER LO LOOT>
+0EC4 0EA5 ; [.1C09.0020.0002.0EA5][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER LO LOOT>
+0EA7 ; [.1C0A.0020.0002.0EA7] # LAO LETTER WO
+0EC0 0EA7 ; [.1C0A.0020.0002.0EA7][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER WO>
+0EC1 0EA7 ; [.1C0A.0020.0002.0EA7][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER WO>
+0EC2 0EA7 ; [.1C0A.0020.0002.0EA7][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER WO>
+0EC3 0EA7 ; [.1C0A.0020.0002.0EA7][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER WO>
+0EC4 0EA7 ; [.1C0A.0020.0002.0EA7][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER WO>
+0EAA ; [.1C0B.0020.0002.0EAA] # LAO LETTER SO SUNG
+0EC0 0EAA ; [.1C0B.0020.0002.0EAA][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER SO SUNG>
+0EC1 0EAA ; [.1C0B.0020.0002.0EAA][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER SO SUNG>
+0EC2 0EAA ; [.1C0B.0020.0002.0EAA][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER SO SUNG>
+0EC3 0EAA ; [.1C0B.0020.0002.0EAA][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER SO SUNG>
+0EC4 0EAA ; [.1C0B.0020.0002.0EAA][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER SO SUNG>
+0EAB ; [.1C0C.0020.0002.0EAB] # LAO LETTER HO SUNG
+0EDC ; [.1C0C.0020.0004.0EDC][.1BFF.0020.0004.0EDC] # LAO HO NO; QQKN
+0EC0 0EDC ; [.1C0C.0020.0004.0EDC][.1BFF.0020.0004.0EDC][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO HO NO>
+0EC1 0EDC ; [.1C0C.0020.0004.0EDC][.1BFF.0020.0004.0EDC][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO HO NO>
+0EC2 0EDC ; [.1C0C.0020.0004.0EDC][.1BFF.0020.0004.0EDC][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO HO NO>
+0EC3 0EDC ; [.1C0C.0020.0004.0EDC][.1BFF.0020.0004.0EDC][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO HO NO>
+0EC4 0EDC ; [.1C0C.0020.0004.0EDC][.1BFF.0020.0004.0EDC][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO HO NO>
+0EDD ; [.1C0C.0020.0004.0EDD][.1C06.0020.0004.0EDD] # LAO HO MO; QQKN
+0EC0 0EDD ; [.1C0C.0020.0004.0EDD][.1C06.0020.0004.0EDD][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO HO MO>
+0EC1 0EDD ; [.1C0C.0020.0004.0EDD][.1C06.0020.0004.0EDD][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO HO MO>
+0EC2 0EDD ; [.1C0C.0020.0004.0EDD][.1C06.0020.0004.0EDD][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO HO MO>
+0EC3 0EDD ; [.1C0C.0020.0004.0EDD][.1C06.0020.0004.0EDD][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO HO MO>
+0EC4 0EDD ; [.1C0C.0020.0004.0EDD][.1C06.0020.0004.0EDD][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO HO MO>
+0EC0 0EAB ; [.1C0C.0020.0002.0EAB][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER HO SUNG>
+0EC1 0EAB ; [.1C0C.0020.0002.0EAB][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER HO SUNG>
+0EC2 0EAB ; [.1C0C.0020.0002.0EAB][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER HO SUNG>
+0EC3 0EAB ; [.1C0C.0020.0002.0EAB][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER HO SUNG>
+0EC4 0EAB ; [.1C0C.0020.0002.0EAB][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER HO SUNG>
+0EAD ; [.1C0D.0020.0002.0EAD] # LAO LETTER O
+0EC0 0EAD ; [.1C0D.0020.0002.0EAD][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER O>
+0EC1 0EAD ; [.1C0D.0020.0002.0EAD][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER O>
+0EC2 0EAD ; [.1C0D.0020.0002.0EAD][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER O>
+0EC3 0EAD ; [.1C0D.0020.0002.0EAD][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER O>
+0EC4 0EAD ; [.1C0D.0020.0002.0EAD][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER O>
+0EAE ; [.1C0E.0020.0002.0EAE] # LAO LETTER HO TAM
+0EC0 0EAE ; [.1C0E.0020.0002.0EAE][.1C1D.0020.001F.0EC0] # <LAO VOWEL SIGN E, LAO LETTER HO TAM>
+0EC1 0EAE ; [.1C0E.0020.0002.0EAE][.1C1E.0020.001F.0EC1] # <LAO VOWEL SIGN EI, LAO LETTER HO TAM>
+0EC2 0EAE ; [.1C0E.0020.0002.0EAE][.1C1F.0020.001F.0EC2] # <LAO VOWEL SIGN O, LAO LETTER HO TAM>
+0EC3 0EAE ; [.1C0E.0020.0002.0EAE][.1C20.0020.001F.0EC3] # <LAO VOWEL SIGN AY, LAO LETTER HO TAM>
+0EC4 0EAE ; [.1C0E.0020.0002.0EAE][.1C21.0020.001F.0EC4] # <LAO VOWEL SIGN AI, LAO LETTER HO TAM>
+0EAF ; [.1C0F.0020.0002.0EAF] # LAO ELLIPSIS
+0EB0 ; [.1C10.0020.0002.0EB0] # LAO VOWEL SIGN A
+0EB1 ; [.1C11.0020.0002.0EB1] # LAO VOWEL SIGN MAI KAN
+0EB2 ; [.1C12.0020.0002.0EB2] # LAO VOWEL SIGN AA
+0EB3 ; [.1C13.0020.0002.0EB3] # LAO VOWEL SIGN AM
+0ECD 0EB2 ; [.1C13.0020.0002.0EB3] # LAO VOWEL SIGN AM
+0EB4 ; [.1C14.0020.0002.0EB4] # LAO VOWEL SIGN I
+0EB5 ; [.1C15.0020.0002.0EB5] # LAO VOWEL SIGN II
+0EB6 ; [.1C16.0020.0002.0EB6] # LAO VOWEL SIGN Y
+0EB7 ; [.1C17.0020.0002.0EB7] # LAO VOWEL SIGN YY
+0EB8 ; [.1C18.0020.0002.0EB8] # LAO VOWEL SIGN U
+0EB9 ; [.1C19.0020.0002.0EB9] # LAO VOWEL SIGN UU
+0EBB ; [.1C1A.0020.0002.0EBB] # LAO VOWEL SIGN MAI KON
+0EBC ; [.1C1B.0020.0002.0EBC] # LAO SEMIVOWEL SIGN LO
+0EBD ; [.1C1C.0020.0002.0EBD] # LAO SEMIVOWEL SIGN NYO
+0EC0 ; [.1C1D.0020.0002.0EC0] # LAO VOWEL SIGN E
+0EC1 ; [.1C1E.0020.0002.0EC1] # LAO VOWEL SIGN EI
+0EC2 ; [.1C1F.0020.0002.0EC2] # LAO VOWEL SIGN O
+0EC3 ; [.1C20.0020.0002.0EC3] # LAO VOWEL SIGN AY
+0EC4 ; [.1C21.0020.0002.0EC4] # LAO VOWEL SIGN AI
+0F40 ; [.1C22.0020.0002.0F40] # TIBETAN LETTER KA
+0F69 ; [.1C22.0020.0002.0F40][.1C61.0020.0002.0FB5] # TIBETAN LETTER KSSA; QQCN
+0F90 ; [.1C23.0020.0002.0F90] # TIBETAN SUBJOINED LETTER KA
+0FB9 ; [.1C23.0020.0002.0F90][.1C61.0020.0002.0FB5] # TIBETAN SUBJOINED LETTER KSSA; QQCN
+0F41 ; [.1C24.0020.0002.0F41] # TIBETAN LETTER KHA
+0F91 ; [.1C25.0020.0002.0F91] # TIBETAN SUBJOINED LETTER KHA
+0F42 ; [.1C26.0020.0002.0F42] # TIBETAN LETTER GA
+0F43 ; [.1C26.0020.0002.0F42][.1C65.0020.0002.0FB7] # TIBETAN LETTER GHA; QQCN
+0F92 ; [.1C27.0020.0002.0F92] # TIBETAN SUBJOINED LETTER GA
+0F93 ; [.1C27.0020.0002.0F92][.1C65.0020.0002.0FB7] # TIBETAN SUBJOINED LETTER GHA; QQCN
+0F44 ; [.1C28.0020.0002.0F44] # TIBETAN LETTER NGA
+0F94 ; [.1C29.0020.0002.0F94] # TIBETAN SUBJOINED LETTER NGA
+0F45 ; [.1C2A.0020.0002.0F45] # TIBETAN LETTER CA
+0F95 ; [.1C2B.0020.0002.0F95] # TIBETAN SUBJOINED LETTER CA
+0F46 ; [.1C2C.0020.0002.0F46] # TIBETAN LETTER CHA
+0F96 ; [.1C2D.0020.0002.0F96] # TIBETAN SUBJOINED LETTER CHA
+0F47 ; [.1C2E.0020.0002.0F47] # TIBETAN LETTER JA
+0F97 ; [.1C2F.0020.0002.0F97] # TIBETAN SUBJOINED LETTER JA
+0F49 ; [.1C30.0020.0002.0F49] # TIBETAN LETTER NYA
+0F99 ; [.1C31.0020.0002.0F99] # TIBETAN SUBJOINED LETTER NYA
+0F4A ; [.1C32.0020.0002.0F4A] # TIBETAN LETTER TTA
+0F9A ; [.1C33.0020.0002.0F9A] # TIBETAN SUBJOINED LETTER TTA
+0F4B ; [.1C34.0020.0002.0F4B] # TIBETAN LETTER TTHA
+0F9B ; [.1C35.0020.0002.0F9B] # TIBETAN SUBJOINED LETTER TTHA
+0F4C ; [.1C36.0020.0002.0F4C] # TIBETAN LETTER DDA
+0F4D ; [.1C36.0020.0002.0F4C][.1C65.0020.0002.0FB7] # TIBETAN LETTER DDHA; QQCN
+0F9C ; [.1C37.0020.0002.0F9C] # TIBETAN SUBJOINED LETTER DDA
+0F9D ; [.1C37.0020.0002.0F9C][.1C65.0020.0002.0FB7] # TIBETAN SUBJOINED LETTER DDHA; QQCN
+0F4E ; [.1C38.0020.0002.0F4E] # TIBETAN LETTER NNA
+0F9E ; [.1C39.0020.0002.0F9E] # TIBETAN SUBJOINED LETTER NNA
+0F4F ; [.1C3A.0020.0002.0F4F] # TIBETAN LETTER TA
+0F9F ; [.1C3B.0020.0002.0F9F] # TIBETAN SUBJOINED LETTER TA
+0F50 ; [.1C3C.0020.0002.0F50] # TIBETAN LETTER THA
+0FA0 ; [.1C3D.0020.0002.0FA0] # TIBETAN SUBJOINED LETTER THA
+0F51 ; [.1C3E.0020.0002.0F51] # TIBETAN LETTER DA
+0F52 ; [.1C3E.0020.0002.0F51][.1C65.0020.0002.0FB7] # TIBETAN LETTER DHA; QQCN
+0FA1 ; [.1C3F.0020.0002.0FA1] # TIBETAN SUBJOINED LETTER DA
+0FA2 ; [.1C3F.0020.0002.0FA1][.1C65.0020.0002.0FB7] # TIBETAN SUBJOINED LETTER DHA; QQCN
+0F53 ; [.1C40.0020.0002.0F53] # TIBETAN LETTER NA
+0FA3 ; [.1C41.0020.0002.0FA3] # TIBETAN SUBJOINED LETTER NA
+0F54 ; [.1C42.0020.0002.0F54] # TIBETAN LETTER PA
+0FA4 ; [.1C43.0020.0002.0FA4] # TIBETAN SUBJOINED LETTER PA
+0F55 ; [.1C44.0020.0002.0F55] # TIBETAN LETTER PHA
+0FA5 ; [.1C45.0020.0002.0FA5] # TIBETAN SUBJOINED LETTER PHA
+0F56 ; [.1C46.0020.0002.0F56] # TIBETAN LETTER BA
+0F57 ; [.1C46.0020.0002.0F56][.1C65.0020.0002.0FB7] # TIBETAN LETTER BHA; QQCN
+0FA6 ; [.1C47.0020.0002.0FA6] # TIBETAN SUBJOINED LETTER BA
+0FA7 ; [.1C47.0020.0002.0FA6][.1C65.0020.0002.0FB7] # TIBETAN SUBJOINED LETTER BHA; QQCN
+0F58 ; [.1C48.0020.0002.0F58] # TIBETAN LETTER MA
+0FA8 ; [.1C49.0020.0002.0FA8] # TIBETAN SUBJOINED LETTER MA
+0F59 ; [.1C4A.0020.0002.0F59] # TIBETAN LETTER TSA
+0FA9 ; [.1C4B.0020.0002.0FA9] # TIBETAN SUBJOINED LETTER TSA
+0F5A ; [.1C4C.0020.0002.0F5A] # TIBETAN LETTER TSHA
+0FAA ; [.1C4D.0020.0002.0FAA] # TIBETAN SUBJOINED LETTER TSHA
+0F5B ; [.1C4E.0020.0002.0F5B] # TIBETAN LETTER DZA
+0F5C ; [.1C4E.0020.0002.0F5B][.1C65.0020.0002.0FB7] # TIBETAN LETTER DZHA; QQCN
+0FAB ; [.1C4F.0020.0002.0FAB] # TIBETAN SUBJOINED LETTER DZA
+0FAC ; [.1C4F.0020.0002.0FAB][.1C65.0020.0002.0FB7] # TIBETAN SUBJOINED LETTER DZHA; QQCN
+0F5D ; [.1C50.0020.0002.0F5D] # TIBETAN LETTER WA
+0FAD ; [.1C51.0020.0002.0FAD] # TIBETAN SUBJOINED LETTER WA
+0FBA ; [.1C51.0020.0004.0FBA][.0000.019A.0004.0FBA] # TIBETAN SUBJOINED LETTER FIXED-FORM WA; QQKN
+0F5E ; [.1C52.0020.0002.0F5E] # TIBETAN LETTER ZHA
+0FAE ; [.1C53.0020.0002.0FAE] # TIBETAN SUBJOINED LETTER ZHA
+0F5F ; [.1C54.0020.0002.0F5F] # TIBETAN LETTER ZA
+0FAF ; [.1C55.0020.0002.0FAF] # TIBETAN SUBJOINED LETTER ZA
+0F60 ; [.1C56.0020.0002.0F60] # TIBETAN LETTER -A
+0FB0 ; [.1C57.0020.0002.0FB0] # TIBETAN SUBJOINED LETTER -A
+0F61 ; [.1C58.0020.0002.0F61] # TIBETAN LETTER YA
+0FB1 ; [.1C59.0020.0002.0FB1] # TIBETAN SUBJOINED LETTER YA
+0FBB ; [.1C59.0020.0004.0FBB][.0000.019A.0004.0FBB] # TIBETAN SUBJOINED LETTER FIXED-FORM YA; QQKN
+0F62 ; [.1C5A.0020.0002.0F62] # TIBETAN LETTER RA
+0F6A ; [.1C5A.0020.0004.0F6A][.0000.019A.0004.0F6A] # TIBETAN LETTER FIXED-FORM RA; QQKN
+0FB2 ; [.1C5B.0020.0002.0FB2] # TIBETAN SUBJOINED LETTER RA
+0FBC ; [.1C5B.0020.0004.0FBC][.0000.019A.0004.0FBC] # TIBETAN SUBJOINED LETTER FIXED-FORM RA; QQKN
+0F63 ; [.1C5C.0020.0002.0F63] # TIBETAN LETTER LA
+0FB3 ; [.1C5D.0020.0002.0FB3] # TIBETAN SUBJOINED LETTER LA
+0F64 ; [.1C5E.0020.0002.0F64] # TIBETAN LETTER SHA
+0FB4 ; [.1C5F.0020.0002.0FB4] # TIBETAN SUBJOINED LETTER SHA
+0F65 ; [.1C60.0020.0002.0F65] # TIBETAN LETTER SSA
+0FB5 ; [.1C61.0020.0002.0FB5] # TIBETAN SUBJOINED LETTER SSA
+0F66 ; [.1C62.0020.0002.0F66] # TIBETAN LETTER SA
+0FB6 ; [.1C63.0020.0002.0FB6] # TIBETAN SUBJOINED LETTER SA
+0F67 ; [.1C64.0020.0002.0F67] # TIBETAN LETTER HA
+0FB7 ; [.1C65.0020.0002.0FB7] # TIBETAN SUBJOINED LETTER HA
+0F68 ; [.1C66.0020.0002.0F68] # TIBETAN LETTER A
+0F00 ; [.1C66.0020.0004.0F00][.1C79.0020.0004.0F00][.0000.015A.001F.0F00] # TIBETAN SYLLABLE OM; QQKN
+0FB8 ; [.1C67.0020.0002.0FB8] # TIBETAN SUBJOINED LETTER A
+0F88 ; [.1C68.0020.0002.0F88] # TIBETAN SIGN LCE TSA CAN
+0F89 ; [.1C69.0020.0002.0F89] # TIBETAN SIGN MCHU CAN
+0F8A ; [.1C6A.0020.0002.0F8A] # TIBETAN SIGN GRU CAN RGYINGS
+0F8B ; [.1C6B.0020.0002.0F8B] # TIBETAN SIGN GRU MED RGYINGS
+0F71 ; [.1C6C.0020.0002.0F71] # TIBETAN VOWEL SIGN AA
+0F72 ; [.1C6D.0020.0002.0F72] # TIBETAN VOWEL SIGN I
+0F73 ; [.1C6E.0020.0002.0F73] # TIBETAN VOWEL SIGN II
+0F71 0F72 ; [.1C6E.0020.0002.0F73] # TIBETAN VOWEL SIGN II
+0F80 ; [.1C6F.0020.0002.0F80] # TIBETAN VOWEL SIGN REVERSED I
+0F81 ; [.1C70.0020.0002.0F81] # TIBETAN VOWEL SIGN REVERSED II
+0F71 0F80 ; [.1C70.0020.0002.0F81] # TIBETAN VOWEL SIGN REVERSED II
+0F74 ; [.1C71.0020.0002.0F74] # TIBETAN VOWEL SIGN U
+0F75 ; [.1C72.0020.0002.0F75] # TIBETAN VOWEL SIGN UU
+0F71 0F74 ; [.1C72.0020.0002.0F75] # TIBETAN VOWEL SIGN UU
+0F76 ; [.1C73.0020.0002.0F76] # TIBETAN VOWEL SIGN VOCALIC R
+0FB2 0F80 ; [.1C73.0020.0002.0F76] # TIBETAN VOWEL SIGN VOCALIC R
+0F77 ; [.1C74.0020.0002.0F77] # TIBETAN VOWEL SIGN VOCALIC RR
+0FB2 0F71 0F80 ; [.1C74.0020.0002.0F77] # TIBETAN VOWEL SIGN VOCALIC RR
+0FB2 0F81 ; [.1C74.0020.0002.0F77] # TIBETAN VOWEL SIGN VOCALIC RR
+0F78 ; [.1C75.0020.0002.0F78] # TIBETAN VOWEL SIGN VOCALIC L
+0FB3 0F80 ; [.1C75.0020.0002.0F78] # TIBETAN VOWEL SIGN VOCALIC L
+0F79 ; [.1C76.0020.0002.0F79] # TIBETAN VOWEL SIGN VOCALIC LL
+0FB3 0F71 0F80 ; [.1C76.0020.0002.0F79] # TIBETAN VOWEL SIGN VOCALIC LL
+0FB3 0F81 ; [.1C76.0020.0002.0F79] # TIBETAN VOWEL SIGN VOCALIC LL
+0F7A ; [.1C77.0020.0002.0F7A] # TIBETAN VOWEL SIGN E
+0F7B ; [.1C78.0020.0002.0F7B] # TIBETAN VOWEL SIGN EE
+0F7C ; [.1C79.0020.0002.0F7C] # TIBETAN VOWEL SIGN O
+0F7D ; [.1C7A.0020.0002.0F7D] # TIBETAN VOWEL SIGN OO
+0F84 ; [.1C7B.0020.0002.0F84] # TIBETAN MARK HALANTA
+A840 ; [.1C7C.0020.0002.A840] # PHAGS-PA LETTER KA
+A841 ; [.1C7D.0020.0002.A841] # PHAGS-PA LETTER KHA
+A842 ; [.1C7E.0020.0002.A842] # PHAGS-PA LETTER GA
+A843 ; [.1C7F.0020.0002.A843] # PHAGS-PA LETTER NGA
+A844 ; [.1C80.0020.0002.A844] # PHAGS-PA LETTER CA
+A845 ; [.1C81.0020.0002.A845] # PHAGS-PA LETTER CHA
+A846 ; [.1C82.0020.0002.A846] # PHAGS-PA LETTER JA
+A847 ; [.1C83.0020.0002.A847] # PHAGS-PA LETTER NYA
+A869 ; [.1C84.0020.0002.A869] # PHAGS-PA LETTER TTA
+A86A ; [.1C85.0020.0002.A86A] # PHAGS-PA LETTER TTHA
+A86B ; [.1C86.0020.0002.A86B] # PHAGS-PA LETTER DDA
+A86C ; [.1C87.0020.0002.A86C] # PHAGS-PA LETTER NNA
+A848 ; [.1C88.0020.0002.A848] # PHAGS-PA LETTER TA
+A849 ; [.1C89.0020.0002.A849] # PHAGS-PA LETTER THA
+A84A ; [.1C8A.0020.0002.A84A] # PHAGS-PA LETTER DA
+A84B ; [.1C8B.0020.0002.A84B] # PHAGS-PA LETTER NA
+A84C ; [.1C8C.0020.0002.A84C] # PHAGS-PA LETTER PA
+A84D ; [.1C8D.0020.0002.A84D] # PHAGS-PA LETTER PHA
+A84E ; [.1C8E.0020.0002.A84E] # PHAGS-PA LETTER BA
+A84F ; [.1C8F.0020.0002.A84F] # PHAGS-PA LETTER MA
+A850 ; [.1C90.0020.0002.A850] # PHAGS-PA LETTER TSA
+A851 ; [.1C91.0020.0002.A851] # PHAGS-PA LETTER TSHA
+A852 ; [.1C92.0020.0002.A852] # PHAGS-PA LETTER DZA
+A853 ; [.1C93.0020.0002.A853] # PHAGS-PA LETTER WA
+A867 ; [.1C94.0020.0002.A867] # PHAGS-PA SUBJOINED LETTER WA
+A854 ; [.1C95.0020.0002.A854] # PHAGS-PA LETTER ZHA
+A855 ; [.1C96.0020.0002.A855] # PHAGS-PA LETTER ZA
+A856 ; [.1C97.0020.0002.A856] # PHAGS-PA LETTER SMALL A
+A857 ; [.1C98.0020.0002.A857] # PHAGS-PA LETTER YA
+A868 ; [.1C99.0020.0002.A868] # PHAGS-PA SUBJOINED LETTER YA
+A86D ; [.1C9A.0020.0002.A86D] # PHAGS-PA LETTER ALTERNATE YA
+A858 ; [.1C9B.0020.0002.A858] # PHAGS-PA LETTER RA
+A871 ; [.1C9C.0020.0002.A871] # PHAGS-PA SUBJOINED LETTER RA
+A872 ; [.1C9D.0020.0002.A872] # PHAGS-PA SUPERFIXED LETTER RA
+A859 ; [.1C9E.0020.0002.A859] # PHAGS-PA LETTER LA
+A85A ; [.1C9F.0020.0002.A85A] # PHAGS-PA LETTER SHA
+A86E ; [.1CA0.0020.0002.A86E] # PHAGS-PA LETTER VOICELESS SHA
+A85B ; [.1CA1.0020.0002.A85B] # PHAGS-PA LETTER SA
+A85C ; [.1CA2.0020.0002.A85C] # PHAGS-PA LETTER HA
+A86F ; [.1CA3.0020.0002.A86F] # PHAGS-PA LETTER VOICED HA
+A870 ; [.1CA4.0020.0002.A870] # PHAGS-PA LETTER ASPIRATED FA
+A85D ; [.1CA5.0020.0002.A85D] # PHAGS-PA LETTER A
+A862 ; [.1CA6.0020.0002.A862] # PHAGS-PA LETTER QA
+A863 ; [.1CA7.0020.0002.A863] # PHAGS-PA LETTER XA
+A864 ; [.1CA8.0020.0002.A864] # PHAGS-PA LETTER FA
+A865 ; [.1CA9.0020.0002.A865] # PHAGS-PA LETTER GGA
+A85E ; [.1CAA.0020.0002.A85E] # PHAGS-PA LETTER I
+A85F ; [.1CAB.0020.0002.A85F] # PHAGS-PA LETTER U
+A860 ; [.1CAC.0020.0002.A860] # PHAGS-PA LETTER E
+A861 ; [.1CAD.0020.0002.A861] # PHAGS-PA LETTER O
+A866 ; [.1CAE.0020.0002.A866] # PHAGS-PA LETTER EE
+A873 ; [.1CAF.0020.0002.A873] # PHAGS-PA LETTER CANDRABINDU
+1900 ; [.1CB0.0020.0002.1900] # LIMBU VOWEL-CARRIER LETTER
+1901 ; [.1CB1.0020.0002.1901] # LIMBU LETTER KA
+1902 ; [.1CB2.0020.0002.1902] # LIMBU LETTER KHA
+1903 ; [.1CB3.0020.0002.1903] # LIMBU LETTER GA
+1904 ; [.1CB4.0020.0002.1904] # LIMBU LETTER GHA
+1905 ; [.1CB5.0020.0002.1905] # LIMBU LETTER NGA
+1906 ; [.1CB6.0020.0002.1906] # LIMBU LETTER CA
+1907 ; [.1CB7.0020.0002.1907] # LIMBU LETTER CHA
+1908 ; [.1CB8.0020.0002.1908] # LIMBU LETTER JA
+1909 ; [.1CB9.0020.0002.1909] # LIMBU LETTER JHA
+190A ; [.1CBA.0020.0002.190A] # LIMBU LETTER YAN
+190B ; [.1CBB.0020.0002.190B] # LIMBU LETTER TA
+190C ; [.1CBC.0020.0002.190C] # LIMBU LETTER THA
+190D ; [.1CBD.0020.0002.190D] # LIMBU LETTER DA
+190E ; [.1CBE.0020.0002.190E] # LIMBU LETTER DHA
+190F ; [.1CBF.0020.0002.190F] # LIMBU LETTER NA
+1910 ; [.1CC0.0020.0002.1910] # LIMBU LETTER PA
+1911 ; [.1CC1.0020.0002.1911] # LIMBU LETTER PHA
+1912 ; [.1CC2.0020.0002.1912] # LIMBU LETTER BA
+1913 ; [.1CC3.0020.0002.1913] # LIMBU LETTER BHA
+1914 ; [.1CC4.0020.0002.1914] # LIMBU LETTER MA
+1915 ; [.1CC5.0020.0002.1915] # LIMBU LETTER YA
+1916 ; [.1CC6.0020.0002.1916] # LIMBU LETTER RA
+1917 ; [.1CC7.0020.0002.1917] # LIMBU LETTER LA
+1918 ; [.1CC8.0020.0002.1918] # LIMBU LETTER WA
+1919 ; [.1CC9.0020.0002.1919] # LIMBU LETTER SHA
+191A ; [.1CCA.0020.0002.191A] # LIMBU LETTER SSA
+191B ; [.1CCB.0020.0002.191B] # LIMBU LETTER SA
+191C ; [.1CCC.0020.0002.191C] # LIMBU LETTER HA
+1920 ; [.1CCD.0020.0002.1920] # LIMBU VOWEL SIGN A
+1921 ; [.1CCE.0020.0002.1921] # LIMBU VOWEL SIGN I
+1922 ; [.1CCF.0020.0002.1922] # LIMBU VOWEL SIGN U
+1923 ; [.1CD0.0020.0002.1923] # LIMBU VOWEL SIGN EE
+1924 ; [.1CD1.0020.0002.1924] # LIMBU VOWEL SIGN AI
+1925 ; [.1CD2.0020.0002.1925] # LIMBU VOWEL SIGN OO
+1926 ; [.1CD3.0020.0002.1926] # LIMBU VOWEL SIGN AU
+1927 ; [.1CD4.0020.0002.1927] # LIMBU VOWEL SIGN E
+1928 ; [.1CD5.0020.0002.1928] # LIMBU VOWEL SIGN O
+1929 ; [.1CD6.0020.0002.1929] # LIMBU SUBJOINED LETTER YA
+192A ; [.1CD7.0020.0002.192A] # LIMBU SUBJOINED LETTER RA
+192B ; [.1CD8.0020.0002.192B] # LIMBU SUBJOINED LETTER WA
+1930 ; [.1CD9.0020.0002.1930] # LIMBU SMALL LETTER KA
+1931 ; [.1CDA.0020.0002.1931] # LIMBU SMALL LETTER NGA
+1932 ; [.1CDB.0020.0002.1932] # LIMBU SMALL LETTER ANUSVARA
+1933 ; [.1CDC.0020.0002.1933] # LIMBU SMALL LETTER TA
+1934 ; [.1CDD.0020.0002.1934] # LIMBU SMALL LETTER NA
+1935 ; [.1CDE.0020.0002.1935] # LIMBU SMALL LETTER PA
+1936 ; [.1CDF.0020.0002.1936] # LIMBU SMALL LETTER MA
+1937 ; [.1CE0.0020.0002.1937] # LIMBU SMALL LETTER RA
+1938 ; [.1CE1.0020.0002.1938] # LIMBU SMALL LETTER LA
+1700 ; [.1CE2.0020.0002.1700] # TAGALOG LETTER A
+1701 ; [.1CE3.0020.0002.1701] # TAGALOG LETTER I
+1702 ; [.1CE4.0020.0002.1702] # TAGALOG LETTER U
+1703 ; [.1CE5.0020.0002.1703] # TAGALOG LETTER KA
+1704 ; [.1CE6.0020.0002.1704] # TAGALOG LETTER GA
+1705 ; [.1CE7.0020.0002.1705] # TAGALOG LETTER NGA
+1706 ; [.1CE8.0020.0002.1706] # TAGALOG LETTER TA
+1707 ; [.1CE9.0020.0002.1707] # TAGALOG LETTER DA
+1708 ; [.1CEA.0020.0002.1708] # TAGALOG LETTER NA
+1709 ; [.1CEB.0020.0002.1709] # TAGALOG LETTER PA
+170A ; [.1CEC.0020.0002.170A] # TAGALOG LETTER BA
+170B ; [.1CED.0020.0002.170B] # TAGALOG LETTER MA
+170C ; [.1CEE.0020.0002.170C] # TAGALOG LETTER YA
+170E ; [.1CEF.0020.0002.170E] # TAGALOG LETTER LA
+170F ; [.1CF0.0020.0002.170F] # TAGALOG LETTER WA
+1710 ; [.1CF1.0020.0002.1710] # TAGALOG LETTER SA
+1711 ; [.1CF2.0020.0002.1711] # TAGALOG LETTER HA
+1712 ; [.1CF3.0020.0002.1712] # TAGALOG VOWEL SIGN I
+1713 ; [.1CF4.0020.0002.1713] # TAGALOG VOWEL SIGN U
+1714 ; [.1CF5.0020.0002.1714] # TAGALOG SIGN VIRAMA
+1720 ; [.1CF6.0020.0002.1720] # HANUNOO LETTER A
+1721 ; [.1CF7.0020.0002.1721] # HANUNOO LETTER I
+1722 ; [.1CF8.0020.0002.1722] # HANUNOO LETTER U
+1723 ; [.1CF9.0020.0002.1723] # HANUNOO LETTER KA
+1724 ; [.1CFA.0020.0002.1724] # HANUNOO LETTER GA
+1725 ; [.1CFB.0020.0002.1725] # HANUNOO LETTER NGA
+1726 ; [.1CFC.0020.0002.1726] # HANUNOO LETTER TA
+1727 ; [.1CFD.0020.0002.1727] # HANUNOO LETTER DA
+1728 ; [.1CFE.0020.0002.1728] # HANUNOO LETTER NA
+1729 ; [.1CFF.0020.0002.1729] # HANUNOO LETTER PA
+172A ; [.1D00.0020.0002.172A] # HANUNOO LETTER BA
+172B ; [.1D01.0020.0002.172B] # HANUNOO LETTER MA
+172C ; [.1D02.0020.0002.172C] # HANUNOO LETTER YA
+172D ; [.1D03.0020.0002.172D] # HANUNOO LETTER RA
+172E ; [.1D04.0020.0002.172E] # HANUNOO LETTER LA
+172F ; [.1D05.0020.0002.172F] # HANUNOO LETTER WA
+1730 ; [.1D06.0020.0002.1730] # HANUNOO LETTER SA
+1731 ; [.1D07.0020.0002.1731] # HANUNOO LETTER HA
+1732 ; [.1D08.0020.0002.1732] # HANUNOO VOWEL SIGN I
+1733 ; [.1D09.0020.0002.1733] # HANUNOO VOWEL SIGN U
+1734 ; [.1D0A.0020.0002.1734] # HANUNOO SIGN PAMUDPOD
+1740 ; [.1D0B.0020.0002.1740] # BUHID LETTER A
+1741 ; [.1D0C.0020.0002.1741] # BUHID LETTER I
+1742 ; [.1D0D.0020.0002.1742] # BUHID LETTER U
+1743 ; [.1D0E.0020.0002.1743] # BUHID LETTER KA
+1744 ; [.1D0F.0020.0002.1744] # BUHID LETTER GA
+1745 ; [.1D10.0020.0002.1745] # BUHID LETTER NGA
+1746 ; [.1D11.0020.0002.1746] # BUHID LETTER TA
+1747 ; [.1D12.0020.0002.1747] # BUHID LETTER DA
+1748 ; [.1D13.0020.0002.1748] # BUHID LETTER NA
+1749 ; [.1D14.0020.0002.1749] # BUHID LETTER PA
+174A ; [.1D15.0020.0002.174A] # BUHID LETTER BA
+174B ; [.1D16.0020.0002.174B] # BUHID LETTER MA
+174C ; [.1D17.0020.0002.174C] # BUHID LETTER YA
+174D ; [.1D18.0020.0002.174D] # BUHID LETTER RA
+174E ; [.1D19.0020.0002.174E] # BUHID LETTER LA
+174F ; [.1D1A.0020.0002.174F] # BUHID LETTER WA
+1750 ; [.1D1B.0020.0002.1750] # BUHID LETTER SA
+1751 ; [.1D1C.0020.0002.1751] # BUHID LETTER HA
+1752 ; [.1D1D.0020.0002.1752] # BUHID VOWEL SIGN I
+1753 ; [.1D1E.0020.0002.1753] # BUHID VOWEL SIGN U
+1760 ; [.1D1F.0020.0002.1760] # TAGBANWA LETTER A
+1761 ; [.1D20.0020.0002.1761] # TAGBANWA LETTER I
+1762 ; [.1D21.0020.0002.1762] # TAGBANWA LETTER U
+1763 ; [.1D22.0020.0002.1763] # TAGBANWA LETTER KA
+1764 ; [.1D23.0020.0002.1764] # TAGBANWA LETTER GA
+1765 ; [.1D24.0020.0002.1765] # TAGBANWA LETTER NGA
+1766 ; [.1D25.0020.0002.1766] # TAGBANWA LETTER TA
+1767 ; [.1D26.0020.0002.1767] # TAGBANWA LETTER DA
+1768 ; [.1D27.0020.0002.1768] # TAGBANWA LETTER NA
+1769 ; [.1D28.0020.0002.1769] # TAGBANWA LETTER PA
+176A ; [.1D29.0020.0002.176A] # TAGBANWA LETTER BA
+176B ; [.1D2A.0020.0002.176B] # TAGBANWA LETTER MA
+176C ; [.1D2B.0020.0002.176C] # TAGBANWA LETTER YA
+176E ; [.1D2C.0020.0002.176E] # TAGBANWA LETTER LA
+176F ; [.1D2D.0020.0002.176F] # TAGBANWA LETTER WA
+1770 ; [.1D2E.0020.0002.1770] # TAGBANWA LETTER SA
+1772 ; [.1D2F.0020.0002.1772] # TAGBANWA VOWEL SIGN I
+1773 ; [.1D30.0020.0002.1773] # TAGBANWA VOWEL SIGN U
+1A00 ; [.1D31.0020.0002.1A00] # BUGINESE LETTER KA
+1A01 ; [.1D32.0020.0002.1A01] # BUGINESE LETTER GA
+1A02 ; [.1D33.0020.0002.1A02] # BUGINESE LETTER NGA
+1A03 ; [.1D34.0020.0002.1A03] # BUGINESE LETTER NGKA
+1A04 ; [.1D35.0020.0002.1A04] # BUGINESE LETTER PA
+1A05 ; [.1D36.0020.0002.1A05] # BUGINESE LETTER BA
+1A06 ; [.1D37.0020.0002.1A06] # BUGINESE LETTER MA
+1A07 ; [.1D38.0020.0002.1A07] # BUGINESE LETTER MPA
+1A08 ; [.1D39.0020.0002.1A08] # BUGINESE LETTER TA
+1A09 ; [.1D3A.0020.0002.1A09] # BUGINESE LETTER DA
+1A0A ; [.1D3B.0020.0002.1A0A] # BUGINESE LETTER NA
+1A0B ; [.1D3C.0020.0002.1A0B] # BUGINESE LETTER NRA
+1A0C ; [.1D3D.0020.0002.1A0C] # BUGINESE LETTER CA
+1A0D ; [.1D3E.0020.0002.1A0D] # BUGINESE LETTER JA
+1A0E ; [.1D3F.0020.0002.1A0E] # BUGINESE LETTER NYA
+1A0F ; [.1D40.0020.0002.1A0F] # BUGINESE LETTER NYCA
+1A10 ; [.1D41.0020.0002.1A10] # BUGINESE LETTER YA
+1A11 ; [.1D42.0020.0002.1A11] # BUGINESE LETTER RA
+1A12 ; [.1D43.0020.0002.1A12] # BUGINESE LETTER LA
+1A13 ; [.1D44.0020.0002.1A13] # BUGINESE LETTER VA
+1A14 ; [.1D45.0020.0002.1A14] # BUGINESE LETTER SA
+1A15 ; [.1D46.0020.0002.1A15] # BUGINESE LETTER A
+1A16 ; [.1D47.0020.0002.1A16] # BUGINESE LETTER HA
+1A17 ; [.1D48.0020.0002.1A17] # BUGINESE VOWEL SIGN I
+1A18 ; [.1D49.0020.0002.1A18] # BUGINESE VOWEL SIGN U
+1A19 ; [.1D4A.0020.0002.1A19] # BUGINESE VOWEL SIGN E
+1A1A ; [.1D4B.0020.0002.1A1A] # BUGINESE VOWEL SIGN O
+1A1B ; [.1D4C.0020.0002.1A1B] # BUGINESE VOWEL SIGN AE
+1000 ; [.1D4D.0020.0002.1000] # MYANMAR LETTER KA
+1001 ; [.1D4E.0020.0002.1001] # MYANMAR LETTER KHA
+1002 ; [.1D4F.0020.0002.1002] # MYANMAR LETTER GA
+1003 ; [.1D50.0020.0002.1003] # MYANMAR LETTER GHA
+1004 ; [.1D51.0020.0002.1004] # MYANMAR LETTER NGA
+1005 ; [.1D52.0020.0002.1005] # MYANMAR LETTER CA
+1006 ; [.1D53.0020.0002.1006] # MYANMAR LETTER CHA
+1007 ; [.1D54.0020.0002.1007] # MYANMAR LETTER JA
+1008 ; [.1D55.0020.0002.1008] # MYANMAR LETTER JHA
+1009 ; [.1D56.0020.0002.1009] # MYANMAR LETTER NYA
+100A ; [.1D57.0020.0002.100A] # MYANMAR LETTER NNYA
+100B ; [.1D58.0020.0002.100B] # MYANMAR LETTER TTA
+100C ; [.1D59.0020.0002.100C] # MYANMAR LETTER TTHA
+100D ; [.1D5A.0020.0002.100D] # MYANMAR LETTER DDA
+100E ; [.1D5B.0020.0002.100E] # MYANMAR LETTER DDHA
+100F ; [.1D5C.0020.0002.100F] # MYANMAR LETTER NNA
+1010 ; [.1D5D.0020.0002.1010] # MYANMAR LETTER TA
+1011 ; [.1D5E.0020.0002.1011] # MYANMAR LETTER THA
+1012 ; [.1D5F.0020.0002.1012] # MYANMAR LETTER DA
+1013 ; [.1D60.0020.0002.1013] # MYANMAR LETTER DHA
+1014 ; [.1D61.0020.0002.1014] # MYANMAR LETTER NA
+1015 ; [.1D62.0020.0002.1015] # MYANMAR LETTER PA
+1016 ; [.1D63.0020.0002.1016] # MYANMAR LETTER PHA
+1017 ; [.1D64.0020.0002.1017] # MYANMAR LETTER BA
+1018 ; [.1D65.0020.0002.1018] # MYANMAR LETTER BHA
+1019 ; [.1D66.0020.0002.1019] # MYANMAR LETTER MA
+101A ; [.1D67.0020.0002.101A] # MYANMAR LETTER YA
+101B ; [.1D68.0020.0002.101B] # MYANMAR LETTER RA
+101C ; [.1D69.0020.0002.101C] # MYANMAR LETTER LA
+101D ; [.1D6A.0020.0002.101D] # MYANMAR LETTER WA
+1050 ; [.1D6B.0020.0002.1050] # MYANMAR LETTER SHA
+1051 ; [.1D6C.0020.0002.1051] # MYANMAR LETTER SSA
+101E ; [.1D6D.0020.0002.101E] # MYANMAR LETTER SA
+101F ; [.1D6E.0020.0002.101F] # MYANMAR LETTER HA
+1020 ; [.1D6F.0020.0002.1020] # MYANMAR LETTER LLA
+1021 ; [.1D70.0020.0002.1021] # MYANMAR LETTER A
+1023 ; [.1D71.0020.0002.1023] # MYANMAR LETTER I
+1024 ; [.1D72.0020.0002.1024] # MYANMAR LETTER II
+1025 ; [.1D73.0020.0002.1025] # MYANMAR LETTER U
+1026 ; [.1D74.0020.0002.1026] # MYANMAR LETTER UU
+1025 102E ; [.1D74.0020.0002.1026] # MYANMAR LETTER UU
+1027 ; [.1D75.0020.0002.1027] # MYANMAR LETTER E
+1029 ; [.1D76.0020.0002.1029] # MYANMAR LETTER O
+102A ; [.1D77.0020.0002.102A] # MYANMAR LETTER AU
+1052 ; [.1D78.0020.0002.1052] # MYANMAR LETTER VOCALIC R
+1053 ; [.1D79.0020.0002.1053] # MYANMAR LETTER VOCALIC RR
+1054 ; [.1D7A.0020.0002.1054] # MYANMAR LETTER VOCALIC L
+1055 ; [.1D7B.0020.0002.1055] # MYANMAR LETTER VOCALIC LL
+102C ; [.1D7C.0020.0002.102C] # MYANMAR VOWEL SIGN AA
+102D ; [.1D7D.0020.0002.102D] # MYANMAR VOWEL SIGN I
+102E ; [.1D7E.0020.0002.102E] # MYANMAR VOWEL SIGN II
+102F ; [.1D7F.0020.0002.102F] # MYANMAR VOWEL SIGN U
+1030 ; [.1D80.0020.0002.1030] # MYANMAR VOWEL SIGN UU
+1031 ; [.1D81.0020.0002.1031] # MYANMAR VOWEL SIGN E
+1032 ; [.1D82.0020.0002.1032] # MYANMAR VOWEL SIGN AI
+1056 ; [.1D83.0020.0002.1056] # MYANMAR VOWEL SIGN VOCALIC R
+1057 ; [.1D84.0020.0002.1057] # MYANMAR VOWEL SIGN VOCALIC RR
+1058 ; [.1D85.0020.0002.1058] # MYANMAR VOWEL SIGN VOCALIC L
+1059 ; [.1D86.0020.0002.1059] # MYANMAR VOWEL SIGN VOCALIC LL
+1039 ; [.1D87.0020.0002.1039] # MYANMAR SIGN VIRAMA
+1780 ; [.1D88.0020.0002.1780] # KHMER LETTER KA
+1781 ; [.1D89.0020.0002.1781] # KHMER LETTER KHA
+1782 ; [.1D8A.0020.0002.1782] # KHMER LETTER KO
+1783 ; [.1D8B.0020.0002.1783] # KHMER LETTER KHO
+1784 ; [.1D8C.0020.0002.1784] # KHMER LETTER NGO
+1785 ; [.1D8D.0020.0002.1785] # KHMER LETTER CA
+1786 ; [.1D8E.0020.0002.1786] # KHMER LETTER CHA
+1787 ; [.1D8F.0020.0002.1787] # KHMER LETTER CO
+1788 ; [.1D90.0020.0002.1788] # KHMER LETTER CHO
+1789 ; [.1D91.0020.0002.1789] # KHMER LETTER NYO
+178A ; [.1D92.0020.0002.178A] # KHMER LETTER DA
+178B ; [.1D93.0020.0002.178B] # KHMER LETTER TTHA
+178C ; [.1D94.0020.0002.178C] # KHMER LETTER DO
+178D ; [.1D95.0020.0002.178D] # KHMER LETTER TTHO
+178E ; [.1D96.0020.0002.178E] # KHMER LETTER NNO
+178F ; [.1D97.0020.0002.178F] # KHMER LETTER TA
+1790 ; [.1D98.0020.0002.1790] # KHMER LETTER THA
+1791 ; [.1D99.0020.0002.1791] # KHMER LETTER TO
+1792 ; [.1D9A.0020.0002.1792] # KHMER LETTER THO
+1793 ; [.1D9B.0020.0002.1793] # KHMER LETTER NO
+1794 ; [.1D9C.0020.0002.1794] # KHMER LETTER BA
+1795 ; [.1D9D.0020.0002.1795] # KHMER LETTER PHA
+1796 ; [.1D9E.0020.0002.1796] # KHMER LETTER PO
+1797 ; [.1D9F.0020.0002.1797] # KHMER LETTER PHO
+1798 ; [.1DA0.0020.0002.1798] # KHMER LETTER MO
+1799 ; [.1DA1.0020.0002.1799] # KHMER LETTER YO
+179A ; [.1DA2.0020.0002.179A] # KHMER LETTER RO
+179B ; [.1DA3.0020.0002.179B] # KHMER LETTER LO
+179C ; [.1DA4.0020.0002.179C] # KHMER LETTER VO
+179D ; [.1DA5.0020.0002.179D] # KHMER LETTER SHA
+179E ; [.1DA6.0020.0002.179E] # KHMER LETTER SSO
+179F ; [.1DA7.0020.0002.179F] # KHMER LETTER SA
+17A0 ; [.1DA8.0020.0002.17A0] # KHMER LETTER HA
+17A1 ; [.1DA9.0020.0002.17A1] # KHMER LETTER LA
+17A2 ; [.1DAA.0020.0002.17A2] # KHMER LETTER QA
+17DC ; [.1DAB.0020.0002.17DC] # KHMER SIGN AVAKRAHASANYA
+17A3 ; [.1DAC.0020.0002.17A3] # KHMER INDEPENDENT VOWEL QAQ
+17A4 ; [.1DAD.0020.0002.17A4] # KHMER INDEPENDENT VOWEL QAA
+17A5 ; [.1DAE.0020.0002.17A5] # KHMER INDEPENDENT VOWEL QI
+17A6 ; [.1DAF.0020.0002.17A6] # KHMER INDEPENDENT VOWEL QII
+17A7 ; [.1DB0.0020.0002.17A7] # KHMER INDEPENDENT VOWEL QU
+17A8 ; [.1DB1.0020.0002.17A8] # KHMER INDEPENDENT VOWEL QUK
+17A9 ; [.1DB2.0020.0002.17A9] # KHMER INDEPENDENT VOWEL QUU
+17AA ; [.1DB3.0020.0002.17AA] # KHMER INDEPENDENT VOWEL QUUV
+17AB ; [.1DB4.0020.0002.17AB] # KHMER INDEPENDENT VOWEL RY
+17AC ; [.1DB5.0020.0002.17AC] # KHMER INDEPENDENT VOWEL RYY
+17AD ; [.1DB6.0020.0002.17AD] # KHMER INDEPENDENT VOWEL LY
+17AE ; [.1DB7.0020.0002.17AE] # KHMER INDEPENDENT VOWEL LYY
+17AF ; [.1DB8.0020.0002.17AF] # KHMER INDEPENDENT VOWEL QE
+17B0 ; [.1DB9.0020.0002.17B0] # KHMER INDEPENDENT VOWEL QAI
+17B1 ; [.1DBA.0020.0002.17B1] # KHMER INDEPENDENT VOWEL QOO TYPE ONE
+17B2 ; [.1DBB.0020.0002.17B2] # KHMER INDEPENDENT VOWEL QOO TYPE TWO
+17B3 ; [.1DBC.0020.0002.17B3] # KHMER INDEPENDENT VOWEL QAU
+17B4 ; [.1DBD.0020.0002.17B4] # KHMER VOWEL INHERENT AQ
+17B5 ; [.1DBE.0020.0002.17B5] # KHMER VOWEL INHERENT AA
+17B6 ; [.1DBF.0020.0002.17B6] # KHMER VOWEL SIGN AA
+17B7 ; [.1DC0.0020.0002.17B7] # KHMER VOWEL SIGN I
+17B8 ; [.1DC1.0020.0002.17B8] # KHMER VOWEL SIGN II
+17B9 ; [.1DC2.0020.0002.17B9] # KHMER VOWEL SIGN Y
+17BA ; [.1DC3.0020.0002.17BA] # KHMER VOWEL SIGN YY
+17BB ; [.1DC4.0020.0002.17BB] # KHMER VOWEL SIGN U
+17BC ; [.1DC5.0020.0002.17BC] # KHMER VOWEL SIGN UU
+17BD ; [.1DC6.0020.0002.17BD] # KHMER VOWEL SIGN UA
+17BE ; [.1DC7.0020.0002.17BE] # KHMER VOWEL SIGN OE
+17BF ; [.1DC8.0020.0002.17BF] # KHMER VOWEL SIGN YA
+17C0 ; [.1DC9.0020.0002.17C0] # KHMER VOWEL SIGN IE
+17C1 ; [.1DCA.0020.0002.17C1] # KHMER VOWEL SIGN E
+17C2 ; [.1DCB.0020.0002.17C2] # KHMER VOWEL SIGN AE
+17C3 ; [.1DCC.0020.0002.17C3] # KHMER VOWEL SIGN AI
+17C4 ; [.1DCD.0020.0002.17C4] # KHMER VOWEL SIGN OO
+17C5 ; [.1DCE.0020.0002.17C5] # KHMER VOWEL SIGN AU
+17D2 ; [.1DCF.0020.0002.17D2] # KHMER SIGN COENG
+1950 ; [.1DD0.0020.0002.1950] # TAI LE LETTER KA
+1951 ; [.1DD1.0020.0002.1951] # TAI LE LETTER XA
+1952 ; [.1DD2.0020.0002.1952] # TAI LE LETTER NGA
+1953 ; [.1DD3.0020.0002.1953] # TAI LE LETTER TSA
+1954 ; [.1DD4.0020.0002.1954] # TAI LE LETTER SA
+1955 ; [.1DD5.0020.0002.1955] # TAI LE LETTER YA
+1956 ; [.1DD6.0020.0002.1956] # TAI LE LETTER TA
+1957 ; [.1DD7.0020.0002.1957] # TAI LE LETTER THA
+1958 ; [.1DD8.0020.0002.1958] # TAI LE LETTER LA
+1959 ; [.1DD9.0020.0002.1959] # TAI LE LETTER PA
+195A ; [.1DDA.0020.0002.195A] # TAI LE LETTER PHA
+195B ; [.1DDB.0020.0002.195B] # TAI LE LETTER MA
+195C ; [.1DDC.0020.0002.195C] # TAI LE LETTER FA
+195D ; [.1DDD.0020.0002.195D] # TAI LE LETTER VA
+195E ; [.1DDE.0020.0002.195E] # TAI LE LETTER HA
+195F ; [.1DDF.0020.0002.195F] # TAI LE LETTER QA
+1960 ; [.1DE0.0020.0002.1960] # TAI LE LETTER KHA
+1961 ; [.1DE1.0020.0002.1961] # TAI LE LETTER TSHA
+1962 ; [.1DE2.0020.0002.1962] # TAI LE LETTER NA
+1963 ; [.1DE3.0020.0002.1963] # TAI LE LETTER A
+1964 ; [.1DE4.0020.0002.1964] # TAI LE LETTER I
+1965 ; [.1DE5.0020.0002.1965] # TAI LE LETTER EE
+1966 ; [.1DE6.0020.0002.1966] # TAI LE LETTER EH
+1967 ; [.1DE7.0020.0002.1967] # TAI LE LETTER U
+1968 ; [.1DE8.0020.0002.1968] # TAI LE LETTER OO
+1969 ; [.1DE9.0020.0002.1969] # TAI LE LETTER O
+196A ; [.1DEA.0020.0002.196A] # TAI LE LETTER UE
+196B ; [.1DEB.0020.0002.196B] # TAI LE LETTER E
+196C ; [.1DEC.0020.0002.196C] # TAI LE LETTER AUE
+196D ; [.1DED.0020.0002.196D] # TAI LE LETTER AI
+1970 ; [.1DEE.0020.0002.1970] # TAI LE LETTER TONE-2
+1971 ; [.1DEF.0020.0002.1971] # TAI LE LETTER TONE-3
+1972 ; [.1DF0.0020.0002.1972] # TAI LE LETTER TONE-4
+1973 ; [.1DF1.0020.0002.1973] # TAI LE LETTER TONE-5
+1974 ; [.1DF2.0020.0002.1974] # TAI LE LETTER TONE-6
+1980 ; [.1DF3.0020.0002.1980] # NEW TAI LUE LETTER HIGH QA
+1981 ; [.1DF4.0020.0002.1981] # NEW TAI LUE LETTER LOW QA
+1982 ; [.1DF5.0020.0002.1982] # NEW TAI LUE LETTER HIGH KA
+1983 ; [.1DF6.0020.0002.1983] # NEW TAI LUE LETTER HIGH XA
+1984 ; [.1DF7.0020.0002.1984] # NEW TAI LUE LETTER HIGH NGA
+1985 ; [.1DF8.0020.0002.1985] # NEW TAI LUE LETTER LOW KA
+1986 ; [.1DF9.0020.0002.1986] # NEW TAI LUE LETTER LOW XA
+1987 ; [.1DFA.0020.0002.1987] # NEW TAI LUE LETTER LOW NGA
+1988 ; [.1DFB.0020.0002.1988] # NEW TAI LUE LETTER HIGH TSA
+1989 ; [.1DFC.0020.0002.1989] # NEW TAI LUE LETTER HIGH SA
+198A ; [.1DFD.0020.0002.198A] # NEW TAI LUE LETTER HIGH YA
+198B ; [.1DFE.0020.0002.198B] # NEW TAI LUE LETTER LOW TSA
+198C ; [.1DFF.0020.0002.198C] # NEW TAI LUE LETTER LOW SA
+198D ; [.1E00.0020.0002.198D] # NEW TAI LUE LETTER LOW YA
+198E ; [.1E01.0020.0002.198E] # NEW TAI LUE LETTER HIGH TA
+198F ; [.1E02.0020.0002.198F] # NEW TAI LUE LETTER HIGH THA
+1990 ; [.1E03.0020.0002.1990] # NEW TAI LUE LETTER HIGH NA
+1991 ; [.1E04.0020.0002.1991] # NEW TAI LUE LETTER LOW TA
+1992 ; [.1E05.0020.0002.1992] # NEW TAI LUE LETTER LOW THA
+1993 ; [.1E06.0020.0002.1993] # NEW TAI LUE LETTER LOW NA
+1994 ; [.1E07.0020.0002.1994] # NEW TAI LUE LETTER HIGH PA
+1995 ; [.1E08.0020.0002.1995] # NEW TAI LUE LETTER HIGH PHA
+1996 ; [.1E09.0020.0002.1996] # NEW TAI LUE LETTER HIGH MA
+1997 ; [.1E0A.0020.0002.1997] # NEW TAI LUE LETTER LOW PA
+1998 ; [.1E0B.0020.0002.1998] # NEW TAI LUE LETTER LOW PHA
+1999 ; [.1E0C.0020.0002.1999] # NEW TAI LUE LETTER LOW MA
+199A ; [.1E0D.0020.0002.199A] # NEW TAI LUE LETTER HIGH FA
+199B ; [.1E0E.0020.0002.199B] # NEW TAI LUE LETTER HIGH VA
+199C ; [.1E0F.0020.0002.199C] # NEW TAI LUE LETTER HIGH LA
+19DE ; [.1E0F.0020.0004.19DE][.1E23.0020.0004.19DE] # NEW TAI LUE SIGN LAE; QQKN
+19DF ; [.1E0F.0020.0004.19DF][.1E23.0020.0004.19DF][.1E2E.0020.001F.19DF] # NEW TAI LUE SIGN LAEV; QQKN
+199D ; [.1E10.0020.0002.199D] # NEW TAI LUE LETTER LOW FA
+199E ; [.1E11.0020.0002.199E] # NEW TAI LUE LETTER LOW VA
+199F ; [.1E12.0020.0002.199F] # NEW TAI LUE LETTER LOW LA
+19A0 ; [.1E13.0020.0002.19A0] # NEW TAI LUE LETTER HIGH HA
+19A1 ; [.1E14.0020.0002.19A1] # NEW TAI LUE LETTER HIGH DA
+19A2 ; [.1E15.0020.0002.19A2] # NEW TAI LUE LETTER HIGH BA
+19A3 ; [.1E16.0020.0002.19A3] # NEW TAI LUE LETTER LOW HA
+19A4 ; [.1E17.0020.0002.19A4] # NEW TAI LUE LETTER LOW DA
+19A5 ; [.1E18.0020.0002.19A5] # NEW TAI LUE LETTER LOW BA
+19A6 ; [.1E19.0020.0002.19A6] # NEW TAI LUE LETTER HIGH KVA
+19A7 ; [.1E1A.0020.0002.19A7] # NEW TAI LUE LETTER HIGH XVA
+19A8 ; [.1E1B.0020.0002.19A8] # NEW TAI LUE LETTER LOW KVA
+19A9 ; [.1E1C.0020.0002.19A9] # NEW TAI LUE LETTER LOW XVA
+19B0 ; [.1E1D.0020.0002.19B0] # NEW TAI LUE VOWEL SIGN VOWEL SHORTENER
+19B1 ; [.1E1E.0020.0002.19B1] # NEW TAI LUE VOWEL SIGN AA
+19B2 ; [.1E1F.0020.0002.19B2] # NEW TAI LUE VOWEL SIGN II
+19B3 ; [.1E20.0020.0002.19B3] # NEW TAI LUE VOWEL SIGN U
+19B4 ; [.1E21.0020.0002.19B4] # NEW TAI LUE VOWEL SIGN UU
+19B5 ; [.1E22.0020.0002.19B5] # NEW TAI LUE VOWEL SIGN E
+19B6 ; [.1E23.0020.0002.19B6] # NEW TAI LUE VOWEL SIGN AE
+19B7 ; [.1E24.0020.0002.19B7] # NEW TAI LUE VOWEL SIGN O
+19B8 ; [.1E25.0020.0002.19B8] # NEW TAI LUE VOWEL SIGN OA
+19B9 ; [.1E26.0020.0002.19B9] # NEW TAI LUE VOWEL SIGN UE
+19BA ; [.1E27.0020.0002.19BA] # NEW TAI LUE VOWEL SIGN AY
+19BB ; [.1E28.0020.0002.19BB] # NEW TAI LUE VOWEL SIGN AAY
+19BC ; [.1E29.0020.0002.19BC] # NEW TAI LUE VOWEL SIGN UY
+19BD ; [.1E2A.0020.0002.19BD] # NEW TAI LUE VOWEL SIGN OY
+19BE ; [.1E2B.0020.0002.19BE] # NEW TAI LUE VOWEL SIGN OAY
+19BF ; [.1E2C.0020.0002.19BF] # NEW TAI LUE VOWEL SIGN UEY
+19C0 ; [.1E2D.0020.0002.19C0] # NEW TAI LUE VOWEL SIGN IY
+19C1 ; [.1E2E.0020.0002.19C1] # NEW TAI LUE LETTER FINAL V
+19C2 ; [.1E2F.0020.0002.19C2] # NEW TAI LUE LETTER FINAL NG
+19C3 ; [.1E30.0020.0002.19C3] # NEW TAI LUE LETTER FINAL N
+19C4 ; [.1E31.0020.0002.19C4] # NEW TAI LUE LETTER FINAL M
+19C5 ; [.1E32.0020.0002.19C5] # NEW TAI LUE LETTER FINAL K
+19C6 ; [.1E33.0020.0002.19C6] # NEW TAI LUE LETTER FINAL D
+19C7 ; [.1E34.0020.0002.19C7] # NEW TAI LUE LETTER FINAL B
+19C8 ; [.1E35.0020.0002.19C8] # NEW TAI LUE TONE MARK-1
+19C9 ; [.1E36.0020.0002.19C9] # NEW TAI LUE TONE MARK-2
+1B05 ; [.1E37.0020.0002.1B05] # BALINESE LETTER AKARA
+1B06 ; [.1E38.0020.0002.1B06] # BALINESE LETTER AKARA TEDUNG
+1B05 1B35 ; [.1E38.0020.0002.1B06] # BALINESE LETTER AKARA TEDUNG
+1B07 ; [.1E39.0020.0002.1B07] # BALINESE LETTER IKARA
+1B08 ; [.1E3A.0020.0002.1B08] # BALINESE LETTER IKARA TEDUNG
+1B07 1B35 ; [.1E3A.0020.0002.1B08] # BALINESE LETTER IKARA TEDUNG
+1B09 ; [.1E3B.0020.0002.1B09] # BALINESE LETTER UKARA
+1B0A ; [.1E3C.0020.0002.1B0A] # BALINESE LETTER UKARA TEDUNG
+1B09 1B35 ; [.1E3C.0020.0002.1B0A] # BALINESE LETTER UKARA TEDUNG
+1B0B ; [.1E3D.0020.0002.1B0B] # BALINESE LETTER RA REPA
+1B0C ; [.1E3E.0020.0002.1B0C] # BALINESE LETTER RA REPA TEDUNG
+1B0B 1B35 ; [.1E3E.0020.0002.1B0C] # BALINESE LETTER RA REPA TEDUNG
+1B0D ; [.1E3F.0020.0002.1B0D] # BALINESE LETTER LA LENGA
+1B0E ; [.1E40.0020.0002.1B0E] # BALINESE LETTER LA LENGA TEDUNG
+1B0D 1B35 ; [.1E40.0020.0002.1B0E] # BALINESE LETTER LA LENGA TEDUNG
+1B0F ; [.1E41.0020.0002.1B0F] # BALINESE LETTER EKARA
+1B10 ; [.1E42.0020.0002.1B10] # BALINESE LETTER AIKARA
+1B11 ; [.1E43.0020.0002.1B11] # BALINESE LETTER OKARA
+1B12 ; [.1E44.0020.0002.1B12] # BALINESE LETTER OKARA TEDUNG
+1B11 1B35 ; [.1E44.0020.0002.1B12] # BALINESE LETTER OKARA TEDUNG
+1B13 ; [.1E45.0020.0002.1B13] # BALINESE LETTER KA
+1B45 ; [.1E46.0020.0002.1B45] # BALINESE LETTER KAF SASAK
+1B46 ; [.1E47.0020.0002.1B46] # BALINESE LETTER KHOT SASAK
+1B14 ; [.1E48.0020.0002.1B14] # BALINESE LETTER KA MAHAPRANA
+1B15 ; [.1E49.0020.0002.1B15] # BALINESE LETTER GA
+1B16 ; [.1E4A.0020.0002.1B16] # BALINESE LETTER GA GORA
+1B17 ; [.1E4B.0020.0002.1B17] # BALINESE LETTER NGA
+1B18 ; [.1E4C.0020.0002.1B18] # BALINESE LETTER CA
+1B19 ; [.1E4D.0020.0002.1B19] # BALINESE LETTER CA LACA
+1B1A ; [.1E4E.0020.0002.1B1A] # BALINESE LETTER JA
+1B1B ; [.1E4F.0020.0002.1B1B] # BALINESE LETTER JA JERA
+1B1C ; [.1E50.0020.0002.1B1C] # BALINESE LETTER NYA
+1B1D ; [.1E51.0020.0002.1B1D] # BALINESE LETTER TA LATIK
+1B1E ; [.1E52.0020.0002.1B1E] # BALINESE LETTER TA MURDA MAHAPRANA
+1B1F ; [.1E53.0020.0002.1B1F] # BALINESE LETTER DA MURDA ALPAPRANA
+1B20 ; [.1E54.0020.0002.1B20] # BALINESE LETTER DA MURDA MAHAPRANA
+1B21 ; [.1E55.0020.0002.1B21] # BALINESE LETTER NA RAMBAT
+1B22 ; [.1E56.0020.0002.1B22] # BALINESE LETTER TA
+1B47 ; [.1E57.0020.0002.1B47] # BALINESE LETTER TZIR SASAK
+1B23 ; [.1E58.0020.0002.1B23] # BALINESE LETTER TA TAWA
+1B24 ; [.1E59.0020.0002.1B24] # BALINESE LETTER DA
+1B25 ; [.1E5A.0020.0002.1B25] # BALINESE LETTER DA MADU
+1B26 ; [.1E5B.0020.0002.1B26] # BALINESE LETTER NA
+1B27 ; [.1E5C.0020.0002.1B27] # BALINESE LETTER PA
+1B48 ; [.1E5D.0020.0002.1B48] # BALINESE LETTER EF SASAK
+1B28 ; [.1E5E.0020.0002.1B28] # BALINESE LETTER PA KAPAL
+1B29 ; [.1E5F.0020.0002.1B29] # BALINESE LETTER BA
+1B2A ; [.1E60.0020.0002.1B2A] # BALINESE LETTER BA KEMBANG
+1B2B ; [.1E61.0020.0002.1B2B] # BALINESE LETTER MA
+1B2C ; [.1E62.0020.0002.1B2C] # BALINESE LETTER YA
+1B2D ; [.1E63.0020.0002.1B2D] # BALINESE LETTER RA
+1B2E ; [.1E64.0020.0002.1B2E] # BALINESE LETTER LA
+1B2F ; [.1E65.0020.0002.1B2F] # BALINESE LETTER WA
+1B49 ; [.1E66.0020.0002.1B49] # BALINESE LETTER VE SASAK
+1B30 ; [.1E67.0020.0002.1B30] # BALINESE LETTER SA SAGA
+1B31 ; [.1E68.0020.0002.1B31] # BALINESE LETTER SA SAPA
+1B32 ; [.1E69.0020.0002.1B32] # BALINESE LETTER SA
+1B4A ; [.1E6A.0020.0002.1B4A] # BALINESE LETTER ZAL SASAK
+1B4B ; [.1E6B.0020.0002.1B4B] # BALINESE LETTER ASYURA SASAK
+1B33 ; [.1E6C.0020.0002.1B33] # BALINESE LETTER HA
+1B35 ; [.1E6D.0020.0002.1B35] # BALINESE VOWEL SIGN TEDUNG
+1B36 ; [.1E6E.0020.0002.1B36] # BALINESE VOWEL SIGN ULU
+1B37 ; [.1E6F.0020.0002.1B37] # BALINESE VOWEL SIGN ULU SARI
+1B38 ; [.1E70.0020.0002.1B38] # BALINESE VOWEL SIGN SUKU
+1B39 ; [.1E71.0020.0002.1B39] # BALINESE VOWEL SIGN SUKU ILUT
+1B3A ; [.1E72.0020.0002.1B3A] # BALINESE VOWEL SIGN RA REPA
+1B3B ; [.1E73.0020.0002.1B3B] # BALINESE VOWEL SIGN RA REPA TEDUNG
+1B3A 1B35 ; [.1E73.0020.0002.1B3B] # BALINESE VOWEL SIGN RA REPA TEDUNG
+1B3C ; [.1E74.0020.0002.1B3C] # BALINESE VOWEL SIGN LA LENGA
+1B3D ; [.1E75.0020.0002.1B3D] # BALINESE VOWEL SIGN LA LENGA TEDUNG
+1B3C 1B35 ; [.1E75.0020.0002.1B3D] # BALINESE VOWEL SIGN LA LENGA TEDUNG
+1B3E ; [.1E76.0020.0002.1B3E] # BALINESE VOWEL SIGN TALING
+1B3F ; [.1E77.0020.0002.1B3F] # BALINESE VOWEL SIGN TALING REPA
+1B40 ; [.1E78.0020.0002.1B40] # BALINESE VOWEL SIGN TALING TEDUNG
+1B3E 1B35 ; [.1E78.0020.0002.1B40] # BALINESE VOWEL SIGN TALING TEDUNG
+1B41 ; [.1E79.0020.0002.1B41] # BALINESE VOWEL SIGN TALING REPA TEDUNG
+1B3F 1B35 ; [.1E79.0020.0002.1B41] # BALINESE VOWEL SIGN TALING REPA TEDUNG
+1B42 ; [.1E7A.0020.0002.1B42] # BALINESE VOWEL SIGN PEPET
+1B43 ; [.1E7B.0020.0002.1B43] # BALINESE VOWEL SIGN PEPET TEDUNG
+1B42 1B35 ; [.1E7B.0020.0002.1B43] # BALINESE VOWEL SIGN PEPET TEDUNG
+1B44 ; [.1E7C.0020.0002.1B44] # BALINESE ADEG ADEG
+1880 ; [.1E7D.0020.0002.1880] # MONGOLIAN LETTER ALI GALI ANUSVARA ONE
+1881 ; [.1E7E.0020.0002.1881] # MONGOLIAN LETTER ALI GALI VISARGA ONE
+1882 ; [.1E7F.0020.0002.1882] # MONGOLIAN LETTER ALI GALI DAMARU
+1883 ; [.1E80.0020.0002.1883] # MONGOLIAN LETTER ALI GALI UBADAMA
+1884 ; [.1E81.0020.0002.1884] # MONGOLIAN LETTER ALI GALI INVERTED UBADAMA
+1885 ; [.1E82.0020.0002.1885] # MONGOLIAN LETTER ALI GALI BALUDA
+1886 ; [.1E83.0020.0002.1886] # MONGOLIAN LETTER ALI GALI THREE BALUDA
+1843 ; [.1E84.0020.0002.1843] # MONGOLIAN LETTER TODO LONG VOWEL SIGN
+1820 ; [.1E85.0020.0002.1820] # MONGOLIAN LETTER A
+1887 ; [.1E86.0020.0002.1887] # MONGOLIAN LETTER ALI GALI A
+1821 ; [.1E87.0020.0002.1821] # MONGOLIAN LETTER E
+1844 ; [.1E88.0020.0002.1844] # MONGOLIAN LETTER TODO E
+185D ; [.1E89.0020.0002.185D] # MONGOLIAN LETTER SIBE E
+1822 ; [.1E8A.0020.0002.1822] # MONGOLIAN LETTER I
+1845 ; [.1E8B.0020.0002.1845] # MONGOLIAN LETTER TODO I
+185E ; [.1E8C.0020.0002.185E] # MONGOLIAN LETTER SIBE I
+1873 ; [.1E8D.0020.0002.1873] # MONGOLIAN LETTER MANCHU I
+1888 ; [.1E8E.0020.0002.1888] # MONGOLIAN LETTER ALI GALI I
+185F ; [.1E8F.0020.0002.185F] # MONGOLIAN LETTER SIBE IY
+1823 ; [.1E90.0020.0002.1823] # MONGOLIAN LETTER O
+1846 ; [.1E91.0020.0002.1846] # MONGOLIAN LETTER TODO O
+1824 ; [.1E92.0020.0002.1824] # MONGOLIAN LETTER U
+1847 ; [.1E93.0020.0002.1847] # MONGOLIAN LETTER TODO U
+1861 ; [.1E94.0020.0002.1861] # MONGOLIAN LETTER SIBE U
+1825 ; [.1E95.0020.0002.1825] # MONGOLIAN LETTER OE
+1848 ; [.1E96.0020.0002.1848] # MONGOLIAN LETTER TODO OE
+1826 ; [.1E97.0020.0002.1826] # MONGOLIAN LETTER UE
+1849 ; [.1E98.0020.0002.1849] # MONGOLIAN LETTER TODO UE
+1860 ; [.1E99.0020.0002.1860] # MONGOLIAN LETTER SIBE UE
+1827 ; [.1E9A.0020.0002.1827] # MONGOLIAN LETTER EE
+1828 ; [.1E9B.0020.0002.1828] # MONGOLIAN LETTER NA
+1829 ; [.1E9C.0020.0002.1829] # MONGOLIAN LETTER ANG
+184A ; [.1E9D.0020.0002.184A] # MONGOLIAN LETTER TODO ANG
+1862 ; [.1E9E.0020.0002.1862] # MONGOLIAN LETTER SIBE ANG
+188A ; [.1E9F.0020.0002.188A] # MONGOLIAN LETTER ALI GALI NGA
+189B ; [.1EA0.0020.0002.189B] # MONGOLIAN LETTER MANCHU ALI GALI NGA
+182A ; [.1EA1.0020.0002.182A] # MONGOLIAN LETTER BA
+184B ; [.1EA2.0020.0002.184B] # MONGOLIAN LETTER TODO BA
+182B ; [.1EA3.0020.0002.182B] # MONGOLIAN LETTER PA
+184C ; [.1EA4.0020.0002.184C] # MONGOLIAN LETTER TODO PA
+1866 ; [.1EA5.0020.0002.1866] # MONGOLIAN LETTER SIBE PA
+182C ; [.1EA6.0020.0002.182C] # MONGOLIAN LETTER QA
+184D ; [.1EA7.0020.0002.184D] # MONGOLIAN LETTER TODO QA
+182D ; [.1EA8.0020.0002.182D] # MONGOLIAN LETTER GA
+184E ; [.1EA9.0020.0002.184E] # MONGOLIAN LETTER TODO GA
+1864 ; [.1EAA.0020.0002.1864] # MONGOLIAN LETTER SIBE GA
+189A ; [.1EAB.0020.0002.189A] # MONGOLIAN LETTER MANCHU ALI GALI GHA
+1865 ; [.1EAC.0020.0002.1865] # MONGOLIAN LETTER SIBE HA
+182E ; [.1EAD.0020.0002.182E] # MONGOLIAN LETTER MA
+184F ; [.1EAE.0020.0002.184F] # MONGOLIAN LETTER TODO MA
+182F ; [.1EAF.0020.0002.182F] # MONGOLIAN LETTER LA
+1830 ; [.1EB0.0020.0002.1830] # MONGOLIAN LETTER SA
+1831 ; [.1EB1.0020.0002.1831] # MONGOLIAN LETTER SHA
+1867 ; [.1EB2.0020.0002.1867] # MONGOLIAN LETTER SIBE SHA
+189C ; [.1EB3.0020.0002.189C] # MONGOLIAN LETTER MANCHU ALI GALI CA
+189D ; [.1EB4.0020.0002.189D] # MONGOLIAN LETTER MANCHU ALI GALI JHA
+18A2 ; [.1EB5.0020.0002.18A2] # MONGOLIAN LETTER MANCHU ALI GALI SSA
+18A4 ; [.1EB6.0020.0002.18A4] # MONGOLIAN LETTER MANCHU ALI GALI ZHA
+18A5 ; [.1EB7.0020.0002.18A5] # MONGOLIAN LETTER MANCHU ALI GALI ZA
+1832 ; [.1EB8.0020.0002.1832] # MONGOLIAN LETTER TA
+1850 ; [.1EB9.0020.0002.1850] # MONGOLIAN LETTER TODO TA
+1868 ; [.1EBA.0020.0002.1868] # MONGOLIAN LETTER SIBE TA
+1833 ; [.1EBB.0020.0002.1833] # MONGOLIAN LETTER DA
+1851 ; [.1EBC.0020.0002.1851] # MONGOLIAN LETTER TODO DA
+1869 ; [.1EBD.0020.0002.1869] # MONGOLIAN LETTER SIBE DA
+1834 ; [.1EBE.0020.0002.1834] # MONGOLIAN LETTER CHA
+1852 ; [.1EBF.0020.0002.1852] # MONGOLIAN LETTER TODO CHA
+1871 ; [.1EC0.0020.0002.1871] # MONGOLIAN LETTER SIBE CHA
+185C ; [.1EC1.0020.0002.185C] # MONGOLIAN LETTER TODO DZA
+188B ; [.1EC2.0020.0002.188B] # MONGOLIAN LETTER ALI GALI CA
+1835 ; [.1EC3.0020.0002.1835] # MONGOLIAN LETTER JA
+1853 ; [.1EC4.0020.0002.1853] # MONGOLIAN LETTER TODO JA
+186A ; [.1EC5.0020.0002.186A] # MONGOLIAN LETTER SIBE JA
+1877 ; [.1EC6.0020.0002.1877] # MONGOLIAN LETTER MANCHU ZHA
+1836 ; [.1EC7.0020.0002.1836] # MONGOLIAN LETTER YA
+1855 ; [.1EC8.0020.0002.1855] # MONGOLIAN LETTER TODO YA
+1872 ; [.1EC9.0020.0002.1872] # MONGOLIAN LETTER SIBE ZHA
+1837 ; [.1ECA.0020.0002.1837] # MONGOLIAN LETTER RA
+1875 ; [.1ECB.0020.0002.1875] # MONGOLIAN LETTER MANCHU RA
+1838 ; [.1ECC.0020.0002.1838] # MONGOLIAN LETTER WA
+1856 ; [.1ECD.0020.0002.1856] # MONGOLIAN LETTER TODO WA
+1839 ; [.1ECE.0020.0002.1839] # MONGOLIAN LETTER FA
+186B ; [.1ECF.0020.0002.186B] # MONGOLIAN LETTER SIBE FA
+1876 ; [.1ED0.0020.0002.1876] # MONGOLIAN LETTER MANCHU FA
+183A ; [.1ED1.0020.0002.183A] # MONGOLIAN LETTER KA
+1857 ; [.1ED2.0020.0002.1857] # MONGOLIAN LETTER TODO KA
+1863 ; [.1ED3.0020.0002.1863] # MONGOLIAN LETTER SIBE KA
+1874 ; [.1ED4.0020.0002.1874] # MONGOLIAN LETTER MANCHU KA
+1889 ; [.1ED5.0020.0002.1889] # MONGOLIAN LETTER ALI GALI KA
+183B ; [.1ED6.0020.0002.183B] # MONGOLIAN LETTER KHA
+183C ; [.1ED7.0020.0002.183C] # MONGOLIAN LETTER TSA
+1854 ; [.1ED8.0020.0002.1854] # MONGOLIAN LETTER TODO TSA
+186E ; [.1ED9.0020.0002.186E] # MONGOLIAN LETTER SIBE TSA
+183D ; [.1EDA.0020.0002.183D] # MONGOLIAN LETTER ZA
+186F ; [.1EDB.0020.0002.186F] # MONGOLIAN LETTER SIBE ZA
+1858 ; [.1EDC.0020.0002.1858] # MONGOLIAN LETTER TODO GAA
+186C ; [.1EDD.0020.0002.186C] # MONGOLIAN LETTER SIBE GAA
+183E ; [.1EDE.0020.0002.183E] # MONGOLIAN LETTER HAA
+1859 ; [.1EDF.0020.0002.1859] # MONGOLIAN LETTER TODO HAA
+186D ; [.1EE0.0020.0002.186D] # MONGOLIAN LETTER SIBE HAA
+183F ; [.1EE1.0020.0002.183F] # MONGOLIAN LETTER ZRA
+1840 ; [.1EE2.0020.0002.1840] # MONGOLIAN LETTER LHA
+1841 ; [.1EE3.0020.0002.1841] # MONGOLIAN LETTER ZHI
+1842 ; [.1EE4.0020.0002.1842] # MONGOLIAN LETTER CHI
+185A ; [.1EE5.0020.0002.185A] # MONGOLIAN LETTER TODO JIA
+185B ; [.1EE6.0020.0002.185B] # MONGOLIAN LETTER TODO NIA
+1870 ; [.1EE7.0020.0002.1870] # MONGOLIAN LETTER SIBE RAA
+188C ; [.1EE8.0020.0002.188C] # MONGOLIAN LETTER ALI GALI TTA
+189E ; [.1EE9.0020.0002.189E] # MONGOLIAN LETTER MANCHU ALI GALI TTA
+188D ; [.1EEA.0020.0002.188D] # MONGOLIAN LETTER ALI GALI TTHA
+188E ; [.1EEB.0020.0002.188E] # MONGOLIAN LETTER ALI GALI DDA
+189F ; [.1EEC.0020.0002.189F] # MONGOLIAN LETTER MANCHU ALI GALI DDHA
+188F ; [.1EED.0020.0002.188F] # MONGOLIAN LETTER ALI GALI NNA
+1890 ; [.1EEE.0020.0002.1890] # MONGOLIAN LETTER ALI GALI TA
+1898 ; [.1EEF.0020.0002.1898] # MONGOLIAN LETTER TODO ALI GALI TA
+18A0 ; [.1EF0.0020.0002.18A0] # MONGOLIAN LETTER MANCHU ALI GALI TA
+1891 ; [.1EF1.0020.0002.1891] # MONGOLIAN LETTER ALI GALI DA
+18A1 ; [.1EF2.0020.0002.18A1] # MONGOLIAN LETTER MANCHU ALI GALI DHA
+1892 ; [.1EF3.0020.0002.1892] # MONGOLIAN LETTER ALI GALI PA
+1893 ; [.1EF4.0020.0002.1893] # MONGOLIAN LETTER ALI GALI PHA
+18A8 ; [.1EF5.0020.0002.18A8] # MONGOLIAN LETTER MANCHU ALI GALI BHA
+1894 ; [.1EF6.0020.0002.1894] # MONGOLIAN LETTER ALI GALI SSA
+18A3 ; [.1EF7.0020.0002.18A3] # MONGOLIAN LETTER MANCHU ALI GALI CYA
+1895 ; [.1EF8.0020.0002.1895] # MONGOLIAN LETTER ALI GALI ZHA
+1899 ; [.1EF9.0020.0002.1899] # MONGOLIAN LETTER TODO ALI GALI ZHA
+1896 ; [.1EFA.0020.0002.1896] # MONGOLIAN LETTER ALI GALI ZA
+1897 ; [.1EFB.0020.0002.1897] # MONGOLIAN LETTER ALI GALI AH
+18A6 ; [.1EFC.0020.0002.18A6] # MONGOLIAN LETTER ALI GALI HALF U
+18A7 ; [.1EFD.0020.0002.18A7] # MONGOLIAN LETTER ALI GALI HALF YA
+18A9 ; [.1EFE.0020.0002.18A9] # MONGOLIAN LETTER ALI GALI DAGALGA
+13A0 ; [.1EFF.0020.0002.13A0] # CHEROKEE LETTER A
+13A1 ; [.1F00.0020.0002.13A1] # CHEROKEE LETTER E
+13A2 ; [.1F01.0020.0002.13A2] # CHEROKEE LETTER I
+13A3 ; [.1F02.0020.0002.13A3] # CHEROKEE LETTER O
+13A4 ; [.1F03.0020.0002.13A4] # CHEROKEE LETTER U
+13A5 ; [.1F04.0020.0002.13A5] # CHEROKEE LETTER V
+13A6 ; [.1F05.0020.0002.13A6] # CHEROKEE LETTER GA
+13A7 ; [.1F06.0020.0002.13A7] # CHEROKEE LETTER KA
+13A8 ; [.1F07.0020.0002.13A8] # CHEROKEE LETTER GE
+13A9 ; [.1F08.0020.0002.13A9] # CHEROKEE LETTER GI
+13AA ; [.1F09.0020.0002.13AA] # CHEROKEE LETTER GO
+13AB ; [.1F0A.0020.0002.13AB] # CHEROKEE LETTER GU
+13AC ; [.1F0B.0020.0002.13AC] # CHEROKEE LETTER GV
+13AD ; [.1F0C.0020.0002.13AD] # CHEROKEE LETTER HA
+13AE ; [.1F0D.0020.0002.13AE] # CHEROKEE LETTER HE
+13AF ; [.1F0E.0020.0002.13AF] # CHEROKEE LETTER HI
+13B0 ; [.1F0F.0020.0002.13B0] # CHEROKEE LETTER HO
+13B1 ; [.1F10.0020.0002.13B1] # CHEROKEE LETTER HU
+13B2 ; [.1F11.0020.0002.13B2] # CHEROKEE LETTER HV
+13B3 ; [.1F12.0020.0002.13B3] # CHEROKEE LETTER LA
+13B4 ; [.1F13.0020.0002.13B4] # CHEROKEE LETTER LE
+13B5 ; [.1F14.0020.0002.13B5] # CHEROKEE LETTER LI
+13B6 ; [.1F15.0020.0002.13B6] # CHEROKEE LETTER LO
+13B7 ; [.1F16.0020.0002.13B7] # CHEROKEE LETTER LU
+13B8 ; [.1F17.0020.0002.13B8] # CHEROKEE LETTER LV
+13B9 ; [.1F18.0020.0002.13B9] # CHEROKEE LETTER MA
+13BA ; [.1F19.0020.0002.13BA] # CHEROKEE LETTER ME
+13BB ; [.1F1A.0020.0002.13BB] # CHEROKEE LETTER MI
+13BC ; [.1F1B.0020.0002.13BC] # CHEROKEE LETTER MO
+13BD ; [.1F1C.0020.0002.13BD] # CHEROKEE LETTER MU
+13BE ; [.1F1D.0020.0002.13BE] # CHEROKEE LETTER NA
+13BF ; [.1F1E.0020.0002.13BF] # CHEROKEE LETTER HNA
+13C0 ; [.1F1F.0020.0002.13C0] # CHEROKEE LETTER NAH
+13C1 ; [.1F20.0020.0002.13C1] # CHEROKEE LETTER NE
+13C2 ; [.1F21.0020.0002.13C2] # CHEROKEE LETTER NI
+13C3 ; [.1F22.0020.0002.13C3] # CHEROKEE LETTER NO
+13C4 ; [.1F23.0020.0002.13C4] # CHEROKEE LETTER NU
+13C5 ; [.1F24.0020.0002.13C5] # CHEROKEE LETTER NV
+13C6 ; [.1F25.0020.0002.13C6] # CHEROKEE LETTER QUA
+13C7 ; [.1F26.0020.0002.13C7] # CHEROKEE LETTER QUE
+13C8 ; [.1F27.0020.0002.13C8] # CHEROKEE LETTER QUI
+13C9 ; [.1F28.0020.0002.13C9] # CHEROKEE LETTER QUO
+13CA ; [.1F29.0020.0002.13CA] # CHEROKEE LETTER QUU
+13CB ; [.1F2A.0020.0002.13CB] # CHEROKEE LETTER QUV
+13CC ; [.1F2B.0020.0002.13CC] # CHEROKEE LETTER SA
+13CD ; [.1F2C.0020.0002.13CD] # CHEROKEE LETTER S
+13CE ; [.1F2D.0020.0002.13CE] # CHEROKEE LETTER SE
+13CF ; [.1F2E.0020.0002.13CF] # CHEROKEE LETTER SI
+13D0 ; [.1F2F.0020.0002.13D0] # CHEROKEE LETTER SO
+13D1 ; [.1F30.0020.0002.13D1] # CHEROKEE LETTER SU
+13D2 ; [.1F31.0020.0002.13D2] # CHEROKEE LETTER SV
+13D3 ; [.1F32.0020.0002.13D3] # CHEROKEE LETTER DA
+13D4 ; [.1F33.0020.0002.13D4] # CHEROKEE LETTER TA
+13D5 ; [.1F34.0020.0002.13D5] # CHEROKEE LETTER DE
+13D6 ; [.1F35.0020.0002.13D6] # CHEROKEE LETTER TE
+13D7 ; [.1F36.0020.0002.13D7] # CHEROKEE LETTER DI
+13D8 ; [.1F37.0020.0002.13D8] # CHEROKEE LETTER TI
+13D9 ; [.1F38.0020.0002.13D9] # CHEROKEE LETTER DO
+13DA ; [.1F39.0020.0002.13DA] # CHEROKEE LETTER DU
+13DB ; [.1F3A.0020.0002.13DB] # CHEROKEE LETTER DV
+13DC ; [.1F3B.0020.0002.13DC] # CHEROKEE LETTER DLA
+13DD ; [.1F3C.0020.0002.13DD] # CHEROKEE LETTER TLA
+13DE ; [.1F3D.0020.0002.13DE] # CHEROKEE LETTER TLE
+13DF ; [.1F3E.0020.0002.13DF] # CHEROKEE LETTER TLI
+13E0 ; [.1F3F.0020.0002.13E0] # CHEROKEE LETTER TLO
+13E1 ; [.1F40.0020.0002.13E1] # CHEROKEE LETTER TLU
+13E2 ; [.1F41.0020.0002.13E2] # CHEROKEE LETTER TLV
+13E3 ; [.1F42.0020.0002.13E3] # CHEROKEE LETTER TSA
+13E4 ; [.1F43.0020.0002.13E4] # CHEROKEE LETTER TSE
+13E5 ; [.1F44.0020.0002.13E5] # CHEROKEE LETTER TSI
+13E6 ; [.1F45.0020.0002.13E6] # CHEROKEE LETTER TSO
+13E7 ; [.1F46.0020.0002.13E7] # CHEROKEE LETTER TSU
+13E8 ; [.1F47.0020.0002.13E8] # CHEROKEE LETTER TSV
+13E9 ; [.1F48.0020.0002.13E9] # CHEROKEE LETTER WA
+13EA ; [.1F49.0020.0002.13EA] # CHEROKEE LETTER WE
+13EB ; [.1F4A.0020.0002.13EB] # CHEROKEE LETTER WI
+13EC ; [.1F4B.0020.0002.13EC] # CHEROKEE LETTER WO
+13ED ; [.1F4C.0020.0002.13ED] # CHEROKEE LETTER WU
+13EE ; [.1F4D.0020.0002.13EE] # CHEROKEE LETTER WV
+13EF ; [.1F4E.0020.0002.13EF] # CHEROKEE LETTER YA
+13F0 ; [.1F4F.0020.0002.13F0] # CHEROKEE LETTER YE
+13F1 ; [.1F50.0020.0002.13F1] # CHEROKEE LETTER YI
+13F2 ; [.1F51.0020.0002.13F2] # CHEROKEE LETTER YO
+13F3 ; [.1F52.0020.0002.13F3] # CHEROKEE LETTER YU
+13F4 ; [.1F53.0020.0002.13F4] # CHEROKEE LETTER YV
+1401 ; [.1F54.0020.0002.1401] # CANADIAN SYLLABICS E
+1402 ; [.1F55.0020.0002.1402] # CANADIAN SYLLABICS AAI
+1403 ; [.1F56.0020.0002.1403] # CANADIAN SYLLABICS I
+1404 ; [.1F57.0020.0002.1404] # CANADIAN SYLLABICS II
+1405 ; [.1F58.0020.0002.1405] # CANADIAN SYLLABICS O
+1406 ; [.1F59.0020.0002.1406] # CANADIAN SYLLABICS OO
+1407 ; [.1F5A.0020.0002.1407] # CANADIAN SYLLABICS Y-CREE OO
+1408 ; [.1F5B.0020.0002.1408] # CANADIAN SYLLABICS CARRIER EE
+1409 ; [.1F5C.0020.0002.1409] # CANADIAN SYLLABICS CARRIER I
+140A ; [.1F5D.0020.0002.140A] # CANADIAN SYLLABICS A
+140B ; [.1F5E.0020.0002.140B] # CANADIAN SYLLABICS AA
+140C ; [.1F5F.0020.0002.140C] # CANADIAN SYLLABICS WE
+140D ; [.1F60.0020.0002.140D] # CANADIAN SYLLABICS WEST-CREE WE
+140E ; [.1F61.0020.0002.140E] # CANADIAN SYLLABICS WI
+140F ; [.1F62.0020.0002.140F] # CANADIAN SYLLABICS WEST-CREE WI
+1410 ; [.1F63.0020.0002.1410] # CANADIAN SYLLABICS WII
+1411 ; [.1F64.0020.0002.1411] # CANADIAN SYLLABICS WEST-CREE WII
+1412 ; [.1F65.0020.0002.1412] # CANADIAN SYLLABICS WO
+1413 ; [.1F66.0020.0002.1413] # CANADIAN SYLLABICS WEST-CREE WO
+1414 ; [.1F67.0020.0002.1414] # CANADIAN SYLLABICS WOO
+1415 ; [.1F68.0020.0002.1415] # CANADIAN SYLLABICS WEST-CREE WOO
+1416 ; [.1F69.0020.0002.1416] # CANADIAN SYLLABICS NASKAPI WOO
+1417 ; [.1F6A.0020.0002.1417] # CANADIAN SYLLABICS WA
+1418 ; [.1F6B.0020.0002.1418] # CANADIAN SYLLABICS WEST-CREE WA
+1419 ; [.1F6C.0020.0002.1419] # CANADIAN SYLLABICS WAA
+141A ; [.1F6D.0020.0002.141A] # CANADIAN SYLLABICS WEST-CREE WAA
+141B ; [.1F6E.0020.0002.141B] # CANADIAN SYLLABICS NASKAPI WAA
+141C ; [.1F6F.0020.0002.141C] # CANADIAN SYLLABICS AI
+141D ; [.1F70.0020.0002.141D] # CANADIAN SYLLABICS Y-CREE W
+141E ; [.1F71.0020.0002.141E] # CANADIAN SYLLABICS GLOTTAL STOP
+141F ; [.1F72.0020.0002.141F] # CANADIAN SYLLABICS FINAL ACUTE
+1420 ; [.1F73.0020.0002.1420] # CANADIAN SYLLABICS FINAL GRAVE
+1421 ; [.1F74.0020.0002.1421] # CANADIAN SYLLABICS FINAL BOTTOM HALF RING
+1422 ; [.1F75.0020.0002.1422] # CANADIAN SYLLABICS FINAL TOP HALF RING
+1423 ; [.1F76.0020.0002.1423] # CANADIAN SYLLABICS FINAL RIGHT HALF RING
+1424 ; [.1F77.0020.0002.1424] # CANADIAN SYLLABICS FINAL RING
+1425 ; [.1F78.0020.0002.1425] # CANADIAN SYLLABICS FINAL DOUBLE ACUTE
+1426 ; [.1F79.0020.0002.1426] # CANADIAN SYLLABICS FINAL DOUBLE SHORT VERTICAL STROKES
+1427 ; [.1F7A.0020.0002.1427] # CANADIAN SYLLABICS FINAL MIDDLE DOT
+1428 ; [.1F7B.0020.0002.1428] # CANADIAN SYLLABICS FINAL SHORT HORIZONTAL STROKE
+1429 ; [.1F7C.0020.0002.1429] # CANADIAN SYLLABICS FINAL PLUS
+142A ; [.1F7D.0020.0002.142A] # CANADIAN SYLLABICS FINAL DOWN TACK
+142B ; [.1F7E.0020.0002.142B] # CANADIAN SYLLABICS EN
+142C ; [.1F7F.0020.0002.142C] # CANADIAN SYLLABICS IN
+142D ; [.1F80.0020.0002.142D] # CANADIAN SYLLABICS ON
+142E ; [.1F81.0020.0002.142E] # CANADIAN SYLLABICS AN
+142F ; [.1F82.0020.0002.142F] # CANADIAN SYLLABICS PE
+1430 ; [.1F83.0020.0002.1430] # CANADIAN SYLLABICS PAAI
+1431 ; [.1F84.0020.0002.1431] # CANADIAN SYLLABICS PI
+1432 ; [.1F85.0020.0002.1432] # CANADIAN SYLLABICS PII
+1433 ; [.1F86.0020.0002.1433] # CANADIAN SYLLABICS PO
+1434 ; [.1F87.0020.0002.1434] # CANADIAN SYLLABICS POO
+1435 ; [.1F88.0020.0002.1435] # CANADIAN SYLLABICS Y-CREE POO
+1436 ; [.1F89.0020.0002.1436] # CANADIAN SYLLABICS CARRIER HEE
+1437 ; [.1F8A.0020.0002.1437] # CANADIAN SYLLABICS CARRIER HI
+1438 ; [.1F8B.0020.0002.1438] # CANADIAN SYLLABICS PA
+1439 ; [.1F8C.0020.0002.1439] # CANADIAN SYLLABICS PAA
+143A ; [.1F8D.0020.0002.143A] # CANADIAN SYLLABICS PWE
+143B ; [.1F8E.0020.0002.143B] # CANADIAN SYLLABICS WEST-CREE PWE
+143C ; [.1F8F.0020.0002.143C] # CANADIAN SYLLABICS PWI
+143D ; [.1F90.0020.0002.143D] # CANADIAN SYLLABICS WEST-CREE PWI
+143E ; [.1F91.0020.0002.143E] # CANADIAN SYLLABICS PWII
+143F ; [.1F92.0020.0002.143F] # CANADIAN SYLLABICS WEST-CREE PWII
+1440 ; [.1F93.0020.0002.1440] # CANADIAN SYLLABICS PWO
+1441 ; [.1F94.0020.0002.1441] # CANADIAN SYLLABICS WEST-CREE PWO
+1442 ; [.1F95.0020.0002.1442] # CANADIAN SYLLABICS PWOO
+1443 ; [.1F96.0020.0002.1443] # CANADIAN SYLLABICS WEST-CREE PWOO
+1444 ; [.1F97.0020.0002.1444] # CANADIAN SYLLABICS PWA
+1445 ; [.1F98.0020.0002.1445] # CANADIAN SYLLABICS WEST-CREE PWA
+1446 ; [.1F99.0020.0002.1446] # CANADIAN SYLLABICS PWAA
+1447 ; [.1F9A.0020.0002.1447] # CANADIAN SYLLABICS WEST-CREE PWAA
+1448 ; [.1F9B.0020.0002.1448] # CANADIAN SYLLABICS Y-CREE PWAA
+1449 ; [.1F9C.0020.0002.1449] # CANADIAN SYLLABICS P
+144A ; [.1F9D.0020.0002.144A] # CANADIAN SYLLABICS WEST-CREE P
+144B ; [.1F9E.0020.0002.144B] # CANADIAN SYLLABICS CARRIER H
+144C ; [.1F9F.0020.0002.144C] # CANADIAN SYLLABICS TE
+144D ; [.1FA0.0020.0002.144D] # CANADIAN SYLLABICS TAAI
+144E ; [.1FA1.0020.0002.144E] # CANADIAN SYLLABICS TI
+144F ; [.1FA2.0020.0002.144F] # CANADIAN SYLLABICS TII
+1450 ; [.1FA3.0020.0002.1450] # CANADIAN SYLLABICS TO
+1451 ; [.1FA4.0020.0002.1451] # CANADIAN SYLLABICS TOO
+1452 ; [.1FA5.0020.0002.1452] # CANADIAN SYLLABICS Y-CREE TOO
+1453 ; [.1FA6.0020.0002.1453] # CANADIAN SYLLABICS CARRIER DEE
+1454 ; [.1FA7.0020.0002.1454] # CANADIAN SYLLABICS CARRIER DI
+1455 ; [.1FA8.0020.0002.1455] # CANADIAN SYLLABICS TA
+1456 ; [.1FA9.0020.0002.1456] # CANADIAN SYLLABICS TAA
+1457 ; [.1FAA.0020.0002.1457] # CANADIAN SYLLABICS TWE
+1458 ; [.1FAB.0020.0002.1458] # CANADIAN SYLLABICS WEST-CREE TWE
+1459 ; [.1FAC.0020.0002.1459] # CANADIAN SYLLABICS TWI
+145A ; [.1FAD.0020.0002.145A] # CANADIAN SYLLABICS WEST-CREE TWI
+145B ; [.1FAE.0020.0002.145B] # CANADIAN SYLLABICS TWII
+145C ; [.1FAF.0020.0002.145C] # CANADIAN SYLLABICS WEST-CREE TWII
+145D ; [.1FB0.0020.0002.145D] # CANADIAN SYLLABICS TWO
+145E ; [.1FB1.0020.0002.145E] # CANADIAN SYLLABICS WEST-CREE TWO
+145F ; [.1FB2.0020.0002.145F] # CANADIAN SYLLABICS TWOO
+1460 ; [.1FB3.0020.0002.1460] # CANADIAN SYLLABICS WEST-CREE TWOO
+1461 ; [.1FB4.0020.0002.1461] # CANADIAN SYLLABICS TWA
+1462 ; [.1FB5.0020.0002.1462] # CANADIAN SYLLABICS WEST-CREE TWA
+1463 ; [.1FB6.0020.0002.1463] # CANADIAN SYLLABICS TWAA
+1464 ; [.1FB7.0020.0002.1464] # CANADIAN SYLLABICS WEST-CREE TWAA
+1465 ; [.1FB8.0020.0002.1465] # CANADIAN SYLLABICS NASKAPI TWAA
+1466 ; [.1FB9.0020.0002.1466] # CANADIAN SYLLABICS T
+1467 ; [.1FBA.0020.0002.1467] # CANADIAN SYLLABICS TTE
+1468 ; [.1FBB.0020.0002.1468] # CANADIAN SYLLABICS TTI
+1469 ; [.1FBC.0020.0002.1469] # CANADIAN SYLLABICS TTO
+146A ; [.1FBD.0020.0002.146A] # CANADIAN SYLLABICS TTA
+146B ; [.1FBE.0020.0002.146B] # CANADIAN SYLLABICS KE
+146C ; [.1FBF.0020.0002.146C] # CANADIAN SYLLABICS KAAI
+146D ; [.1FC0.0020.0002.146D] # CANADIAN SYLLABICS KI
+146E ; [.1FC1.0020.0002.146E] # CANADIAN SYLLABICS KII
+146F ; [.1FC2.0020.0002.146F] # CANADIAN SYLLABICS KO
+1470 ; [.1FC3.0020.0002.1470] # CANADIAN SYLLABICS KOO
+1471 ; [.1FC4.0020.0002.1471] # CANADIAN SYLLABICS Y-CREE KOO
+1472 ; [.1FC5.0020.0002.1472] # CANADIAN SYLLABICS KA
+1473 ; [.1FC6.0020.0002.1473] # CANADIAN SYLLABICS KAA
+1474 ; [.1FC7.0020.0002.1474] # CANADIAN SYLLABICS KWE
+1475 ; [.1FC8.0020.0002.1475] # CANADIAN SYLLABICS WEST-CREE KWE
+1476 ; [.1FC9.0020.0002.1476] # CANADIAN SYLLABICS KWI
+1477 ; [.1FCA.0020.0002.1477] # CANADIAN SYLLABICS WEST-CREE KWI
+1478 ; [.1FCB.0020.0002.1478] # CANADIAN SYLLABICS KWII
+1479 ; [.1FCC.0020.0002.1479] # CANADIAN SYLLABICS WEST-CREE KWII
+147A ; [.1FCD.0020.0002.147A] # CANADIAN SYLLABICS KWO
+147B ; [.1FCE.0020.0002.147B] # CANADIAN SYLLABICS WEST-CREE KWO
+147C ; [.1FCF.0020.0002.147C] # CANADIAN SYLLABICS KWOO
+147D ; [.1FD0.0020.0002.147D] # CANADIAN SYLLABICS WEST-CREE KWOO
+147E ; [.1FD1.0020.0002.147E] # CANADIAN SYLLABICS KWA
+147F ; [.1FD2.0020.0002.147F] # CANADIAN SYLLABICS WEST-CREE KWA
+1480 ; [.1FD3.0020.0002.1480] # CANADIAN SYLLABICS KWAA
+1481 ; [.1FD4.0020.0002.1481] # CANADIAN SYLLABICS WEST-CREE KWAA
+1482 ; [.1FD5.0020.0002.1482] # CANADIAN SYLLABICS NASKAPI KWAA
+1483 ; [.1FD6.0020.0002.1483] # CANADIAN SYLLABICS K
+1484 ; [.1FD7.0020.0002.1484] # CANADIAN SYLLABICS KW
+1485 ; [.1FD8.0020.0002.1485] # CANADIAN SYLLABICS SOUTH-SLAVEY KEH
+1486 ; [.1FD9.0020.0002.1486] # CANADIAN SYLLABICS SOUTH-SLAVEY KIH
+1487 ; [.1FDA.0020.0002.1487] # CANADIAN SYLLABICS SOUTH-SLAVEY KOH
+1488 ; [.1FDB.0020.0002.1488] # CANADIAN SYLLABICS SOUTH-SLAVEY KAH
+1489 ; [.1FDC.0020.0002.1489] # CANADIAN SYLLABICS CE
+148A ; [.1FDD.0020.0002.148A] # CANADIAN SYLLABICS CAAI
+148B ; [.1FDE.0020.0002.148B] # CANADIAN SYLLABICS CI
+148C ; [.1FDF.0020.0002.148C] # CANADIAN SYLLABICS CII
+148D ; [.1FE0.0020.0002.148D] # CANADIAN SYLLABICS CO
+148E ; [.1FE1.0020.0002.148E] # CANADIAN SYLLABICS COO
+148F ; [.1FE2.0020.0002.148F] # CANADIAN SYLLABICS Y-CREE COO
+1490 ; [.1FE3.0020.0002.1490] # CANADIAN SYLLABICS CA
+1491 ; [.1FE4.0020.0002.1491] # CANADIAN SYLLABICS CAA
+1492 ; [.1FE5.0020.0002.1492] # CANADIAN SYLLABICS CWE
+1493 ; [.1FE6.0020.0002.1493] # CANADIAN SYLLABICS WEST-CREE CWE
+1494 ; [.1FE7.0020.0002.1494] # CANADIAN SYLLABICS CWI
+1495 ; [.1FE8.0020.0002.1495] # CANADIAN SYLLABICS WEST-CREE CWI
+1496 ; [.1FE9.0020.0002.1496] # CANADIAN SYLLABICS CWII
+1497 ; [.1FEA.0020.0002.1497] # CANADIAN SYLLABICS WEST-CREE CWII
+1498 ; [.1FEB.0020.0002.1498] # CANADIAN SYLLABICS CWO
+1499 ; [.1FEC.0020.0002.1499] # CANADIAN SYLLABICS WEST-CREE CWO
+149A ; [.1FED.0020.0002.149A] # CANADIAN SYLLABICS CWOO
+149B ; [.1FEE.0020.0002.149B] # CANADIAN SYLLABICS WEST-CREE CWOO
+149C ; [.1FEF.0020.0002.149C] # CANADIAN SYLLABICS CWA
+149D ; [.1FF0.0020.0002.149D] # CANADIAN SYLLABICS WEST-CREE CWA
+149E ; [.1FF1.0020.0002.149E] # CANADIAN SYLLABICS CWAA
+149F ; [.1FF2.0020.0002.149F] # CANADIAN SYLLABICS WEST-CREE CWAA
+14A0 ; [.1FF3.0020.0002.14A0] # CANADIAN SYLLABICS NASKAPI CWAA
+14A1 ; [.1FF4.0020.0002.14A1] # CANADIAN SYLLABICS C
+14A2 ; [.1FF5.0020.0002.14A2] # CANADIAN SYLLABICS SAYISI TH
+14A3 ; [.1FF6.0020.0002.14A3] # CANADIAN SYLLABICS ME
+14A4 ; [.1FF7.0020.0002.14A4] # CANADIAN SYLLABICS MAAI
+14A5 ; [.1FF8.0020.0002.14A5] # CANADIAN SYLLABICS MI
+14A6 ; [.1FF9.0020.0002.14A6] # CANADIAN SYLLABICS MII
+14A7 ; [.1FFA.0020.0002.14A7] # CANADIAN SYLLABICS MO
+14A8 ; [.1FFB.0020.0002.14A8] # CANADIAN SYLLABICS MOO
+14A9 ; [.1FFC.0020.0002.14A9] # CANADIAN SYLLABICS Y-CREE MOO
+14AA ; [.1FFD.0020.0002.14AA] # CANADIAN SYLLABICS MA
+14AB ; [.1FFE.0020.0002.14AB] # CANADIAN SYLLABICS MAA
+14AC ; [.1FFF.0020.0002.14AC] # CANADIAN SYLLABICS MWE
+14AD ; [.2000.0020.0002.14AD] # CANADIAN SYLLABICS WEST-CREE MWE
+14AE ; [.2001.0020.0002.14AE] # CANADIAN SYLLABICS MWI
+14AF ; [.2002.0020.0002.14AF] # CANADIAN SYLLABICS WEST-CREE MWI
+14B0 ; [.2003.0020.0002.14B0] # CANADIAN SYLLABICS MWII
+14B1 ; [.2004.0020.0002.14B1] # CANADIAN SYLLABICS WEST-CREE MWII
+14B2 ; [.2005.0020.0002.14B2] # CANADIAN SYLLABICS MWO
+14B3 ; [.2006.0020.0002.14B3] # CANADIAN SYLLABICS WEST-CREE MWO
+14B4 ; [.2007.0020.0002.14B4] # CANADIAN SYLLABICS MWOO
+14B5 ; [.2008.0020.0002.14B5] # CANADIAN SYLLABICS WEST-CREE MWOO
+14B6 ; [.2009.0020.0002.14B6] # CANADIAN SYLLABICS MWA
+14B7 ; [.200A.0020.0002.14B7] # CANADIAN SYLLABICS WEST-CREE MWA
+14B8 ; [.200B.0020.0002.14B8] # CANADIAN SYLLABICS MWAA
+14B9 ; [.200C.0020.0002.14B9] # CANADIAN SYLLABICS WEST-CREE MWAA
+14BA ; [.200D.0020.0002.14BA] # CANADIAN SYLLABICS NASKAPI MWAA
+14BB ; [.200E.0020.0002.14BB] # CANADIAN SYLLABICS M
+14BC ; [.200F.0020.0002.14BC] # CANADIAN SYLLABICS WEST-CREE M
+14BD ; [.2010.0020.0002.14BD] # CANADIAN SYLLABICS MH
+14BE ; [.2011.0020.0002.14BE] # CANADIAN SYLLABICS ATHAPASCAN M
+14BF ; [.2012.0020.0002.14BF] # CANADIAN SYLLABICS SAYISI M
+14C0 ; [.2013.0020.0002.14C0] # CANADIAN SYLLABICS NE
+14C1 ; [.2014.0020.0002.14C1] # CANADIAN SYLLABICS NAAI
+14C2 ; [.2015.0020.0002.14C2] # CANADIAN SYLLABICS NI
+14C3 ; [.2016.0020.0002.14C3] # CANADIAN SYLLABICS NII
+14C4 ; [.2017.0020.0002.14C4] # CANADIAN SYLLABICS NO
+14C5 ; [.2018.0020.0002.14C5] # CANADIAN SYLLABICS NOO
+14C6 ; [.2019.0020.0002.14C6] # CANADIAN SYLLABICS Y-CREE NOO
+14C7 ; [.201A.0020.0002.14C7] # CANADIAN SYLLABICS NA
+14C8 ; [.201B.0020.0002.14C8] # CANADIAN SYLLABICS NAA
+14C9 ; [.201C.0020.0002.14C9] # CANADIAN SYLLABICS NWE
+14CA ; [.201D.0020.0002.14CA] # CANADIAN SYLLABICS WEST-CREE NWE
+14CB ; [.201E.0020.0002.14CB] # CANADIAN SYLLABICS NWA
+14CC ; [.201F.0020.0002.14CC] # CANADIAN SYLLABICS WEST-CREE NWA
+14CD ; [.2020.0020.0002.14CD] # CANADIAN SYLLABICS NWAA
+14CE ; [.2021.0020.0002.14CE] # CANADIAN SYLLABICS WEST-CREE NWAA
+14CF ; [.2022.0020.0002.14CF] # CANADIAN SYLLABICS NASKAPI NWAA
+14D0 ; [.2023.0020.0002.14D0] # CANADIAN SYLLABICS N
+14D1 ; [.2024.0020.0002.14D1] # CANADIAN SYLLABICS CARRIER NG
+14D2 ; [.2025.0020.0002.14D2] # CANADIAN SYLLABICS NH
+14D3 ; [.2026.0020.0002.14D3] # CANADIAN SYLLABICS LE
+14D4 ; [.2027.0020.0002.14D4] # CANADIAN SYLLABICS LAAI
+14D5 ; [.2028.0020.0002.14D5] # CANADIAN SYLLABICS LI
+14D6 ; [.2029.0020.0002.14D6] # CANADIAN SYLLABICS LII
+14D7 ; [.202A.0020.0002.14D7] # CANADIAN SYLLABICS LO
+14D8 ; [.202B.0020.0002.14D8] # CANADIAN SYLLABICS LOO
+14D9 ; [.202C.0020.0002.14D9] # CANADIAN SYLLABICS Y-CREE LOO
+14DA ; [.202D.0020.0002.14DA] # CANADIAN SYLLABICS LA
+14DB ; [.202E.0020.0002.14DB] # CANADIAN SYLLABICS LAA
+14DC ; [.202F.0020.0002.14DC] # CANADIAN SYLLABICS LWE
+14DD ; [.2030.0020.0002.14DD] # CANADIAN SYLLABICS WEST-CREE LWE
+14DE ; [.2031.0020.0002.14DE] # CANADIAN SYLLABICS LWI
+14DF ; [.2032.0020.0002.14DF] # CANADIAN SYLLABICS WEST-CREE LWI
+14E0 ; [.2033.0020.0002.14E0] # CANADIAN SYLLABICS LWII
+14E1 ; [.2034.0020.0002.14E1] # CANADIAN SYLLABICS WEST-CREE LWII
+14E2 ; [.2035.0020.0002.14E2] # CANADIAN SYLLABICS LWO
+14E3 ; [.2036.0020.0002.14E3] # CANADIAN SYLLABICS WEST-CREE LWO
+14E4 ; [.2037.0020.0002.14E4] # CANADIAN SYLLABICS LWOO
+14E5 ; [.2038.0020.0002.14E5] # CANADIAN SYLLABICS WEST-CREE LWOO
+14E6 ; [.2039.0020.0002.14E6] # CANADIAN SYLLABICS LWA
+14E7 ; [.203A.0020.0002.14E7] # CANADIAN SYLLABICS WEST-CREE LWA
+14E8 ; [.203B.0020.0002.14E8] # CANADIAN SYLLABICS LWAA
+14E9 ; [.203C.0020.0002.14E9] # CANADIAN SYLLABICS WEST-CREE LWAA
+14EA ; [.203D.0020.0002.14EA] # CANADIAN SYLLABICS L
+14EB ; [.203E.0020.0002.14EB] # CANADIAN SYLLABICS WEST-CREE L
+14EC ; [.203F.0020.0002.14EC] # CANADIAN SYLLABICS MEDIAL L
+14ED ; [.2040.0020.0002.14ED] # CANADIAN SYLLABICS SE
+14EE ; [.2041.0020.0002.14EE] # CANADIAN SYLLABICS SAAI
+14EF ; [.2042.0020.0002.14EF] # CANADIAN SYLLABICS SI
+14F0 ; [.2043.0020.0002.14F0] # CANADIAN SYLLABICS SII
+14F1 ; [.2044.0020.0002.14F1] # CANADIAN SYLLABICS SO
+14F2 ; [.2045.0020.0002.14F2] # CANADIAN SYLLABICS SOO
+14F3 ; [.2046.0020.0002.14F3] # CANADIAN SYLLABICS Y-CREE SOO
+14F4 ; [.2047.0020.0002.14F4] # CANADIAN SYLLABICS SA
+14F5 ; [.2048.0020.0002.14F5] # CANADIAN SYLLABICS SAA
+14F6 ; [.2049.0020.0002.14F6] # CANADIAN SYLLABICS SWE
+14F7 ; [.204A.0020.0002.14F7] # CANADIAN SYLLABICS WEST-CREE SWE
+14F8 ; [.204B.0020.0002.14F8] # CANADIAN SYLLABICS SWI
+14F9 ; [.204C.0020.0002.14F9] # CANADIAN SYLLABICS WEST-CREE SWI
+14FA ; [.204D.0020.0002.14FA] # CANADIAN SYLLABICS SWII
+14FB ; [.204E.0020.0002.14FB] # CANADIAN SYLLABICS WEST-CREE SWII
+14FC ; [.204F.0020.0002.14FC] # CANADIAN SYLLABICS SWO
+14FD ; [.2050.0020.0002.14FD] # CANADIAN SYLLABICS WEST-CREE SWO
+14FE ; [.2051.0020.0002.14FE] # CANADIAN SYLLABICS SWOO
+14FF ; [.2052.0020.0002.14FF] # CANADIAN SYLLABICS WEST-CREE SWOO
+1500 ; [.2053.0020.0002.1500] # CANADIAN SYLLABICS SWA
+1501 ; [.2054.0020.0002.1501] # CANADIAN SYLLABICS WEST-CREE SWA
+1502 ; [.2055.0020.0002.1502] # CANADIAN SYLLABICS SWAA
+1503 ; [.2056.0020.0002.1503] # CANADIAN SYLLABICS WEST-CREE SWAA
+1504 ; [.2057.0020.0002.1504] # CANADIAN SYLLABICS NASKAPI SWAA
+1505 ; [.2058.0020.0002.1505] # CANADIAN SYLLABICS S
+1506 ; [.2059.0020.0002.1506] # CANADIAN SYLLABICS ATHAPASCAN S
+1507 ; [.205A.0020.0002.1507] # CANADIAN SYLLABICS SW
+1508 ; [.205B.0020.0002.1508] # CANADIAN SYLLABICS BLACKFOOT S
+1509 ; [.205C.0020.0002.1509] # CANADIAN SYLLABICS MOOSE-CREE SK
+150A ; [.205D.0020.0002.150A] # CANADIAN SYLLABICS NASKAPI SKW
+150B ; [.205E.0020.0002.150B] # CANADIAN SYLLABICS NASKAPI S-W
+150C ; [.205F.0020.0002.150C] # CANADIAN SYLLABICS NASKAPI SPWA
+150D ; [.2060.0020.0002.150D] # CANADIAN SYLLABICS NASKAPI STWA
+150E ; [.2061.0020.0002.150E] # CANADIAN SYLLABICS NASKAPI SKWA
+150F ; [.2062.0020.0002.150F] # CANADIAN SYLLABICS NASKAPI SCWA
+1510 ; [.2063.0020.0002.1510] # CANADIAN SYLLABICS SHE
+1511 ; [.2064.0020.0002.1511] # CANADIAN SYLLABICS SHI
+1512 ; [.2065.0020.0002.1512] # CANADIAN SYLLABICS SHII
+1513 ; [.2066.0020.0002.1513] # CANADIAN SYLLABICS SHO
+1514 ; [.2067.0020.0002.1514] # CANADIAN SYLLABICS SHOO
+1515 ; [.2068.0020.0002.1515] # CANADIAN SYLLABICS SHA
+1516 ; [.2069.0020.0002.1516] # CANADIAN SYLLABICS SHAA
+1517 ; [.206A.0020.0002.1517] # CANADIAN SYLLABICS SHWE
+1518 ; [.206B.0020.0002.1518] # CANADIAN SYLLABICS WEST-CREE SHWE
+1519 ; [.206C.0020.0002.1519] # CANADIAN SYLLABICS SHWI
+151A ; [.206D.0020.0002.151A] # CANADIAN SYLLABICS WEST-CREE SHWI
+151B ; [.206E.0020.0002.151B] # CANADIAN SYLLABICS SHWII
+151C ; [.206F.0020.0002.151C] # CANADIAN SYLLABICS WEST-CREE SHWII
+151D ; [.2070.0020.0002.151D] # CANADIAN SYLLABICS SHWO
+151E ; [.2071.0020.0002.151E] # CANADIAN SYLLABICS WEST-CREE SHWO
+151F ; [.2072.0020.0002.151F] # CANADIAN SYLLABICS SHWOO
+1520 ; [.2073.0020.0002.1520] # CANADIAN SYLLABICS WEST-CREE SHWOO
+1521 ; [.2074.0020.0002.1521] # CANADIAN SYLLABICS SHWA
+1522 ; [.2075.0020.0002.1522] # CANADIAN SYLLABICS WEST-CREE SHWA
+1523 ; [.2076.0020.0002.1523] # CANADIAN SYLLABICS SHWAA
+1524 ; [.2077.0020.0002.1524] # CANADIAN SYLLABICS WEST-CREE SHWAA
+1525 ; [.2078.0020.0002.1525] # CANADIAN SYLLABICS SH
+1526 ; [.2079.0020.0002.1526] # CANADIAN SYLLABICS YE
+1527 ; [.207A.0020.0002.1527] # CANADIAN SYLLABICS YAAI
+1528 ; [.207B.0020.0002.1528] # CANADIAN SYLLABICS YI
+1529 ; [.207C.0020.0002.1529] # CANADIAN SYLLABICS YII
+152A ; [.207D.0020.0002.152A] # CANADIAN SYLLABICS YO
+152B ; [.207E.0020.0002.152B] # CANADIAN SYLLABICS YOO
+152C ; [.207F.0020.0002.152C] # CANADIAN SYLLABICS Y-CREE YOO
+152D ; [.2080.0020.0002.152D] # CANADIAN SYLLABICS YA
+152E ; [.2081.0020.0002.152E] # CANADIAN SYLLABICS YAA
+152F ; [.2082.0020.0002.152F] # CANADIAN SYLLABICS YWE
+1530 ; [.2083.0020.0002.1530] # CANADIAN SYLLABICS WEST-CREE YWE
+1531 ; [.2084.0020.0002.1531] # CANADIAN SYLLABICS YWI
+1532 ; [.2085.0020.0002.1532] # CANADIAN SYLLABICS WEST-CREE YWI
+1533 ; [.2086.0020.0002.1533] # CANADIAN SYLLABICS YWII
+1534 ; [.2087.0020.0002.1534] # CANADIAN SYLLABICS WEST-CREE YWII
+1535 ; [.2088.0020.0002.1535] # CANADIAN SYLLABICS YWO
+1536 ; [.2089.0020.0002.1536] # CANADIAN SYLLABICS WEST-CREE YWO
+1537 ; [.208A.0020.0002.1537] # CANADIAN SYLLABICS YWOO
+1538 ; [.208B.0020.0002.1538] # CANADIAN SYLLABICS WEST-CREE YWOO
+1539 ; [.208C.0020.0002.1539] # CANADIAN SYLLABICS YWA
+153A ; [.208D.0020.0002.153A] # CANADIAN SYLLABICS WEST-CREE YWA
+153B ; [.208E.0020.0002.153B] # CANADIAN SYLLABICS YWAA
+153C ; [.208F.0020.0002.153C] # CANADIAN SYLLABICS WEST-CREE YWAA
+153D ; [.2090.0020.0002.153D] # CANADIAN SYLLABICS NASKAPI YWAA
+153E ; [.2091.0020.0002.153E] # CANADIAN SYLLABICS Y
+153F ; [.2092.0020.0002.153F] # CANADIAN SYLLABICS BIBLE-CREE Y
+1540 ; [.2093.0020.0002.1540] # CANADIAN SYLLABICS WEST-CREE Y
+1541 ; [.2094.0020.0002.1541] # CANADIAN SYLLABICS SAYISI YI
+1542 ; [.2095.0020.0002.1542] # CANADIAN SYLLABICS RE
+1543 ; [.2096.0020.0002.1543] # CANADIAN SYLLABICS R-CREE RE
+1544 ; [.2097.0020.0002.1544] # CANADIAN SYLLABICS WEST-CREE LE
+1545 ; [.2098.0020.0002.1545] # CANADIAN SYLLABICS RAAI
+1546 ; [.2099.0020.0002.1546] # CANADIAN SYLLABICS RI
+1547 ; [.209A.0020.0002.1547] # CANADIAN SYLLABICS RII
+1548 ; [.209B.0020.0002.1548] # CANADIAN SYLLABICS RO
+1549 ; [.209C.0020.0002.1549] # CANADIAN SYLLABICS ROO
+154A ; [.209D.0020.0002.154A] # CANADIAN SYLLABICS WEST-CREE LO
+154B ; [.209E.0020.0002.154B] # CANADIAN SYLLABICS RA
+154C ; [.209F.0020.0002.154C] # CANADIAN SYLLABICS RAA
+154D ; [.20A0.0020.0002.154D] # CANADIAN SYLLABICS WEST-CREE LA
+154E ; [.20A1.0020.0002.154E] # CANADIAN SYLLABICS RWAA
+154F ; [.20A2.0020.0002.154F] # CANADIAN SYLLABICS WEST-CREE RWAA
+1550 ; [.20A3.0020.0002.1550] # CANADIAN SYLLABICS R
+1551 ; [.20A4.0020.0002.1551] # CANADIAN SYLLABICS WEST-CREE R
+1552 ; [.20A5.0020.0002.1552] # CANADIAN SYLLABICS MEDIAL R
+1553 ; [.20A6.0020.0002.1553] # CANADIAN SYLLABICS FE
+1554 ; [.20A7.0020.0002.1554] # CANADIAN SYLLABICS FAAI
+1555 ; [.20A8.0020.0002.1555] # CANADIAN SYLLABICS FI
+1556 ; [.20A9.0020.0002.1556] # CANADIAN SYLLABICS FII
+1557 ; [.20AA.0020.0002.1557] # CANADIAN SYLLABICS FO
+1558 ; [.20AB.0020.0002.1558] # CANADIAN SYLLABICS FOO
+1559 ; [.20AC.0020.0002.1559] # CANADIAN SYLLABICS FA
+155A ; [.20AD.0020.0002.155A] # CANADIAN SYLLABICS FAA
+155B ; [.20AE.0020.0002.155B] # CANADIAN SYLLABICS FWAA
+155C ; [.20AF.0020.0002.155C] # CANADIAN SYLLABICS WEST-CREE FWAA
+155D ; [.20B0.0020.0002.155D] # CANADIAN SYLLABICS F
+155E ; [.20B1.0020.0002.155E] # CANADIAN SYLLABICS THE
+155F ; [.20B2.0020.0002.155F] # CANADIAN SYLLABICS N-CREE THE
+1560 ; [.20B3.0020.0002.1560] # CANADIAN SYLLABICS THI
+1561 ; [.20B4.0020.0002.1561] # CANADIAN SYLLABICS N-CREE THI
+1562 ; [.20B5.0020.0002.1562] # CANADIAN SYLLABICS THII
+1563 ; [.20B6.0020.0002.1563] # CANADIAN SYLLABICS N-CREE THII
+1564 ; [.20B7.0020.0002.1564] # CANADIAN SYLLABICS THO
+1565 ; [.20B8.0020.0002.1565] # CANADIAN SYLLABICS THOO
+1566 ; [.20B9.0020.0002.1566] # CANADIAN SYLLABICS THA
+1567 ; [.20BA.0020.0002.1567] # CANADIAN SYLLABICS THAA
+1568 ; [.20BB.0020.0002.1568] # CANADIAN SYLLABICS THWAA
+1569 ; [.20BC.0020.0002.1569] # CANADIAN SYLLABICS WEST-CREE THWAA
+156A ; [.20BD.0020.0002.156A] # CANADIAN SYLLABICS TH
+156B ; [.20BE.0020.0002.156B] # CANADIAN SYLLABICS TTHE
+156C ; [.20BF.0020.0002.156C] # CANADIAN SYLLABICS TTHI
+156D ; [.20C0.0020.0002.156D] # CANADIAN SYLLABICS TTHO
+156E ; [.20C1.0020.0002.156E] # CANADIAN SYLLABICS TTHA
+156F ; [.20C2.0020.0002.156F] # CANADIAN SYLLABICS TTH
+1570 ; [.20C3.0020.0002.1570] # CANADIAN SYLLABICS TYE
+1571 ; [.20C4.0020.0002.1571] # CANADIAN SYLLABICS TYI
+1572 ; [.20C5.0020.0002.1572] # CANADIAN SYLLABICS TYO
+1573 ; [.20C6.0020.0002.1573] # CANADIAN SYLLABICS TYA
+1574 ; [.20C7.0020.0002.1574] # CANADIAN SYLLABICS NUNAVIK HE
+1575 ; [.20C8.0020.0002.1575] # CANADIAN SYLLABICS NUNAVIK HI
+1576 ; [.20C9.0020.0002.1576] # CANADIAN SYLLABICS NUNAVIK HII
+1577 ; [.20CA.0020.0002.1577] # CANADIAN SYLLABICS NUNAVIK HO
+1578 ; [.20CB.0020.0002.1578] # CANADIAN SYLLABICS NUNAVIK HOO
+1579 ; [.20CC.0020.0002.1579] # CANADIAN SYLLABICS NUNAVIK HA
+157A ; [.20CD.0020.0002.157A] # CANADIAN SYLLABICS NUNAVIK HAA
+157B ; [.20CE.0020.0002.157B] # CANADIAN SYLLABICS NUNAVIK H
+157D ; [.20CF.0020.0002.157D] # CANADIAN SYLLABICS HK
+166F ; [.20D0.0020.0002.166F] # CANADIAN SYLLABICS QAI
+157E ; [.20D1.0020.0002.157E] # CANADIAN SYLLABICS QAAI
+157F ; [.20D2.0020.0002.157F] # CANADIAN SYLLABICS QI
+1580 ; [.20D3.0020.0002.1580] # CANADIAN SYLLABICS QII
+1581 ; [.20D4.0020.0002.1581] # CANADIAN SYLLABICS QO
+1582 ; [.20D5.0020.0002.1582] # CANADIAN SYLLABICS QOO
+1583 ; [.20D6.0020.0002.1583] # CANADIAN SYLLABICS QA
+1584 ; [.20D7.0020.0002.1584] # CANADIAN SYLLABICS QAA
+1585 ; [.20D8.0020.0002.1585] # CANADIAN SYLLABICS Q
+1586 ; [.20D9.0020.0002.1586] # CANADIAN SYLLABICS TLHE
+1587 ; [.20DA.0020.0002.1587] # CANADIAN SYLLABICS TLHI
+1588 ; [.20DB.0020.0002.1588] # CANADIAN SYLLABICS TLHO
+1589 ; [.20DC.0020.0002.1589] # CANADIAN SYLLABICS TLHA
+158A ; [.20DD.0020.0002.158A] # CANADIAN SYLLABICS WEST-CREE RE
+158B ; [.20DE.0020.0002.158B] # CANADIAN SYLLABICS WEST-CREE RI
+158C ; [.20DF.0020.0002.158C] # CANADIAN SYLLABICS WEST-CREE RO
+158D ; [.20E0.0020.0002.158D] # CANADIAN SYLLABICS WEST-CREE RA
+1670 ; [.20E1.0020.0002.1670] # CANADIAN SYLLABICS NGAI
+158E ; [.20E2.0020.0002.158E] # CANADIAN SYLLABICS NGAAI
+158F ; [.20E3.0020.0002.158F] # CANADIAN SYLLABICS NGI
+1590 ; [.20E4.0020.0002.1590] # CANADIAN SYLLABICS NGII
+1591 ; [.20E5.0020.0002.1591] # CANADIAN SYLLABICS NGO
+1592 ; [.20E6.0020.0002.1592] # CANADIAN SYLLABICS NGOO
+1593 ; [.20E7.0020.0002.1593] # CANADIAN SYLLABICS NGA
+1594 ; [.20E8.0020.0002.1594] # CANADIAN SYLLABICS NGAA
+1595 ; [.20E9.0020.0002.1595] # CANADIAN SYLLABICS NG
+1671 ; [.20EA.0020.0002.1671] # CANADIAN SYLLABICS NNGI
+1672 ; [.20EB.0020.0002.1672] # CANADIAN SYLLABICS NNGII
+1673 ; [.20EC.0020.0002.1673] # CANADIAN SYLLABICS NNGO
+1674 ; [.20ED.0020.0002.1674] # CANADIAN SYLLABICS NNGOO
+1675 ; [.20EE.0020.0002.1675] # CANADIAN SYLLABICS NNGA
+1676 ; [.20EF.0020.0002.1676] # CANADIAN SYLLABICS NNGAA
+1596 ; [.20F0.0020.0002.1596] # CANADIAN SYLLABICS NNG
+1597 ; [.20F1.0020.0002.1597] # CANADIAN SYLLABICS SAYISI SHE
+1598 ; [.20F2.0020.0002.1598] # CANADIAN SYLLABICS SAYISI SHI
+1599 ; [.20F3.0020.0002.1599] # CANADIAN SYLLABICS SAYISI SHO
+159A ; [.20F4.0020.0002.159A] # CANADIAN SYLLABICS SAYISI SHA
+159B ; [.20F5.0020.0002.159B] # CANADIAN SYLLABICS WOODS-CREE THE
+159C ; [.20F6.0020.0002.159C] # CANADIAN SYLLABICS WOODS-CREE THI
+159D ; [.20F7.0020.0002.159D] # CANADIAN SYLLABICS WOODS-CREE THO
+159E ; [.20F8.0020.0002.159E] # CANADIAN SYLLABICS WOODS-CREE THA
+159F ; [.20F9.0020.0002.159F] # CANADIAN SYLLABICS WOODS-CREE TH
+15A0 ; [.20FA.0020.0002.15A0] # CANADIAN SYLLABICS LHI
+15A1 ; [.20FB.0020.0002.15A1] # CANADIAN SYLLABICS LHII
+15A2 ; [.20FC.0020.0002.15A2] # CANADIAN SYLLABICS LHO
+15A3 ; [.20FD.0020.0002.15A3] # CANADIAN SYLLABICS LHOO
+15A4 ; [.20FE.0020.0002.15A4] # CANADIAN SYLLABICS LHA
+15A5 ; [.20FF.0020.0002.15A5] # CANADIAN SYLLABICS LHAA
+15A6 ; [.2100.0020.0002.15A6] # CANADIAN SYLLABICS LH
+157C ; [.2101.0020.0002.157C] # CANADIAN SYLLABICS NUNAVUT H
+15A7 ; [.2102.0020.0002.15A7] # CANADIAN SYLLABICS TH-CREE THE
+15A8 ; [.2103.0020.0002.15A8] # CANADIAN SYLLABICS TH-CREE THI
+15A9 ; [.2104.0020.0002.15A9] # CANADIAN SYLLABICS TH-CREE THII
+15AA ; [.2105.0020.0002.15AA] # CANADIAN SYLLABICS TH-CREE THO
+15AB ; [.2106.0020.0002.15AB] # CANADIAN SYLLABICS TH-CREE THOO
+15AC ; [.2107.0020.0002.15AC] # CANADIAN SYLLABICS TH-CREE THA
+15AD ; [.2108.0020.0002.15AD] # CANADIAN SYLLABICS TH-CREE THAA
+15AE ; [.2109.0020.0002.15AE] # CANADIAN SYLLABICS TH-CREE TH
+15AF ; [.210A.0020.0002.15AF] # CANADIAN SYLLABICS AIVILIK B
+15B0 ; [.210B.0020.0002.15B0] # CANADIAN SYLLABICS BLACKFOOT E
+15B1 ; [.210C.0020.0002.15B1] # CANADIAN SYLLABICS BLACKFOOT I
+15B2 ; [.210D.0020.0002.15B2] # CANADIAN SYLLABICS BLACKFOOT O
+15B3 ; [.210E.0020.0002.15B3] # CANADIAN SYLLABICS BLACKFOOT A
+15B4 ; [.210F.0020.0002.15B4] # CANADIAN SYLLABICS BLACKFOOT WE
+15B5 ; [.2110.0020.0002.15B5] # CANADIAN SYLLABICS BLACKFOOT WI
+15B6 ; [.2111.0020.0002.15B6] # CANADIAN SYLLABICS BLACKFOOT WO
+15B7 ; [.2112.0020.0002.15B7] # CANADIAN SYLLABICS BLACKFOOT WA
+15B8 ; [.2113.0020.0002.15B8] # CANADIAN SYLLABICS BLACKFOOT NE
+15B9 ; [.2114.0020.0002.15B9] # CANADIAN SYLLABICS BLACKFOOT NI
+15BA ; [.2115.0020.0002.15BA] # CANADIAN SYLLABICS BLACKFOOT NO
+15BB ; [.2116.0020.0002.15BB] # CANADIAN SYLLABICS BLACKFOOT NA
+15BC ; [.2117.0020.0002.15BC] # CANADIAN SYLLABICS BLACKFOOT KE
+15BD ; [.2118.0020.0002.15BD] # CANADIAN SYLLABICS BLACKFOOT KI
+15BE ; [.2119.0020.0002.15BE] # CANADIAN SYLLABICS BLACKFOOT KO
+15BF ; [.211A.0020.0002.15BF] # CANADIAN SYLLABICS BLACKFOOT KA
+15C0 ; [.211B.0020.0002.15C0] # CANADIAN SYLLABICS SAYISI HE
+15C1 ; [.211C.0020.0002.15C1] # CANADIAN SYLLABICS SAYISI HI
+15C2 ; [.211D.0020.0002.15C2] # CANADIAN SYLLABICS SAYISI HO
+15C3 ; [.211E.0020.0002.15C3] # CANADIAN SYLLABICS SAYISI HA
+15C4 ; [.211F.0020.0002.15C4] # CANADIAN SYLLABICS CARRIER GHU
+15C5 ; [.2120.0020.0002.15C5] # CANADIAN SYLLABICS CARRIER GHO
+15C6 ; [.2121.0020.0002.15C6] # CANADIAN SYLLABICS CARRIER GHE
+15C7 ; [.2122.0020.0002.15C7] # CANADIAN SYLLABICS CARRIER GHEE
+15C8 ; [.2123.0020.0002.15C8] # CANADIAN SYLLABICS CARRIER GHI
+15C9 ; [.2124.0020.0002.15C9] # CANADIAN SYLLABICS CARRIER GHA
+15CA ; [.2125.0020.0002.15CA] # CANADIAN SYLLABICS CARRIER RU
+15CB ; [.2126.0020.0002.15CB] # CANADIAN SYLLABICS CARRIER RO
+15CC ; [.2127.0020.0002.15CC] # CANADIAN SYLLABICS CARRIER RE
+15CD ; [.2128.0020.0002.15CD] # CANADIAN SYLLABICS CARRIER REE
+15CE ; [.2129.0020.0002.15CE] # CANADIAN SYLLABICS CARRIER RI
+15CF ; [.212A.0020.0002.15CF] # CANADIAN SYLLABICS CARRIER RA
+15D0 ; [.212B.0020.0002.15D0] # CANADIAN SYLLABICS CARRIER WU
+15D1 ; [.212C.0020.0002.15D1] # CANADIAN SYLLABICS CARRIER WO
+15D2 ; [.212D.0020.0002.15D2] # CANADIAN SYLLABICS CARRIER WE
+15D3 ; [.212E.0020.0002.15D3] # CANADIAN SYLLABICS CARRIER WEE
+15D4 ; [.212F.0020.0002.15D4] # CANADIAN SYLLABICS CARRIER WI
+15D5 ; [.2130.0020.0002.15D5] # CANADIAN SYLLABICS CARRIER WA
+15D6 ; [.2131.0020.0002.15D6] # CANADIAN SYLLABICS CARRIER HWU
+15D7 ; [.2132.0020.0002.15D7] # CANADIAN SYLLABICS CARRIER HWO
+15D8 ; [.2133.0020.0002.15D8] # CANADIAN SYLLABICS CARRIER HWE
+15D9 ; [.2134.0020.0002.15D9] # CANADIAN SYLLABICS CARRIER HWEE
+15DA ; [.2135.0020.0002.15DA] # CANADIAN SYLLABICS CARRIER HWI
+15DB ; [.2136.0020.0002.15DB] # CANADIAN SYLLABICS CARRIER HWA
+15DC ; [.2137.0020.0002.15DC] # CANADIAN SYLLABICS CARRIER THU
+15DD ; [.2138.0020.0002.15DD] # CANADIAN SYLLABICS CARRIER THO
+15DE ; [.2139.0020.0002.15DE] # CANADIAN SYLLABICS CARRIER THE
+15DF ; [.213A.0020.0002.15DF] # CANADIAN SYLLABICS CARRIER THEE
+15E0 ; [.213B.0020.0002.15E0] # CANADIAN SYLLABICS CARRIER THI
+15E1 ; [.213C.0020.0002.15E1] # CANADIAN SYLLABICS CARRIER THA
+15E2 ; [.213D.0020.0002.15E2] # CANADIAN SYLLABICS CARRIER TTU
+15E3 ; [.213E.0020.0002.15E3] # CANADIAN SYLLABICS CARRIER TTO
+15E4 ; [.213F.0020.0002.15E4] # CANADIAN SYLLABICS CARRIER TTE
+15E5 ; [.2140.0020.0002.15E5] # CANADIAN SYLLABICS CARRIER TTEE
+15E6 ; [.2141.0020.0002.15E6] # CANADIAN SYLLABICS CARRIER TTI
+15E7 ; [.2142.0020.0002.15E7] # CANADIAN SYLLABICS CARRIER TTA
+15E8 ; [.2143.0020.0002.15E8] # CANADIAN SYLLABICS CARRIER PU
+15E9 ; [.2144.0020.0002.15E9] # CANADIAN SYLLABICS CARRIER PO
+15EA ; [.2145.0020.0002.15EA] # CANADIAN SYLLABICS CARRIER PE
+15EB ; [.2146.0020.0002.15EB] # CANADIAN SYLLABICS CARRIER PEE
+15EC ; [.2147.0020.0002.15EC] # CANADIAN SYLLABICS CARRIER PI
+15ED ; [.2148.0020.0002.15ED] # CANADIAN SYLLABICS CARRIER PA
+15EE ; [.2149.0020.0002.15EE] # CANADIAN SYLLABICS CARRIER P
+15EF ; [.214A.0020.0002.15EF] # CANADIAN SYLLABICS CARRIER GU
+15F0 ; [.214B.0020.0002.15F0] # CANADIAN SYLLABICS CARRIER GO
+15F1 ; [.214C.0020.0002.15F1] # CANADIAN SYLLABICS CARRIER GE
+15F2 ; [.214D.0020.0002.15F2] # CANADIAN SYLLABICS CARRIER GEE
+15F3 ; [.214E.0020.0002.15F3] # CANADIAN SYLLABICS CARRIER GI
+15F4 ; [.214F.0020.0002.15F4] # CANADIAN SYLLABICS CARRIER GA
+15F5 ; [.2150.0020.0002.15F5] # CANADIAN SYLLABICS CARRIER KHU
+15F6 ; [.2151.0020.0002.15F6] # CANADIAN SYLLABICS CARRIER KHO
+15F7 ; [.2152.0020.0002.15F7] # CANADIAN SYLLABICS CARRIER KHE
+15F8 ; [.2153.0020.0002.15F8] # CANADIAN SYLLABICS CARRIER KHEE
+15F9 ; [.2154.0020.0002.15F9] # CANADIAN SYLLABICS CARRIER KHI
+15FA ; [.2155.0020.0002.15FA] # CANADIAN SYLLABICS CARRIER KHA
+15FB ; [.2156.0020.0002.15FB] # CANADIAN SYLLABICS CARRIER KKU
+15FC ; [.2157.0020.0002.15FC] # CANADIAN SYLLABICS CARRIER KKO
+15FD ; [.2158.0020.0002.15FD] # CANADIAN SYLLABICS CARRIER KKE
+15FE ; [.2159.0020.0002.15FE] # CANADIAN SYLLABICS CARRIER KKEE
+15FF ; [.215A.0020.0002.15FF] # CANADIAN SYLLABICS CARRIER KKI
+1600 ; [.215B.0020.0002.1600] # CANADIAN SYLLABICS CARRIER KKA
+1601 ; [.215C.0020.0002.1601] # CANADIAN SYLLABICS CARRIER KK
+1602 ; [.215D.0020.0002.1602] # CANADIAN SYLLABICS CARRIER NU
+1603 ; [.215E.0020.0002.1603] # CANADIAN SYLLABICS CARRIER NO
+1604 ; [.215F.0020.0002.1604] # CANADIAN SYLLABICS CARRIER NE
+1605 ; [.2160.0020.0002.1605] # CANADIAN SYLLABICS CARRIER NEE
+1606 ; [.2161.0020.0002.1606] # CANADIAN SYLLABICS CARRIER NI
+1607 ; [.2162.0020.0002.1607] # CANADIAN SYLLABICS CARRIER NA
+1608 ; [.2163.0020.0002.1608] # CANADIAN SYLLABICS CARRIER MU
+1609 ; [.2164.0020.0002.1609] # CANADIAN SYLLABICS CARRIER MO
+160A ; [.2165.0020.0002.160A] # CANADIAN SYLLABICS CARRIER ME
+160B ; [.2166.0020.0002.160B] # CANADIAN SYLLABICS CARRIER MEE
+160C ; [.2167.0020.0002.160C] # CANADIAN SYLLABICS CARRIER MI
+160D ; [.2168.0020.0002.160D] # CANADIAN SYLLABICS CARRIER MA
+160E ; [.2169.0020.0002.160E] # CANADIAN SYLLABICS CARRIER YU
+160F ; [.216A.0020.0002.160F] # CANADIAN SYLLABICS CARRIER YO
+1610 ; [.216B.0020.0002.1610] # CANADIAN SYLLABICS CARRIER YE
+1611 ; [.216C.0020.0002.1611] # CANADIAN SYLLABICS CARRIER YEE
+1612 ; [.216D.0020.0002.1612] # CANADIAN SYLLABICS CARRIER YI
+1613 ; [.216E.0020.0002.1613] # CANADIAN SYLLABICS CARRIER YA
+1614 ; [.216F.0020.0002.1614] # CANADIAN SYLLABICS CARRIER JU
+1615 ; [.2170.0020.0002.1615] # CANADIAN SYLLABICS SAYISI JU
+1616 ; [.2171.0020.0002.1616] # CANADIAN SYLLABICS CARRIER JO
+1617 ; [.2172.0020.0002.1617] # CANADIAN SYLLABICS CARRIER JE
+1618 ; [.2173.0020.0002.1618] # CANADIAN SYLLABICS CARRIER JEE
+1619 ; [.2174.0020.0002.1619] # CANADIAN SYLLABICS CARRIER JI
+161A ; [.2175.0020.0002.161A] # CANADIAN SYLLABICS SAYISI JI
+161B ; [.2176.0020.0002.161B] # CANADIAN SYLLABICS CARRIER JA
+161C ; [.2177.0020.0002.161C] # CANADIAN SYLLABICS CARRIER JJU
+161D ; [.2178.0020.0002.161D] # CANADIAN SYLLABICS CARRIER JJO
+161E ; [.2179.0020.0002.161E] # CANADIAN SYLLABICS CARRIER JJE
+161F ; [.217A.0020.0002.161F] # CANADIAN SYLLABICS CARRIER JJEE
+1620 ; [.217B.0020.0002.1620] # CANADIAN SYLLABICS CARRIER JJI
+1621 ; [.217C.0020.0002.1621] # CANADIAN SYLLABICS CARRIER JJA
+1622 ; [.217D.0020.0002.1622] # CANADIAN SYLLABICS CARRIER LU
+1623 ; [.217E.0020.0002.1623] # CANADIAN SYLLABICS CARRIER LO
+1624 ; [.217F.0020.0002.1624] # CANADIAN SYLLABICS CARRIER LE
+1625 ; [.2180.0020.0002.1625] # CANADIAN SYLLABICS CARRIER LEE
+1626 ; [.2181.0020.0002.1626] # CANADIAN SYLLABICS CARRIER LI
+1627 ; [.2182.0020.0002.1627] # CANADIAN SYLLABICS CARRIER LA
+1628 ; [.2183.0020.0002.1628] # CANADIAN SYLLABICS CARRIER DLU
+1629 ; [.2184.0020.0002.1629] # CANADIAN SYLLABICS CARRIER DLO
+162A ; [.2185.0020.0002.162A] # CANADIAN SYLLABICS CARRIER DLE
+162B ; [.2186.0020.0002.162B] # CANADIAN SYLLABICS CARRIER DLEE
+162C ; [.2187.0020.0002.162C] # CANADIAN SYLLABICS CARRIER DLI
+162D ; [.2188.0020.0002.162D] # CANADIAN SYLLABICS CARRIER DLA
+162E ; [.2189.0020.0002.162E] # CANADIAN SYLLABICS CARRIER LHU
+162F ; [.218A.0020.0002.162F] # CANADIAN SYLLABICS CARRIER LHO
+1630 ; [.218B.0020.0002.1630] # CANADIAN SYLLABICS CARRIER LHE
+1631 ; [.218C.0020.0002.1631] # CANADIAN SYLLABICS CARRIER LHEE
+1632 ; [.218D.0020.0002.1632] # CANADIAN SYLLABICS CARRIER LHI
+1633 ; [.218E.0020.0002.1633] # CANADIAN SYLLABICS CARRIER LHA
+1634 ; [.218F.0020.0002.1634] # CANADIAN SYLLABICS CARRIER TLHU
+1635 ; [.2190.0020.0002.1635] # CANADIAN SYLLABICS CARRIER TLHO
+1636 ; [.2191.0020.0002.1636] # CANADIAN SYLLABICS CARRIER TLHE
+1637 ; [.2192.0020.0002.1637] # CANADIAN SYLLABICS CARRIER TLHEE
+1638 ; [.2193.0020.0002.1638] # CANADIAN SYLLABICS CARRIER TLHI
+1639 ; [.2194.0020.0002.1639] # CANADIAN SYLLABICS CARRIER TLHA
+163A ; [.2195.0020.0002.163A] # CANADIAN SYLLABICS CARRIER TLU
+163B ; [.2196.0020.0002.163B] # CANADIAN SYLLABICS CARRIER TLO
+163C ; [.2197.0020.0002.163C] # CANADIAN SYLLABICS CARRIER TLE
+163D ; [.2198.0020.0002.163D] # CANADIAN SYLLABICS CARRIER TLEE
+163E ; [.2199.0020.0002.163E] # CANADIAN SYLLABICS CARRIER TLI
+163F ; [.219A.0020.0002.163F] # CANADIAN SYLLABICS CARRIER TLA
+1640 ; [.219B.0020.0002.1640] # CANADIAN SYLLABICS CARRIER ZU
+1641 ; [.219C.0020.0002.1641] # CANADIAN SYLLABICS CARRIER ZO
+1642 ; [.219D.0020.0002.1642] # CANADIAN SYLLABICS CARRIER ZE
+1643 ; [.219E.0020.0002.1643] # CANADIAN SYLLABICS CARRIER ZEE
+1644 ; [.219F.0020.0002.1644] # CANADIAN SYLLABICS CARRIER ZI
+1645 ; [.21A0.0020.0002.1645] # CANADIAN SYLLABICS CARRIER ZA
+1646 ; [.21A1.0020.0002.1646] # CANADIAN SYLLABICS CARRIER Z
+1647 ; [.21A2.0020.0002.1647] # CANADIAN SYLLABICS CARRIER INITIAL Z
+1648 ; [.21A3.0020.0002.1648] # CANADIAN SYLLABICS CARRIER DZU
+1649 ; [.21A4.0020.0002.1649] # CANADIAN SYLLABICS CARRIER DZO
+164A ; [.21A5.0020.0002.164A] # CANADIAN SYLLABICS CARRIER DZE
+164B ; [.21A6.0020.0002.164B] # CANADIAN SYLLABICS CARRIER DZEE
+164C ; [.21A7.0020.0002.164C] # CANADIAN SYLLABICS CARRIER DZI
+164D ; [.21A8.0020.0002.164D] # CANADIAN SYLLABICS CARRIER DZA
+164E ; [.21A9.0020.0002.164E] # CANADIAN SYLLABICS CARRIER SU
+164F ; [.21AA.0020.0002.164F] # CANADIAN SYLLABICS CARRIER SO
+1650 ; [.21AB.0020.0002.1650] # CANADIAN SYLLABICS CARRIER SE
+1651 ; [.21AC.0020.0002.1651] # CANADIAN SYLLABICS CARRIER SEE
+1652 ; [.21AD.0020.0002.1652] # CANADIAN SYLLABICS CARRIER SI
+1653 ; [.21AE.0020.0002.1653] # CANADIAN SYLLABICS CARRIER SA
+1654 ; [.21AF.0020.0002.1654] # CANADIAN SYLLABICS CARRIER SHU
+1655 ; [.21B0.0020.0002.1655] # CANADIAN SYLLABICS CARRIER SHO
+1656 ; [.21B1.0020.0002.1656] # CANADIAN SYLLABICS CARRIER SHE
+1657 ; [.21B2.0020.0002.1657] # CANADIAN SYLLABICS CARRIER SHEE
+1658 ; [.21B3.0020.0002.1658] # CANADIAN SYLLABICS CARRIER SHI
+1659 ; [.21B4.0020.0002.1659] # CANADIAN SYLLABICS CARRIER SHA
+165A ; [.21B5.0020.0002.165A] # CANADIAN SYLLABICS CARRIER SH
+165B ; [.21B6.0020.0002.165B] # CANADIAN SYLLABICS CARRIER TSU
+165C ; [.21B7.0020.0002.165C] # CANADIAN SYLLABICS CARRIER TSO
+165D ; [.21B8.0020.0002.165D] # CANADIAN SYLLABICS CARRIER TSE
+165E ; [.21B9.0020.0002.165E] # CANADIAN SYLLABICS CARRIER TSEE
+165F ; [.21BA.0020.0002.165F] # CANADIAN SYLLABICS CARRIER TSI
+1660 ; [.21BB.0020.0002.1660] # CANADIAN SYLLABICS CARRIER TSA
+1661 ; [.21BC.0020.0002.1661] # CANADIAN SYLLABICS CARRIER CHU
+1662 ; [.21BD.0020.0002.1662] # CANADIAN SYLLABICS CARRIER CHO
+1663 ; [.21BE.0020.0002.1663] # CANADIAN SYLLABICS CARRIER CHE
+1664 ; [.21BF.0020.0002.1664] # CANADIAN SYLLABICS CARRIER CHEE
+1665 ; [.21C0.0020.0002.1665] # CANADIAN SYLLABICS CARRIER CHI
+1666 ; [.21C1.0020.0002.1666] # CANADIAN SYLLABICS CARRIER CHA
+1667 ; [.21C2.0020.0002.1667] # CANADIAN SYLLABICS CARRIER TTSU
+1668 ; [.21C3.0020.0002.1668] # CANADIAN SYLLABICS CARRIER TTSO
+1669 ; [.21C4.0020.0002.1669] # CANADIAN SYLLABICS CARRIER TTSE
+166A ; [.21C5.0020.0002.166A] # CANADIAN SYLLABICS CARRIER TTSEE
+166B ; [.21C6.0020.0002.166B] # CANADIAN SYLLABICS CARRIER TTSI
+166C ; [.21C7.0020.0002.166C] # CANADIAN SYLLABICS CARRIER TTSA
+1681 ; [.21C8.0020.0002.1681] # OGHAM LETTER BEITH
+1682 ; [.21C9.0020.0002.1682] # OGHAM LETTER LUIS
+1683 ; [.21CA.0020.0002.1683] # OGHAM LETTER FEARN
+1684 ; [.21CB.0020.0002.1684] # OGHAM LETTER SAIL
+1685 ; [.21CC.0020.0002.1685] # OGHAM LETTER NION
+1686 ; [.21CD.0020.0002.1686] # OGHAM LETTER UATH
+1687 ; [.21CE.0020.0002.1687] # OGHAM LETTER DAIR
+1688 ; [.21CF.0020.0002.1688] # OGHAM LETTER TINNE
+1689 ; [.21D0.0020.0002.1689] # OGHAM LETTER COLL
+168A ; [.21D1.0020.0002.168A] # OGHAM LETTER CEIRT
+168B ; [.21D2.0020.0002.168B] # OGHAM LETTER MUIN
+168C ; [.21D3.0020.0002.168C] # OGHAM LETTER GORT
+168D ; [.21D4.0020.0002.168D] # OGHAM LETTER NGEADAL
+168E ; [.21D5.0020.0002.168E] # OGHAM LETTER STRAIF
+168F ; [.21D6.0020.0002.168F] # OGHAM LETTER RUIS
+1690 ; [.21D7.0020.0002.1690] # OGHAM LETTER AILM
+1691 ; [.21D8.0020.0002.1691] # OGHAM LETTER ONN
+1692 ; [.21D9.0020.0002.1692] # OGHAM LETTER UR
+1693 ; [.21DA.0020.0002.1693] # OGHAM LETTER EADHADH
+1694 ; [.21DB.0020.0002.1694] # OGHAM LETTER IODHADH
+1695 ; [.21DC.0020.0002.1695] # OGHAM LETTER EABHADH
+1696 ; [.21DD.0020.0002.1696] # OGHAM LETTER OR
+1697 ; [.21DE.0020.0002.1697] # OGHAM LETTER UILLEANN
+1698 ; [.21DF.0020.0002.1698] # OGHAM LETTER IFIN
+1699 ; [.21E0.0020.0002.1699] # OGHAM LETTER EAMHANCHOLL
+169A ; [.21E1.0020.0002.169A] # OGHAM LETTER PEITH
+16A0 ; [.21E2.0020.0002.16A0] # RUNIC LETTER FEHU FEOH FE F
+16A1 ; [.21E2.0020.0004.16A1][.0000.0199.0004.16A1] # RUNIC LETTER V; QQKN
+16A2 ; [.21E3.0020.0002.16A2] # RUNIC LETTER URUZ UR U
+16A4 ; [.21E3.0020.0004.16A4][.0000.0199.0004.16A4] # RUNIC LETTER Y; QQKN
+16A5 ; [.21E3.0020.0004.16A5][.0000.019A.0004.16A5] # RUNIC LETTER W; QQKN
+16A6 ; [.21E4.0020.0002.16A6] # RUNIC LETTER THURISAZ THURS THORN
+16A7 ; [.21E4.0020.0004.16A7][.0000.0199.0004.16A7] # RUNIC LETTER ETH; QQKN
+16F0 ; [.21E4.0020.0004.16F0][.21E4.0020.0004.16F0] # RUNIC BELGTHOR SYMBOL; QQKN
+16A8 ; [.21E5.0020.0002.16A8] # RUNIC LETTER ANSUZ A
+16A9 ; [.21E5.0020.0004.16A9][.0000.0199.0004.16A9] # RUNIC LETTER OS O; QQKN
+16AC ; [.21E5.0020.0004.16AC][.0000.019A.0004.16AC] # RUNIC LETTER LONG-BRANCH-OSS O; QQKN
+16AD ; [.21E5.0020.0004.16AD][.0000.019C.0004.16AD] # RUNIC LETTER SHORT-TWIG-OSS O; QQKN
+16AE ; [.21E5.0020.0004.16AE][.0000.019D.0004.16AE] # RUNIC LETTER O; QQKN
+16AF ; [.21E6.0020.0002.16AF] # RUNIC LETTER OE
+16B0 ; [.21E7.0020.0002.16B0] # RUNIC LETTER ON
+16B1 ; [.21E8.0020.0002.16B1] # RUNIC LETTER RAIDO RAD REID R
+16B2 ; [.21E9.0020.0002.16B2] # RUNIC LETTER KAUNA
+16B3 ; [.21E9.0020.0004.16B3][.0000.0199.0004.16B3] # RUNIC LETTER CEN; QQKN
+16B4 ; [.21E9.0020.0004.16B4][.0000.019A.0004.16B4] # RUNIC LETTER KAUN K; QQKN
+16B5 ; [.21E9.0020.0004.16B5][.0000.019C.0004.16B5] # RUNIC LETTER G; QQKN
+16B6 ; [.21E9.0020.0004.16B6][.0000.019D.0004.16B6] # RUNIC LETTER ENG; QQKN
+16B7 ; [.21EA.0020.0002.16B7] # RUNIC LETTER GEBO GYFU G
+16B9 ; [.21EB.0020.0002.16B9] # RUNIC LETTER WUNJO WYNN W
+16E9 ; [.21EB.0020.0004.16E9][.0000.0199.0004.16E9] # RUNIC LETTER Q; QQKN
+16BA ; [.21EC.0020.0002.16BA] # RUNIC LETTER HAGLAZ H
+16BB ; [.21EC.0020.0004.16BB][.0000.0199.0004.16BB] # RUNIC LETTER HAEGL H; QQKN
+16BC ; [.21EC.0020.0004.16BC][.0000.019A.0004.16BC] # RUNIC LETTER LONG-BRANCH-HAGALL H; QQKN
+16BD ; [.21EC.0020.0004.16BD][.0000.019C.0004.16BD] # RUNIC LETTER SHORT-TWIG-HAGALL H; QQKN
+16BE ; [.21ED.0020.0002.16BE] # RUNIC LETTER NAUDIZ NYD NAUD N
+16BF ; [.21ED.0020.0004.16BF][.0000.0199.0004.16BF] # RUNIC LETTER SHORT-TWIG-NAUD N; QQKN
+16C0 ; [.21ED.0020.0004.16C0][.0000.019A.0004.16C0] # RUNIC LETTER DOTTED-N; QQKN
+16C1 ; [.21EE.0020.0002.16C1] # RUNIC LETTER ISAZ IS ISS I
+16C2 ; [.21EE.0020.0004.16C2][.0000.0199.0004.16C2] # RUNIC LETTER E; QQKN
+16C3 ; [.21EF.0020.0002.16C3] # RUNIC LETTER JERAN J
+16C4 ; [.21EF.0020.0004.16C4][.0000.0199.0004.16C4] # RUNIC LETTER GER; QQKN
+16C5 ; [.21F0.0020.0002.16C5] # RUNIC LETTER LONG-BRANCH-AR AE
+16C6 ; [.21F0.0020.0004.16C6][.0000.0199.0004.16C6] # RUNIC LETTER SHORT-TWIG-AR A; QQKN
+16EE ; [.21F0.0020.0004.16EE][.21F9.0020.0004.16EE] # RUNIC ARLAUG SYMBOL; QQKN
+16C7 ; [.21F1.0020.0002.16C7] # RUNIC LETTER IWAZ EOH
+16C8 ; [.21F2.0020.0002.16C8] # RUNIC LETTER PERTHO PEORTH P
+16D5 ; [.21F2.0020.0004.16D5][.0000.0199.0004.16D5] # RUNIC LETTER OPEN-P; QQKN
+16C9 ; [.21F3.0020.0002.16C9] # RUNIC LETTER ALGIZ EOLHX
+16CA ; [.21F4.0020.0002.16CA] # RUNIC LETTER SOWILO S
+16CB ; [.21F4.0020.0004.16CB][.0000.0199.0004.16CB] # RUNIC LETTER SIGEL LONG-BRANCH-SOL S; QQKN
+16EA ; [.21F4.0020.0004.16EA][.0000.019A.0004.16EA] # RUNIC LETTER X; QQKN
+16CC ; [.21F4.0020.0004.16CC][.0000.019C.0004.16CC] # RUNIC LETTER SHORT-TWIG-SOL S; QQKN
+16CD ; [.21F4.0020.0004.16CD][.0000.019D.0004.16CD] # RUNIC LETTER C; QQKN
+16CE ; [.21F4.0020.0004.16CE][.0000.019E.0004.16CE] # RUNIC LETTER Z; QQKN
+16CF ; [.21F5.0020.0002.16CF] # RUNIC LETTER TIWAZ TIR TYR T
+16D0 ; [.21F5.0020.0004.16D0][.0000.0199.0004.16D0] # RUNIC LETTER SHORT-TWIG-TYR T; QQKN
+16D1 ; [.21F5.0020.0004.16D1][.0000.019A.0004.16D1] # RUNIC LETTER D; QQKN
+16D2 ; [.21F6.0020.0002.16D2] # RUNIC LETTER BERKANAN BEORC BJARKAN B
+16D3 ; [.21F6.0020.0004.16D3][.0000.0199.0004.16D3] # RUNIC LETTER SHORT-TWIG-BJARKAN B; QQKN
+16D4 ; [.21F6.0020.0004.16D4][.0000.019A.0004.16D4] # RUNIC LETTER DOTTED-P; QQKN
+16D6 ; [.21F7.0020.0002.16D6] # RUNIC LETTER EHWAZ EH E
+16D7 ; [.21F8.0020.0002.16D7] # RUNIC LETTER MANNAZ MAN M
+16D8 ; [.21F8.0020.0004.16D8][.0000.0199.0004.16D8] # RUNIC LETTER LONG-BRANCH-MADR M; QQKN
+16D9 ; [.21F8.0020.0004.16D9][.0000.019A.0004.16D9] # RUNIC LETTER SHORT-TWIG-MADR M; QQKN
+16EF ; [.21F8.0020.0004.16EF][.0000.0199.0004.16EF][.21F8.0020.001F.16EF][.0000.0199.001F.16EF] # RUNIC TVIMADUR SYMBOL; QQKN
+16DA ; [.21F9.0020.0002.16DA] # RUNIC LETTER LAUKAZ LAGU LOGR L
+16DB ; [.21F9.0020.0004.16DB][.0000.0199.0004.16DB] # RUNIC LETTER DOTTED-L; QQKN
+16DC ; [.21FA.0020.0002.16DC] # RUNIC LETTER INGWAZ
+16DD ; [.21FA.0020.0004.16DD][.0000.0199.0004.16DD] # RUNIC LETTER ING; QQKN
+16DE ; [.21FB.0020.0002.16DE] # RUNIC LETTER DAGAZ DAEG D
+16DF ; [.21FC.0020.0002.16DF] # RUNIC LETTER OTHALAN ETHEL O
+16AA ; [.21FD.0020.0002.16AA] # RUNIC LETTER AC A
+16AB ; [.21FE.0020.0002.16AB] # RUNIC LETTER AESC
+16A3 ; [.21FF.0020.0002.16A3] # RUNIC LETTER YR
+16E0 ; [.2200.0020.0002.16E0] # RUNIC LETTER EAR
+16E3 ; [.2201.0020.0002.16E3] # RUNIC LETTER CALC
+16B8 ; [.2202.0020.0002.16B8] # RUNIC LETTER GAR
+16E4 ; [.2203.0020.0002.16E4] # RUNIC LETTER CEALC
+16E1 ; [.2204.0020.0002.16E1] # RUNIC LETTER IOR
+16E2 ; [.2205.0020.0002.16E2] # RUNIC LETTER CWEORTH
+16E5 ; [.2206.0020.0002.16E5] # RUNIC LETTER STAN
+16E6 ; [.2207.0020.0002.16E6] # RUNIC LETTER LONG-BRANCH-YR
+16E7 ; [.2207.0020.0004.16E7][.0000.0199.0004.16E7] # RUNIC LETTER SHORT-TWIG-YR; QQKN
+16E8 ; [.2207.0020.0004.16E8][.0000.019A.0004.16E8] # RUNIC LETTER ICELANDIC-YR; QQKN
+1100 ; [.2208.0020.0002.1100] # HANGUL CHOSEONG KIYEOK
+3131 ; [.2208.0020.0004.3131] # HANGUL LETTER KIYEOK; QQK
+3200 ; [*02B1.0020.0004.3200][.2208.0020.0004.3200][*02B2.0020.001F.3200] # PARENTHESIZED HANGUL KIYEOK; QQKN
+3260 ; [.2208.0020.0006.3260] # CIRCLED HANGUL KIYEOK; QQK
+FFA1 ; [.2208.0020.0012.FFA1] # HALFWIDTH HANGUL LETTER KIYEOK; QQK
+320E ; [*02B1.0020.0004.320E][.2208.0020.0004.320E][.2264.0020.001F.320E][*02B2.0020.001F.320E] # PARENTHESIZED HANGUL KIYEOK A; QQKN
+326E ; [.2208.0020.0006.326E][.2264.0020.0006.326E] # CIRCLED HANGUL KIYEOK A; QQKN
+1101 ; [.2209.0020.0002.1101] # HANGUL CHOSEONG SSANGKIYEOK
+3132 ; [.2209.0020.0004.3132] # HANGUL LETTER SSANGKIYEOK; QQK
+FFA2 ; [.2209.0020.0012.FFA2] # HALFWIDTH HANGUL LETTER SSANGKIYEOK; QQK
+1102 ; [.220A.0020.0002.1102] # HANGUL CHOSEONG NIEUN
+3134 ; [.220A.0020.0004.3134] # HANGUL LETTER NIEUN; QQK
+3201 ; [*02B1.0020.0004.3201][.220A.0020.0004.3201][*02B2.0020.001F.3201] # PARENTHESIZED HANGUL NIEUN; QQKN
+3261 ; [.220A.0020.0006.3261] # CIRCLED HANGUL NIEUN; QQK
+FFA4 ; [.220A.0020.0012.FFA4] # HALFWIDTH HANGUL LETTER NIEUN; QQK
+320F ; [*02B1.0020.0004.320F][.220A.0020.0004.320F][.2264.0020.001F.320F][*02B2.0020.001F.320F] # PARENTHESIZED HANGUL NIEUN A; QQKN
+326F ; [.220A.0020.0006.326F][.2264.0020.0006.326F] # CIRCLED HANGUL NIEUN A; QQKN
+1103 ; [.220B.0020.0002.1103] # HANGUL CHOSEONG TIKEUT
+3137 ; [.220B.0020.0004.3137] # HANGUL LETTER TIKEUT; QQK
+3202 ; [*02B1.0020.0004.3202][.220B.0020.0004.3202][*02B2.0020.001F.3202] # PARENTHESIZED HANGUL TIKEUT; QQKN
+3262 ; [.220B.0020.0006.3262] # CIRCLED HANGUL TIKEUT; QQK
+FFA7 ; [.220B.0020.0012.FFA7] # HALFWIDTH HANGUL LETTER TIKEUT; QQK
+3210 ; [*02B1.0020.0004.3210][.220B.0020.0004.3210][.2264.0020.001F.3210][*02B2.0020.001F.3210] # PARENTHESIZED HANGUL TIKEUT A; QQKN
+3270 ; [.220B.0020.0006.3270][.2264.0020.0006.3270] # CIRCLED HANGUL TIKEUT A; QQKN
+1104 ; [.220C.0020.0002.1104] # HANGUL CHOSEONG SSANGTIKEUT
+3138 ; [.220C.0020.0004.3138] # HANGUL LETTER SSANGTIKEUT; QQK
+FFA8 ; [.220C.0020.0012.FFA8] # HALFWIDTH HANGUL LETTER SSANGTIKEUT; QQK
+1105 ; [.220D.0020.0002.1105] # HANGUL CHOSEONG RIEUL
+3139 ; [.220D.0020.0004.3139] # HANGUL LETTER RIEUL; QQK
+3203 ; [*02B1.0020.0004.3203][.220D.0020.0004.3203][*02B2.0020.001F.3203] # PARENTHESIZED HANGUL RIEUL; QQKN
+3263 ; [.220D.0020.0006.3263] # CIRCLED HANGUL RIEUL; QQK
+FFA9 ; [.220D.0020.0012.FFA9] # HALFWIDTH HANGUL LETTER RIEUL; QQK
+3211 ; [*02B1.0020.0004.3211][.220D.0020.0004.3211][.2264.0020.001F.3211][*02B2.0020.001F.3211] # PARENTHESIZED HANGUL RIEUL A; QQKN
+3271 ; [.220D.0020.0006.3271][.2264.0020.0006.3271] # CIRCLED HANGUL RIEUL A; QQKN
+1106 ; [.220E.0020.0002.1106] # HANGUL CHOSEONG MIEUM
+3141 ; [.220E.0020.0004.3141] # HANGUL LETTER MIEUM; QQK
+3204 ; [*02B1.0020.0004.3204][.220E.0020.0004.3204][*02B2.0020.001F.3204] # PARENTHESIZED HANGUL MIEUM; QQKN
+3264 ; [.220E.0020.0006.3264] # CIRCLED HANGUL MIEUM; QQK
+FFB1 ; [.220E.0020.0012.FFB1] # HALFWIDTH HANGUL LETTER MIEUM; QQK
+3212 ; [*02B1.0020.0004.3212][.220E.0020.0004.3212][.2264.0020.001F.3212][*02B2.0020.001F.3212] # PARENTHESIZED HANGUL MIEUM A; QQKN
+3272 ; [.220E.0020.0006.3272][.2264.0020.0006.3272] # CIRCLED HANGUL MIEUM A; QQKN
+1107 ; [.220F.0020.0002.1107] # HANGUL CHOSEONG PIEUP
+3142 ; [.220F.0020.0004.3142] # HANGUL LETTER PIEUP; QQK
+3205 ; [*02B1.0020.0004.3205][.220F.0020.0004.3205][*02B2.0020.001F.3205] # PARENTHESIZED HANGUL PIEUP; QQKN
+3265 ; [.220F.0020.0006.3265] # CIRCLED HANGUL PIEUP; QQK
+FFB2 ; [.220F.0020.0012.FFB2] # HALFWIDTH HANGUL LETTER PIEUP; QQK
+3213 ; [*02B1.0020.0004.3213][.220F.0020.0004.3213][.2264.0020.001F.3213][*02B2.0020.001F.3213] # PARENTHESIZED HANGUL PIEUP A; QQKN
+3273 ; [.220F.0020.0006.3273][.2264.0020.0006.3273] # CIRCLED HANGUL PIEUP A; QQKN
+1108 ; [.2210.0020.0002.1108] # HANGUL CHOSEONG SSANGPIEUP
+3143 ; [.2210.0020.0004.3143] # HANGUL LETTER SSANGPIEUP; QQK
+FFB3 ; [.2210.0020.0012.FFB3] # HALFWIDTH HANGUL LETTER SSANGPIEUP; QQK
+1109 ; [.2211.0020.0002.1109] # HANGUL CHOSEONG SIOS
+3145 ; [.2211.0020.0004.3145] # HANGUL LETTER SIOS; QQK
+3206 ; [*02B1.0020.0004.3206][.2211.0020.0004.3206][*02B2.0020.001F.3206] # PARENTHESIZED HANGUL SIOS; QQKN
+3266 ; [.2211.0020.0006.3266] # CIRCLED HANGUL SIOS; QQK
+FFB5 ; [.2211.0020.0012.FFB5] # HALFWIDTH HANGUL LETTER SIOS; QQK
+3214 ; [*02B1.0020.0004.3214][.2211.0020.0004.3214][.2264.0020.001F.3214][*02B2.0020.001F.3214] # PARENTHESIZED HANGUL SIOS A; QQKN
+3274 ; [.2211.0020.0006.3274][.2264.0020.0006.3274] # CIRCLED HANGUL SIOS A; QQKN
+110A ; [.2212.0020.0002.110A] # HANGUL CHOSEONG SSANGSIOS
+3146 ; [.2212.0020.0004.3146] # HANGUL LETTER SSANGSIOS; QQK
+FFB6 ; [.2212.0020.0012.FFB6] # HALFWIDTH HANGUL LETTER SSANGSIOS; QQK
+110B ; [.2213.0020.0002.110B] # HANGUL CHOSEONG IEUNG
+3147 ; [.2213.0020.0004.3147] # HANGUL LETTER IEUNG; QQK
+3207 ; [*02B1.0020.0004.3207][.2213.0020.0004.3207][*02B2.0020.001F.3207] # PARENTHESIZED HANGUL IEUNG; QQKN
+3267 ; [.2213.0020.0006.3267] # CIRCLED HANGUL IEUNG; QQK
+FFB7 ; [.2213.0020.0012.FFB7] # HALFWIDTH HANGUL LETTER IEUNG; QQK
+3215 ; [*02B1.0020.0004.3215][.2213.0020.0004.3215][.2264.0020.001F.3215][*02B2.0020.001F.3215] # PARENTHESIZED HANGUL IEUNG A; QQKN
+3275 ; [.2213.0020.0006.3275][.2264.0020.0006.3275] # CIRCLED HANGUL IEUNG A; QQKN
+321D ; [*02B1.0020.0004.321D][.2213.0020.0004.321D][.226C.0020.001F.321D][.2214.0020.001F.321D][.2268.0020.001F.321D][.22A9.0020.001F.321D][*02B2.0020.001F.321D] # PARENTHESIZED KOREAN CHARACTER OJEON; QQKN
+321E ; [*02B1.0020.0004.321E][.2213.0020.0004.321E][.226C.0020.001F.321E][.221A.0020.001F.321E][.2271.0020.001F.321E][*02B2.0020.001F.321E] # PARENTHESIZED KOREAN CHARACTER O HU; QQKN
+327E ; [.2213.0020.0006.327E][.2271.0020.0006.327E] # CIRCLED HANGUL IEUNG U; QQKN
+110C ; [.2214.0020.0002.110C] # HANGUL CHOSEONG CIEUC
+3148 ; [.2214.0020.0004.3148] # HANGUL LETTER CIEUC; QQK
+3208 ; [*02B1.0020.0004.3208][.2214.0020.0004.3208][*02B2.0020.001F.3208] # PARENTHESIZED HANGUL CIEUC; QQKN
+3268 ; [.2214.0020.0006.3268] # CIRCLED HANGUL CIEUC; QQK
+FFB8 ; [.2214.0020.0012.FFB8] # HALFWIDTH HANGUL LETTER CIEUC; QQK
+3216 ; [*02B1.0020.0004.3216][.2214.0020.0004.3216][.2264.0020.001F.3216][*02B2.0020.001F.3216] # PARENTHESIZED HANGUL CIEUC A; QQKN
+3276 ; [.2214.0020.0006.3276][.2264.0020.0006.3276] # CIRCLED HANGUL CIEUC A; QQKN
+321C ; [*02B1.0020.0004.321C][.2214.0020.0004.321C][.2271.0020.001F.321C][*02B2.0020.001F.321C] # PARENTHESIZED HANGUL CIEUC U; QQKN
+327D ; [.2214.0020.0006.327D][.2271.0020.0006.327D][.2213.0020.001F.327D][.2277.0020.001F.327D] # CIRCLED KOREAN CHARACTER JUEUI; QQKN
+110D ; [.2215.0020.0002.110D] # HANGUL CHOSEONG SSANGCIEUC
+3149 ; [.2215.0020.0004.3149] # HANGUL LETTER SSANGCIEUC; QQK
+FFB9 ; [.2215.0020.0012.FFB9] # HALFWIDTH HANGUL LETTER SSANGCIEUC; QQK
+110E ; [.2216.0020.0002.110E] # HANGUL CHOSEONG CHIEUCH
+314A ; [.2216.0020.0004.314A] # HANGUL LETTER CHIEUCH; QQK
+3209 ; [*02B1.0020.0004.3209][.2216.0020.0004.3209][*02B2.0020.001F.3209] # PARENTHESIZED HANGUL CHIEUCH; QQKN
+3269 ; [.2216.0020.0006.3269] # CIRCLED HANGUL CHIEUCH; QQK
+FFBA ; [.2216.0020.0012.FFBA] # HALFWIDTH HANGUL LETTER CHIEUCH; QQK
+3217 ; [*02B1.0020.0004.3217][.2216.0020.0004.3217][.2264.0020.001F.3217][*02B2.0020.001F.3217] # PARENTHESIZED HANGUL CHIEUCH A; QQKN
+3277 ; [.2216.0020.0006.3277][.2264.0020.0006.3277] # CIRCLED HANGUL CHIEUCH A; QQKN
+327C ; [.2216.0020.0006.327C][.2264.0020.0006.327C][.22B5.0020.001F.327C][.2208.0020.001F.327C][.226C.0020.001F.327C] # CIRCLED KOREAN CHARACTER CHAMKO; QQKN
+110F ; [.2217.0020.0002.110F] # HANGUL CHOSEONG KHIEUKH
+314B ; [.2217.0020.0004.314B] # HANGUL LETTER KHIEUKH; QQK
+320A ; [*02B1.0020.0004.320A][.2217.0020.0004.320A][*02B2.0020.001F.320A] # PARENTHESIZED HANGUL KHIEUKH; QQKN
+326A ; [.2217.0020.0006.326A] # CIRCLED HANGUL KHIEUKH; QQK
+FFBB ; [.2217.0020.0012.FFBB] # HALFWIDTH HANGUL LETTER KHIEUKH; QQK
+3218 ; [*02B1.0020.0004.3218][.2217.0020.0004.3218][.2264.0020.001F.3218][*02B2.0020.001F.3218] # PARENTHESIZED HANGUL KHIEUKH A; QQKN
+3278 ; [.2217.0020.0006.3278][.2264.0020.0006.3278] # CIRCLED HANGUL KHIEUKH A; QQKN
+1110 ; [.2218.0020.0002.1110] # HANGUL CHOSEONG THIEUTH
+314C ; [.2218.0020.0004.314C] # HANGUL LETTER THIEUTH; QQK
+320B ; [*02B1.0020.0004.320B][.2218.0020.0004.320B][*02B2.0020.001F.320B] # PARENTHESIZED HANGUL THIEUTH; QQKN
+326B ; [.2218.0020.0006.326B] # CIRCLED HANGUL THIEUTH; QQK
+FFBC ; [.2218.0020.0012.FFBC] # HALFWIDTH HANGUL LETTER THIEUTH; QQK
+3219 ; [*02B1.0020.0004.3219][.2218.0020.0004.3219][.2264.0020.001F.3219][*02B2.0020.001F.3219] # PARENTHESIZED HANGUL THIEUTH A; QQKN
+3279 ; [.2218.0020.0006.3279][.2264.0020.0006.3279] # CIRCLED HANGUL THIEUTH A; QQKN
+1111 ; [.2219.0020.0002.1111] # HANGUL CHOSEONG PHIEUPH
+314D ; [.2219.0020.0004.314D] # HANGUL LETTER PHIEUPH; QQK
+320C ; [*02B1.0020.0004.320C][.2219.0020.0004.320C][*02B2.0020.001F.320C] # PARENTHESIZED HANGUL PHIEUPH; QQKN
+326C ; [.2219.0020.0006.326C] # CIRCLED HANGUL PHIEUPH; QQK
+FFBD ; [.2219.0020.0012.FFBD] # HALFWIDTH HANGUL LETTER PHIEUPH; QQK
+321A ; [*02B1.0020.0004.321A][.2219.0020.0004.321A][.2264.0020.001F.321A][*02B2.0020.001F.321A] # PARENTHESIZED HANGUL PHIEUPH A; QQKN
+327A ; [.2219.0020.0006.327A][.2264.0020.0006.327A] # CIRCLED HANGUL PHIEUPH A; QQKN
+1112 ; [.221A.0020.0002.1112] # HANGUL CHOSEONG HIEUH
+314E ; [.221A.0020.0004.314E] # HANGUL LETTER HIEUH; QQK
+320D ; [*02B1.0020.0004.320D][.221A.0020.0004.320D][*02B2.0020.001F.320D] # PARENTHESIZED HANGUL HIEUH; QQKN
+326D ; [.221A.0020.0006.326D] # CIRCLED HANGUL HIEUH; QQK
+FFBE ; [.221A.0020.0012.FFBE] # HALFWIDTH HANGUL LETTER HIEUH; QQK
+321B ; [*02B1.0020.0004.321B][.221A.0020.0004.321B][.2264.0020.001F.321B][*02B2.0020.001F.321B] # PARENTHESIZED HANGUL HIEUH A; QQKN
+327B ; [.221A.0020.0006.327B][.2264.0020.0006.327B] # CIRCLED HANGUL HIEUH A; QQKN
+1113 ; [.221B.0020.0002.1113] # HANGUL CHOSEONG NIEUN-KIYEOK
+1114 ; [.221C.0020.0002.1114] # HANGUL CHOSEONG SSANGNIEUN
+3165 ; [.221C.0020.0004.3165] # HANGUL LETTER SSANGNIEUN; QQK
+1115 ; [.221D.0020.0002.1115] # HANGUL CHOSEONG NIEUN-TIKEUT
+3166 ; [.221D.0020.0004.3166] # HANGUL LETTER NIEUN-TIKEUT; QQK
+1116 ; [.221E.0020.0002.1116] # HANGUL CHOSEONG NIEUN-PIEUP
+1117 ; [.221F.0020.0002.1117] # HANGUL CHOSEONG TIKEUT-KIYEOK
+1118 ; [.2220.0020.0002.1118] # HANGUL CHOSEONG RIEUL-NIEUN
+1119 ; [.2221.0020.0002.1119] # HANGUL CHOSEONG SSANGRIEUL
+111A ; [.2222.0020.0002.111A] # HANGUL CHOSEONG RIEUL-HIEUH
+3140 ; [.2222.0020.0004.3140] # HANGUL LETTER RIEUL-HIEUH; QQK
+FFB0 ; [.2222.0020.0012.FFB0] # HALFWIDTH HANGUL LETTER RIEUL-HIEUH; QQK
+111B ; [.2223.0020.0002.111B] # HANGUL CHOSEONG KAPYEOUNRIEUL
+111C ; [.2224.0020.0002.111C] # HANGUL CHOSEONG MIEUM-PIEUP
+316E ; [.2224.0020.0004.316E] # HANGUL LETTER MIEUM-PIEUP; QQK
+111D ; [.2225.0020.0002.111D] # HANGUL CHOSEONG KAPYEOUNMIEUM
+3171 ; [.2225.0020.0004.3171] # HANGUL LETTER KAPYEOUNMIEUM; QQK
+111E ; [.2226.0020.0002.111E] # HANGUL CHOSEONG PIEUP-KIYEOK
+3172 ; [.2226.0020.0004.3172] # HANGUL LETTER PIEUP-KIYEOK; QQK
+111F ; [.2227.0020.0002.111F] # HANGUL CHOSEONG PIEUP-NIEUN
+1120 ; [.2228.0020.0002.1120] # HANGUL CHOSEONG PIEUP-TIKEUT
+3173 ; [.2228.0020.0004.3173] # HANGUL LETTER PIEUP-TIKEUT; QQK
+1121 ; [.2229.0020.0002.1121] # HANGUL CHOSEONG PIEUP-SIOS
+3144 ; [.2229.0020.0004.3144] # HANGUL LETTER PIEUP-SIOS; QQK
+FFB4 ; [.2229.0020.0012.FFB4] # HALFWIDTH HANGUL LETTER PIEUP-SIOS; QQK
+1122 ; [.222A.0020.0002.1122] # HANGUL CHOSEONG PIEUP-SIOS-KIYEOK
+3174 ; [.222A.0020.0004.3174] # HANGUL LETTER PIEUP-SIOS-KIYEOK; QQK
+1123 ; [.222B.0020.0002.1123] # HANGUL CHOSEONG PIEUP-SIOS-TIKEUT
+3175 ; [.222B.0020.0004.3175] # HANGUL LETTER PIEUP-SIOS-TIKEUT; QQK
+1124 ; [.222C.0020.0002.1124] # HANGUL CHOSEONG PIEUP-SIOS-PIEUP
+1125 ; [.222D.0020.0002.1125] # HANGUL CHOSEONG PIEUP-SSANGSIOS
+1126 ; [.222E.0020.0002.1126] # HANGUL CHOSEONG PIEUP-SIOS-CIEUC
+1127 ; [.222F.0020.0002.1127] # HANGUL CHOSEONG PIEUP-CIEUC
+3176 ; [.222F.0020.0004.3176] # HANGUL LETTER PIEUP-CIEUC; QQK
+1128 ; [.2230.0020.0002.1128] # HANGUL CHOSEONG PIEUP-CHIEUCH
+1129 ; [.2231.0020.0002.1129] # HANGUL CHOSEONG PIEUP-THIEUTH
+3177 ; [.2231.0020.0004.3177] # HANGUL LETTER PIEUP-THIEUTH; QQK
+112A ; [.2232.0020.0002.112A] # HANGUL CHOSEONG PIEUP-PHIEUPH
+112B ; [.2233.0020.0002.112B] # HANGUL CHOSEONG KAPYEOUNPIEUP
+3178 ; [.2233.0020.0004.3178] # HANGUL LETTER KAPYEOUNPIEUP; QQK
+112C ; [.2234.0020.0002.112C] # HANGUL CHOSEONG KAPYEOUNSSANGPIEUP
+3179 ; [.2234.0020.0004.3179] # HANGUL LETTER KAPYEOUNSSANGPIEUP; QQK
+112D ; [.2235.0020.0002.112D] # HANGUL CHOSEONG SIOS-KIYEOK
+317A ; [.2235.0020.0004.317A] # HANGUL LETTER SIOS-KIYEOK; QQK
+112E ; [.2236.0020.0002.112E] # HANGUL CHOSEONG SIOS-NIEUN
+317B ; [.2236.0020.0004.317B] # HANGUL LETTER SIOS-NIEUN; QQK
+112F ; [.2237.0020.0002.112F] # HANGUL CHOSEONG SIOS-TIKEUT
+317C ; [.2237.0020.0004.317C] # HANGUL LETTER SIOS-TIKEUT; QQK
+1130 ; [.2238.0020.0002.1130] # HANGUL CHOSEONG SIOS-RIEUL
+1131 ; [.2239.0020.0002.1131] # HANGUL CHOSEONG SIOS-MIEUM
+1132 ; [.223A.0020.0002.1132] # HANGUL CHOSEONG SIOS-PIEUP
+317D ; [.223A.0020.0004.317D] # HANGUL LETTER SIOS-PIEUP; QQK
+1133 ; [.223B.0020.0002.1133] # HANGUL CHOSEONG SIOS-PIEUP-KIYEOK
+1134 ; [.223C.0020.0002.1134] # HANGUL CHOSEONG SIOS-SSANGSIOS
+1135 ; [.223D.0020.0002.1135] # HANGUL CHOSEONG SIOS-IEUNG
+1136 ; [.223E.0020.0002.1136] # HANGUL CHOSEONG SIOS-CIEUC
+317E ; [.223E.0020.0004.317E] # HANGUL LETTER SIOS-CIEUC; QQK
+1137 ; [.223F.0020.0002.1137] # HANGUL CHOSEONG SIOS-CHIEUCH
+1138 ; [.2240.0020.0002.1138] # HANGUL CHOSEONG SIOS-KHIEUKH
+1139 ; [.2241.0020.0002.1139] # HANGUL CHOSEONG SIOS-THIEUTH
+113A ; [.2242.0020.0002.113A] # HANGUL CHOSEONG SIOS-PHIEUPH
+113B ; [.2243.0020.0002.113B] # HANGUL CHOSEONG SIOS-HIEUH
+113C ; [.2244.0020.0002.113C] # HANGUL CHOSEONG CHITUEUMSIOS
+113D ; [.2245.0020.0002.113D] # HANGUL CHOSEONG CHITUEUMSSANGSIOS
+113E ; [.2246.0020.0002.113E] # HANGUL CHOSEONG CEONGCHIEUMSIOS
+113F ; [.2247.0020.0002.113F] # HANGUL CHOSEONG CEONGCHIEUMSSANGSIOS
+1140 ; [.2248.0020.0002.1140] # HANGUL CHOSEONG PANSIOS
+317F ; [.2248.0020.0004.317F] # HANGUL LETTER PANSIOS; QQK
+1141 ; [.2249.0020.0002.1141] # HANGUL CHOSEONG IEUNG-KIYEOK
+1142 ; [.224A.0020.0002.1142] # HANGUL CHOSEONG IEUNG-TIKEUT
+1143 ; [.224B.0020.0002.1143] # HANGUL CHOSEONG IEUNG-MIEUM
+1144 ; [.224C.0020.0002.1144] # HANGUL CHOSEONG IEUNG-PIEUP
+1145 ; [.224D.0020.0002.1145] # HANGUL CHOSEONG IEUNG-SIOS
+1146 ; [.224E.0020.0002.1146] # HANGUL CHOSEONG IEUNG-PANSIOS
+1147 ; [.224F.0020.0002.1147] # HANGUL CHOSEONG SSANGIEUNG
+3180 ; [.224F.0020.0004.3180] # HANGUL LETTER SSANGIEUNG; QQK
+1148 ; [.2250.0020.0002.1148] # HANGUL CHOSEONG IEUNG-CIEUC
+1149 ; [.2251.0020.0002.1149] # HANGUL CHOSEONG IEUNG-CHIEUCH
+114A ; [.2252.0020.0002.114A] # HANGUL CHOSEONG IEUNG-THIEUTH
+114B ; [.2253.0020.0002.114B] # HANGUL CHOSEONG IEUNG-PHIEUPH
+114C ; [.2254.0020.0002.114C] # HANGUL CHOSEONG YESIEUNG
+3181 ; [.2254.0020.0004.3181] # HANGUL LETTER YESIEUNG; QQK
+114D ; [.2255.0020.0002.114D] # HANGUL CHOSEONG CIEUC-IEUNG
+114E ; [.2256.0020.0002.114E] # HANGUL CHOSEONG CHITUEUMCIEUC
+114F ; [.2257.0020.0002.114F] # HANGUL CHOSEONG CHITUEUMSSANGCIEUC
+1150 ; [.2258.0020.0002.1150] # HANGUL CHOSEONG CEONGCHIEUMCIEUC
+1151 ; [.2259.0020.0002.1151] # HANGUL CHOSEONG CEONGCHIEUMSSANGCIEUC
+1152 ; [.225A.0020.0002.1152] # HANGUL CHOSEONG CHIEUCH-KHIEUKH
+1153 ; [.225B.0020.0002.1153] # HANGUL CHOSEONG CHIEUCH-HIEUH
+1154 ; [.225C.0020.0002.1154] # HANGUL CHOSEONG CHITUEUMCHIEUCH
+1155 ; [.225D.0020.0002.1155] # HANGUL CHOSEONG CEONGCHIEUMCHIEUCH
+1156 ; [.225E.0020.0002.1156] # HANGUL CHOSEONG PHIEUPH-PIEUP
+1157 ; [.225F.0020.0002.1157] # HANGUL CHOSEONG KAPYEOUNPHIEUPH
+3184 ; [.225F.0020.0004.3184] # HANGUL LETTER KAPYEOUNPHIEUPH; QQK
+1158 ; [.2260.0020.0002.1158] # HANGUL CHOSEONG SSANGHIEUH
+3185 ; [.2260.0020.0004.3185] # HANGUL LETTER SSANGHIEUH; QQK
+1159 ; [.2261.0020.0002.1159] # HANGUL CHOSEONG YEORINHIEUH
+3186 ; [.2261.0020.0004.3186] # HANGUL LETTER YEORINHIEUH; QQK
+115F ; [.2262.0020.0002.115F] # HANGUL CHOSEONG FILLER
+1160 ; [.2263.0020.0002.1160] # HANGUL JUNGSEONG FILLER
+3164 ; [.2263.0020.0004.3164] # HANGUL FILLER; QQK
+FFA0 ; [.2263.0020.0012.FFA0] # HALFWIDTH HANGUL FILLER; QQK
+1161 ; [.2264.0020.0002.1161] # HANGUL JUNGSEONG A
+314F ; [.2264.0020.0004.314F] # HANGUL LETTER A; QQK
+FFC2 ; [.2264.0020.0012.FFC2] # HALFWIDTH HANGUL LETTER A; QQK
+1162 ; [.2265.0020.0002.1162] # HANGUL JUNGSEONG AE
+3150 ; [.2265.0020.0004.3150] # HANGUL LETTER AE; QQK
+FFC3 ; [.2265.0020.0012.FFC3] # HALFWIDTH HANGUL LETTER AE; QQK
+1163 ; [.2266.0020.0002.1163] # HANGUL JUNGSEONG YA
+3151 ; [.2266.0020.0004.3151] # HANGUL LETTER YA; QQK
+FFC4 ; [.2266.0020.0012.FFC4] # HALFWIDTH HANGUL LETTER YA; QQK
+1164 ; [.2267.0020.0002.1164] # HANGUL JUNGSEONG YAE
+3152 ; [.2267.0020.0004.3152] # HANGUL LETTER YAE; QQK
+FFC5 ; [.2267.0020.0012.FFC5] # HALFWIDTH HANGUL LETTER YAE; QQK
+1165 ; [.2268.0020.0002.1165] # HANGUL JUNGSEONG EO
+3153 ; [.2268.0020.0004.3153] # HANGUL LETTER EO; QQK
+FFC6 ; [.2268.0020.0012.FFC6] # HALFWIDTH HANGUL LETTER EO; QQK
+1166 ; [.2269.0020.0002.1166] # HANGUL JUNGSEONG E
+3154 ; [.2269.0020.0004.3154] # HANGUL LETTER E; QQK
+FFC7 ; [.2269.0020.0012.FFC7] # HALFWIDTH HANGUL LETTER E; QQK
+1167 ; [.226A.0020.0002.1167] # HANGUL JUNGSEONG YEO
+3155 ; [.226A.0020.0004.3155] # HANGUL LETTER YEO; QQK
+FFCA ; [.226A.0020.0012.FFCA] # HALFWIDTH HANGUL LETTER YEO; QQK
+1168 ; [.226B.0020.0002.1168] # HANGUL JUNGSEONG YE
+3156 ; [.226B.0020.0004.3156] # HANGUL LETTER YE; QQK
+FFCB ; [.226B.0020.0012.FFCB] # HALFWIDTH HANGUL LETTER YE; QQK
+1169 ; [.226C.0020.0002.1169] # HANGUL JUNGSEONG O
+3157 ; [.226C.0020.0004.3157] # HANGUL LETTER O; QQK
+FFCC ; [.226C.0020.0012.FFCC] # HALFWIDTH HANGUL LETTER O; QQK
+116A ; [.226D.0020.0002.116A] # HANGUL JUNGSEONG WA
+3158 ; [.226D.0020.0004.3158] # HANGUL LETTER WA; QQK
+FFCD ; [.226D.0020.0012.FFCD] # HALFWIDTH HANGUL LETTER WA; QQK
+116B ; [.226E.0020.0002.116B] # HANGUL JUNGSEONG WAE
+3159 ; [.226E.0020.0004.3159] # HANGUL LETTER WAE; QQK
+FFCE ; [.226E.0020.0012.FFCE] # HALFWIDTH HANGUL LETTER WAE; QQK
+116C ; [.226F.0020.0002.116C] # HANGUL JUNGSEONG OE
+315A ; [.226F.0020.0004.315A] # HANGUL LETTER OE; QQK
+FFCF ; [.226F.0020.0012.FFCF] # HALFWIDTH HANGUL LETTER OE; QQK
+116D ; [.2270.0020.0002.116D] # HANGUL JUNGSEONG YO
+315B ; [.2270.0020.0004.315B] # HANGUL LETTER YO; QQK
+FFD2 ; [.2270.0020.0012.FFD2] # HALFWIDTH HANGUL LETTER YO; QQK
+116E ; [.2271.0020.0002.116E] # HANGUL JUNGSEONG U
+315C ; [.2271.0020.0004.315C] # HANGUL LETTER U; QQK
+FFD3 ; [.2271.0020.0012.FFD3] # HALFWIDTH HANGUL LETTER U; QQK
+116F ; [.2272.0020.0002.116F] # HANGUL JUNGSEONG WEO
+315D ; [.2272.0020.0004.315D] # HANGUL LETTER WEO; QQK
+FFD4 ; [.2272.0020.0012.FFD4] # HALFWIDTH HANGUL LETTER WEO; QQK
+1170 ; [.2273.0020.0002.1170] # HANGUL JUNGSEONG WE
+315E ; [.2273.0020.0004.315E] # HANGUL LETTER WE; QQK
+FFD5 ; [.2273.0020.0012.FFD5] # HALFWIDTH HANGUL LETTER WE; QQK
+1171 ; [.2274.0020.0002.1171] # HANGUL JUNGSEONG WI
+315F ; [.2274.0020.0004.315F] # HANGUL LETTER WI; QQK
+FFD6 ; [.2274.0020.0012.FFD6] # HALFWIDTH HANGUL LETTER WI; QQK
+1172 ; [.2275.0020.0002.1172] # HANGUL JUNGSEONG YU
+3160 ; [.2275.0020.0004.3160] # HANGUL LETTER YU; QQK
+FFD7 ; [.2275.0020.0012.FFD7] # HALFWIDTH HANGUL LETTER YU; QQK
+1173 ; [.2276.0020.0002.1173] # HANGUL JUNGSEONG EU
+3161 ; [.2276.0020.0004.3161] # HANGUL LETTER EU; QQK
+FFDA ; [.2276.0020.0012.FFDA] # HALFWIDTH HANGUL LETTER EU; QQK
+1174 ; [.2277.0020.0002.1174] # HANGUL JUNGSEONG YI
+3162 ; [.2277.0020.0004.3162] # HANGUL LETTER YI; QQK
+FFDB ; [.2277.0020.0012.FFDB] # HALFWIDTH HANGUL LETTER YI; QQK
+1175 ; [.2278.0020.0002.1175] # HANGUL JUNGSEONG I
+3163 ; [.2278.0020.0004.3163] # HANGUL LETTER I; QQK
+FFDC ; [.2278.0020.0012.FFDC] # HALFWIDTH HANGUL LETTER I; QQK
+1176 ; [.2279.0020.0002.1176] # HANGUL JUNGSEONG A-O
+1177 ; [.227A.0020.0002.1177] # HANGUL JUNGSEONG A-U
+1178 ; [.227B.0020.0002.1178] # HANGUL JUNGSEONG YA-O
+1179 ; [.227C.0020.0002.1179] # HANGUL JUNGSEONG YA-YO
+117A ; [.227D.0020.0002.117A] # HANGUL JUNGSEONG EO-O
+117B ; [.227E.0020.0002.117B] # HANGUL JUNGSEONG EO-U
+117C ; [.227F.0020.0002.117C] # HANGUL JUNGSEONG EO-EU
+117D ; [.2280.0020.0002.117D] # HANGUL JUNGSEONG YEO-O
+117E ; [.2281.0020.0002.117E] # HANGUL JUNGSEONG YEO-U
+117F ; [.2282.0020.0002.117F] # HANGUL JUNGSEONG O-EO
+1180 ; [.2283.0020.0002.1180] # HANGUL JUNGSEONG O-E
+1181 ; [.2284.0020.0002.1181] # HANGUL JUNGSEONG O-YE
+1182 ; [.2285.0020.0002.1182] # HANGUL JUNGSEONG O-O
+1183 ; [.2286.0020.0002.1183] # HANGUL JUNGSEONG O-U
+1184 ; [.2287.0020.0002.1184] # HANGUL JUNGSEONG YO-YA
+3187 ; [.2287.0020.0004.3187] # HANGUL LETTER YO-YA; QQK
+1185 ; [.2288.0020.0002.1185] # HANGUL JUNGSEONG YO-YAE
+3188 ; [.2288.0020.0004.3188] # HANGUL LETTER YO-YAE; QQK
+1186 ; [.2289.0020.0002.1186] # HANGUL JUNGSEONG YO-YEO
+1187 ; [.228A.0020.0002.1187] # HANGUL JUNGSEONG YO-O
+1188 ; [.228B.0020.0002.1188] # HANGUL JUNGSEONG YO-I
+3189 ; [.228B.0020.0004.3189] # HANGUL LETTER YO-I; QQK
+1189 ; [.228C.0020.0002.1189] # HANGUL JUNGSEONG U-A
+118A ; [.228D.0020.0002.118A] # HANGUL JUNGSEONG U-AE
+118B ; [.228E.0020.0002.118B] # HANGUL JUNGSEONG U-EO-EU
+118C ; [.228F.0020.0002.118C] # HANGUL JUNGSEONG U-YE
+118D ; [.2290.0020.0002.118D] # HANGUL JUNGSEONG U-U
+118E ; [.2291.0020.0002.118E] # HANGUL JUNGSEONG YU-A
+118F ; [.2292.0020.0002.118F] # HANGUL JUNGSEONG YU-EO
+1190 ; [.2293.0020.0002.1190] # HANGUL JUNGSEONG YU-E
+1191 ; [.2294.0020.0002.1191] # HANGUL JUNGSEONG YU-YEO
+318A ; [.2294.0020.0004.318A] # HANGUL LETTER YU-YEO; QQK
+1192 ; [.2295.0020.0002.1192] # HANGUL JUNGSEONG YU-YE
+318B ; [.2295.0020.0004.318B] # HANGUL LETTER YU-YE; QQK
+1193 ; [.2296.0020.0002.1193] # HANGUL JUNGSEONG YU-U
+1194 ; [.2297.0020.0002.1194] # HANGUL JUNGSEONG YU-I
+318C ; [.2297.0020.0004.318C] # HANGUL LETTER YU-I; QQK
+1195 ; [.2298.0020.0002.1195] # HANGUL JUNGSEONG EU-U
+1196 ; [.2299.0020.0002.1196] # HANGUL JUNGSEONG EU-EU
+1197 ; [.229A.0020.0002.1197] # HANGUL JUNGSEONG YI-U
+1198 ; [.229B.0020.0002.1198] # HANGUL JUNGSEONG I-A
+1199 ; [.229C.0020.0002.1199] # HANGUL JUNGSEONG I-YA
+119A ; [.229D.0020.0002.119A] # HANGUL JUNGSEONG I-O
+119B ; [.229E.0020.0002.119B] # HANGUL JUNGSEONG I-U
+119C ; [.229F.0020.0002.119C] # HANGUL JUNGSEONG I-EU
+119D ; [.22A0.0020.0002.119D] # HANGUL JUNGSEONG I-ARAEA
+119E ; [.22A1.0020.0002.119E] # HANGUL JUNGSEONG ARAEA
+318D ; [.22A1.0020.0004.318D] # HANGUL LETTER ARAEA; QQK
+119F ; [.22A2.0020.0002.119F] # HANGUL JUNGSEONG ARAEA-EO
+11A0 ; [.22A3.0020.0002.11A0] # HANGUL JUNGSEONG ARAEA-U
+11A1 ; [.22A4.0020.0002.11A1] # HANGUL JUNGSEONG ARAEA-I
+318E ; [.22A4.0020.0004.318E] # HANGUL LETTER ARAEAE; QQK
+11A2 ; [.22A5.0020.0002.11A2] # HANGUL JUNGSEONG SSANGARAEA
+11A8 ; [.22A6.0020.0002.11A8] # HANGUL JONGSEONG KIYEOK
+11A9 ; [.22A7.0020.0002.11A9] # HANGUL JONGSEONG SSANGKIYEOK
+11AA ; [.22A8.0020.0002.11AA] # HANGUL JONGSEONG KIYEOK-SIOS
+3133 ; [.22A8.0020.0004.3133] # HANGUL LETTER KIYEOK-SIOS; QQK
+FFA3 ; [.22A8.0020.0012.FFA3] # HALFWIDTH HANGUL LETTER KIYEOK-SIOS; QQK
+11AB ; [.22A9.0020.0002.11AB] # HANGUL JONGSEONG NIEUN
+11AC ; [.22AA.0020.0002.11AC] # HANGUL JONGSEONG NIEUN-CIEUC
+3135 ; [.22AA.0020.0004.3135] # HANGUL LETTER NIEUN-CIEUC; QQK
+FFA5 ; [.22AA.0020.0012.FFA5] # HALFWIDTH HANGUL LETTER NIEUN-CIEUC; QQK
+11AD ; [.22AB.0020.0002.11AD] # HANGUL JONGSEONG NIEUN-HIEUH
+3136 ; [.22AB.0020.0004.3136] # HANGUL LETTER NIEUN-HIEUH; QQK
+FFA6 ; [.22AB.0020.0012.FFA6] # HALFWIDTH HANGUL LETTER NIEUN-HIEUH; QQK
+11AE ; [.22AC.0020.0002.11AE] # HANGUL JONGSEONG TIKEUT
+11AF ; [.22AD.0020.0002.11AF] # HANGUL JONGSEONG RIEUL
+11B0 ; [.22AE.0020.0002.11B0] # HANGUL JONGSEONG RIEUL-KIYEOK
+313A ; [.22AE.0020.0004.313A] # HANGUL LETTER RIEUL-KIYEOK; QQK
+FFAA ; [.22AE.0020.0012.FFAA] # HALFWIDTH HANGUL LETTER RIEUL-KIYEOK; QQK
+11B1 ; [.22AF.0020.0002.11B1] # HANGUL JONGSEONG RIEUL-MIEUM
+313B ; [.22AF.0020.0004.313B] # HANGUL LETTER RIEUL-MIEUM; QQK
+FFAB ; [.22AF.0020.0012.FFAB] # HALFWIDTH HANGUL LETTER RIEUL-MIEUM; QQK
+11B2 ; [.22B0.0020.0002.11B2] # HANGUL JONGSEONG RIEUL-PIEUP
+313C ; [.22B0.0020.0004.313C] # HANGUL LETTER RIEUL-PIEUP; QQK
+FFAC ; [.22B0.0020.0012.FFAC] # HALFWIDTH HANGUL LETTER RIEUL-PIEUP; QQK
+11B3 ; [.22B1.0020.0002.11B3] # HANGUL JONGSEONG RIEUL-SIOS
+313D ; [.22B1.0020.0004.313D] # HANGUL LETTER RIEUL-SIOS; QQK
+FFAD ; [.22B1.0020.0012.FFAD] # HALFWIDTH HANGUL LETTER RIEUL-SIOS; QQK
+11B4 ; [.22B2.0020.0002.11B4] # HANGUL JONGSEONG RIEUL-THIEUTH
+313E ; [.22B2.0020.0004.313E] # HANGUL LETTER RIEUL-THIEUTH; QQK
+FFAE ; [.22B2.0020.0012.FFAE] # HALFWIDTH HANGUL LETTER RIEUL-THIEUTH; QQK
+11B5 ; [.22B3.0020.0002.11B5] # HANGUL JONGSEONG RIEUL-PHIEUPH
+313F ; [.22B3.0020.0004.313F] # HANGUL LETTER RIEUL-PHIEUPH; QQK
+FFAF ; [.22B3.0020.0012.FFAF] # HALFWIDTH HANGUL LETTER RIEUL-PHIEUPH; QQK
+11B6 ; [.22B4.0020.0002.11B6] # HANGUL JONGSEONG RIEUL-HIEUH
+11B7 ; [.22B5.0020.0002.11B7] # HANGUL JONGSEONG MIEUM
+11B8 ; [.22B6.0020.0002.11B8] # HANGUL JONGSEONG PIEUP
+11B9 ; [.22B7.0020.0002.11B9] # HANGUL JONGSEONG PIEUP-SIOS
+11BA ; [.22B8.0020.0002.11BA] # HANGUL JONGSEONG SIOS
+11BB ; [.22B9.0020.0002.11BB] # HANGUL JONGSEONG SSANGSIOS
+11BC ; [.22BA.0020.0002.11BC] # HANGUL JONGSEONG IEUNG
+11BD ; [.22BB.0020.0002.11BD] # HANGUL JONGSEONG CIEUC
+11BE ; [.22BC.0020.0002.11BE] # HANGUL JONGSEONG CHIEUCH
+11BF ; [.22BD.0020.0002.11BF] # HANGUL JONGSEONG KHIEUKH
+11C0 ; [.22BE.0020.0002.11C0] # HANGUL JONGSEONG THIEUTH
+11C1 ; [.22BF.0020.0002.11C1] # HANGUL JONGSEONG PHIEUPH
+11C2 ; [.22C0.0020.0002.11C2] # HANGUL JONGSEONG HIEUH
+11C3 ; [.22C1.0020.0002.11C3] # HANGUL JONGSEONG KIYEOK-RIEUL
+11C4 ; [.22C2.0020.0002.11C4] # HANGUL JONGSEONG KIYEOK-SIOS-KIYEOK
+11C5 ; [.22C3.0020.0002.11C5] # HANGUL JONGSEONG NIEUN-KIYEOK
+11C6 ; [.22C4.0020.0002.11C6] # HANGUL JONGSEONG NIEUN-TIKEUT
+11C7 ; [.22C5.0020.0002.11C7] # HANGUL JONGSEONG NIEUN-SIOS
+3167 ; [.22C5.0020.0004.3167] # HANGUL LETTER NIEUN-SIOS; QQK
+11C8 ; [.22C6.0020.0002.11C8] # HANGUL JONGSEONG NIEUN-PANSIOS
+3168 ; [.22C6.0020.0004.3168] # HANGUL LETTER NIEUN-PANSIOS; QQK
+11C9 ; [.22C7.0020.0002.11C9] # HANGUL JONGSEONG NIEUN-THIEUTH
+11CA ; [.22C8.0020.0002.11CA] # HANGUL JONGSEONG TIKEUT-KIYEOK
+11CB ; [.22C9.0020.0002.11CB] # HANGUL JONGSEONG TIKEUT-RIEUL
+11CC ; [.22CA.0020.0002.11CC] # HANGUL JONGSEONG RIEUL-KIYEOK-SIOS
+3169 ; [.22CA.0020.0004.3169] # HANGUL LETTER RIEUL-KIYEOK-SIOS; QQK
+11CD ; [.22CB.0020.0002.11CD] # HANGUL JONGSEONG RIEUL-NIEUN
+11CE ; [.22CC.0020.0002.11CE] # HANGUL JONGSEONG RIEUL-TIKEUT
+316A ; [.22CC.0020.0004.316A] # HANGUL LETTER RIEUL-TIKEUT; QQK
+11CF ; [.22CD.0020.0002.11CF] # HANGUL JONGSEONG RIEUL-TIKEUT-HIEUH
+11D0 ; [.22CE.0020.0002.11D0] # HANGUL JONGSEONG SSANGRIEUL
+11D1 ; [.22CF.0020.0002.11D1] # HANGUL JONGSEONG RIEUL-MIEUM-KIYEOK
+11D2 ; [.22D0.0020.0002.11D2] # HANGUL JONGSEONG RIEUL-MIEUM-SIOS
+11D3 ; [.22D1.0020.0002.11D3] # HANGUL JONGSEONG RIEUL-PIEUP-SIOS
+316B ; [.22D1.0020.0004.316B] # HANGUL LETTER RIEUL-PIEUP-SIOS; QQK
+11D4 ; [.22D2.0020.0002.11D4] # HANGUL JONGSEONG RIEUL-PIEUP-HIEUH
+11D5 ; [.22D3.0020.0002.11D5] # HANGUL JONGSEONG RIEUL-KAPYEOUNPIEUP
+11D6 ; [.22D4.0020.0002.11D6] # HANGUL JONGSEONG RIEUL-SSANGSIOS
+11D7 ; [.22D5.0020.0002.11D7] # HANGUL JONGSEONG RIEUL-PANSIOS
+316C ; [.22D5.0020.0004.316C] # HANGUL LETTER RIEUL-PANSIOS; QQK
+11D8 ; [.22D6.0020.0002.11D8] # HANGUL JONGSEONG RIEUL-KHIEUKH
+11D9 ; [.22D7.0020.0002.11D9] # HANGUL JONGSEONG RIEUL-YEORINHIEUH
+316D ; [.22D7.0020.0004.316D] # HANGUL LETTER RIEUL-YEORINHIEUH; QQK
+11DA ; [.22D8.0020.0002.11DA] # HANGUL JONGSEONG MIEUM-KIYEOK
+11DB ; [.22D9.0020.0002.11DB] # HANGUL JONGSEONG MIEUM-RIEUL
+11DC ; [.22DA.0020.0002.11DC] # HANGUL JONGSEONG MIEUM-PIEUP
+11DD ; [.22DB.0020.0002.11DD] # HANGUL JONGSEONG MIEUM-SIOS
+316F ; [.22DB.0020.0004.316F] # HANGUL LETTER MIEUM-SIOS; QQK
+11DE ; [.22DC.0020.0002.11DE] # HANGUL JONGSEONG MIEUM-SSANGSIOS
+11DF ; [.22DD.0020.0002.11DF] # HANGUL JONGSEONG MIEUM-PANSIOS
+3170 ; [.22DD.0020.0004.3170] # HANGUL LETTER MIEUM-PANSIOS; QQK
+11E0 ; [.22DE.0020.0002.11E0] # HANGUL JONGSEONG MIEUM-CHIEUCH
+11E1 ; [.22DF.0020.0002.11E1] # HANGUL JONGSEONG MIEUM-HIEUH
+11E2 ; [.22E0.0020.0002.11E2] # HANGUL JONGSEONG KAPYEOUNMIEUM
+11E3 ; [.22E1.0020.0002.11E3] # HANGUL JONGSEONG PIEUP-RIEUL
+11E4 ; [.22E2.0020.0002.11E4] # HANGUL JONGSEONG PIEUP-PHIEUPH
+11E5 ; [.22E3.0020.0002.11E5] # HANGUL JONGSEONG PIEUP-HIEUH
+11E6 ; [.22E4.0020.0002.11E6] # HANGUL JONGSEONG KAPYEOUNPIEUP
+11E7 ; [.22E5.0020.0002.11E7] # HANGUL JONGSEONG SIOS-KIYEOK
+11E8 ; [.22E6.0020.0002.11E8] # HANGUL JONGSEONG SIOS-TIKEUT
+11E9 ; [.22E7.0020.0002.11E9] # HANGUL JONGSEONG SIOS-RIEUL
+11EA ; [.22E8.0020.0002.11EA] # HANGUL JONGSEONG SIOS-PIEUP
+11EB ; [.22E9.0020.0002.11EB] # HANGUL JONGSEONG PANSIOS
+11EC ; [.22EA.0020.0002.11EC] # HANGUL JONGSEONG IEUNG-KIYEOK
+11ED ; [.22EB.0020.0002.11ED] # HANGUL JONGSEONG IEUNG-SSANGKIYEOK
+11EE ; [.22EC.0020.0002.11EE] # HANGUL JONGSEONG SSANGIEUNG
+11EF ; [.22ED.0020.0002.11EF] # HANGUL JONGSEONG IEUNG-KHIEUKH
+11F0 ; [.22EE.0020.0002.11F0] # HANGUL JONGSEONG YESIEUNG
+11F1 ; [.22EF.0020.0002.11F1] # HANGUL JONGSEONG YESIEUNG-SIOS
+3182 ; [.22EF.0020.0004.3182] # HANGUL LETTER YESIEUNG-SIOS; QQK
+11F2 ; [.22F0.0020.0002.11F2] # HANGUL JONGSEONG YESIEUNG-PANSIOS
+3183 ; [.22F0.0020.0004.3183] # HANGUL LETTER YESIEUNG-PANSIOS; QQK
+11F3 ; [.22F1.0020.0002.11F3] # HANGUL JONGSEONG PHIEUPH-PIEUP
+11F4 ; [.22F2.0020.0002.11F4] # HANGUL JONGSEONG KAPYEOUNPHIEUPH
+11F5 ; [.22F3.0020.0002.11F5] # HANGUL JONGSEONG HIEUH-NIEUN
+11F6 ; [.22F4.0020.0002.11F6] # HANGUL JONGSEONG HIEUH-RIEUL
+11F7 ; [.22F5.0020.0002.11F7] # HANGUL JONGSEONG HIEUH-MIEUM
+11F8 ; [.22F6.0020.0002.11F8] # HANGUL JONGSEONG HIEUH-PIEUP
+11F9 ; [.22F7.0020.0002.11F9] # HANGUL JONGSEONG YEORINHIEUH
+3041 ; [.22F8.0020.000D.3041] # HIRAGANA LETTER SMALL A
+3042 ; [.22F8.0020.000E.3042] # HIRAGANA LETTER A
+30A1 ; [.22F8.0020.000F.30A1] # KATAKANA LETTER SMALL A
+FF67 ; [.22F8.0020.0010.FF67] # HALFWIDTH KATAKANA LETTER SMALL A; QQK
+30A2 ; [.22F8.0020.0011.30A2] # KATAKANA LETTER A
+FF71 ; [.22F8.0020.0012.FF71] # HALFWIDTH KATAKANA LETTER A; QQK
+32D0 ; [.22F8.0020.0013.32D0] # CIRCLED KATAKANA A; QQK
+3303 ; [.22F8.0020.001C.3303][.0FA3.0020.001C.3303][.2320.0020.001F.3303] # SQUARE AARU; QQKN
+3300 ; [.22F8.0020.001C.3300][.2311.0020.001C.3300][.0000.0178.001F.3300][.0FA3.0020.001F.3300][.230B.0020.001F.3300] # SQUARE APAATO; QQKN
+3301 ; [.22F8.0020.001C.3301][.2320.0020.001C.3301][.2313.0020.001F.3301][.22F8.0020.001F.3301] # SQUARE ARUHUA; QQKN
+3302 ; [.22F8.0020.001C.3302][.2327.0020.001C.3302][.2314.0020.001F.3302][.0000.0178.001F.3302][.22F8.0020.001F.3302] # SQUARE ANPEA; QQKN
+3043 ; [.22F9.0020.000D.3043] # HIRAGANA LETTER SMALL I
+3044 ; [.22F9.0020.000E.3044] # HIRAGANA LETTER I
+30A3 ; [.22F9.0020.000F.30A3] # KATAKANA LETTER SMALL I
+FF68 ; [.22F9.0020.0010.FF68] # HALFWIDTH KATAKANA LETTER SMALL I; QQK
+30A4 ; [.22F9.0020.0011.30A4] # KATAKANA LETTER I
+FF72 ; [.22F9.0020.0012.FF72] # HALFWIDTH KATAKANA LETTER I; QQK
+32D1 ; [.22F9.0020.0013.32D1] # CIRCLED KATAKANA I; QQK
+3304 ; [.22F9.0020.001C.3304][.230D.0020.001C.3304][.2327.0020.001F.3304][.22FF.0020.001F.3304][.0000.0177.001F.3304] # SQUARE ININGU; QQKN
+3305 ; [.22F9.0020.001C.3305][.2327.0020.001C.3305][.2308.0020.001F.3305] # SQUARE INTI; QQKN
+3045 ; [.22FA.0020.000D.3045] # HIRAGANA LETTER SMALL U
+3046 ; [.22FA.0020.000E.3046] # HIRAGANA LETTER U
+30A5 ; [.22FA.0020.000F.30A5] # KATAKANA LETTER SMALL U
+FF69 ; [.22FA.0020.0010.FF69] # HALFWIDTH KATAKANA LETTER SMALL U; QQK
+30A6 ; [.22FA.0020.0011.30A6] # KATAKANA LETTER U
+FF73 ; [.22FA.0020.0012.FF73] # HALFWIDTH KATAKANA LETTER U; QQK
+32D2 ; [.22FA.0020.0013.32D2] # CIRCLED KATAKANA U; QQK
+3094 ; [.22FA.0020.000E.3046][.0000.0177.0002.3099] # HIRAGANA LETTER VU; QQCM
+30F4 ; [.22FA.0020.0011.30A6][.0000.0177.0002.3099] # KATAKANA LETTER VU; QQCM
+3306 ; [.22FA.0020.001C.3306][.22FC.0020.001C.3306][.2327.0020.001F.3306] # SQUARE UON; QQKN
+3047 ; [.22FB.0020.000D.3047] # HIRAGANA LETTER SMALL E
+3048 ; [.22FB.0020.000E.3048] # HIRAGANA LETTER E
+30A7 ; [.22FB.0020.000F.30A7] # KATAKANA LETTER SMALL E
+FF6A ; [.22FB.0020.0010.FF6A] # HALFWIDTH KATAKANA LETTER SMALL E; QQK
+30A8 ; [.22FB.0020.0011.30A8] # KATAKANA LETTER E
+FF74 ; [.22FB.0020.0012.FF74] # HALFWIDTH KATAKANA LETTER E; QQK
+32D3 ; [.22FB.0020.0013.32D3] # CIRCLED KATAKANA E; QQK
+3308 ; [.22FB.0020.001C.3308][.0FA3.0020.001C.3308][.22FD.0020.001F.3308][.0FA3.0020.001F.3308] # SQUARE EEKAA; QQKN
+3307 ; [.22FB.0020.001C.3307][.2304.0020.001C.3307][.22FF.0020.001F.3307][.0FA3.0020.001F.3307][.230B.0020.001F.3307][.0000.0177.001F.3307] # SQUARE ESUKUUDO; QQKN
+3049 ; [.22FC.0020.000D.3049] # HIRAGANA LETTER SMALL O
+304A ; [.22FC.0020.000E.304A] # HIRAGANA LETTER O
+30A9 ; [.22FC.0020.000F.30A9] # KATAKANA LETTER SMALL O
+FF6B ; [.22FC.0020.0010.FF6B] # HALFWIDTH KATAKANA LETTER SMALL O; QQK
+30AA ; [.22FC.0020.0011.30AA] # KATAKANA LETTER O
+FF75 ; [.22FC.0020.0012.FF75] # HALFWIDTH KATAKANA LETTER O; QQK
+32D4 ; [.22FC.0020.0013.32D4] # CIRCLED KATAKANA O; QQK
+330A ; [.22FC.0020.001C.330A][.0FA3.0020.001C.330A][.2318.0020.001F.330A] # SQUARE OOMU; QQKN
+3309 ; [.22FC.0020.001C.3309][.2327.0020.001C.3309][.2304.0020.001F.3309] # SQUARE ONSU; QQKN
+3095 ; [.22FD.0020.000D.3095] # HIRAGANA LETTER SMALL KA
+304B ; [.22FD.0020.000E.304B] # HIRAGANA LETTER KA
+30F5 ; [.22FD.0020.000F.30F5] # KATAKANA LETTER SMALL KA
+30AB ; [.22FD.0020.0011.30AB] # KATAKANA LETTER KA
+FF76 ; [.22FD.0020.0012.FF76] # HALFWIDTH KATAKANA LETTER KA; QQK
+32D5 ; [.22FD.0020.0013.32D5] # CIRCLED KATAKANA KA; QQK
+304C ; [.22FD.0020.000E.304B][.0000.0177.0002.3099] # HIRAGANA LETTER GA; QQCM
+30AC ; [.22FD.0020.0011.30AB][.0000.0177.0002.3099] # KATAKANA LETTER GA; QQCM
+330B ; [.22FD.0020.001C.330B][.22F9.0020.001C.330B][.231F.0020.001F.330B] # SQUARE KAIRI; QQKN
+330C ; [.22FD.0020.001C.330C][.231E.0020.001C.330C][.2309.0020.001F.330C][.230B.0020.001F.330C] # SQUARE KARATTO; QQKN
+330D ; [.22FD.0020.001C.330D][.2322.0020.001C.330D][.231F.0020.001F.330D][.0FA3.0020.001F.330D] # SQUARE KARORII; QQKN
+330E ; [.22FD.0020.001C.330E][.0000.0177.001C.330E][.2322.0020.001F.330E][.2327.0020.001F.330E] # SQUARE GARON; QQKN
+330F ; [.22FD.0020.001C.330F][.0000.0177.001C.330F][.2327.0020.001F.330F][.2316.0020.001F.330F] # SQUARE GANMA; QQKN
+304D ; [.22FE.0020.000E.304D] # HIRAGANA LETTER KI
+30AD ; [.22FE.0020.0011.30AD] # KATAKANA LETTER KI
+FF77 ; [.22FE.0020.0012.FF77] # HALFWIDTH KATAKANA LETTER KI; QQK
+32D6 ; [.22FE.0020.0013.32D6] # CIRCLED KATAKANA KI; QQK
+304E ; [.22FE.0020.000E.304D][.0000.0177.0002.3099] # HIRAGANA LETTER GI; QQCM
+30AE ; [.22FE.0020.0011.30AD][.0000.0177.0002.3099] # KATAKANA LETTER GI; QQCM
+3310 ; [.22FE.0020.001C.3310][.0000.0177.001C.3310][.22FD.0020.001F.3310][.0000.0177.001F.3310] # SQUARE GIGA; QQKN
+3311 ; [.22FE.0020.001C.3311][.0000.0177.001C.3311][.230D.0020.001F.3311][.0FA3.0020.001F.3311] # SQUARE GINII; QQKN
+3312 ; [.22FE.0020.001C.3312][.231C.0020.001C.3312][.231F.0020.001F.3312][.0FA3.0020.001F.3312] # SQUARE KYURII; QQKN
+3313 ; [.22FE.0020.001C.3313][.0000.0177.001C.3313][.2320.0020.001F.3313][.2307.0020.001F.3313][.0000.0177.001F.3313][.0FA3.0020.001F.3313] # SQUARE GIRUDAA; QQKN
+3314 ; [.22FE.0020.001C.3314][.2322.0020.001C.3314] # SQUARE KIRO; QQKN
+3315 ; [.22FE.0020.001C.3315][.2322.0020.001C.3315][.22FF.0020.001F.3315][.0000.0177.001F.3315][.231E.0020.001F.3315][.2318.0020.001F.3315] # SQUARE KIROGURAMU; QQKN
+3316 ; [.22FE.0020.001C.3316][.2322.0020.001C.3316][.2319.0020.001F.3316][.0FA3.0020.001F.3316][.230B.0020.001F.3316][.2320.0020.001F.3316] # SQUARE KIROMEETORU; QQKN
+3317 ; [.22FE.0020.001C.3317][.2322.0020.001C.3317][.2323.0020.001F.3317][.2309.0020.001F.3317][.230B.0020.001F.3317] # SQUARE KIROWATTO; QQKN
+304F ; [.22FF.0020.000E.304F] # HIRAGANA LETTER KU
+31F0 ; [.22FF.0020.000F.31F0] # KATAKANA LETTER SMALL KU
+30AF ; [.22FF.0020.0011.30AF] # KATAKANA LETTER KU
+FF78 ; [.22FF.0020.0012.FF78] # HALFWIDTH KATAKANA LETTER KU; QQK
+32D7 ; [.22FF.0020.0013.32D7] # CIRCLED KATAKANA KU; QQK
+3050 ; [.22FF.0020.000E.304F][.0000.0177.0002.3099] # HIRAGANA LETTER GU; QQCM
+30B0 ; [.22FF.0020.0011.30AF][.0000.0177.0002.3099] # KATAKANA LETTER GU; QQCM
+3318 ; [.22FF.0020.001C.3318][.0000.0177.001C.3318][.231E.0020.001F.3318][.2318.0020.001F.3318] # SQUARE GURAMU; QQKN
+3319 ; [.22FF.0020.001C.3319][.0000.0177.001C.3319][.231E.0020.001F.3319][.2318.0020.001F.3319][.230B.0020.001F.3319][.2327.0020.001F.3319] # SQUARE GURAMUTON; QQKN
+331A ; [.22FF.0020.001C.331A][.2320.0020.001C.331A][.2305.0020.001F.331A][.0000.0177.001F.331A][.22F9.0020.001F.331A][.2322.0020.001F.331A] # SQUARE KURUZEIRO; QQKN
+331B ; [.22FF.0020.001C.331B][.2322.0020.001C.331B][.0FA3.0020.001F.331B][.230F.0020.001F.331B] # SQUARE KUROONE; QQKN
+3096 ; [.2300.0020.000D.3096] # HIRAGANA LETTER SMALL KE
+3051 ; [.2300.0020.000E.3051] # HIRAGANA LETTER KE
+30F6 ; [.2300.0020.000F.30F6] # KATAKANA LETTER SMALL KE
+30B1 ; [.2300.0020.0011.30B1] # KATAKANA LETTER KE
+FF79 ; [.2300.0020.0012.FF79] # HALFWIDTH KATAKANA LETTER KE; QQK
+32D8 ; [.2300.0020.0013.32D8] # CIRCLED KATAKANA KE; QQK
+3052 ; [.2300.0020.000E.3051][.0000.0177.0002.3099] # HIRAGANA LETTER GE; QQCM
+30B2 ; [.2300.0020.0011.30B1][.0000.0177.0002.3099] # KATAKANA LETTER GE; QQCM
+331C ; [.2300.0020.001C.331C][.0FA3.0020.001C.331C][.2304.0020.001F.331C] # SQUARE KEESU; QQKN
+3053 ; [.2301.0020.000E.3053] # HIRAGANA LETTER KO
+30B3 ; [.2301.0020.0011.30B3] # KATAKANA LETTER KO
+FF7A ; [.2301.0020.0012.FF7A] # HALFWIDTH KATAKANA LETTER KO; QQK
+32D9 ; [.2301.0020.0013.32D9] # CIRCLED KATAKANA KO; QQK
+3054 ; [.2301.0020.000E.3053][.0000.0177.0002.3099] # HIRAGANA LETTER GO; QQCM
+30B4 ; [.2301.0020.0011.30B3][.0000.0177.0002.3099] # KATAKANA LETTER GO; QQCM
+331E ; [.2301.0020.001C.331E][.0FA3.0020.001C.331E][.2315.0020.001F.331E][.0000.0178.001F.331E] # SQUARE KOOPO; QQKN
+30FF ; [.2301.0020.0016.30FF][.230B.0020.0016.30FF] # KATAKANA DIGRAPH KOTO; QQKN
+331D ; [.2301.0020.001C.331D][.2320.0020.001C.331D][.230C.0020.001F.331D] # SQUARE KORUNA; QQKN
+3055 ; [.2302.0020.000E.3055] # HIRAGANA LETTER SA
+30B5 ; [.2302.0020.0011.30B5] # KATAKANA LETTER SA
+FF7B ; [.2302.0020.0012.FF7B] # HALFWIDTH KATAKANA LETTER SA; QQK
+32DA ; [.2302.0020.0013.32DA] # CIRCLED KATAKANA SA; QQK
+3056 ; [.2302.0020.000E.3055][.0000.0177.0002.3099] # HIRAGANA LETTER ZA; QQCM
+30B6 ; [.2302.0020.0011.30B5][.0000.0177.0002.3099] # KATAKANA LETTER ZA; QQCM
+331F ; [.2302.0020.001C.331F][.22F9.0020.001C.331F][.22FF.0020.001F.331F][.2320.0020.001F.331F] # SQUARE SAIKURU; QQKN
+3320 ; [.2302.0020.001C.3320][.2327.0020.001C.3320][.2308.0020.001F.3320][.0FA3.0020.001F.3320][.2318.0020.001F.3320] # SQUARE SANTIIMU; QQKN
+3057 ; [.2303.0020.000E.3057] # HIRAGANA LETTER SI
+31F1 ; [.2303.0020.000F.31F1] # KATAKANA LETTER SMALL SI
+30B7 ; [.2303.0020.0011.30B7] # KATAKANA LETTER SI
+FF7C ; [.2303.0020.0012.FF7C] # HALFWIDTH KATAKANA LETTER SI; QQK
+32DB ; [.2303.0020.0013.32DB] # CIRCLED KATAKANA SI; QQK
+3058 ; [.2303.0020.000E.3057][.0000.0177.0002.3099] # HIRAGANA LETTER ZI; QQCM
+30B8 ; [.2303.0020.0011.30B7][.0000.0177.0002.3099] # KATAKANA LETTER ZI; QQCM
+3006 ; [.2303.0020.0004.3006][.2319.0020.0004.3006] # IDEOGRAPHIC CLOSING MARK; QQKN
+3321 ; [.2303.0020.001C.3321][.231F.0020.001C.3321][.2327.0020.001F.3321][.22FF.0020.001F.3321][.0000.0177.001F.3321] # SQUARE SIRINGU; QQKN
+3059 ; [.2304.0020.000E.3059] # HIRAGANA LETTER SU
+31F2 ; [.2304.0020.000F.31F2] # KATAKANA LETTER SMALL SU
+30B9 ; [.2304.0020.0011.30B9] # KATAKANA LETTER SU
+FF7D ; [.2304.0020.0012.FF7D] # HALFWIDTH KATAKANA LETTER SU; QQK
+32DC ; [.2304.0020.0013.32DC] # CIRCLED KATAKANA SU; QQK
+305A ; [.2304.0020.000E.3059][.0000.0177.0002.3099] # HIRAGANA LETTER ZU; QQCM
+30BA ; [.2304.0020.0011.30B9][.0000.0177.0002.3099] # KATAKANA LETTER ZU; QQCM
+305B ; [.2305.0020.000E.305B] # HIRAGANA LETTER SE
+30BB ; [.2305.0020.0011.30BB] # KATAKANA LETTER SE
+FF7E ; [.2305.0020.0012.FF7E] # HALFWIDTH KATAKANA LETTER SE; QQK
+32DD ; [.2305.0020.0013.32DD] # CIRCLED KATAKANA SE; QQK
+305C ; [.2305.0020.000E.305B][.0000.0177.0002.3099] # HIRAGANA LETTER ZE; QQCM
+30BC ; [.2305.0020.0011.30BB][.0000.0177.0002.3099] # KATAKANA LETTER ZE; QQCM
+3322 ; [.2305.0020.001C.3322][.2327.0020.001C.3322][.2308.0020.001F.3322] # SQUARE SENTI; QQKN
+3323 ; [.2305.0020.001C.3323][.2327.0020.001C.3323][.230B.0020.001F.3323] # SQUARE SENTO; QQKN
+305D ; [.2306.0020.000E.305D] # HIRAGANA LETTER SO
+30BD ; [.2306.0020.0011.30BD] # KATAKANA LETTER SO
+FF7F ; [.2306.0020.0012.FF7F] # HALFWIDTH KATAKANA LETTER SO; QQK
+32DE ; [.2306.0020.0013.32DE] # CIRCLED KATAKANA SO; QQK
+305E ; [.2306.0020.000E.305D][.0000.0177.0002.3099] # HIRAGANA LETTER ZO; QQCM
+30BE ; [.2306.0020.0011.30BD][.0000.0177.0002.3099] # KATAKANA LETTER ZO; QQCM
+305F ; [.2307.0020.000E.305F] # HIRAGANA LETTER TA
+30BF ; [.2307.0020.0011.30BF] # KATAKANA LETTER TA
+FF80 ; [.2307.0020.0012.FF80] # HALFWIDTH KATAKANA LETTER TA; QQK
+32DF ; [.2307.0020.0013.32DF] # CIRCLED KATAKANA TA; QQK
+3060 ; [.2307.0020.000E.305F][.0000.0177.0002.3099] # HIRAGANA LETTER DA; QQCM
+30C0 ; [.2307.0020.0011.30BF][.0000.0177.0002.3099] # KATAKANA LETTER DA; QQCM
+3324 ; [.2307.0020.001C.3324][.0000.0177.001C.3324][.0FA3.0020.001F.3324][.2304.0020.001F.3324] # SQUARE DAASU; QQKN
+3061 ; [.2308.0020.000E.3061] # HIRAGANA LETTER TI
+30C1 ; [.2308.0020.0011.30C1] # KATAKANA LETTER TI
+FF81 ; [.2308.0020.0012.FF81] # HALFWIDTH KATAKANA LETTER TI; QQK
+32E0 ; [.2308.0020.0013.32E0] # CIRCLED KATAKANA TI; QQK
+3062 ; [.2308.0020.000E.3061][.0000.0177.0002.3099] # HIRAGANA LETTER DI; QQCM
+30C2 ; [.2308.0020.0011.30C1][.0000.0177.0002.3099] # KATAKANA LETTER DI; QQCM
+3063 ; [.2309.0020.000D.3063] # HIRAGANA LETTER SMALL TU
+3064 ; [.2309.0020.000E.3064] # HIRAGANA LETTER TU
+30C3 ; [.2309.0020.000F.30C3] # KATAKANA LETTER SMALL TU
+FF6F ; [.2309.0020.0010.FF6F] # HALFWIDTH KATAKANA LETTER SMALL TU; QQK
+30C4 ; [.2309.0020.0011.30C4] # KATAKANA LETTER TU
+FF82 ; [.2309.0020.0012.FF82] # HALFWIDTH KATAKANA LETTER TU; QQK
+32E1 ; [.2309.0020.0013.32E1] # CIRCLED KATAKANA TU; QQK
+3065 ; [.2309.0020.000E.3064][.0000.0177.0002.3099] # HIRAGANA LETTER DU; QQCM
+30C5 ; [.2309.0020.0011.30C4][.0000.0177.0002.3099] # KATAKANA LETTER DU; QQCM
+3066 ; [.230A.0020.000E.3066] # HIRAGANA LETTER TE
+30C6 ; [.230A.0020.0011.30C6] # KATAKANA LETTER TE
+FF83 ; [.230A.0020.0012.FF83] # HALFWIDTH KATAKANA LETTER TE; QQK
+32E2 ; [.230A.0020.0013.32E2] # CIRCLED KATAKANA TE; QQK
+3067 ; [.230A.0020.000E.3066][.0000.0177.0002.3099] # HIRAGANA LETTER DE; QQCM
+30C7 ; [.230A.0020.0011.30C6][.0000.0177.0002.3099] # KATAKANA LETTER DE; QQCM
+3325 ; [.230A.0020.001C.3325][.0000.0177.001C.3325][.2303.0020.001F.3325] # SQUARE DESI; QQKN
+3068 ; [.230B.0020.000E.3068] # HIRAGANA LETTER TO
+31F3 ; [.230B.0020.000F.31F3] # KATAKANA LETTER SMALL TO
+30C8 ; [.230B.0020.0011.30C8] # KATAKANA LETTER TO
+FF84 ; [.230B.0020.0012.FF84] # HALFWIDTH KATAKANA LETTER TO; QQK
+32E3 ; [.230B.0020.0013.32E3] # CIRCLED KATAKANA TO; QQK
+3069 ; [.230B.0020.000E.3068][.0000.0177.0002.3099] # HIRAGANA LETTER DO; QQCM
+30C9 ; [.230B.0020.0011.30C8][.0000.0177.0002.3099] # KATAKANA LETTER DO; QQCM
+3326 ; [.230B.0020.001C.3326][.0000.0177.001C.3326][.2320.0020.001F.3326] # SQUARE DORU; QQKN
+3327 ; [.230B.0020.001C.3327][.2327.0020.001C.3327] # SQUARE TON; QQKN
+306A ; [.230C.0020.000E.306A] # HIRAGANA LETTER NA
+30CA ; [.230C.0020.0011.30CA] # KATAKANA LETTER NA
+FF85 ; [.230C.0020.0012.FF85] # HALFWIDTH KATAKANA LETTER NA; QQK
+32E4 ; [.230C.0020.0013.32E4] # CIRCLED KATAKANA NA; QQK
+3328 ; [.230C.0020.001C.3328][.2310.0020.001C.3328] # SQUARE NANO; QQKN
+306B ; [.230D.0020.000E.306B] # HIRAGANA LETTER NI
+30CB ; [.230D.0020.0011.30CB] # KATAKANA LETTER NI
+FF86 ; [.230D.0020.0012.FF86] # HALFWIDTH KATAKANA LETTER NI; QQK
+32E5 ; [.230D.0020.0013.32E5] # CIRCLED KATAKANA NI; QQK
+306C ; [.230E.0020.000E.306C] # HIRAGANA LETTER NU
+31F4 ; [.230E.0020.000F.31F4] # KATAKANA LETTER SMALL NU
+30CC ; [.230E.0020.0011.30CC] # KATAKANA LETTER NU
+FF87 ; [.230E.0020.0012.FF87] # HALFWIDTH KATAKANA LETTER NU; QQK
+32E6 ; [.230E.0020.0013.32E6] # CIRCLED KATAKANA NU; QQK
+306D ; [.230F.0020.000E.306D] # HIRAGANA LETTER NE
+30CD ; [.230F.0020.0011.30CD] # KATAKANA LETTER NE
+FF88 ; [.230F.0020.0012.FF88] # HALFWIDTH KATAKANA LETTER NE; QQK
+32E7 ; [.230F.0020.0013.32E7] # CIRCLED KATAKANA NE; QQK
+306E ; [.2310.0020.000E.306E] # HIRAGANA LETTER NO
+30CE ; [.2310.0020.0011.30CE] # KATAKANA LETTER NO
+FF89 ; [.2310.0020.0012.FF89] # HALFWIDTH KATAKANA LETTER NO; QQK
+32E8 ; [.2310.0020.0013.32E8] # CIRCLED KATAKANA NO; QQK
+3329 ; [.2310.0020.001C.3329][.2309.0020.001C.3329][.230B.0020.001F.3329] # SQUARE NOTTO; QQKN
+306F ; [.2311.0020.000E.306F] # HIRAGANA LETTER HA
+31F5 ; [.2311.0020.000F.31F5] # KATAKANA LETTER SMALL HA
+30CF ; [.2311.0020.0011.30CF] # KATAKANA LETTER HA
+FF8A ; [.2311.0020.0012.FF8A] # HALFWIDTH KATAKANA LETTER HA; QQK
+32E9 ; [.2311.0020.0013.32E9] # CIRCLED KATAKANA HA; QQK
+3070 ; [.2311.0020.000E.306F][.0000.0177.0002.3099] # HIRAGANA LETTER BA; QQCM
+30D0 ; [.2311.0020.0011.30CF][.0000.0177.0002.3099] # KATAKANA LETTER BA; QQCM
+3071 ; [.2311.0020.000E.306F][.0000.0178.0002.309A] # HIRAGANA LETTER PA; QQCM
+30D1 ; [.2311.0020.0011.30CF][.0000.0178.0002.309A] # KATAKANA LETTER PA; QQCM
+332B ; [.2311.0020.001C.332B][.0000.0178.001C.332B][.0FA3.0020.001F.332B][.2305.0020.001F.332B][.2327.0020.001F.332B][.230B.0020.001F.332B] # SQUARE PAASENTO; QQKN
+332C ; [.2311.0020.001C.332C][.0000.0178.001C.332C][.0FA3.0020.001F.332C][.2309.0020.001F.332C] # SQUARE PAATU; QQKN
+332D ; [.2311.0020.001C.332D][.0000.0177.001C.332D][.0FA3.0020.001F.332D][.2321.0020.001F.332D][.2320.0020.001F.332D] # SQUARE BAARERU; QQKN
+332A ; [.2311.0020.001C.332A][.22F9.0020.001C.332A][.2309.0020.001F.332A] # SQUARE HAITU; QQKN
+3072 ; [.2312.0020.000E.3072] # HIRAGANA LETTER HI
+31F6 ; [.2312.0020.000F.31F6] # KATAKANA LETTER SMALL HI
+30D2 ; [.2312.0020.0011.30D2] # KATAKANA LETTER HI
+FF8B ; [.2312.0020.0012.FF8B] # HALFWIDTH KATAKANA LETTER HI; QQK
+32EA ; [.2312.0020.0013.32EA] # CIRCLED KATAKANA HI; QQK
+3073 ; [.2312.0020.000E.3072][.0000.0177.0002.3099] # HIRAGANA LETTER BI; QQCM
+30D3 ; [.2312.0020.0011.30D2][.0000.0177.0002.3099] # KATAKANA LETTER BI; QQCM
+3074 ; [.2312.0020.000E.3072][.0000.0178.0002.309A] # HIRAGANA LETTER PI; QQCM
+30D4 ; [.2312.0020.0011.30D2][.0000.0178.0002.309A] # KATAKANA LETTER PI; QQCM
+332E ; [.2312.0020.001C.332E][.0000.0178.001C.332E][.22F8.0020.001F.332E][.2304.0020.001F.332E][.230B.0020.001F.332E][.2320.0020.001F.332E] # SQUARE PIASUTORU; QQKN
+332F ; [.2312.0020.001C.332F][.0000.0178.001C.332F][.22FF.0020.001F.332F][.2320.0020.001F.332F] # SQUARE PIKURU; QQKN
+3330 ; [.2312.0020.001C.3330][.0000.0178.001C.3330][.2301.0020.001F.3330] # SQUARE PIKO; QQKN
+3331 ; [.2312.0020.001C.3331][.0000.0177.001C.3331][.2320.0020.001F.3331] # SQUARE BIRU; QQKN
+3075 ; [.2313.0020.000E.3075] # HIRAGANA LETTER HU
+31F7 ; [.2313.0020.000F.31F7] # KATAKANA LETTER SMALL HU
+30D5 ; [.2313.0020.0011.30D5] # KATAKANA LETTER HU
+FF8C ; [.2313.0020.0012.FF8C] # HALFWIDTH KATAKANA LETTER HU; QQK
+32EB ; [.2313.0020.0013.32EB] # CIRCLED KATAKANA HU; QQK
+3076 ; [.2313.0020.000E.3075][.0000.0177.0002.3099] # HIRAGANA LETTER BU; QQCM
+30D6 ; [.2313.0020.0011.30D5][.0000.0177.0002.3099] # KATAKANA LETTER BU; QQCM
+3077 ; [.2313.0020.000E.3075][.0000.0178.0002.309A] # HIRAGANA LETTER PU; QQCM
+30D7 ; [.2313.0020.0011.30D5][.0000.0178.0002.309A] # KATAKANA LETTER PU; QQCM
+3332 ; [.2313.0020.001C.3332][.22F8.0020.001C.3332][.231E.0020.001F.3332][.2309.0020.001F.3332][.230B.0020.001F.3332][.0000.0177.001F.3332] # SQUARE HUARADDO; QQKN
+3333 ; [.2313.0020.001C.3333][.22F9.0020.001C.3333][.0FA3.0020.001F.3333][.230B.0020.001F.3333] # SQUARE HUIITO; QQKN
+3334 ; [.2313.0020.001C.3334][.0000.0177.001C.3334][.2309.0020.001F.3334][.2303.0020.001F.3334][.22FB.0020.001F.3334][.2320.0020.001F.3334] # SQUARE BUSSYERU; QQKN
+3335 ; [.2313.0020.001C.3335][.231E.0020.001C.3335][.2327.0020.001F.3335] # SQUARE HURAN; QQKN
+3078 ; [.2314.0020.000E.3078] # HIRAGANA LETTER HE
+31F8 ; [.2314.0020.000F.31F8] # KATAKANA LETTER SMALL HE
+30D8 ; [.2314.0020.0011.30D8] # KATAKANA LETTER HE
+FF8D ; [.2314.0020.0012.FF8D] # HALFWIDTH KATAKANA LETTER HE; QQK
+32EC ; [.2314.0020.0013.32EC] # CIRCLED KATAKANA HE; QQK
+3079 ; [.2314.0020.000E.3078][.0000.0177.0002.3099] # HIRAGANA LETTER BE; QQCM
+30D9 ; [.2314.0020.0011.30D8][.0000.0177.0002.3099] # KATAKANA LETTER BE; QQCM
+307A ; [.2314.0020.000E.3078][.0000.0178.0002.309A] # HIRAGANA LETTER PE; QQCM
+30DA ; [.2314.0020.0011.30D8][.0000.0178.0002.309A] # KATAKANA LETTER PE; QQCM
+333B ; [.2314.0020.001C.333B][.0000.0178.001C.333B][.0FA3.0020.001F.333B][.2303.0020.001F.333B][.0000.0177.001F.333B] # SQUARE PEEZI; QQKN
+333C ; [.2314.0020.001C.333C][.0000.0177.001C.333C][.0FA3.0020.001F.333C][.2307.0020.001F.333C] # SQUARE BEETA; QQKN
+3336 ; [.2314.0020.001C.3336][.22FF.0020.001C.3336][.2307.0020.001F.3336][.0FA3.0020.001F.3336][.2320.0020.001F.3336] # SQUARE HEKUTAARU; QQKN
+3337 ; [.2314.0020.001C.3337][.0000.0178.001C.3337][.2306.0020.001F.3337] # SQUARE PESO; QQKN
+3338 ; [.2314.0020.001C.3338][.0000.0178.001C.3338][.230D.0020.001F.3338][.2312.0020.001F.3338] # SQUARE PENIHI; QQKN
+3339 ; [.2314.0020.001C.3339][.2320.0020.001C.3339][.2309.0020.001F.3339] # SQUARE HERUTU; QQKN
+333A ; [.2314.0020.001C.333A][.0000.0178.001C.333A][.2327.0020.001F.333A][.2304.0020.001F.333A] # SQUARE PENSU; QQKN
+307B ; [.2315.0020.000E.307B] # HIRAGANA LETTER HO
+31F9 ; [.2315.0020.000F.31F9] # KATAKANA LETTER SMALL HO
+30DB ; [.2315.0020.0011.30DB] # KATAKANA LETTER HO
+FF8E ; [.2315.0020.0012.FF8E] # HALFWIDTH KATAKANA LETTER HO; QQK
+32ED ; [.2315.0020.0013.32ED] # CIRCLED KATAKANA HO; QQK
+307C ; [.2315.0020.000E.307B][.0000.0177.0002.3099] # HIRAGANA LETTER BO; QQCM
+30DC ; [.2315.0020.0011.30DB][.0000.0177.0002.3099] # KATAKANA LETTER BO; QQCM
+307D ; [.2315.0020.000E.307B][.0000.0178.0002.309A] # HIRAGANA LETTER PO; QQCM
+30DD ; [.2315.0020.0011.30DB][.0000.0178.0002.309A] # KATAKANA LETTER PO; QQCM
+3341 ; [.2315.0020.001C.3341][.0FA3.0020.001C.3341][.2320.0020.001F.3341] # SQUARE HOORU; QQKN
+3342 ; [.2315.0020.001C.3342][.0FA3.0020.001C.3342][.2327.0020.001F.3342] # SQUARE HOON; QQKN
+333D ; [.2315.0020.001C.333D][.0000.0178.001C.333D][.22F9.0020.001F.333D][.2327.0020.001F.333D][.230B.0020.001F.333D] # SQUARE POINTO; QQKN
+333E ; [.2315.0020.001C.333E][.0000.0177.001C.333E][.2320.0020.001F.333E][.230B.0020.001F.333E] # SQUARE BORUTO; QQKN
+333F ; [.2315.0020.001C.333F][.2327.0020.001C.333F] # SQUARE HON; QQKN
+3340 ; [.2315.0020.001C.3340][.0000.0178.001C.3340][.2327.0020.001F.3340][.230B.0020.001F.3340][.0000.0177.001F.3340] # SQUARE PONDO; QQKN
+307E ; [.2316.0020.000E.307E] # HIRAGANA LETTER MA
+30DE ; [.2316.0020.0011.30DE] # KATAKANA LETTER MA
+FF8F ; [.2316.0020.0012.FF8F] # HALFWIDTH KATAKANA LETTER MA; QQK
+32EE ; [.2316.0020.0013.32EE] # CIRCLED KATAKANA MA; QQK
+3343 ; [.2316.0020.001C.3343][.22F9.0020.001C.3343][.22FF.0020.001F.3343][.2322.0020.001F.3343] # SQUARE MAIKURO; QQKN
+3344 ; [.2316.0020.001C.3344][.22F9.0020.001C.3344][.2320.0020.001F.3344] # SQUARE MAIRU; QQKN
+303C ; [.2316.0020.0004.303C][.2304.0020.0004.303C] # MASU MARK; QQKN
+3345 ; [.2316.0020.001C.3345][.2309.0020.001C.3345][.2311.0020.001F.3345] # SQUARE MAHHA; QQKN
+3346 ; [.2316.0020.001C.3346][.2320.0020.001C.3346][.22FF.0020.001F.3346] # SQUARE MARUKU; QQKN
+3347 ; [.2316.0020.001C.3347][.2327.0020.001C.3347][.2303.0020.001F.3347][.231D.0020.001F.3347][.2327.0020.001F.3347] # SQUARE MANSYON; QQKN
+307F ; [.2317.0020.000E.307F] # HIRAGANA LETTER MI
+30DF ; [.2317.0020.0011.30DF] # KATAKANA LETTER MI
+FF90 ; [.2317.0020.0012.FF90] # HALFWIDTH KATAKANA LETTER MI; QQK
+32EF ; [.2317.0020.0013.32EF] # CIRCLED KATAKANA MI; QQK
+3348 ; [.2317.0020.001C.3348][.22FF.0020.001C.3348][.2322.0020.001F.3348][.2327.0020.001F.3348] # SQUARE MIKURON; QQKN
+3349 ; [.2317.0020.001C.3349][.231F.0020.001C.3349] # SQUARE MIRI; QQKN
+334A ; [.2317.0020.001C.334A][.231F.0020.001C.334A][.2311.0020.001F.334A][.0000.0177.001F.334A][.0FA3.0020.001F.334A][.2320.0020.001F.334A] # SQUARE MIRIBAARU; QQKN
+3080 ; [.2318.0020.000E.3080] # HIRAGANA LETTER MU
+31FA ; [.2318.0020.000F.31FA] # KATAKANA LETTER SMALL MU
+30E0 ; [.2318.0020.0011.30E0] # KATAKANA LETTER MU
+FF91 ; [.2318.0020.0012.FF91] # HALFWIDTH KATAKANA LETTER MU; QQK
+32F0 ; [.2318.0020.0013.32F0] # CIRCLED KATAKANA MU; QQK
+3081 ; [.2319.0020.000E.3081] # HIRAGANA LETTER ME
+30E1 ; [.2319.0020.0011.30E1] # KATAKANA LETTER ME
+FF92 ; [.2319.0020.0012.FF92] # HALFWIDTH KATAKANA LETTER ME; QQK
+32F1 ; [.2319.0020.0013.32F1] # CIRCLED KATAKANA ME; QQK
+334D ; [.2319.0020.001C.334D][.0FA3.0020.001C.334D][.230B.0020.001F.334D][.2320.0020.001F.334D] # SQUARE MEETORU; QQKN
+334B ; [.2319.0020.001C.334B][.22FD.0020.001C.334B][.0000.0177.001F.334B] # SQUARE MEGA; QQKN
+334C ; [.2319.0020.001C.334C][.22FD.0020.001C.334C][.0000.0177.001F.334C][.230B.0020.001F.334C][.2327.0020.001F.334C] # SQUARE MEGATON; QQKN
+3082 ; [.231A.0020.000E.3082] # HIRAGANA LETTER MO
+30E2 ; [.231A.0020.0011.30E2] # KATAKANA LETTER MO
+FF93 ; [.231A.0020.0012.FF93] # HALFWIDTH KATAKANA LETTER MO; QQK
+32F2 ; [.231A.0020.0013.32F2] # CIRCLED KATAKANA MO; QQK
+3083 ; [.231B.0020.000D.3083] # HIRAGANA LETTER SMALL YA
+3084 ; [.231B.0020.000E.3084] # HIRAGANA LETTER YA
+30E3 ; [.231B.0020.000F.30E3] # KATAKANA LETTER SMALL YA
+FF6C ; [.231B.0020.0010.FF6C] # HALFWIDTH KATAKANA LETTER SMALL YA; QQK
+30E4 ; [.231B.0020.0011.30E4] # KATAKANA LETTER YA
+FF94 ; [.231B.0020.0012.FF94] # HALFWIDTH KATAKANA LETTER YA; QQK
+32F3 ; [.231B.0020.0013.32F3] # CIRCLED KATAKANA YA; QQK
+334E ; [.231B.0020.001C.334E][.0FA3.0020.001C.334E][.230B.0020.001F.334E][.0000.0177.001F.334E] # SQUARE YAADO; QQKN
+334F ; [.231B.0020.001C.334F][.0FA3.0020.001C.334F][.2320.0020.001F.334F] # SQUARE YAARU; QQKN
+3085 ; [.231C.0020.000D.3085] # HIRAGANA LETTER SMALL YU
+3086 ; [.231C.0020.000E.3086] # HIRAGANA LETTER YU
+30E5 ; [.231C.0020.000F.30E5] # KATAKANA LETTER SMALL YU
+FF6D ; [.231C.0020.0010.FF6D] # HALFWIDTH KATAKANA LETTER SMALL YU; QQK
+30E6 ; [.231C.0020.0011.30E6] # KATAKANA LETTER YU
+FF95 ; [.231C.0020.0012.FF95] # HALFWIDTH KATAKANA LETTER YU; QQK
+32F4 ; [.231C.0020.0013.32F4] # CIRCLED KATAKANA YU; QQK
+3350 ; [.231C.0020.001C.3350][.22F8.0020.001C.3350][.2327.0020.001F.3350] # SQUARE YUAN; QQKN
+3087 ; [.231D.0020.000D.3087] # HIRAGANA LETTER SMALL YO
+3088 ; [.231D.0020.000E.3088] # HIRAGANA LETTER YO
+30E7 ; [.231D.0020.000F.30E7] # KATAKANA LETTER SMALL YO
+FF6E ; [.231D.0020.0010.FF6E] # HALFWIDTH KATAKANA LETTER SMALL YO; QQK
+30E8 ; [.231D.0020.0011.30E8] # KATAKANA LETTER YO
+FF96 ; [.231D.0020.0012.FF96] # HALFWIDTH KATAKANA LETTER YO; QQK
+32F5 ; [.231D.0020.0013.32F5] # CIRCLED KATAKANA YO; QQK
+309F ; [.231D.0020.0016.309F][.231F.0020.0016.309F] # HIRAGANA DIGRAPH YORI; QQKN
+3089 ; [.231E.0020.000E.3089] # HIRAGANA LETTER RA
+31FB ; [.231E.0020.000F.31FB] # KATAKANA LETTER SMALL RA
+30E9 ; [.231E.0020.0011.30E9] # KATAKANA LETTER RA
+FF97 ; [.231E.0020.0012.FF97] # HALFWIDTH KATAKANA LETTER RA; QQK
+32F6 ; [.231E.0020.0013.32F6] # CIRCLED KATAKANA RA; QQK
+308A ; [.231F.0020.000E.308A] # HIRAGANA LETTER RI
+31FC ; [.231F.0020.000F.31FC] # KATAKANA LETTER SMALL RI
+30EA ; [.231F.0020.0011.30EA] # KATAKANA LETTER RI
+FF98 ; [.231F.0020.0012.FF98] # HALFWIDTH KATAKANA LETTER RI; QQK
+32F7 ; [.231F.0020.0013.32F7] # CIRCLED KATAKANA RI; QQK
+3351 ; [.231F.0020.001C.3351][.2309.0020.001C.3351][.230B.0020.001F.3351][.2320.0020.001F.3351] # SQUARE RITTORU; QQKN
+3352 ; [.231F.0020.001C.3352][.231E.0020.001C.3352] # SQUARE RIRA; QQKN
+308B ; [.2320.0020.000E.308B] # HIRAGANA LETTER RU
+31FD ; [.2320.0020.000F.31FD] # KATAKANA LETTER SMALL RU
+30EB ; [.2320.0020.0011.30EB] # KATAKANA LETTER RU
+FF99 ; [.2320.0020.0012.FF99] # HALFWIDTH KATAKANA LETTER RU; QQK
+32F8 ; [.2320.0020.0013.32F8] # CIRCLED KATAKANA RU; QQK
+3354 ; [.2320.0020.001C.3354][.0FA3.0020.001C.3354][.2313.0020.001F.3354][.0000.0177.001F.3354][.2320.0020.001F.3354] # SQUARE RUUBURU; QQKN
+3353 ; [.2320.0020.001C.3353][.2312.0020.001C.3353][.0000.0178.001F.3353][.0FA3.0020.001F.3353] # SQUARE RUPII; QQKN
+308C ; [.2321.0020.000E.308C] # HIRAGANA LETTER RE
+31FE ; [.2321.0020.000F.31FE] # KATAKANA LETTER SMALL RE
+30EC ; [.2321.0020.0011.30EC] # KATAKANA LETTER RE
+FF9A ; [.2321.0020.0012.FF9A] # HALFWIDTH KATAKANA LETTER RE; QQK
+32F9 ; [.2321.0020.0013.32F9] # CIRCLED KATAKANA RE; QQK
+3355 ; [.2321.0020.001C.3355][.2318.0020.001C.3355] # SQUARE REMU; QQKN
+3356 ; [.2321.0020.001C.3356][.2327.0020.001C.3356][.230B.0020.001F.3356][.2300.0020.001F.3356][.0000.0177.001F.3356][.2327.0020.001F.3356] # SQUARE RENTOGEN; QQKN
+308D ; [.2322.0020.000E.308D] # HIRAGANA LETTER RO
+31FF ; [.2322.0020.000F.31FF] # KATAKANA LETTER SMALL RO
+30ED ; [.2322.0020.0011.30ED] # KATAKANA LETTER RO
+FF9B ; [.2322.0020.0012.FF9B] # HALFWIDTH KATAKANA LETTER RO; QQK
+32FA ; [.2322.0020.0013.32FA] # CIRCLED KATAKANA RO; QQK
+308E ; [.2323.0020.000D.308E] # HIRAGANA LETTER SMALL WA
+308F ; [.2323.0020.000E.308F] # HIRAGANA LETTER WA
+30EE ; [.2323.0020.000F.30EE] # KATAKANA LETTER SMALL WA
+30EF ; [.2323.0020.0011.30EF] # KATAKANA LETTER WA
+FF9C ; [.2323.0020.0012.FF9C] # HALFWIDTH KATAKANA LETTER WA; QQK
+32FB ; [.2323.0020.0013.32FB] # CIRCLED KATAKANA WA; QQK
+30F7 ; [.2323.0020.0011.30EF][.0000.0177.0002.3099] # KATAKANA LETTER VA; QQCM
+3357 ; [.2323.0020.001C.3357][.2309.0020.001C.3357][.230B.0020.001F.3357] # SQUARE WATTO; QQKN
+3090 ; [.2324.0020.000E.3090] # HIRAGANA LETTER WI
+30F0 ; [.2324.0020.0011.30F0] # KATAKANA LETTER WI
+32FC ; [.2324.0020.0013.32FC] # CIRCLED KATAKANA WI; QQK
+30F8 ; [.2324.0020.0011.30F0][.0000.0177.0002.3099] # KATAKANA LETTER VI; QQCM
+3091 ; [.2325.0020.000E.3091] # HIRAGANA LETTER WE
+30F1 ; [.2325.0020.0011.30F1] # KATAKANA LETTER WE
+32FD ; [.2325.0020.0013.32FD] # CIRCLED KATAKANA WE; QQK
+30F9 ; [.2325.0020.0011.30F1][.0000.0177.0002.3099] # KATAKANA LETTER VE; QQCM
+3092 ; [.2326.0020.000E.3092] # HIRAGANA LETTER WO
+30F2 ; [.2326.0020.0011.30F2] # KATAKANA LETTER WO
+FF66 ; [.2326.0020.0012.FF66] # HALFWIDTH KATAKANA LETTER WO; QQK
+32FE ; [.2326.0020.0013.32FE] # CIRCLED KATAKANA WO; QQK
+30FA ; [.2326.0020.0011.30F2][.0000.0177.0002.3099] # KATAKANA LETTER VO; QQCM
+3093 ; [.2327.0020.000E.3093] # HIRAGANA LETTER N
+30F3 ; [.2327.0020.0011.30F3] # KATAKANA LETTER N
+FF9D ; [.2327.0020.0012.FF9D] # HALFWIDTH KATAKANA LETTER N; QQK
+3105 ; [.2328.0020.0002.3105] # BOPOMOFO LETTER B
+31A0 ; [.2328.0020.0004.31A0][.0000.019A.0004.31A0] # BOPOMOFO LETTER BU; QQKN
+3106 ; [.2329.0020.0002.3106] # BOPOMOFO LETTER P
+31B4 ; [.2329.0020.0019.31B4] # BOPOMOFO FINAL LETTER P; QQK
+3107 ; [.232A.0020.0002.3107] # BOPOMOFO LETTER M
+3108 ; [.232B.0020.0002.3108] # BOPOMOFO LETTER F
+312A ; [.232C.0020.0002.312A] # BOPOMOFO LETTER V
+3109 ; [.232D.0020.0002.3109] # BOPOMOFO LETTER D
+310A ; [.232E.0020.0002.310A] # BOPOMOFO LETTER T
+31B5 ; [.232E.0020.0019.31B5] # BOPOMOFO FINAL LETTER T; QQK
+310B ; [.232F.0020.0002.310B] # BOPOMOFO LETTER N
+310C ; [.2330.0020.0002.310C] # BOPOMOFO LETTER L
+310D ; [.2331.0020.0002.310D] # BOPOMOFO LETTER G
+31A3 ; [.2331.0020.0004.31A3][.0000.019A.0004.31A3] # BOPOMOFO LETTER GU; QQKN
+310E ; [.2332.0020.0002.310E] # BOPOMOFO LETTER K
+31B6 ; [.2332.0020.0019.31B6] # BOPOMOFO FINAL LETTER K; QQK
+312B ; [.2333.0020.0002.312B] # BOPOMOFO LETTER NG
+31AD ; [.2334.0020.0002.31AD] # BOPOMOFO LETTER NGG
+310F ; [.2335.0020.0002.310F] # BOPOMOFO LETTER H
+31B7 ; [.2335.0020.0019.31B7] # BOPOMOFO FINAL LETTER H; QQK
+3110 ; [.2336.0020.0002.3110] # BOPOMOFO LETTER J
+31A2 ; [.2336.0020.0004.31A2][.0000.019A.0004.31A2] # BOPOMOFO LETTER JI; QQKN
+3111 ; [.2337.0020.0002.3111] # BOPOMOFO LETTER Q
+3112 ; [.2338.0020.0002.3112] # BOPOMOFO LETTER X
+312C ; [.2339.0020.0002.312C] # BOPOMOFO LETTER GN
+3113 ; [.233A.0020.0002.3113] # BOPOMOFO LETTER ZH
+3114 ; [.233B.0020.0002.3114] # BOPOMOFO LETTER CH
+3115 ; [.233C.0020.0002.3115] # BOPOMOFO LETTER SH
+3116 ; [.233D.0020.0002.3116] # BOPOMOFO LETTER R
+3117 ; [.233E.0020.0002.3117] # BOPOMOFO LETTER Z
+31A1 ; [.233E.0020.0004.31A1][.0000.019A.0004.31A1] # BOPOMOFO LETTER ZI; QQKN
+3118 ; [.233F.0020.0002.3118] # BOPOMOFO LETTER C
+3119 ; [.2340.0020.0002.3119] # BOPOMOFO LETTER S
+311A ; [.2341.0020.0002.311A] # BOPOMOFO LETTER A
+31A9 ; [.2341.0020.0004.31A9][.0000.019A.0004.31A9] # BOPOMOFO LETTER ANN; QQKN
+311B ; [.2342.0020.0002.311B] # BOPOMOFO LETTER O
+31A7 ; [.2342.0020.0004.31A7][.0000.019A.0004.31A7] # BOPOMOFO LETTER ONN; QQKN
+31A6 ; [.2343.0020.0002.31A6] # BOPOMOFO LETTER OO
+311C ; [.2344.0020.0002.311C] # BOPOMOFO LETTER E
+311D ; [.2345.0020.0002.311D] # BOPOMOFO LETTER EH
+31A4 ; [.2346.0020.0002.31A4] # BOPOMOFO LETTER EE
+31A5 ; [.2346.0020.0004.31A5][.0000.019A.0004.31A5] # BOPOMOFO LETTER ENN; QQKN
+311E ; [.2347.0020.0002.311E] # BOPOMOFO LETTER AI
+31AE ; [.2347.0020.0004.31AE][.0000.019A.0004.31AE] # BOPOMOFO LETTER AINN; QQKN
+311F ; [.2348.0020.0002.311F] # BOPOMOFO LETTER EI
+3120 ; [.2349.0020.0002.3120] # BOPOMOFO LETTER AU
+31AF ; [.2349.0020.0004.31AF][.0000.019A.0004.31AF] # BOPOMOFO LETTER AUNN; QQKN
+3121 ; [.234A.0020.0002.3121] # BOPOMOFO LETTER OU
+3122 ; [.234B.0020.0002.3122] # BOPOMOFO LETTER AN
+3123 ; [.234C.0020.0002.3123] # BOPOMOFO LETTER EN
+3124 ; [.234D.0020.0002.3124] # BOPOMOFO LETTER ANG
+31B2 ; [.234E.0020.0002.31B2] # BOPOMOFO LETTER ONG
+3125 ; [.234F.0020.0002.3125] # BOPOMOFO LETTER ENG
+31B0 ; [.2350.0020.0002.31B0] # BOPOMOFO LETTER AM
+31B1 ; [.2351.0020.0002.31B1] # BOPOMOFO LETTER OM
+31AC ; [.2352.0020.0002.31AC] # BOPOMOFO LETTER IM
+3126 ; [.2353.0020.0002.3126] # BOPOMOFO LETTER ER
+3127 ; [.2354.0020.0002.3127] # BOPOMOFO LETTER I
+31AA ; [.2354.0020.0004.31AA][.0000.019A.0004.31AA] # BOPOMOFO LETTER INN; QQKN
+31B3 ; [.2354.0020.0016.31B3][.0000.019A.0016.31B3] # BOPOMOFO LETTER INNN; QQKN
+3128 ; [.2355.0020.0002.3128] # BOPOMOFO LETTER U
+31AB ; [.2355.0020.0004.31AB][.0000.019A.0004.31AB] # BOPOMOFO LETTER UNN; QQKN
+31A8 ; [.2355.0020.0004.31A8][.0000.019C.0004.31A8] # BOPOMOFO LETTER IR; QQKN
+3129 ; [.2356.0020.0002.3129] # BOPOMOFO LETTER IU
+A000 ; [.2357.0020.0002.A000] # YI SYLLABLE IT
+A001 ; [.2358.0020.0002.A001] # YI SYLLABLE IX
+A002 ; [.2359.0020.0002.A002] # YI SYLLABLE I
+A003 ; [.235A.0020.0002.A003] # YI SYLLABLE IP
+A004 ; [.235B.0020.0002.A004] # YI SYLLABLE IET
+A005 ; [.235C.0020.0002.A005] # YI SYLLABLE IEX
+A006 ; [.235D.0020.0002.A006] # YI SYLLABLE IE
+A007 ; [.235E.0020.0002.A007] # YI SYLLABLE IEP
+A008 ; [.235F.0020.0002.A008] # YI SYLLABLE AT
+A009 ; [.2360.0020.0002.A009] # YI SYLLABLE AX
+A00A ; [.2361.0020.0002.A00A] # YI SYLLABLE A
+A00B ; [.2362.0020.0002.A00B] # YI SYLLABLE AP
+A00C ; [.2363.0020.0002.A00C] # YI SYLLABLE UOX
+A00D ; [.2364.0020.0002.A00D] # YI SYLLABLE UO
+A00E ; [.2365.0020.0002.A00E] # YI SYLLABLE UOP
+A00F ; [.2366.0020.0002.A00F] # YI SYLLABLE OT
+A010 ; [.2367.0020.0002.A010] # YI SYLLABLE OX
+A011 ; [.2368.0020.0002.A011] # YI SYLLABLE O
+A012 ; [.2369.0020.0002.A012] # YI SYLLABLE OP
+A013 ; [.236A.0020.0002.A013] # YI SYLLABLE EX
+A014 ; [.236B.0020.0002.A014] # YI SYLLABLE E
+A015 ; [.236C.0020.0002.A015] # YI SYLLABLE WU
+A016 ; [.236D.0020.0002.A016] # YI SYLLABLE BIT
+A017 ; [.236E.0020.0002.A017] # YI SYLLABLE BIX
+A018 ; [.236F.0020.0002.A018] # YI SYLLABLE BI
+A019 ; [.2370.0020.0002.A019] # YI SYLLABLE BIP
+A01A ; [.2371.0020.0002.A01A] # YI SYLLABLE BIET
+A01B ; [.2372.0020.0002.A01B] # YI SYLLABLE BIEX
+A01C ; [.2373.0020.0002.A01C] # YI SYLLABLE BIE
+A01D ; [.2374.0020.0002.A01D] # YI SYLLABLE BIEP
+A01E ; [.2375.0020.0002.A01E] # YI SYLLABLE BAT
+A01F ; [.2376.0020.0002.A01F] # YI SYLLABLE BAX
+A020 ; [.2377.0020.0002.A020] # YI SYLLABLE BA
+A021 ; [.2378.0020.0002.A021] # YI SYLLABLE BAP
+A022 ; [.2379.0020.0002.A022] # YI SYLLABLE BUOX
+A023 ; [.237A.0020.0002.A023] # YI SYLLABLE BUO
+A024 ; [.237B.0020.0002.A024] # YI SYLLABLE BUOP
+A025 ; [.237C.0020.0002.A025] # YI SYLLABLE BOT
+A026 ; [.237D.0020.0002.A026] # YI SYLLABLE BOX
+A027 ; [.237E.0020.0002.A027] # YI SYLLABLE BO
+A028 ; [.237F.0020.0002.A028] # YI SYLLABLE BOP
+A029 ; [.2380.0020.0002.A029] # YI SYLLABLE BEX
+A02A ; [.2381.0020.0002.A02A] # YI SYLLABLE BE
+A02B ; [.2382.0020.0002.A02B] # YI SYLLABLE BEP
+A02C ; [.2383.0020.0002.A02C] # YI SYLLABLE BUT
+A02D ; [.2384.0020.0002.A02D] # YI SYLLABLE BUX
+A02E ; [.2385.0020.0002.A02E] # YI SYLLABLE BU
+A02F ; [.2386.0020.0002.A02F] # YI SYLLABLE BUP
+A030 ; [.2387.0020.0002.A030] # YI SYLLABLE BURX
+A031 ; [.2388.0020.0002.A031] # YI SYLLABLE BUR
+A032 ; [.2389.0020.0002.A032] # YI SYLLABLE BYT
+A033 ; [.238A.0020.0002.A033] # YI SYLLABLE BYX
+A034 ; [.238B.0020.0002.A034] # YI SYLLABLE BY
+A035 ; [.238C.0020.0002.A035] # YI SYLLABLE BYP
+A036 ; [.238D.0020.0002.A036] # YI SYLLABLE BYRX
+A037 ; [.238E.0020.0002.A037] # YI SYLLABLE BYR
+A038 ; [.238F.0020.0002.A038] # YI SYLLABLE PIT
+A039 ; [.2390.0020.0002.A039] # YI SYLLABLE PIX
+A03A ; [.2391.0020.0002.A03A] # YI SYLLABLE PI
+A03B ; [.2392.0020.0002.A03B] # YI SYLLABLE PIP
+A03C ; [.2393.0020.0002.A03C] # YI SYLLABLE PIEX
+A03D ; [.2394.0020.0002.A03D] # YI SYLLABLE PIE
+A03E ; [.2395.0020.0002.A03E] # YI SYLLABLE PIEP
+A03F ; [.2396.0020.0002.A03F] # YI SYLLABLE PAT
+A040 ; [.2397.0020.0002.A040] # YI SYLLABLE PAX
+A041 ; [.2398.0020.0002.A041] # YI SYLLABLE PA
+A042 ; [.2399.0020.0002.A042] # YI SYLLABLE PAP
+A043 ; [.239A.0020.0002.A043] # YI SYLLABLE PUOX
+A044 ; [.239B.0020.0002.A044] # YI SYLLABLE PUO
+A045 ; [.239C.0020.0002.A045] # YI SYLLABLE PUOP
+A046 ; [.239D.0020.0002.A046] # YI SYLLABLE POT
+A047 ; [.239E.0020.0002.A047] # YI SYLLABLE POX
+A048 ; [.239F.0020.0002.A048] # YI SYLLABLE PO
+A049 ; [.23A0.0020.0002.A049] # YI SYLLABLE POP
+A04A ; [.23A1.0020.0002.A04A] # YI SYLLABLE PUT
+A04B ; [.23A2.0020.0002.A04B] # YI SYLLABLE PUX
+A04C ; [.23A3.0020.0002.A04C] # YI SYLLABLE PU
+A04D ; [.23A4.0020.0002.A04D] # YI SYLLABLE PUP
+A04E ; [.23A5.0020.0002.A04E] # YI SYLLABLE PURX
+A04F ; [.23A6.0020.0002.A04F] # YI SYLLABLE PUR
+A050 ; [.23A7.0020.0002.A050] # YI SYLLABLE PYT
+A051 ; [.23A8.0020.0002.A051] # YI SYLLABLE PYX
+A052 ; [.23A9.0020.0002.A052] # YI SYLLABLE PY
+A053 ; [.23AA.0020.0002.A053] # YI SYLLABLE PYP
+A054 ; [.23AB.0020.0002.A054] # YI SYLLABLE PYRX
+A055 ; [.23AC.0020.0002.A055] # YI SYLLABLE PYR
+A056 ; [.23AD.0020.0002.A056] # YI SYLLABLE BBIT
+A057 ; [.23AE.0020.0002.A057] # YI SYLLABLE BBIX
+A058 ; [.23AF.0020.0002.A058] # YI SYLLABLE BBI
+A059 ; [.23B0.0020.0002.A059] # YI SYLLABLE BBIP
+A05A ; [.23B1.0020.0002.A05A] # YI SYLLABLE BBIET
+A05B ; [.23B2.0020.0002.A05B] # YI SYLLABLE BBIEX
+A05C ; [.23B3.0020.0002.A05C] # YI SYLLABLE BBIE
+A05D ; [.23B4.0020.0002.A05D] # YI SYLLABLE BBIEP
+A05E ; [.23B5.0020.0002.A05E] # YI SYLLABLE BBAT
+A05F ; [.23B6.0020.0002.A05F] # YI SYLLABLE BBAX
+A060 ; [.23B7.0020.0002.A060] # YI SYLLABLE BBA
+A061 ; [.23B8.0020.0002.A061] # YI SYLLABLE BBAP
+A062 ; [.23B9.0020.0002.A062] # YI SYLLABLE BBUOX
+A063 ; [.23BA.0020.0002.A063] # YI SYLLABLE BBUO
+A064 ; [.23BB.0020.0002.A064] # YI SYLLABLE BBUOP
+A065 ; [.23BC.0020.0002.A065] # YI SYLLABLE BBOT
+A066 ; [.23BD.0020.0002.A066] # YI SYLLABLE BBOX
+A067 ; [.23BE.0020.0002.A067] # YI SYLLABLE BBO
+A068 ; [.23BF.0020.0002.A068] # YI SYLLABLE BBOP
+A069 ; [.23C0.0020.0002.A069] # YI SYLLABLE BBEX
+A06A ; [.23C1.0020.0002.A06A] # YI SYLLABLE BBE
+A06B ; [.23C2.0020.0002.A06B] # YI SYLLABLE BBEP
+A06C ; [.23C3.0020.0002.A06C] # YI SYLLABLE BBUT
+A06D ; [.23C4.0020.0002.A06D] # YI SYLLABLE BBUX
+A06E ; [.23C5.0020.0002.A06E] # YI SYLLABLE BBU
+A06F ; [.23C6.0020.0002.A06F] # YI SYLLABLE BBUP
+A070 ; [.23C7.0020.0002.A070] # YI SYLLABLE BBURX
+A071 ; [.23C8.0020.0002.A071] # YI SYLLABLE BBUR
+A072 ; [.23C9.0020.0002.A072] # YI SYLLABLE BBYT
+A073 ; [.23CA.0020.0002.A073] # YI SYLLABLE BBYX
+A074 ; [.23CB.0020.0002.A074] # YI SYLLABLE BBY
+A075 ; [.23CC.0020.0002.A075] # YI SYLLABLE BBYP
+A076 ; [.23CD.0020.0002.A076] # YI SYLLABLE NBIT
+A077 ; [.23CE.0020.0002.A077] # YI SYLLABLE NBIX
+A078 ; [.23CF.0020.0002.A078] # YI SYLLABLE NBI
+A079 ; [.23D0.0020.0002.A079] # YI SYLLABLE NBIP
+A07A ; [.23D1.0020.0002.A07A] # YI SYLLABLE NBIEX
+A07B ; [.23D2.0020.0002.A07B] # YI SYLLABLE NBIE
+A07C ; [.23D3.0020.0002.A07C] # YI SYLLABLE NBIEP
+A07D ; [.23D4.0020.0002.A07D] # YI SYLLABLE NBAT
+A07E ; [.23D5.0020.0002.A07E] # YI SYLLABLE NBAX
+A07F ; [.23D6.0020.0002.A07F] # YI SYLLABLE NBA
+A080 ; [.23D7.0020.0002.A080] # YI SYLLABLE NBAP
+A081 ; [.23D8.0020.0002.A081] # YI SYLLABLE NBOT
+A082 ; [.23D9.0020.0002.A082] # YI SYLLABLE NBOX
+A083 ; [.23DA.0020.0002.A083] # YI SYLLABLE NBO
+A084 ; [.23DB.0020.0002.A084] # YI SYLLABLE NBOP
+A085 ; [.23DC.0020.0002.A085] # YI SYLLABLE NBUT
+A086 ; [.23DD.0020.0002.A086] # YI SYLLABLE NBUX
+A087 ; [.23DE.0020.0002.A087] # YI SYLLABLE NBU
+A088 ; [.23DF.0020.0002.A088] # YI SYLLABLE NBUP
+A089 ; [.23E0.0020.0002.A089] # YI SYLLABLE NBURX
+A08A ; [.23E1.0020.0002.A08A] # YI SYLLABLE NBUR
+A08B ; [.23E2.0020.0002.A08B] # YI SYLLABLE NBYT
+A08C ; [.23E3.0020.0002.A08C] # YI SYLLABLE NBYX
+A08D ; [.23E4.0020.0002.A08D] # YI SYLLABLE NBY
+A08E ; [.23E5.0020.0002.A08E] # YI SYLLABLE NBYP
+A08F ; [.23E6.0020.0002.A08F] # YI SYLLABLE NBYRX
+A090 ; [.23E7.0020.0002.A090] # YI SYLLABLE NBYR
+A091 ; [.23E8.0020.0002.A091] # YI SYLLABLE HMIT
+A092 ; [.23E9.0020.0002.A092] # YI SYLLABLE HMIX
+A093 ; [.23EA.0020.0002.A093] # YI SYLLABLE HMI
+A094 ; [.23EB.0020.0002.A094] # YI SYLLABLE HMIP
+A095 ; [.23EC.0020.0002.A095] # YI SYLLABLE HMIEX
+A096 ; [.23ED.0020.0002.A096] # YI SYLLABLE HMIE
+A097 ; [.23EE.0020.0002.A097] # YI SYLLABLE HMIEP
+A098 ; [.23EF.0020.0002.A098] # YI SYLLABLE HMAT
+A099 ; [.23F0.0020.0002.A099] # YI SYLLABLE HMAX
+A09A ; [.23F1.0020.0002.A09A] # YI SYLLABLE HMA
+A09B ; [.23F2.0020.0002.A09B] # YI SYLLABLE HMAP
+A09C ; [.23F3.0020.0002.A09C] # YI SYLLABLE HMUOX
+A09D ; [.23F4.0020.0002.A09D] # YI SYLLABLE HMUO
+A09E ; [.23F5.0020.0002.A09E] # YI SYLLABLE HMUOP
+A09F ; [.23F6.0020.0002.A09F] # YI SYLLABLE HMOT
+A0A0 ; [.23F7.0020.0002.A0A0] # YI SYLLABLE HMOX
+A0A1 ; [.23F8.0020.0002.A0A1] # YI SYLLABLE HMO
+A0A2 ; [.23F9.0020.0002.A0A2] # YI SYLLABLE HMOP
+A0A3 ; [.23FA.0020.0002.A0A3] # YI SYLLABLE HMUT
+A0A4 ; [.23FB.0020.0002.A0A4] # YI SYLLABLE HMUX
+A0A5 ; [.23FC.0020.0002.A0A5] # YI SYLLABLE HMU
+A0A6 ; [.23FD.0020.0002.A0A6] # YI SYLLABLE HMUP
+A0A7 ; [.23FE.0020.0002.A0A7] # YI SYLLABLE HMURX
+A0A8 ; [.23FF.0020.0002.A0A8] # YI SYLLABLE HMUR
+A0A9 ; [.2400.0020.0002.A0A9] # YI SYLLABLE HMYX
+A0AA ; [.2401.0020.0002.A0AA] # YI SYLLABLE HMY
+A0AB ; [.2402.0020.0002.A0AB] # YI SYLLABLE HMYP
+A0AC ; [.2403.0020.0002.A0AC] # YI SYLLABLE HMYRX
+A0AD ; [.2404.0020.0002.A0AD] # YI SYLLABLE HMYR
+A0AE ; [.2405.0020.0002.A0AE] # YI SYLLABLE MIT
+A0AF ; [.2406.0020.0002.A0AF] # YI SYLLABLE MIX
+A0B0 ; [.2407.0020.0002.A0B0] # YI SYLLABLE MI
+A0B1 ; [.2408.0020.0002.A0B1] # YI SYLLABLE MIP
+A0B2 ; [.2409.0020.0002.A0B2] # YI SYLLABLE MIEX
+A0B3 ; [.240A.0020.0002.A0B3] # YI SYLLABLE MIE
+A0B4 ; [.240B.0020.0002.A0B4] # YI SYLLABLE MIEP
+A0B5 ; [.240C.0020.0002.A0B5] # YI SYLLABLE MAT
+A0B6 ; [.240D.0020.0002.A0B6] # YI SYLLABLE MAX
+A0B7 ; [.240E.0020.0002.A0B7] # YI SYLLABLE MA
+A0B8 ; [.240F.0020.0002.A0B8] # YI SYLLABLE MAP
+A0B9 ; [.2410.0020.0002.A0B9] # YI SYLLABLE MUOT
+A0BA ; [.2411.0020.0002.A0BA] # YI SYLLABLE MUOX
+A0BB ; [.2412.0020.0002.A0BB] # YI SYLLABLE MUO
+A0BC ; [.2413.0020.0002.A0BC] # YI SYLLABLE MUOP
+A0BD ; [.2414.0020.0002.A0BD] # YI SYLLABLE MOT
+A0BE ; [.2415.0020.0002.A0BE] # YI SYLLABLE MOX
+A0BF ; [.2416.0020.0002.A0BF] # YI SYLLABLE MO
+A0C0 ; [.2417.0020.0002.A0C0] # YI SYLLABLE MOP
+A0C1 ; [.2418.0020.0002.A0C1] # YI SYLLABLE MEX
+A0C2 ; [.2419.0020.0002.A0C2] # YI SYLLABLE ME
+A0C3 ; [.241A.0020.0002.A0C3] # YI SYLLABLE MUT
+A0C4 ; [.241B.0020.0002.A0C4] # YI SYLLABLE MUX
+A0C5 ; [.241C.0020.0002.A0C5] # YI SYLLABLE MU
+A0C6 ; [.241D.0020.0002.A0C6] # YI SYLLABLE MUP
+A0C7 ; [.241E.0020.0002.A0C7] # YI SYLLABLE MURX
+A0C8 ; [.241F.0020.0002.A0C8] # YI SYLLABLE MUR
+A0C9 ; [.2420.0020.0002.A0C9] # YI SYLLABLE MYT
+A0CA ; [.2421.0020.0002.A0CA] # YI SYLLABLE MYX
+A0CB ; [.2422.0020.0002.A0CB] # YI SYLLABLE MY
+A0CC ; [.2423.0020.0002.A0CC] # YI SYLLABLE MYP
+A0CD ; [.2424.0020.0002.A0CD] # YI SYLLABLE FIT
+A0CE ; [.2425.0020.0002.A0CE] # YI SYLLABLE FIX
+A0CF ; [.2426.0020.0002.A0CF] # YI SYLLABLE FI
+A0D0 ; [.2427.0020.0002.A0D0] # YI SYLLABLE FIP
+A0D1 ; [.2428.0020.0002.A0D1] # YI SYLLABLE FAT
+A0D2 ; [.2429.0020.0002.A0D2] # YI SYLLABLE FAX
+A0D3 ; [.242A.0020.0002.A0D3] # YI SYLLABLE FA
+A0D4 ; [.242B.0020.0002.A0D4] # YI SYLLABLE FAP
+A0D5 ; [.242C.0020.0002.A0D5] # YI SYLLABLE FOX
+A0D6 ; [.242D.0020.0002.A0D6] # YI SYLLABLE FO
+A0D7 ; [.242E.0020.0002.A0D7] # YI SYLLABLE FOP
+A0D8 ; [.242F.0020.0002.A0D8] # YI SYLLABLE FUT
+A0D9 ; [.2430.0020.0002.A0D9] # YI SYLLABLE FUX
+A0DA ; [.2431.0020.0002.A0DA] # YI SYLLABLE FU
+A0DB ; [.2432.0020.0002.A0DB] # YI SYLLABLE FUP
+A0DC ; [.2433.0020.0002.A0DC] # YI SYLLABLE FURX
+A0DD ; [.2434.0020.0002.A0DD] # YI SYLLABLE FUR
+A0DE ; [.2435.0020.0002.A0DE] # YI SYLLABLE FYT
+A0DF ; [.2436.0020.0002.A0DF] # YI SYLLABLE FYX
+A0E0 ; [.2437.0020.0002.A0E0] # YI SYLLABLE FY
+A0E1 ; [.2438.0020.0002.A0E1] # YI SYLLABLE FYP
+A0E2 ; [.2439.0020.0002.A0E2] # YI SYLLABLE VIT
+A0E3 ; [.243A.0020.0002.A0E3] # YI SYLLABLE VIX
+A0E4 ; [.243B.0020.0002.A0E4] # YI SYLLABLE VI
+A0E5 ; [.243C.0020.0002.A0E5] # YI SYLLABLE VIP
+A0E6 ; [.243D.0020.0002.A0E6] # YI SYLLABLE VIET
+A0E7 ; [.243E.0020.0002.A0E7] # YI SYLLABLE VIEX
+A0E8 ; [.243F.0020.0002.A0E8] # YI SYLLABLE VIE
+A0E9 ; [.2440.0020.0002.A0E9] # YI SYLLABLE VIEP
+A0EA ; [.2441.0020.0002.A0EA] # YI SYLLABLE VAT
+A0EB ; [.2442.0020.0002.A0EB] # YI SYLLABLE VAX
+A0EC ; [.2443.0020.0002.A0EC] # YI SYLLABLE VA
+A0ED ; [.2444.0020.0002.A0ED] # YI SYLLABLE VAP
+A0EE ; [.2445.0020.0002.A0EE] # YI SYLLABLE VOT
+A0EF ; [.2446.0020.0002.A0EF] # YI SYLLABLE VOX
+A0F0 ; [.2447.0020.0002.A0F0] # YI SYLLABLE VO
+A0F1 ; [.2448.0020.0002.A0F1] # YI SYLLABLE VOP
+A0F2 ; [.2449.0020.0002.A0F2] # YI SYLLABLE VEX
+A0F3 ; [.244A.0020.0002.A0F3] # YI SYLLABLE VEP
+A0F4 ; [.244B.0020.0002.A0F4] # YI SYLLABLE VUT
+A0F5 ; [.244C.0020.0002.A0F5] # YI SYLLABLE VUX
+A0F6 ; [.244D.0020.0002.A0F6] # YI SYLLABLE VU
+A0F7 ; [.244E.0020.0002.A0F7] # YI SYLLABLE VUP
+A0F8 ; [.244F.0020.0002.A0F8] # YI SYLLABLE VURX
+A0F9 ; [.2450.0020.0002.A0F9] # YI SYLLABLE VUR
+A0FA ; [.2451.0020.0002.A0FA] # YI SYLLABLE VYT
+A0FB ; [.2452.0020.0002.A0FB] # YI SYLLABLE VYX
+A0FC ; [.2453.0020.0002.A0FC] # YI SYLLABLE VY
+A0FD ; [.2454.0020.0002.A0FD] # YI SYLLABLE VYP
+A0FE ; [.2455.0020.0002.A0FE] # YI SYLLABLE VYRX
+A0FF ; [.2456.0020.0002.A0FF] # YI SYLLABLE VYR
+A100 ; [.2457.0020.0002.A100] # YI SYLLABLE DIT
+A101 ; [.2458.0020.0002.A101] # YI SYLLABLE DIX
+A102 ; [.2459.0020.0002.A102] # YI SYLLABLE DI
+A103 ; [.245A.0020.0002.A103] # YI SYLLABLE DIP
+A104 ; [.245B.0020.0002.A104] # YI SYLLABLE DIEX
+A105 ; [.245C.0020.0002.A105] # YI SYLLABLE DIE
+A106 ; [.245D.0020.0002.A106] # YI SYLLABLE DIEP
+A107 ; [.245E.0020.0002.A107] # YI SYLLABLE DAT
+A108 ; [.245F.0020.0002.A108] # YI SYLLABLE DAX
+A109 ; [.2460.0020.0002.A109] # YI SYLLABLE DA
+A10A ; [.2461.0020.0002.A10A] # YI SYLLABLE DAP
+A10B ; [.2462.0020.0002.A10B] # YI SYLLABLE DUOX
+A10C ; [.2463.0020.0002.A10C] # YI SYLLABLE DUO
+A10D ; [.2464.0020.0002.A10D] # YI SYLLABLE DOT
+A10E ; [.2465.0020.0002.A10E] # YI SYLLABLE DOX
+A10F ; [.2466.0020.0002.A10F] # YI SYLLABLE DO
+A110 ; [.2467.0020.0002.A110] # YI SYLLABLE DOP
+A111 ; [.2468.0020.0002.A111] # YI SYLLABLE DEX
+A112 ; [.2469.0020.0002.A112] # YI SYLLABLE DE
+A113 ; [.246A.0020.0002.A113] # YI SYLLABLE DEP
+A114 ; [.246B.0020.0002.A114] # YI SYLLABLE DUT
+A115 ; [.246C.0020.0002.A115] # YI SYLLABLE DUX
+A116 ; [.246D.0020.0002.A116] # YI SYLLABLE DU
+A117 ; [.246E.0020.0002.A117] # YI SYLLABLE DUP
+A118 ; [.246F.0020.0002.A118] # YI SYLLABLE DURX
+A119 ; [.2470.0020.0002.A119] # YI SYLLABLE DUR
+A11A ; [.2471.0020.0002.A11A] # YI SYLLABLE TIT
+A11B ; [.2472.0020.0002.A11B] # YI SYLLABLE TIX
+A11C ; [.2473.0020.0002.A11C] # YI SYLLABLE TI
+A11D ; [.2474.0020.0002.A11D] # YI SYLLABLE TIP
+A11E ; [.2475.0020.0002.A11E] # YI SYLLABLE TIEX
+A11F ; [.2476.0020.0002.A11F] # YI SYLLABLE TIE
+A120 ; [.2477.0020.0002.A120] # YI SYLLABLE TIEP
+A121 ; [.2478.0020.0002.A121] # YI SYLLABLE TAT
+A122 ; [.2479.0020.0002.A122] # YI SYLLABLE TAX
+A123 ; [.247A.0020.0002.A123] # YI SYLLABLE TA
+A124 ; [.247B.0020.0002.A124] # YI SYLLABLE TAP
+A125 ; [.247C.0020.0002.A125] # YI SYLLABLE TUOT
+A126 ; [.247D.0020.0002.A126] # YI SYLLABLE TUOX
+A127 ; [.247E.0020.0002.A127] # YI SYLLABLE TUO
+A128 ; [.247F.0020.0002.A128] # YI SYLLABLE TUOP
+A129 ; [.2480.0020.0002.A129] # YI SYLLABLE TOT
+A12A ; [.2481.0020.0002.A12A] # YI SYLLABLE TOX
+A12B ; [.2482.0020.0002.A12B] # YI SYLLABLE TO
+A12C ; [.2483.0020.0002.A12C] # YI SYLLABLE TOP
+A12D ; [.2484.0020.0002.A12D] # YI SYLLABLE TEX
+A12E ; [.2485.0020.0002.A12E] # YI SYLLABLE TE
+A12F ; [.2486.0020.0002.A12F] # YI SYLLABLE TEP
+A130 ; [.2487.0020.0002.A130] # YI SYLLABLE TUT
+A131 ; [.2488.0020.0002.A131] # YI SYLLABLE TUX
+A132 ; [.2489.0020.0002.A132] # YI SYLLABLE TU
+A133 ; [.248A.0020.0002.A133] # YI SYLLABLE TUP
+A134 ; [.248B.0020.0002.A134] # YI SYLLABLE TURX
+A135 ; [.248C.0020.0002.A135] # YI SYLLABLE TUR
+A136 ; [.248D.0020.0002.A136] # YI SYLLABLE DDIT
+A137 ; [.248E.0020.0002.A137] # YI SYLLABLE DDIX
+A138 ; [.248F.0020.0002.A138] # YI SYLLABLE DDI
+A139 ; [.2490.0020.0002.A139] # YI SYLLABLE DDIP
+A13A ; [.2491.0020.0002.A13A] # YI SYLLABLE DDIEX
+A13B ; [.2492.0020.0002.A13B] # YI SYLLABLE DDIE
+A13C ; [.2493.0020.0002.A13C] # YI SYLLABLE DDIEP
+A13D ; [.2494.0020.0002.A13D] # YI SYLLABLE DDAT
+A13E ; [.2495.0020.0002.A13E] # YI SYLLABLE DDAX
+A13F ; [.2496.0020.0002.A13F] # YI SYLLABLE DDA
+A140 ; [.2497.0020.0002.A140] # YI SYLLABLE DDAP
+A141 ; [.2498.0020.0002.A141] # YI SYLLABLE DDUOX
+A142 ; [.2499.0020.0002.A142] # YI SYLLABLE DDUO
+A143 ; [.249A.0020.0002.A143] # YI SYLLABLE DDUOP
+A144 ; [.249B.0020.0002.A144] # YI SYLLABLE DDOT
+A145 ; [.249C.0020.0002.A145] # YI SYLLABLE DDOX
+A146 ; [.249D.0020.0002.A146] # YI SYLLABLE DDO
+A147 ; [.249E.0020.0002.A147] # YI SYLLABLE DDOP
+A148 ; [.249F.0020.0002.A148] # YI SYLLABLE DDEX
+A149 ; [.24A0.0020.0002.A149] # YI SYLLABLE DDE
+A14A ; [.24A1.0020.0002.A14A] # YI SYLLABLE DDEP
+A14B ; [.24A2.0020.0002.A14B] # YI SYLLABLE DDUT
+A14C ; [.24A3.0020.0002.A14C] # YI SYLLABLE DDUX
+A14D ; [.24A4.0020.0002.A14D] # YI SYLLABLE DDU
+A14E ; [.24A5.0020.0002.A14E] # YI SYLLABLE DDUP
+A14F ; [.24A6.0020.0002.A14F] # YI SYLLABLE DDURX
+A150 ; [.24A7.0020.0002.A150] # YI SYLLABLE DDUR
+A151 ; [.24A8.0020.0002.A151] # YI SYLLABLE NDIT
+A152 ; [.24A9.0020.0002.A152] # YI SYLLABLE NDIX
+A153 ; [.24AA.0020.0002.A153] # YI SYLLABLE NDI
+A154 ; [.24AB.0020.0002.A154] # YI SYLLABLE NDIP
+A155 ; [.24AC.0020.0002.A155] # YI SYLLABLE NDIEX
+A156 ; [.24AD.0020.0002.A156] # YI SYLLABLE NDIE
+A157 ; [.24AE.0020.0002.A157] # YI SYLLABLE NDAT
+A158 ; [.24AF.0020.0002.A158] # YI SYLLABLE NDAX
+A159 ; [.24B0.0020.0002.A159] # YI SYLLABLE NDA
+A15A ; [.24B1.0020.0002.A15A] # YI SYLLABLE NDAP
+A15B ; [.24B2.0020.0002.A15B] # YI SYLLABLE NDOT
+A15C ; [.24B3.0020.0002.A15C] # YI SYLLABLE NDOX
+A15D ; [.24B4.0020.0002.A15D] # YI SYLLABLE NDO
+A15E ; [.24B5.0020.0002.A15E] # YI SYLLABLE NDOP
+A15F ; [.24B6.0020.0002.A15F] # YI SYLLABLE NDEX
+A160 ; [.24B7.0020.0002.A160] # YI SYLLABLE NDE
+A161 ; [.24B8.0020.0002.A161] # YI SYLLABLE NDEP
+A162 ; [.24B9.0020.0002.A162] # YI SYLLABLE NDUT
+A163 ; [.24BA.0020.0002.A163] # YI SYLLABLE NDUX
+A164 ; [.24BB.0020.0002.A164] # YI SYLLABLE NDU
+A165 ; [.24BC.0020.0002.A165] # YI SYLLABLE NDUP
+A166 ; [.24BD.0020.0002.A166] # YI SYLLABLE NDURX
+A167 ; [.24BE.0020.0002.A167] # YI SYLLABLE NDUR
+A168 ; [.24BF.0020.0002.A168] # YI SYLLABLE HNIT
+A169 ; [.24C0.0020.0002.A169] # YI SYLLABLE HNIX
+A16A ; [.24C1.0020.0002.A16A] # YI SYLLABLE HNI
+A16B ; [.24C2.0020.0002.A16B] # YI SYLLABLE HNIP
+A16C ; [.24C3.0020.0002.A16C] # YI SYLLABLE HNIET
+A16D ; [.24C4.0020.0002.A16D] # YI SYLLABLE HNIEX
+A16E ; [.24C5.0020.0002.A16E] # YI SYLLABLE HNIE
+A16F ; [.24C6.0020.0002.A16F] # YI SYLLABLE HNIEP
+A170 ; [.24C7.0020.0002.A170] # YI SYLLABLE HNAT
+A171 ; [.24C8.0020.0002.A171] # YI SYLLABLE HNAX
+A172 ; [.24C9.0020.0002.A172] # YI SYLLABLE HNA
+A173 ; [.24CA.0020.0002.A173] # YI SYLLABLE HNAP
+A174 ; [.24CB.0020.0002.A174] # YI SYLLABLE HNUOX
+A175 ; [.24CC.0020.0002.A175] # YI SYLLABLE HNUO
+A176 ; [.24CD.0020.0002.A176] # YI SYLLABLE HNOT
+A177 ; [.24CE.0020.0002.A177] # YI SYLLABLE HNOX
+A178 ; [.24CF.0020.0002.A178] # YI SYLLABLE HNOP
+A179 ; [.24D0.0020.0002.A179] # YI SYLLABLE HNEX
+A17A ; [.24D1.0020.0002.A17A] # YI SYLLABLE HNE
+A17B ; [.24D2.0020.0002.A17B] # YI SYLLABLE HNEP
+A17C ; [.24D3.0020.0002.A17C] # YI SYLLABLE HNUT
+A17D ; [.24D4.0020.0002.A17D] # YI SYLLABLE NIT
+A17E ; [.24D5.0020.0002.A17E] # YI SYLLABLE NIX
+A17F ; [.24D6.0020.0002.A17F] # YI SYLLABLE NI
+A180 ; [.24D7.0020.0002.A180] # YI SYLLABLE NIP
+A181 ; [.24D8.0020.0002.A181] # YI SYLLABLE NIEX
+A182 ; [.24D9.0020.0002.A182] # YI SYLLABLE NIE
+A183 ; [.24DA.0020.0002.A183] # YI SYLLABLE NIEP
+A184 ; [.24DB.0020.0002.A184] # YI SYLLABLE NAX
+A185 ; [.24DC.0020.0002.A185] # YI SYLLABLE NA
+A186 ; [.24DD.0020.0002.A186] # YI SYLLABLE NAP
+A187 ; [.24DE.0020.0002.A187] # YI SYLLABLE NUOX
+A188 ; [.24DF.0020.0002.A188] # YI SYLLABLE NUO
+A189 ; [.24E0.0020.0002.A189] # YI SYLLABLE NUOP
+A18A ; [.24E1.0020.0002.A18A] # YI SYLLABLE NOT
+A18B ; [.24E2.0020.0002.A18B] # YI SYLLABLE NOX
+A18C ; [.24E3.0020.0002.A18C] # YI SYLLABLE NO
+A18D ; [.24E4.0020.0002.A18D] # YI SYLLABLE NOP
+A18E ; [.24E5.0020.0002.A18E] # YI SYLLABLE NEX
+A18F ; [.24E6.0020.0002.A18F] # YI SYLLABLE NE
+A190 ; [.24E7.0020.0002.A190] # YI SYLLABLE NEP
+A191 ; [.24E8.0020.0002.A191] # YI SYLLABLE NUT
+A192 ; [.24E9.0020.0002.A192] # YI SYLLABLE NUX
+A193 ; [.24EA.0020.0002.A193] # YI SYLLABLE NU
+A194 ; [.24EB.0020.0002.A194] # YI SYLLABLE NUP
+A195 ; [.24EC.0020.0002.A195] # YI SYLLABLE NURX
+A196 ; [.24ED.0020.0002.A196] # YI SYLLABLE NUR
+A197 ; [.24EE.0020.0002.A197] # YI SYLLABLE HLIT
+A198 ; [.24EF.0020.0002.A198] # YI SYLLABLE HLIX
+A199 ; [.24F0.0020.0002.A199] # YI SYLLABLE HLI
+A19A ; [.24F1.0020.0002.A19A] # YI SYLLABLE HLIP
+A19B ; [.24F2.0020.0002.A19B] # YI SYLLABLE HLIEX
+A19C ; [.24F3.0020.0002.A19C] # YI SYLLABLE HLIE
+A19D ; [.24F4.0020.0002.A19D] # YI SYLLABLE HLIEP
+A19E ; [.24F5.0020.0002.A19E] # YI SYLLABLE HLAT
+A19F ; [.24F6.0020.0002.A19F] # YI SYLLABLE HLAX
+A1A0 ; [.24F7.0020.0002.A1A0] # YI SYLLABLE HLA
+A1A1 ; [.24F8.0020.0002.A1A1] # YI SYLLABLE HLAP
+A1A2 ; [.24F9.0020.0002.A1A2] # YI SYLLABLE HLUOX
+A1A3 ; [.24FA.0020.0002.A1A3] # YI SYLLABLE HLUO
+A1A4 ; [.24FB.0020.0002.A1A4] # YI SYLLABLE HLUOP
+A1A5 ; [.24FC.0020.0002.A1A5] # YI SYLLABLE HLOX
+A1A6 ; [.24FD.0020.0002.A1A6] # YI SYLLABLE HLO
+A1A7 ; [.24FE.0020.0002.A1A7] # YI SYLLABLE HLOP
+A1A8 ; [.24FF.0020.0002.A1A8] # YI SYLLABLE HLEX
+A1A9 ; [.2500.0020.0002.A1A9] # YI SYLLABLE HLE
+A1AA ; [.2501.0020.0002.A1AA] # YI SYLLABLE HLEP
+A1AB ; [.2502.0020.0002.A1AB] # YI SYLLABLE HLUT
+A1AC ; [.2503.0020.0002.A1AC] # YI SYLLABLE HLUX
+A1AD ; [.2504.0020.0002.A1AD] # YI SYLLABLE HLU
+A1AE ; [.2505.0020.0002.A1AE] # YI SYLLABLE HLUP
+A1AF ; [.2506.0020.0002.A1AF] # YI SYLLABLE HLURX
+A1B0 ; [.2507.0020.0002.A1B0] # YI SYLLABLE HLUR
+A1B1 ; [.2508.0020.0002.A1B1] # YI SYLLABLE HLYT
+A1B2 ; [.2509.0020.0002.A1B2] # YI SYLLABLE HLYX
+A1B3 ; [.250A.0020.0002.A1B3] # YI SYLLABLE HLY
+A1B4 ; [.250B.0020.0002.A1B4] # YI SYLLABLE HLYP
+A1B5 ; [.250C.0020.0002.A1B5] # YI SYLLABLE HLYRX
+A1B6 ; [.250D.0020.0002.A1B6] # YI SYLLABLE HLYR
+A1B7 ; [.250E.0020.0002.A1B7] # YI SYLLABLE LIT
+A1B8 ; [.250F.0020.0002.A1B8] # YI SYLLABLE LIX
+A1B9 ; [.2510.0020.0002.A1B9] # YI SYLLABLE LI
+A1BA ; [.2511.0020.0002.A1BA] # YI SYLLABLE LIP
+A1BB ; [.2512.0020.0002.A1BB] # YI SYLLABLE LIET
+A1BC ; [.2513.0020.0002.A1BC] # YI SYLLABLE LIEX
+A1BD ; [.2514.0020.0002.A1BD] # YI SYLLABLE LIE
+A1BE ; [.2515.0020.0002.A1BE] # YI SYLLABLE LIEP
+A1BF ; [.2516.0020.0002.A1BF] # YI SYLLABLE LAT
+A1C0 ; [.2517.0020.0002.A1C0] # YI SYLLABLE LAX
+A1C1 ; [.2518.0020.0002.A1C1] # YI SYLLABLE LA
+A1C2 ; [.2519.0020.0002.A1C2] # YI SYLLABLE LAP
+A1C3 ; [.251A.0020.0002.A1C3] # YI SYLLABLE LUOT
+A1C4 ; [.251B.0020.0002.A1C4] # YI SYLLABLE LUOX
+A1C5 ; [.251C.0020.0002.A1C5] # YI SYLLABLE LUO
+A1C6 ; [.251D.0020.0002.A1C6] # YI SYLLABLE LUOP
+A1C7 ; [.251E.0020.0002.A1C7] # YI SYLLABLE LOT
+A1C8 ; [.251F.0020.0002.A1C8] # YI SYLLABLE LOX
+A1C9 ; [.2520.0020.0002.A1C9] # YI SYLLABLE LO
+A1CA ; [.2521.0020.0002.A1CA] # YI SYLLABLE LOP
+A1CB ; [.2522.0020.0002.A1CB] # YI SYLLABLE LEX
+A1CC ; [.2523.0020.0002.A1CC] # YI SYLLABLE LE
+A1CD ; [.2524.0020.0002.A1CD] # YI SYLLABLE LEP
+A1CE ; [.2525.0020.0002.A1CE] # YI SYLLABLE LUT
+A1CF ; [.2526.0020.0002.A1CF] # YI SYLLABLE LUX
+A1D0 ; [.2527.0020.0002.A1D0] # YI SYLLABLE LU
+A1D1 ; [.2528.0020.0002.A1D1] # YI SYLLABLE LUP
+A1D2 ; [.2529.0020.0002.A1D2] # YI SYLLABLE LURX
+A1D3 ; [.252A.0020.0002.A1D3] # YI SYLLABLE LUR
+A1D4 ; [.252B.0020.0002.A1D4] # YI SYLLABLE LYT
+A1D5 ; [.252C.0020.0002.A1D5] # YI SYLLABLE LYX
+A1D6 ; [.252D.0020.0002.A1D6] # YI SYLLABLE LY
+A1D7 ; [.252E.0020.0002.A1D7] # YI SYLLABLE LYP
+A1D8 ; [.252F.0020.0002.A1D8] # YI SYLLABLE LYRX
+A1D9 ; [.2530.0020.0002.A1D9] # YI SYLLABLE LYR
+A1DA ; [.2531.0020.0002.A1DA] # YI SYLLABLE GIT
+A1DB ; [.2532.0020.0002.A1DB] # YI SYLLABLE GIX
+A1DC ; [.2533.0020.0002.A1DC] # YI SYLLABLE GI
+A1DD ; [.2534.0020.0002.A1DD] # YI SYLLABLE GIP
+A1DE ; [.2535.0020.0002.A1DE] # YI SYLLABLE GIET
+A1DF ; [.2536.0020.0002.A1DF] # YI SYLLABLE GIEX
+A1E0 ; [.2537.0020.0002.A1E0] # YI SYLLABLE GIE
+A1E1 ; [.2538.0020.0002.A1E1] # YI SYLLABLE GIEP
+A1E2 ; [.2539.0020.0002.A1E2] # YI SYLLABLE GAT
+A1E3 ; [.253A.0020.0002.A1E3] # YI SYLLABLE GAX
+A1E4 ; [.253B.0020.0002.A1E4] # YI SYLLABLE GA
+A1E5 ; [.253C.0020.0002.A1E5] # YI SYLLABLE GAP
+A1E6 ; [.253D.0020.0002.A1E6] # YI SYLLABLE GUOT
+A1E7 ; [.253E.0020.0002.A1E7] # YI SYLLABLE GUOX
+A1E8 ; [.253F.0020.0002.A1E8] # YI SYLLABLE GUO
+A1E9 ; [.2540.0020.0002.A1E9] # YI SYLLABLE GUOP
+A1EA ; [.2541.0020.0002.A1EA] # YI SYLLABLE GOT
+A1EB ; [.2542.0020.0002.A1EB] # YI SYLLABLE GOX
+A1EC ; [.2543.0020.0002.A1EC] # YI SYLLABLE GO
+A1ED ; [.2544.0020.0002.A1ED] # YI SYLLABLE GOP
+A1EE ; [.2545.0020.0002.A1EE] # YI SYLLABLE GET
+A1EF ; [.2546.0020.0002.A1EF] # YI SYLLABLE GEX
+A1F0 ; [.2547.0020.0002.A1F0] # YI SYLLABLE GE
+A1F1 ; [.2548.0020.0002.A1F1] # YI SYLLABLE GEP
+A1F2 ; [.2549.0020.0002.A1F2] # YI SYLLABLE GUT
+A1F3 ; [.254A.0020.0002.A1F3] # YI SYLLABLE GUX
+A1F4 ; [.254B.0020.0002.A1F4] # YI SYLLABLE GU
+A1F5 ; [.254C.0020.0002.A1F5] # YI SYLLABLE GUP
+A1F6 ; [.254D.0020.0002.A1F6] # YI SYLLABLE GURX
+A1F7 ; [.254E.0020.0002.A1F7] # YI SYLLABLE GUR
+A1F8 ; [.254F.0020.0002.A1F8] # YI SYLLABLE KIT
+A1F9 ; [.2550.0020.0002.A1F9] # YI SYLLABLE KIX
+A1FA ; [.2551.0020.0002.A1FA] # YI SYLLABLE KI
+A1FB ; [.2552.0020.0002.A1FB] # YI SYLLABLE KIP
+A1FC ; [.2553.0020.0002.A1FC] # YI SYLLABLE KIEX
+A1FD ; [.2554.0020.0002.A1FD] # YI SYLLABLE KIE
+A1FE ; [.2555.0020.0002.A1FE] # YI SYLLABLE KIEP
+A1FF ; [.2556.0020.0002.A1FF] # YI SYLLABLE KAT
+A200 ; [.2557.0020.0002.A200] # YI SYLLABLE KAX
+A201 ; [.2558.0020.0002.A201] # YI SYLLABLE KA
+A202 ; [.2559.0020.0002.A202] # YI SYLLABLE KAP
+A203 ; [.255A.0020.0002.A203] # YI SYLLABLE KUOX
+A204 ; [.255B.0020.0002.A204] # YI SYLLABLE KUO
+A205 ; [.255C.0020.0002.A205] # YI SYLLABLE KUOP
+A206 ; [.255D.0020.0002.A206] # YI SYLLABLE KOT
+A207 ; [.255E.0020.0002.A207] # YI SYLLABLE KOX
+A208 ; [.255F.0020.0002.A208] # YI SYLLABLE KO
+A209 ; [.2560.0020.0002.A209] # YI SYLLABLE KOP
+A20A ; [.2561.0020.0002.A20A] # YI SYLLABLE KET
+A20B ; [.2562.0020.0002.A20B] # YI SYLLABLE KEX
+A20C ; [.2563.0020.0002.A20C] # YI SYLLABLE KE
+A20D ; [.2564.0020.0002.A20D] # YI SYLLABLE KEP
+A20E ; [.2565.0020.0002.A20E] # YI SYLLABLE KUT
+A20F ; [.2566.0020.0002.A20F] # YI SYLLABLE KUX
+A210 ; [.2567.0020.0002.A210] # YI SYLLABLE KU
+A211 ; [.2568.0020.0002.A211] # YI SYLLABLE KUP
+A212 ; [.2569.0020.0002.A212] # YI SYLLABLE KURX
+A213 ; [.256A.0020.0002.A213] # YI SYLLABLE KUR
+A214 ; [.256B.0020.0002.A214] # YI SYLLABLE GGIT
+A215 ; [.256C.0020.0002.A215] # YI SYLLABLE GGIX
+A216 ; [.256D.0020.0002.A216] # YI SYLLABLE GGI
+A217 ; [.256E.0020.0002.A217] # YI SYLLABLE GGIEX
+A218 ; [.256F.0020.0002.A218] # YI SYLLABLE GGIE
+A219 ; [.2570.0020.0002.A219] # YI SYLLABLE GGIEP
+A21A ; [.2571.0020.0002.A21A] # YI SYLLABLE GGAT
+A21B ; [.2572.0020.0002.A21B] # YI SYLLABLE GGAX
+A21C ; [.2573.0020.0002.A21C] # YI SYLLABLE GGA
+A21D ; [.2574.0020.0002.A21D] # YI SYLLABLE GGAP
+A21E ; [.2575.0020.0002.A21E] # YI SYLLABLE GGUOT
+A21F ; [.2576.0020.0002.A21F] # YI SYLLABLE GGUOX
+A220 ; [.2577.0020.0002.A220] # YI SYLLABLE GGUO
+A221 ; [.2578.0020.0002.A221] # YI SYLLABLE GGUOP
+A222 ; [.2579.0020.0002.A222] # YI SYLLABLE GGOT
+A223 ; [.257A.0020.0002.A223] # YI SYLLABLE GGOX
+A224 ; [.257B.0020.0002.A224] # YI SYLLABLE GGO
+A225 ; [.257C.0020.0002.A225] # YI SYLLABLE GGOP
+A226 ; [.257D.0020.0002.A226] # YI SYLLABLE GGET
+A227 ; [.257E.0020.0002.A227] # YI SYLLABLE GGEX
+A228 ; [.257F.0020.0002.A228] # YI SYLLABLE GGE
+A229 ; [.2580.0020.0002.A229] # YI SYLLABLE GGEP
+A22A ; [.2581.0020.0002.A22A] # YI SYLLABLE GGUT
+A22B ; [.2582.0020.0002.A22B] # YI SYLLABLE GGUX
+A22C ; [.2583.0020.0002.A22C] # YI SYLLABLE GGU
+A22D ; [.2584.0020.0002.A22D] # YI SYLLABLE GGUP
+A22E ; [.2585.0020.0002.A22E] # YI SYLLABLE GGURX
+A22F ; [.2586.0020.0002.A22F] # YI SYLLABLE GGUR
+A230 ; [.2587.0020.0002.A230] # YI SYLLABLE MGIEX
+A231 ; [.2588.0020.0002.A231] # YI SYLLABLE MGIE
+A232 ; [.2589.0020.0002.A232] # YI SYLLABLE MGAT
+A233 ; [.258A.0020.0002.A233] # YI SYLLABLE MGAX
+A234 ; [.258B.0020.0002.A234] # YI SYLLABLE MGA
+A235 ; [.258C.0020.0002.A235] # YI SYLLABLE MGAP
+A236 ; [.258D.0020.0002.A236] # YI SYLLABLE MGUOX
+A237 ; [.258E.0020.0002.A237] # YI SYLLABLE MGUO
+A238 ; [.258F.0020.0002.A238] # YI SYLLABLE MGUOP
+A239 ; [.2590.0020.0002.A239] # YI SYLLABLE MGOT
+A23A ; [.2591.0020.0002.A23A] # YI SYLLABLE MGOX
+A23B ; [.2592.0020.0002.A23B] # YI SYLLABLE MGO
+A23C ; [.2593.0020.0002.A23C] # YI SYLLABLE MGOP
+A23D ; [.2594.0020.0002.A23D] # YI SYLLABLE MGEX
+A23E ; [.2595.0020.0002.A23E] # YI SYLLABLE MGE
+A23F ; [.2596.0020.0002.A23F] # YI SYLLABLE MGEP
+A240 ; [.2597.0020.0002.A240] # YI SYLLABLE MGUT
+A241 ; [.2598.0020.0002.A241] # YI SYLLABLE MGUX
+A242 ; [.2599.0020.0002.A242] # YI SYLLABLE MGU
+A243 ; [.259A.0020.0002.A243] # YI SYLLABLE MGUP
+A244 ; [.259B.0020.0002.A244] # YI SYLLABLE MGURX
+A245 ; [.259C.0020.0002.A245] # YI SYLLABLE MGUR
+A246 ; [.259D.0020.0002.A246] # YI SYLLABLE HXIT
+A247 ; [.259E.0020.0002.A247] # YI SYLLABLE HXIX
+A248 ; [.259F.0020.0002.A248] # YI SYLLABLE HXI
+A249 ; [.25A0.0020.0002.A249] # YI SYLLABLE HXIP
+A24A ; [.25A1.0020.0002.A24A] # YI SYLLABLE HXIET
+A24B ; [.25A2.0020.0002.A24B] # YI SYLLABLE HXIEX
+A24C ; [.25A3.0020.0002.A24C] # YI SYLLABLE HXIE
+A24D ; [.25A4.0020.0002.A24D] # YI SYLLABLE HXIEP
+A24E ; [.25A5.0020.0002.A24E] # YI SYLLABLE HXAT
+A24F ; [.25A6.0020.0002.A24F] # YI SYLLABLE HXAX
+A250 ; [.25A7.0020.0002.A250] # YI SYLLABLE HXA
+A251 ; [.25A8.0020.0002.A251] # YI SYLLABLE HXAP
+A252 ; [.25A9.0020.0002.A252] # YI SYLLABLE HXUOT
+A253 ; [.25AA.0020.0002.A253] # YI SYLLABLE HXUOX
+A254 ; [.25AB.0020.0002.A254] # YI SYLLABLE HXUO
+A255 ; [.25AC.0020.0002.A255] # YI SYLLABLE HXUOP
+A256 ; [.25AD.0020.0002.A256] # YI SYLLABLE HXOT
+A257 ; [.25AE.0020.0002.A257] # YI SYLLABLE HXOX
+A258 ; [.25AF.0020.0002.A258] # YI SYLLABLE HXO
+A259 ; [.25B0.0020.0002.A259] # YI SYLLABLE HXOP
+A25A ; [.25B1.0020.0002.A25A] # YI SYLLABLE HXEX
+A25B ; [.25B2.0020.0002.A25B] # YI SYLLABLE HXE
+A25C ; [.25B3.0020.0002.A25C] # YI SYLLABLE HXEP
+A25D ; [.25B4.0020.0002.A25D] # YI SYLLABLE NGIEX
+A25E ; [.25B5.0020.0002.A25E] # YI SYLLABLE NGIE
+A25F ; [.25B6.0020.0002.A25F] # YI SYLLABLE NGIEP
+A260 ; [.25B7.0020.0002.A260] # YI SYLLABLE NGAT
+A261 ; [.25B8.0020.0002.A261] # YI SYLLABLE NGAX
+A262 ; [.25B9.0020.0002.A262] # YI SYLLABLE NGA
+A263 ; [.25BA.0020.0002.A263] # YI SYLLABLE NGAP
+A264 ; [.25BB.0020.0002.A264] # YI SYLLABLE NGUOT
+A265 ; [.25BC.0020.0002.A265] # YI SYLLABLE NGUOX
+A266 ; [.25BD.0020.0002.A266] # YI SYLLABLE NGUO
+A267 ; [.25BE.0020.0002.A267] # YI SYLLABLE NGOT
+A268 ; [.25BF.0020.0002.A268] # YI SYLLABLE NGOX
+A269 ; [.25C0.0020.0002.A269] # YI SYLLABLE NGO
+A26A ; [.25C1.0020.0002.A26A] # YI SYLLABLE NGOP
+A26B ; [.25C2.0020.0002.A26B] # YI SYLLABLE NGEX
+A26C ; [.25C3.0020.0002.A26C] # YI SYLLABLE NGE
+A26D ; [.25C4.0020.0002.A26D] # YI SYLLABLE NGEP
+A26E ; [.25C5.0020.0002.A26E] # YI SYLLABLE HIT
+A26F ; [.25C6.0020.0002.A26F] # YI SYLLABLE HIEX
+A270 ; [.25C7.0020.0002.A270] # YI SYLLABLE HIE
+A271 ; [.25C8.0020.0002.A271] # YI SYLLABLE HAT
+A272 ; [.25C9.0020.0002.A272] # YI SYLLABLE HAX
+A273 ; [.25CA.0020.0002.A273] # YI SYLLABLE HA
+A274 ; [.25CB.0020.0002.A274] # YI SYLLABLE HAP
+A275 ; [.25CC.0020.0002.A275] # YI SYLLABLE HUOT
+A276 ; [.25CD.0020.0002.A276] # YI SYLLABLE HUOX
+A277 ; [.25CE.0020.0002.A277] # YI SYLLABLE HUO
+A278 ; [.25CF.0020.0002.A278] # YI SYLLABLE HUOP
+A279 ; [.25D0.0020.0002.A279] # YI SYLLABLE HOT
+A27A ; [.25D1.0020.0002.A27A] # YI SYLLABLE HOX
+A27B ; [.25D2.0020.0002.A27B] # YI SYLLABLE HO
+A27C ; [.25D3.0020.0002.A27C] # YI SYLLABLE HOP
+A27D ; [.25D4.0020.0002.A27D] # YI SYLLABLE HEX
+A27E ; [.25D5.0020.0002.A27E] # YI SYLLABLE HE
+A27F ; [.25D6.0020.0002.A27F] # YI SYLLABLE HEP
+A280 ; [.25D7.0020.0002.A280] # YI SYLLABLE WAT
+A281 ; [.25D8.0020.0002.A281] # YI SYLLABLE WAX
+A282 ; [.25D9.0020.0002.A282] # YI SYLLABLE WA
+A283 ; [.25DA.0020.0002.A283] # YI SYLLABLE WAP
+A284 ; [.25DB.0020.0002.A284] # YI SYLLABLE WUOX
+A285 ; [.25DC.0020.0002.A285] # YI SYLLABLE WUO
+A286 ; [.25DD.0020.0002.A286] # YI SYLLABLE WUOP
+A287 ; [.25DE.0020.0002.A287] # YI SYLLABLE WOX
+A288 ; [.25DF.0020.0002.A288] # YI SYLLABLE WO
+A289 ; [.25E0.0020.0002.A289] # YI SYLLABLE WOP
+A28A ; [.25E1.0020.0002.A28A] # YI SYLLABLE WEX
+A28B ; [.25E2.0020.0002.A28B] # YI SYLLABLE WE
+A28C ; [.25E3.0020.0002.A28C] # YI SYLLABLE WEP
+A28D ; [.25E4.0020.0002.A28D] # YI SYLLABLE ZIT
+A28E ; [.25E5.0020.0002.A28E] # YI SYLLABLE ZIX
+A28F ; [.25E6.0020.0002.A28F] # YI SYLLABLE ZI
+A290 ; [.25E7.0020.0002.A290] # YI SYLLABLE ZIP
+A291 ; [.25E8.0020.0002.A291] # YI SYLLABLE ZIEX
+A292 ; [.25E9.0020.0002.A292] # YI SYLLABLE ZIE
+A293 ; [.25EA.0020.0002.A293] # YI SYLLABLE ZIEP
+A294 ; [.25EB.0020.0002.A294] # YI SYLLABLE ZAT
+A295 ; [.25EC.0020.0002.A295] # YI SYLLABLE ZAX
+A296 ; [.25ED.0020.0002.A296] # YI SYLLABLE ZA
+A297 ; [.25EE.0020.0002.A297] # YI SYLLABLE ZAP
+A298 ; [.25EF.0020.0002.A298] # YI SYLLABLE ZUOX
+A299 ; [.25F0.0020.0002.A299] # YI SYLLABLE ZUO
+A29A ; [.25F1.0020.0002.A29A] # YI SYLLABLE ZUOP
+A29B ; [.25F2.0020.0002.A29B] # YI SYLLABLE ZOT
+A29C ; [.25F3.0020.0002.A29C] # YI SYLLABLE ZOX
+A29D ; [.25F4.0020.0002.A29D] # YI SYLLABLE ZO
+A29E ; [.25F5.0020.0002.A29E] # YI SYLLABLE ZOP
+A29F ; [.25F6.0020.0002.A29F] # YI SYLLABLE ZEX
+A2A0 ; [.25F7.0020.0002.A2A0] # YI SYLLABLE ZE
+A2A1 ; [.25F8.0020.0002.A2A1] # YI SYLLABLE ZEP
+A2A2 ; [.25F9.0020.0002.A2A2] # YI SYLLABLE ZUT
+A2A3 ; [.25FA.0020.0002.A2A3] # YI SYLLABLE ZUX
+A2A4 ; [.25FB.0020.0002.A2A4] # YI SYLLABLE ZU
+A2A5 ; [.25FC.0020.0002.A2A5] # YI SYLLABLE ZUP
+A2A6 ; [.25FD.0020.0002.A2A6] # YI SYLLABLE ZURX
+A2A7 ; [.25FE.0020.0002.A2A7] # YI SYLLABLE ZUR
+A2A8 ; [.25FF.0020.0002.A2A8] # YI SYLLABLE ZYT
+A2A9 ; [.2600.0020.0002.A2A9] # YI SYLLABLE ZYX
+A2AA ; [.2601.0020.0002.A2AA] # YI SYLLABLE ZY
+A2AB ; [.2602.0020.0002.A2AB] # YI SYLLABLE ZYP
+A2AC ; [.2603.0020.0002.A2AC] # YI SYLLABLE ZYRX
+A2AD ; [.2604.0020.0002.A2AD] # YI SYLLABLE ZYR
+A2AE ; [.2605.0020.0002.A2AE] # YI SYLLABLE CIT
+A2AF ; [.2606.0020.0002.A2AF] # YI SYLLABLE CIX
+A2B0 ; [.2607.0020.0002.A2B0] # YI SYLLABLE CI
+A2B1 ; [.2608.0020.0002.A2B1] # YI SYLLABLE CIP
+A2B2 ; [.2609.0020.0002.A2B2] # YI SYLLABLE CIET
+A2B3 ; [.260A.0020.0002.A2B3] # YI SYLLABLE CIEX
+A2B4 ; [.260B.0020.0002.A2B4] # YI SYLLABLE CIE
+A2B5 ; [.260C.0020.0002.A2B5] # YI SYLLABLE CIEP
+A2B6 ; [.260D.0020.0002.A2B6] # YI SYLLABLE CAT
+A2B7 ; [.260E.0020.0002.A2B7] # YI SYLLABLE CAX
+A2B8 ; [.260F.0020.0002.A2B8] # YI SYLLABLE CA
+A2B9 ; [.2610.0020.0002.A2B9] # YI SYLLABLE CAP
+A2BA ; [.2611.0020.0002.A2BA] # YI SYLLABLE CUOX
+A2BB ; [.2612.0020.0002.A2BB] # YI SYLLABLE CUO
+A2BC ; [.2613.0020.0002.A2BC] # YI SYLLABLE CUOP
+A2BD ; [.2614.0020.0002.A2BD] # YI SYLLABLE COT
+A2BE ; [.2615.0020.0002.A2BE] # YI SYLLABLE COX
+A2BF ; [.2616.0020.0002.A2BF] # YI SYLLABLE CO
+A2C0 ; [.2617.0020.0002.A2C0] # YI SYLLABLE COP
+A2C1 ; [.2618.0020.0002.A2C1] # YI SYLLABLE CEX
+A2C2 ; [.2619.0020.0002.A2C2] # YI SYLLABLE CE
+A2C3 ; [.261A.0020.0002.A2C3] # YI SYLLABLE CEP
+A2C4 ; [.261B.0020.0002.A2C4] # YI SYLLABLE CUT
+A2C5 ; [.261C.0020.0002.A2C5] # YI SYLLABLE CUX
+A2C6 ; [.261D.0020.0002.A2C6] # YI SYLLABLE CU
+A2C7 ; [.261E.0020.0002.A2C7] # YI SYLLABLE CUP
+A2C8 ; [.261F.0020.0002.A2C8] # YI SYLLABLE CURX
+A2C9 ; [.2620.0020.0002.A2C9] # YI SYLLABLE CUR
+A2CA ; [.2621.0020.0002.A2CA] # YI SYLLABLE CYT
+A2CB ; [.2622.0020.0002.A2CB] # YI SYLLABLE CYX
+A2CC ; [.2623.0020.0002.A2CC] # YI SYLLABLE CY
+A2CD ; [.2624.0020.0002.A2CD] # YI SYLLABLE CYP
+A2CE ; [.2625.0020.0002.A2CE] # YI SYLLABLE CYRX
+A2CF ; [.2626.0020.0002.A2CF] # YI SYLLABLE CYR
+A2D0 ; [.2627.0020.0002.A2D0] # YI SYLLABLE ZZIT
+A2D1 ; [.2628.0020.0002.A2D1] # YI SYLLABLE ZZIX
+A2D2 ; [.2629.0020.0002.A2D2] # YI SYLLABLE ZZI
+A2D3 ; [.262A.0020.0002.A2D3] # YI SYLLABLE ZZIP
+A2D4 ; [.262B.0020.0002.A2D4] # YI SYLLABLE ZZIET
+A2D5 ; [.262C.0020.0002.A2D5] # YI SYLLABLE ZZIEX
+A2D6 ; [.262D.0020.0002.A2D6] # YI SYLLABLE ZZIE
+A2D7 ; [.262E.0020.0002.A2D7] # YI SYLLABLE ZZIEP
+A2D8 ; [.262F.0020.0002.A2D8] # YI SYLLABLE ZZAT
+A2D9 ; [.2630.0020.0002.A2D9] # YI SYLLABLE ZZAX
+A2DA ; [.2631.0020.0002.A2DA] # YI SYLLABLE ZZA
+A2DB ; [.2632.0020.0002.A2DB] # YI SYLLABLE ZZAP
+A2DC ; [.2633.0020.0002.A2DC] # YI SYLLABLE ZZOX
+A2DD ; [.2634.0020.0002.A2DD] # YI SYLLABLE ZZO
+A2DE ; [.2635.0020.0002.A2DE] # YI SYLLABLE ZZOP
+A2DF ; [.2636.0020.0002.A2DF] # YI SYLLABLE ZZEX
+A2E0 ; [.2637.0020.0002.A2E0] # YI SYLLABLE ZZE
+A2E1 ; [.2638.0020.0002.A2E1] # YI SYLLABLE ZZEP
+A2E2 ; [.2639.0020.0002.A2E2] # YI SYLLABLE ZZUX
+A2E3 ; [.263A.0020.0002.A2E3] # YI SYLLABLE ZZU
+A2E4 ; [.263B.0020.0002.A2E4] # YI SYLLABLE ZZUP
+A2E5 ; [.263C.0020.0002.A2E5] # YI SYLLABLE ZZURX
+A2E6 ; [.263D.0020.0002.A2E6] # YI SYLLABLE ZZUR
+A2E7 ; [.263E.0020.0002.A2E7] # YI SYLLABLE ZZYT
+A2E8 ; [.263F.0020.0002.A2E8] # YI SYLLABLE ZZYX
+A2E9 ; [.2640.0020.0002.A2E9] # YI SYLLABLE ZZY
+A2EA ; [.2641.0020.0002.A2EA] # YI SYLLABLE ZZYP
+A2EB ; [.2642.0020.0002.A2EB] # YI SYLLABLE ZZYRX
+A2EC ; [.2643.0020.0002.A2EC] # YI SYLLABLE ZZYR
+A2ED ; [.2644.0020.0002.A2ED] # YI SYLLABLE NZIT
+A2EE ; [.2645.0020.0002.A2EE] # YI SYLLABLE NZIX
+A2EF ; [.2646.0020.0002.A2EF] # YI SYLLABLE NZI
+A2F0 ; [.2647.0020.0002.A2F0] # YI SYLLABLE NZIP
+A2F1 ; [.2648.0020.0002.A2F1] # YI SYLLABLE NZIEX
+A2F2 ; [.2649.0020.0002.A2F2] # YI SYLLABLE NZIE
+A2F3 ; [.264A.0020.0002.A2F3] # YI SYLLABLE NZIEP
+A2F4 ; [.264B.0020.0002.A2F4] # YI SYLLABLE NZAT
+A2F5 ; [.264C.0020.0002.A2F5] # YI SYLLABLE NZAX
+A2F6 ; [.264D.0020.0002.A2F6] # YI SYLLABLE NZA
+A2F7 ; [.264E.0020.0002.A2F7] # YI SYLLABLE NZAP
+A2F8 ; [.264F.0020.0002.A2F8] # YI SYLLABLE NZUOX
+A2F9 ; [.2650.0020.0002.A2F9] # YI SYLLABLE NZUO
+A2FA ; [.2651.0020.0002.A2FA] # YI SYLLABLE NZOX
+A2FB ; [.2652.0020.0002.A2FB] # YI SYLLABLE NZOP
+A2FC ; [.2653.0020.0002.A2FC] # YI SYLLABLE NZEX
+A2FD ; [.2654.0020.0002.A2FD] # YI SYLLABLE NZE
+A2FE ; [.2655.0020.0002.A2FE] # YI SYLLABLE NZUX
+A2FF ; [.2656.0020.0002.A2FF] # YI SYLLABLE NZU
+A300 ; [.2657.0020.0002.A300] # YI SYLLABLE NZUP
+A301 ; [.2658.0020.0002.A301] # YI SYLLABLE NZURX
+A302 ; [.2659.0020.0002.A302] # YI SYLLABLE NZUR
+A303 ; [.265A.0020.0002.A303] # YI SYLLABLE NZYT
+A304 ; [.265B.0020.0002.A304] # YI SYLLABLE NZYX
+A305 ; [.265C.0020.0002.A305] # YI SYLLABLE NZY
+A306 ; [.265D.0020.0002.A306] # YI SYLLABLE NZYP
+A307 ; [.265E.0020.0002.A307] # YI SYLLABLE NZYRX
+A308 ; [.265F.0020.0002.A308] # YI SYLLABLE NZYR
+A309 ; [.2660.0020.0002.A309] # YI SYLLABLE SIT
+A30A ; [.2661.0020.0002.A30A] # YI SYLLABLE SIX
+A30B ; [.2662.0020.0002.A30B] # YI SYLLABLE SI
+A30C ; [.2663.0020.0002.A30C] # YI SYLLABLE SIP
+A30D ; [.2664.0020.0002.A30D] # YI SYLLABLE SIEX
+A30E ; [.2665.0020.0002.A30E] # YI SYLLABLE SIE
+A30F ; [.2666.0020.0002.A30F] # YI SYLLABLE SIEP
+A310 ; [.2667.0020.0002.A310] # YI SYLLABLE SAT
+A311 ; [.2668.0020.0002.A311] # YI SYLLABLE SAX
+A312 ; [.2669.0020.0002.A312] # YI SYLLABLE SA
+A313 ; [.266A.0020.0002.A313] # YI SYLLABLE SAP
+A314 ; [.266B.0020.0002.A314] # YI SYLLABLE SUOX
+A315 ; [.266C.0020.0002.A315] # YI SYLLABLE SUO
+A316 ; [.266D.0020.0002.A316] # YI SYLLABLE SUOP
+A317 ; [.266E.0020.0002.A317] # YI SYLLABLE SOT
+A318 ; [.266F.0020.0002.A318] # YI SYLLABLE SOX
+A319 ; [.2670.0020.0002.A319] # YI SYLLABLE SO
+A31A ; [.2671.0020.0002.A31A] # YI SYLLABLE SOP
+A31B ; [.2672.0020.0002.A31B] # YI SYLLABLE SEX
+A31C ; [.2673.0020.0002.A31C] # YI SYLLABLE SE
+A31D ; [.2674.0020.0002.A31D] # YI SYLLABLE SEP
+A31E ; [.2675.0020.0002.A31E] # YI SYLLABLE SUT
+A31F ; [.2676.0020.0002.A31F] # YI SYLLABLE SUX
+A320 ; [.2677.0020.0002.A320] # YI SYLLABLE SU
+A321 ; [.2678.0020.0002.A321] # YI SYLLABLE SUP
+A322 ; [.2679.0020.0002.A322] # YI SYLLABLE SURX
+A323 ; [.267A.0020.0002.A323] # YI SYLLABLE SUR
+A324 ; [.267B.0020.0002.A324] # YI SYLLABLE SYT
+A325 ; [.267C.0020.0002.A325] # YI SYLLABLE SYX
+A326 ; [.267D.0020.0002.A326] # YI SYLLABLE SY
+A327 ; [.267E.0020.0002.A327] # YI SYLLABLE SYP
+A328 ; [.267F.0020.0002.A328] # YI SYLLABLE SYRX
+A329 ; [.2680.0020.0002.A329] # YI SYLLABLE SYR
+A32A ; [.2681.0020.0002.A32A] # YI SYLLABLE SSIT
+A32B ; [.2682.0020.0002.A32B] # YI SYLLABLE SSIX
+A32C ; [.2683.0020.0002.A32C] # YI SYLLABLE SSI
+A32D ; [.2684.0020.0002.A32D] # YI SYLLABLE SSIP
+A32E ; [.2685.0020.0002.A32E] # YI SYLLABLE SSIEX
+A32F ; [.2686.0020.0002.A32F] # YI SYLLABLE SSIE
+A330 ; [.2687.0020.0002.A330] # YI SYLLABLE SSIEP
+A331 ; [.2688.0020.0002.A331] # YI SYLLABLE SSAT
+A332 ; [.2689.0020.0002.A332] # YI SYLLABLE SSAX
+A333 ; [.268A.0020.0002.A333] # YI SYLLABLE SSA
+A334 ; [.268B.0020.0002.A334] # YI SYLLABLE SSAP
+A335 ; [.268C.0020.0002.A335] # YI SYLLABLE SSOT
+A336 ; [.268D.0020.0002.A336] # YI SYLLABLE SSOX
+A337 ; [.268E.0020.0002.A337] # YI SYLLABLE SSO
+A338 ; [.268F.0020.0002.A338] # YI SYLLABLE SSOP
+A339 ; [.2690.0020.0002.A339] # YI SYLLABLE SSEX
+A33A ; [.2691.0020.0002.A33A] # YI SYLLABLE SSE
+A33B ; [.2692.0020.0002.A33B] # YI SYLLABLE SSEP
+A33C ; [.2693.0020.0002.A33C] # YI SYLLABLE SSUT
+A33D ; [.2694.0020.0002.A33D] # YI SYLLABLE SSUX
+A33E ; [.2695.0020.0002.A33E] # YI SYLLABLE SSU
+A33F ; [.2696.0020.0002.A33F] # YI SYLLABLE SSUP
+A340 ; [.2697.0020.0002.A340] # YI SYLLABLE SSYT
+A341 ; [.2698.0020.0002.A341] # YI SYLLABLE SSYX
+A342 ; [.2699.0020.0002.A342] # YI SYLLABLE SSY
+A343 ; [.269A.0020.0002.A343] # YI SYLLABLE SSYP
+A344 ; [.269B.0020.0002.A344] # YI SYLLABLE SSYRX
+A345 ; [.269C.0020.0002.A345] # YI SYLLABLE SSYR
+A346 ; [.269D.0020.0002.A346] # YI SYLLABLE ZHAT
+A347 ; [.269E.0020.0002.A347] # YI SYLLABLE ZHAX
+A348 ; [.269F.0020.0002.A348] # YI SYLLABLE ZHA
+A349 ; [.26A0.0020.0002.A349] # YI SYLLABLE ZHAP
+A34A ; [.26A1.0020.0002.A34A] # YI SYLLABLE ZHUOX
+A34B ; [.26A2.0020.0002.A34B] # YI SYLLABLE ZHUO
+A34C ; [.26A3.0020.0002.A34C] # YI SYLLABLE ZHUOP
+A34D ; [.26A4.0020.0002.A34D] # YI SYLLABLE ZHOT
+A34E ; [.26A5.0020.0002.A34E] # YI SYLLABLE ZHOX
+A34F ; [.26A6.0020.0002.A34F] # YI SYLLABLE ZHO
+A350 ; [.26A7.0020.0002.A350] # YI SYLLABLE ZHOP
+A351 ; [.26A8.0020.0002.A351] # YI SYLLABLE ZHET
+A352 ; [.26A9.0020.0002.A352] # YI SYLLABLE ZHEX
+A353 ; [.26AA.0020.0002.A353] # YI SYLLABLE ZHE
+A354 ; [.26AB.0020.0002.A354] # YI SYLLABLE ZHEP
+A355 ; [.26AC.0020.0002.A355] # YI SYLLABLE ZHUT
+A356 ; [.26AD.0020.0002.A356] # YI SYLLABLE ZHUX
+A357 ; [.26AE.0020.0002.A357] # YI SYLLABLE ZHU
+A358 ; [.26AF.0020.0002.A358] # YI SYLLABLE ZHUP
+A359 ; [.26B0.0020.0002.A359] # YI SYLLABLE ZHURX
+A35A ; [.26B1.0020.0002.A35A] # YI SYLLABLE ZHUR
+A35B ; [.26B2.0020.0002.A35B] # YI SYLLABLE ZHYT
+A35C ; [.26B3.0020.0002.A35C] # YI SYLLABLE ZHYX
+A35D ; [.26B4.0020.0002.A35D] # YI SYLLABLE ZHY
+A35E ; [.26B5.0020.0002.A35E] # YI SYLLABLE ZHYP
+A35F ; [.26B6.0020.0002.A35F] # YI SYLLABLE ZHYRX
+A360 ; [.26B7.0020.0002.A360] # YI SYLLABLE ZHYR
+A361 ; [.26B8.0020.0002.A361] # YI SYLLABLE CHAT
+A362 ; [.26B9.0020.0002.A362] # YI SYLLABLE CHAX
+A363 ; [.26BA.0020.0002.A363] # YI SYLLABLE CHA
+A364 ; [.26BB.0020.0002.A364] # YI SYLLABLE CHAP
+A365 ; [.26BC.0020.0002.A365] # YI SYLLABLE CHUOT
+A366 ; [.26BD.0020.0002.A366] # YI SYLLABLE CHUOX
+A367 ; [.26BE.0020.0002.A367] # YI SYLLABLE CHUO
+A368 ; [.26BF.0020.0002.A368] # YI SYLLABLE CHUOP
+A369 ; [.26C0.0020.0002.A369] # YI SYLLABLE CHOT
+A36A ; [.26C1.0020.0002.A36A] # YI SYLLABLE CHOX
+A36B ; [.26C2.0020.0002.A36B] # YI SYLLABLE CHO
+A36C ; [.26C3.0020.0002.A36C] # YI SYLLABLE CHOP
+A36D ; [.26C4.0020.0002.A36D] # YI SYLLABLE CHET
+A36E ; [.26C5.0020.0002.A36E] # YI SYLLABLE CHEX
+A36F ; [.26C6.0020.0002.A36F] # YI SYLLABLE CHE
+A370 ; [.26C7.0020.0002.A370] # YI SYLLABLE CHEP
+A371 ; [.26C8.0020.0002.A371] # YI SYLLABLE CHUX
+A372 ; [.26C9.0020.0002.A372] # YI SYLLABLE CHU
+A373 ; [.26CA.0020.0002.A373] # YI SYLLABLE CHUP
+A374 ; [.26CB.0020.0002.A374] # YI SYLLABLE CHURX
+A375 ; [.26CC.0020.0002.A375] # YI SYLLABLE CHUR
+A376 ; [.26CD.0020.0002.A376] # YI SYLLABLE CHYT
+A377 ; [.26CE.0020.0002.A377] # YI SYLLABLE CHYX
+A378 ; [.26CF.0020.0002.A378] # YI SYLLABLE CHY
+A379 ; [.26D0.0020.0002.A379] # YI SYLLABLE CHYP
+A37A ; [.26D1.0020.0002.A37A] # YI SYLLABLE CHYRX
+A37B ; [.26D2.0020.0002.A37B] # YI SYLLABLE CHYR
+A37C ; [.26D3.0020.0002.A37C] # YI SYLLABLE RRAX
+A37D ; [.26D4.0020.0002.A37D] # YI SYLLABLE RRA
+A37E ; [.26D5.0020.0002.A37E] # YI SYLLABLE RRUOX
+A37F ; [.26D6.0020.0002.A37F] # YI SYLLABLE RRUO
+A380 ; [.26D7.0020.0002.A380] # YI SYLLABLE RROT
+A381 ; [.26D8.0020.0002.A381] # YI SYLLABLE RROX
+A382 ; [.26D9.0020.0002.A382] # YI SYLLABLE RRO
+A383 ; [.26DA.0020.0002.A383] # YI SYLLABLE RROP
+A384 ; [.26DB.0020.0002.A384] # YI SYLLABLE RRET
+A385 ; [.26DC.0020.0002.A385] # YI SYLLABLE RREX
+A386 ; [.26DD.0020.0002.A386] # YI SYLLABLE RRE
+A387 ; [.26DE.0020.0002.A387] # YI SYLLABLE RREP
+A388 ; [.26DF.0020.0002.A388] # YI SYLLABLE RRUT
+A389 ; [.26E0.0020.0002.A389] # YI SYLLABLE RRUX
+A38A ; [.26E1.0020.0002.A38A] # YI SYLLABLE RRU
+A38B ; [.26E2.0020.0002.A38B] # YI SYLLABLE RRUP
+A38C ; [.26E3.0020.0002.A38C] # YI SYLLABLE RRURX
+A38D ; [.26E4.0020.0002.A38D] # YI SYLLABLE RRUR
+A38E ; [.26E5.0020.0002.A38E] # YI SYLLABLE RRYT
+A38F ; [.26E6.0020.0002.A38F] # YI SYLLABLE RRYX
+A390 ; [.26E7.0020.0002.A390] # YI SYLLABLE RRY
+A391 ; [.26E8.0020.0002.A391] # YI SYLLABLE RRYP
+A392 ; [.26E9.0020.0002.A392] # YI SYLLABLE RRYRX
+A393 ; [.26EA.0020.0002.A393] # YI SYLLABLE RRYR
+A394 ; [.26EB.0020.0002.A394] # YI SYLLABLE NRAT
+A395 ; [.26EC.0020.0002.A395] # YI SYLLABLE NRAX
+A396 ; [.26ED.0020.0002.A396] # YI SYLLABLE NRA
+A397 ; [.26EE.0020.0002.A397] # YI SYLLABLE NRAP
+A398 ; [.26EF.0020.0002.A398] # YI SYLLABLE NROX
+A399 ; [.26F0.0020.0002.A399] # YI SYLLABLE NRO
+A39A ; [.26F1.0020.0002.A39A] # YI SYLLABLE NROP
+A39B ; [.26F2.0020.0002.A39B] # YI SYLLABLE NRET
+A39C ; [.26F3.0020.0002.A39C] # YI SYLLABLE NREX
+A39D ; [.26F4.0020.0002.A39D] # YI SYLLABLE NRE
+A39E ; [.26F5.0020.0002.A39E] # YI SYLLABLE NREP
+A39F ; [.26F6.0020.0002.A39F] # YI SYLLABLE NRUT
+A3A0 ; [.26F7.0020.0002.A3A0] # YI SYLLABLE NRUX
+A3A1 ; [.26F8.0020.0002.A3A1] # YI SYLLABLE NRU
+A3A2 ; [.26F9.0020.0002.A3A2] # YI SYLLABLE NRUP
+A3A3 ; [.26FA.0020.0002.A3A3] # YI SYLLABLE NRURX
+A3A4 ; [.26FB.0020.0002.A3A4] # YI SYLLABLE NRUR
+A3A5 ; [.26FC.0020.0002.A3A5] # YI SYLLABLE NRYT
+A3A6 ; [.26FD.0020.0002.A3A6] # YI SYLLABLE NRYX
+A3A7 ; [.26FE.0020.0002.A3A7] # YI SYLLABLE NRY
+A3A8 ; [.26FF.0020.0002.A3A8] # YI SYLLABLE NRYP
+A3A9 ; [.2700.0020.0002.A3A9] # YI SYLLABLE NRYRX
+A3AA ; [.2701.0020.0002.A3AA] # YI SYLLABLE NRYR
+A3AB ; [.2702.0020.0002.A3AB] # YI SYLLABLE SHAT
+A3AC ; [.2703.0020.0002.A3AC] # YI SYLLABLE SHAX
+A3AD ; [.2704.0020.0002.A3AD] # YI SYLLABLE SHA
+A3AE ; [.2705.0020.0002.A3AE] # YI SYLLABLE SHAP
+A3AF ; [.2706.0020.0002.A3AF] # YI SYLLABLE SHUOX
+A3B0 ; [.2707.0020.0002.A3B0] # YI SYLLABLE SHUO
+A3B1 ; [.2708.0020.0002.A3B1] # YI SYLLABLE SHUOP
+A3B2 ; [.2709.0020.0002.A3B2] # YI SYLLABLE SHOT
+A3B3 ; [.270A.0020.0002.A3B3] # YI SYLLABLE SHOX
+A3B4 ; [.270B.0020.0002.A3B4] # YI SYLLABLE SHO
+A3B5 ; [.270C.0020.0002.A3B5] # YI SYLLABLE SHOP
+A3B6 ; [.270D.0020.0002.A3B6] # YI SYLLABLE SHET
+A3B7 ; [.270E.0020.0002.A3B7] # YI SYLLABLE SHEX
+A3B8 ; [.270F.0020.0002.A3B8] # YI SYLLABLE SHE
+A3B9 ; [.2710.0020.0002.A3B9] # YI SYLLABLE SHEP
+A3BA ; [.2711.0020.0002.A3BA] # YI SYLLABLE SHUT
+A3BB ; [.2712.0020.0002.A3BB] # YI SYLLABLE SHUX
+A3BC ; [.2713.0020.0002.A3BC] # YI SYLLABLE SHU
+A3BD ; [.2714.0020.0002.A3BD] # YI SYLLABLE SHUP
+A3BE ; [.2715.0020.0002.A3BE] # YI SYLLABLE SHURX
+A3BF ; [.2716.0020.0002.A3BF] # YI SYLLABLE SHUR
+A3C0 ; [.2717.0020.0002.A3C0] # YI SYLLABLE SHYT
+A3C1 ; [.2718.0020.0002.A3C1] # YI SYLLABLE SHYX
+A3C2 ; [.2719.0020.0002.A3C2] # YI SYLLABLE SHY
+A3C3 ; [.271A.0020.0002.A3C3] # YI SYLLABLE SHYP
+A3C4 ; [.271B.0020.0002.A3C4] # YI SYLLABLE SHYRX
+A3C5 ; [.271C.0020.0002.A3C5] # YI SYLLABLE SHYR
+A3C6 ; [.271D.0020.0002.A3C6] # YI SYLLABLE RAT
+A3C7 ; [.271E.0020.0002.A3C7] # YI SYLLABLE RAX
+A3C8 ; [.271F.0020.0002.A3C8] # YI SYLLABLE RA
+A3C9 ; [.2720.0020.0002.A3C9] # YI SYLLABLE RAP
+A3CA ; [.2721.0020.0002.A3CA] # YI SYLLABLE RUOX
+A3CB ; [.2722.0020.0002.A3CB] # YI SYLLABLE RUO
+A3CC ; [.2723.0020.0002.A3CC] # YI SYLLABLE RUOP
+A3CD ; [.2724.0020.0002.A3CD] # YI SYLLABLE ROT
+A3CE ; [.2725.0020.0002.A3CE] # YI SYLLABLE ROX
+A3CF ; [.2726.0020.0002.A3CF] # YI SYLLABLE RO
+A3D0 ; [.2727.0020.0002.A3D0] # YI SYLLABLE ROP
+A3D1 ; [.2728.0020.0002.A3D1] # YI SYLLABLE REX
+A3D2 ; [.2729.0020.0002.A3D2] # YI SYLLABLE RE
+A3D3 ; [.272A.0020.0002.A3D3] # YI SYLLABLE REP
+A3D4 ; [.272B.0020.0002.A3D4] # YI SYLLABLE RUT
+A3D5 ; [.272C.0020.0002.A3D5] # YI SYLLABLE RUX
+A3D6 ; [.272D.0020.0002.A3D6] # YI SYLLABLE RU
+A3D7 ; [.272E.0020.0002.A3D7] # YI SYLLABLE RUP
+A3D8 ; [.272F.0020.0002.A3D8] # YI SYLLABLE RURX
+A3D9 ; [.2730.0020.0002.A3D9] # YI SYLLABLE RUR
+A3DA ; [.2731.0020.0002.A3DA] # YI SYLLABLE RYT
+A3DB ; [.2732.0020.0002.A3DB] # YI SYLLABLE RYX
+A3DC ; [.2733.0020.0002.A3DC] # YI SYLLABLE RY
+A3DD ; [.2734.0020.0002.A3DD] # YI SYLLABLE RYP
+A3DE ; [.2735.0020.0002.A3DE] # YI SYLLABLE RYRX
+A3DF ; [.2736.0020.0002.A3DF] # YI SYLLABLE RYR
+A3E0 ; [.2737.0020.0002.A3E0] # YI SYLLABLE JIT
+A3E1 ; [.2738.0020.0002.A3E1] # YI SYLLABLE JIX
+A3E2 ; [.2739.0020.0002.A3E2] # YI SYLLABLE JI
+A3E3 ; [.273A.0020.0002.A3E3] # YI SYLLABLE JIP
+A3E4 ; [.273B.0020.0002.A3E4] # YI SYLLABLE JIET
+A3E5 ; [.273C.0020.0002.A3E5] # YI SYLLABLE JIEX
+A3E6 ; [.273D.0020.0002.A3E6] # YI SYLLABLE JIE
+A3E7 ; [.273E.0020.0002.A3E7] # YI SYLLABLE JIEP
+A3E8 ; [.273F.0020.0002.A3E8] # YI SYLLABLE JUOT
+A3E9 ; [.2740.0020.0002.A3E9] # YI SYLLABLE JUOX
+A3EA ; [.2741.0020.0002.A3EA] # YI SYLLABLE JUO
+A3EB ; [.2742.0020.0002.A3EB] # YI SYLLABLE JUOP
+A3EC ; [.2743.0020.0002.A3EC] # YI SYLLABLE JOT
+A3ED ; [.2744.0020.0002.A3ED] # YI SYLLABLE JOX
+A3EE ; [.2745.0020.0002.A3EE] # YI SYLLABLE JO
+A3EF ; [.2746.0020.0002.A3EF] # YI SYLLABLE JOP
+A3F0 ; [.2747.0020.0002.A3F0] # YI SYLLABLE JUT
+A3F1 ; [.2748.0020.0002.A3F1] # YI SYLLABLE JUX
+A3F2 ; [.2749.0020.0002.A3F2] # YI SYLLABLE JU
+A3F3 ; [.274A.0020.0002.A3F3] # YI SYLLABLE JUP
+A3F4 ; [.274B.0020.0002.A3F4] # YI SYLLABLE JURX
+A3F5 ; [.274C.0020.0002.A3F5] # YI SYLLABLE JUR
+A3F6 ; [.274D.0020.0002.A3F6] # YI SYLLABLE JYT
+A3F7 ; [.274E.0020.0002.A3F7] # YI SYLLABLE JYX
+A3F8 ; [.274F.0020.0002.A3F8] # YI SYLLABLE JY
+A3F9 ; [.2750.0020.0002.A3F9] # YI SYLLABLE JYP
+A3FA ; [.2751.0020.0002.A3FA] # YI SYLLABLE JYRX
+A3FB ; [.2752.0020.0002.A3FB] # YI SYLLABLE JYR
+A3FC ; [.2753.0020.0002.A3FC] # YI SYLLABLE QIT
+A3FD ; [.2754.0020.0002.A3FD] # YI SYLLABLE QIX
+A3FE ; [.2755.0020.0002.A3FE] # YI SYLLABLE QI
+A3FF ; [.2756.0020.0002.A3FF] # YI SYLLABLE QIP
+A400 ; [.2757.0020.0002.A400] # YI SYLLABLE QIET
+A401 ; [.2758.0020.0002.A401] # YI SYLLABLE QIEX
+A402 ; [.2759.0020.0002.A402] # YI SYLLABLE QIE
+A403 ; [.275A.0020.0002.A403] # YI SYLLABLE QIEP
+A404 ; [.275B.0020.0002.A404] # YI SYLLABLE QUOT
+A405 ; [.275C.0020.0002.A405] # YI SYLLABLE QUOX
+A406 ; [.275D.0020.0002.A406] # YI SYLLABLE QUO
+A407 ; [.275E.0020.0002.A407] # YI SYLLABLE QUOP
+A408 ; [.275F.0020.0002.A408] # YI SYLLABLE QOT
+A409 ; [.2760.0020.0002.A409] # YI SYLLABLE QOX
+A40A ; [.2761.0020.0002.A40A] # YI SYLLABLE QO
+A40B ; [.2762.0020.0002.A40B] # YI SYLLABLE QOP
+A40C ; [.2763.0020.0002.A40C] # YI SYLLABLE QUT
+A40D ; [.2764.0020.0002.A40D] # YI SYLLABLE QUX
+A40E ; [.2765.0020.0002.A40E] # YI SYLLABLE QU
+A40F ; [.2766.0020.0002.A40F] # YI SYLLABLE QUP
+A410 ; [.2767.0020.0002.A410] # YI SYLLABLE QURX
+A411 ; [.2768.0020.0002.A411] # YI SYLLABLE QUR
+A412 ; [.2769.0020.0002.A412] # YI SYLLABLE QYT
+A413 ; [.276A.0020.0002.A413] # YI SYLLABLE QYX
+A414 ; [.276B.0020.0002.A414] # YI SYLLABLE QY
+A415 ; [.276C.0020.0002.A415] # YI SYLLABLE QYP
+A416 ; [.276D.0020.0002.A416] # YI SYLLABLE QYRX
+A417 ; [.276E.0020.0002.A417] # YI SYLLABLE QYR
+A418 ; [.276F.0020.0002.A418] # YI SYLLABLE JJIT
+A419 ; [.2770.0020.0002.A419] # YI SYLLABLE JJIX
+A41A ; [.2771.0020.0002.A41A] # YI SYLLABLE JJI
+A41B ; [.2772.0020.0002.A41B] # YI SYLLABLE JJIP
+A41C ; [.2773.0020.0002.A41C] # YI SYLLABLE JJIET
+A41D ; [.2774.0020.0002.A41D] # YI SYLLABLE JJIEX
+A41E ; [.2775.0020.0002.A41E] # YI SYLLABLE JJIE
+A41F ; [.2776.0020.0002.A41F] # YI SYLLABLE JJIEP
+A420 ; [.2777.0020.0002.A420] # YI SYLLABLE JJUOX
+A421 ; [.2778.0020.0002.A421] # YI SYLLABLE JJUO
+A422 ; [.2779.0020.0002.A422] # YI SYLLABLE JJUOP
+A423 ; [.277A.0020.0002.A423] # YI SYLLABLE JJOT
+A424 ; [.277B.0020.0002.A424] # YI SYLLABLE JJOX
+A425 ; [.277C.0020.0002.A425] # YI SYLLABLE JJO
+A426 ; [.277D.0020.0002.A426] # YI SYLLABLE JJOP
+A427 ; [.277E.0020.0002.A427] # YI SYLLABLE JJUT
+A428 ; [.277F.0020.0002.A428] # YI SYLLABLE JJUX
+A429 ; [.2780.0020.0002.A429] # YI SYLLABLE JJU
+A42A ; [.2781.0020.0002.A42A] # YI SYLLABLE JJUP
+A42B ; [.2782.0020.0002.A42B] # YI SYLLABLE JJURX
+A42C ; [.2783.0020.0002.A42C] # YI SYLLABLE JJUR
+A42D ; [.2784.0020.0002.A42D] # YI SYLLABLE JJYT
+A42E ; [.2785.0020.0002.A42E] # YI SYLLABLE JJYX
+A42F ; [.2786.0020.0002.A42F] # YI SYLLABLE JJY
+A430 ; [.2787.0020.0002.A430] # YI SYLLABLE JJYP
+A431 ; [.2788.0020.0002.A431] # YI SYLLABLE NJIT
+A432 ; [.2789.0020.0002.A432] # YI SYLLABLE NJIX
+A433 ; [.278A.0020.0002.A433] # YI SYLLABLE NJI
+A434 ; [.278B.0020.0002.A434] # YI SYLLABLE NJIP
+A435 ; [.278C.0020.0002.A435] # YI SYLLABLE NJIET
+A436 ; [.278D.0020.0002.A436] # YI SYLLABLE NJIEX
+A437 ; [.278E.0020.0002.A437] # YI SYLLABLE NJIE
+A438 ; [.278F.0020.0002.A438] # YI SYLLABLE NJIEP
+A439 ; [.2790.0020.0002.A439] # YI SYLLABLE NJUOX
+A43A ; [.2791.0020.0002.A43A] # YI SYLLABLE NJUO
+A43B ; [.2792.0020.0002.A43B] # YI SYLLABLE NJOT
+A43C ; [.2793.0020.0002.A43C] # YI SYLLABLE NJOX
+A43D ; [.2794.0020.0002.A43D] # YI SYLLABLE NJO
+A43E ; [.2795.0020.0002.A43E] # YI SYLLABLE NJOP
+A43F ; [.2796.0020.0002.A43F] # YI SYLLABLE NJUX
+A440 ; [.2797.0020.0002.A440] # YI SYLLABLE NJU
+A441 ; [.2798.0020.0002.A441] # YI SYLLABLE NJUP
+A442 ; [.2799.0020.0002.A442] # YI SYLLABLE NJURX
+A443 ; [.279A.0020.0002.A443] # YI SYLLABLE NJUR
+A444 ; [.279B.0020.0002.A444] # YI SYLLABLE NJYT
+A445 ; [.279C.0020.0002.A445] # YI SYLLABLE NJYX
+A446 ; [.279D.0020.0002.A446] # YI SYLLABLE NJY
+A447 ; [.279E.0020.0002.A447] # YI SYLLABLE NJYP
+A448 ; [.279F.0020.0002.A448] # YI SYLLABLE NJYRX
+A449 ; [.27A0.0020.0002.A449] # YI SYLLABLE NJYR
+A44A ; [.27A1.0020.0002.A44A] # YI SYLLABLE NYIT
+A44B ; [.27A2.0020.0002.A44B] # YI SYLLABLE NYIX
+A44C ; [.27A3.0020.0002.A44C] # YI SYLLABLE NYI
+A44D ; [.27A4.0020.0002.A44D] # YI SYLLABLE NYIP
+A44E ; [.27A5.0020.0002.A44E] # YI SYLLABLE NYIET
+A44F ; [.27A6.0020.0002.A44F] # YI SYLLABLE NYIEX
+A450 ; [.27A7.0020.0002.A450] # YI SYLLABLE NYIE
+A451 ; [.27A8.0020.0002.A451] # YI SYLLABLE NYIEP
+A452 ; [.27A9.0020.0002.A452] # YI SYLLABLE NYUOX
+A453 ; [.27AA.0020.0002.A453] # YI SYLLABLE NYUO
+A454 ; [.27AB.0020.0002.A454] # YI SYLLABLE NYUOP
+A455 ; [.27AC.0020.0002.A455] # YI SYLLABLE NYOT
+A456 ; [.27AD.0020.0002.A456] # YI SYLLABLE NYOX
+A457 ; [.27AE.0020.0002.A457] # YI SYLLABLE NYO
+A458 ; [.27AF.0020.0002.A458] # YI SYLLABLE NYOP
+A459 ; [.27B0.0020.0002.A459] # YI SYLLABLE NYUT
+A45A ; [.27B1.0020.0002.A45A] # YI SYLLABLE NYUX
+A45B ; [.27B2.0020.0002.A45B] # YI SYLLABLE NYU
+A45C ; [.27B3.0020.0002.A45C] # YI SYLLABLE NYUP
+A45D ; [.27B4.0020.0002.A45D] # YI SYLLABLE XIT
+A45E ; [.27B5.0020.0002.A45E] # YI SYLLABLE XIX
+A45F ; [.27B6.0020.0002.A45F] # YI SYLLABLE XI
+A460 ; [.27B7.0020.0002.A460] # YI SYLLABLE XIP
+A461 ; [.27B8.0020.0002.A461] # YI SYLLABLE XIET
+A462 ; [.27B9.0020.0002.A462] # YI SYLLABLE XIEX
+A463 ; [.27BA.0020.0002.A463] # YI SYLLABLE XIE
+A464 ; [.27BB.0020.0002.A464] # YI SYLLABLE XIEP
+A465 ; [.27BC.0020.0002.A465] # YI SYLLABLE XUOX
+A466 ; [.27BD.0020.0002.A466] # YI SYLLABLE XUO
+A467 ; [.27BE.0020.0002.A467] # YI SYLLABLE XOT
+A468 ; [.27BF.0020.0002.A468] # YI SYLLABLE XOX
+A469 ; [.27C0.0020.0002.A469] # YI SYLLABLE XO
+A46A ; [.27C1.0020.0002.A46A] # YI SYLLABLE XOP
+A46B ; [.27C2.0020.0002.A46B] # YI SYLLABLE XYT
+A46C ; [.27C3.0020.0002.A46C] # YI SYLLABLE XYX
+A46D ; [.27C4.0020.0002.A46D] # YI SYLLABLE XY
+A46E ; [.27C5.0020.0002.A46E] # YI SYLLABLE XYP
+A46F ; [.27C6.0020.0002.A46F] # YI SYLLABLE XYRX
+A470 ; [.27C7.0020.0002.A470] # YI SYLLABLE XYR
+A471 ; [.27C8.0020.0002.A471] # YI SYLLABLE YIT
+A472 ; [.27C9.0020.0002.A472] # YI SYLLABLE YIX
+A473 ; [.27CA.0020.0002.A473] # YI SYLLABLE YI
+A474 ; [.27CB.0020.0002.A474] # YI SYLLABLE YIP
+A475 ; [.27CC.0020.0002.A475] # YI SYLLABLE YIET
+A476 ; [.27CD.0020.0002.A476] # YI SYLLABLE YIEX
+A477 ; [.27CE.0020.0002.A477] # YI SYLLABLE YIE
+A478 ; [.27CF.0020.0002.A478] # YI SYLLABLE YIEP
+A479 ; [.27D0.0020.0002.A479] # YI SYLLABLE YUOT
+A47A ; [.27D1.0020.0002.A47A] # YI SYLLABLE YUOX
+A47B ; [.27D2.0020.0002.A47B] # YI SYLLABLE YUO
+A47C ; [.27D3.0020.0002.A47C] # YI SYLLABLE YUOP
+A47D ; [.27D4.0020.0002.A47D] # YI SYLLABLE YOT
+A47E ; [.27D5.0020.0002.A47E] # YI SYLLABLE YOX
+A47F ; [.27D6.0020.0002.A47F] # YI SYLLABLE YO
+A480 ; [.27D7.0020.0002.A480] # YI SYLLABLE YOP
+A481 ; [.27D8.0020.0002.A481] # YI SYLLABLE YUT
+A482 ; [.27D9.0020.0002.A482] # YI SYLLABLE YUX
+A483 ; [.27DA.0020.0002.A483] # YI SYLLABLE YU
+A484 ; [.27DB.0020.0002.A484] # YI SYLLABLE YUP
+A485 ; [.27DC.0020.0002.A485] # YI SYLLABLE YURX
+A486 ; [.27DD.0020.0002.A486] # YI SYLLABLE YUR
+A487 ; [.27DE.0020.0002.A487] # YI SYLLABLE YYT
+A488 ; [.27DF.0020.0002.A488] # YI SYLLABLE YYX
+A489 ; [.27E0.0020.0002.A489] # YI SYLLABLE YY
+A48A ; [.27E1.0020.0002.A48A] # YI SYLLABLE YYP
+A48B ; [.27E2.0020.0002.A48B] # YI SYLLABLE YYRX
+A48C ; [.27E3.0020.0002.A48C] # YI SYLLABLE YYR
+10300 ; [.27E4.0020.0002.10300] # OLD ITALIC LETTER A
+10301 ; [.27E5.0020.0002.10301] # OLD ITALIC LETTER BE
+10302 ; [.27E6.0020.0002.10302] # OLD ITALIC LETTER KE
+10303 ; [.27E7.0020.0002.10303] # OLD ITALIC LETTER DE
+10304 ; [.27E8.0020.0002.10304] # OLD ITALIC LETTER E
+10305 ; [.27E9.0020.0002.10305] # OLD ITALIC LETTER VE
+10306 ; [.27EA.0020.0002.10306] # OLD ITALIC LETTER ZE
+10307 ; [.27EB.0020.0002.10307] # OLD ITALIC LETTER HE
+10308 ; [.27EC.0020.0002.10308] # OLD ITALIC LETTER THE
+10309 ; [.27ED.0020.0002.10309] # OLD ITALIC LETTER I
+1030A ; [.27EE.0020.0002.1030A] # OLD ITALIC LETTER KA
+1030B ; [.27EF.0020.0002.1030B] # OLD ITALIC LETTER EL
+1030C ; [.27F0.0020.0002.1030C] # OLD ITALIC LETTER EM
+1030D ; [.27F1.0020.0002.1030D] # OLD ITALIC LETTER EN
+1030E ; [.27F2.0020.0002.1030E] # OLD ITALIC LETTER ESH
+1030F ; [.27F3.0020.0002.1030F] # OLD ITALIC LETTER O
+10310 ; [.27F4.0020.0002.10310] # OLD ITALIC LETTER PE
+10311 ; [.27F5.0020.0002.10311] # OLD ITALIC LETTER SHE
+10312 ; [.27F6.0020.0002.10312] # OLD ITALIC LETTER KU
+10313 ; [.27F7.0020.0002.10313] # OLD ITALIC LETTER ER
+10314 ; [.27F8.0020.0002.10314] # OLD ITALIC LETTER ES
+10315 ; [.27F9.0020.0002.10315] # OLD ITALIC LETTER TE
+10316 ; [.27FA.0020.0002.10316] # OLD ITALIC LETTER U
+10317 ; [.27FB.0020.0002.10317] # OLD ITALIC LETTER EKS
+10318 ; [.27FC.0020.0002.10318] # OLD ITALIC LETTER PHE
+10319 ; [.27FD.0020.0002.10319] # OLD ITALIC LETTER KHE
+1031A ; [.27FE.0020.0002.1031A] # OLD ITALIC LETTER EF
+1031B ; [.27FF.0020.0002.1031B] # OLD ITALIC LETTER ERS
+1031C ; [.2800.0020.0002.1031C] # OLD ITALIC LETTER CHE
+1031D ; [.2801.0020.0002.1031D] # OLD ITALIC LETTER II
+1031E ; [.2802.0020.0002.1031E] # OLD ITALIC LETTER UU
+10330 ; [.2803.0020.0002.10330] # GOTHIC LETTER AHSA
+10331 ; [.2804.0020.0002.10331] # GOTHIC LETTER BAIRKAN
+10332 ; [.2805.0020.0002.10332] # GOTHIC LETTER GIBA
+10333 ; [.2806.0020.0002.10333] # GOTHIC LETTER DAGS
+10334 ; [.2807.0020.0002.10334] # GOTHIC LETTER AIHVUS
+10335 ; [.2808.0020.0002.10335] # GOTHIC LETTER QAIRTHRA
+10336 ; [.2809.0020.0002.10336] # GOTHIC LETTER IUJA
+10337 ; [.280A.0020.0002.10337] # GOTHIC LETTER HAGL
+10338 ; [.280B.0020.0002.10338] # GOTHIC LETTER THIUTH
+10339 ; [.280C.0020.0002.10339] # GOTHIC LETTER EIS
+1033A ; [.280D.0020.0002.1033A] # GOTHIC LETTER KUSMA
+1033B ; [.280E.0020.0002.1033B] # GOTHIC LETTER LAGUS
+1033C ; [.280F.0020.0002.1033C] # GOTHIC LETTER MANNA
+1033D ; [.2810.0020.0002.1033D] # GOTHIC LETTER NAUTHS
+1033E ; [.2811.0020.0002.1033E] # GOTHIC LETTER JER
+1033F ; [.2812.0020.0002.1033F] # GOTHIC LETTER URUS
+10340 ; [.2813.0020.0002.10340] # GOTHIC LETTER PAIRTHRA
+10341 ; [.2814.0020.0002.10341] # GOTHIC LETTER NINETY
+10342 ; [.2815.0020.0002.10342] # GOTHIC LETTER RAIDA
+10343 ; [.2816.0020.0002.10343] # GOTHIC LETTER SAUIL
+10344 ; [.2817.0020.0002.10344] # GOTHIC LETTER TEIWS
+10345 ; [.2818.0020.0002.10345] # GOTHIC LETTER WINJA
+10346 ; [.2819.0020.0002.10346] # GOTHIC LETTER FAIHU
+10347 ; [.281A.0020.0002.10347] # GOTHIC LETTER IGGWS
+10348 ; [.281B.0020.0002.10348] # GOTHIC LETTER HWAIR
+10349 ; [.281C.0020.0002.10349] # GOTHIC LETTER OTHAL
+1034A ; [.281D.0020.0002.1034A] # GOTHIC LETTER NINE HUNDRED
+10428 ; [.281E.0020.0002.10428] # DESERET SMALL LETTER LONG I
+10400 ; [.281E.0020.0008.10400] # DESERET CAPITAL LETTER LONG I
+10429 ; [.281F.0020.0002.10429] # DESERET SMALL LETTER LONG E
+10401 ; [.281F.0020.0008.10401] # DESERET CAPITAL LETTER LONG E
+1042A ; [.2820.0020.0002.1042A] # DESERET SMALL LETTER LONG A
+10402 ; [.2820.0020.0008.10402] # DESERET CAPITAL LETTER LONG A
+1042B ; [.2821.0020.0002.1042B] # DESERET SMALL LETTER LONG AH
+10403 ; [.2821.0020.0008.10403] # DESERET CAPITAL LETTER LONG AH
+1042C ; [.2822.0020.0002.1042C] # DESERET SMALL LETTER LONG O
+10404 ; [.2822.0020.0008.10404] # DESERET CAPITAL LETTER LONG O
+1042D ; [.2823.0020.0002.1042D] # DESERET SMALL LETTER LONG OO
+10405 ; [.2823.0020.0008.10405] # DESERET CAPITAL LETTER LONG OO
+1042E ; [.2824.0020.0002.1042E] # DESERET SMALL LETTER SHORT I
+10406 ; [.2824.0020.0008.10406] # DESERET CAPITAL LETTER SHORT I
+1042F ; [.2825.0020.0002.1042F] # DESERET SMALL LETTER SHORT E
+10407 ; [.2825.0020.0008.10407] # DESERET CAPITAL LETTER SHORT E
+10430 ; [.2826.0020.0002.10430] # DESERET SMALL LETTER SHORT A
+10408 ; [.2826.0020.0008.10408] # DESERET CAPITAL LETTER SHORT A
+10431 ; [.2827.0020.0002.10431] # DESERET SMALL LETTER SHORT AH
+10409 ; [.2827.0020.0008.10409] # DESERET CAPITAL LETTER SHORT AH
+10432 ; [.2828.0020.0002.10432] # DESERET SMALL LETTER SHORT O
+1040A ; [.2828.0020.0008.1040A] # DESERET CAPITAL LETTER SHORT O
+10433 ; [.2829.0020.0002.10433] # DESERET SMALL LETTER SHORT OO
+1040B ; [.2829.0020.0008.1040B] # DESERET CAPITAL LETTER SHORT OO
+10434 ; [.282A.0020.0002.10434] # DESERET SMALL LETTER AY
+1040C ; [.282A.0020.0008.1040C] # DESERET CAPITAL LETTER AY
+10435 ; [.282B.0020.0002.10435] # DESERET SMALL LETTER OW
+1040D ; [.282B.0020.0008.1040D] # DESERET CAPITAL LETTER OW
+10436 ; [.282C.0020.0002.10436] # DESERET SMALL LETTER WU
+1040E ; [.282C.0020.0008.1040E] # DESERET CAPITAL LETTER WU
+10437 ; [.282D.0020.0002.10437] # DESERET SMALL LETTER YEE
+1040F ; [.282D.0020.0008.1040F] # DESERET CAPITAL LETTER YEE
+10438 ; [.282E.0020.0002.10438] # DESERET SMALL LETTER H
+10410 ; [.282E.0020.0008.10410] # DESERET CAPITAL LETTER H
+10439 ; [.282F.0020.0002.10439] # DESERET SMALL LETTER PEE
+10411 ; [.282F.0020.0008.10411] # DESERET CAPITAL LETTER PEE
+1043A ; [.2830.0020.0002.1043A] # DESERET SMALL LETTER BEE
+10412 ; [.2830.0020.0008.10412] # DESERET CAPITAL LETTER BEE
+1043B ; [.2831.0020.0002.1043B] # DESERET SMALL LETTER TEE
+10413 ; [.2831.0020.0008.10413] # DESERET CAPITAL LETTER TEE
+1043C ; [.2832.0020.0002.1043C] # DESERET SMALL LETTER DEE
+10414 ; [.2832.0020.0008.10414] # DESERET CAPITAL LETTER DEE
+1043D ; [.2833.0020.0002.1043D] # DESERET SMALL LETTER CHEE
+10415 ; [.2833.0020.0008.10415] # DESERET CAPITAL LETTER CHEE
+1043E ; [.2834.0020.0002.1043E] # DESERET SMALL LETTER JEE
+10416 ; [.2834.0020.0008.10416] # DESERET CAPITAL LETTER JEE
+1043F ; [.2835.0020.0002.1043F] # DESERET SMALL LETTER KAY
+10417 ; [.2835.0020.0008.10417] # DESERET CAPITAL LETTER KAY
+10440 ; [.2836.0020.0002.10440] # DESERET SMALL LETTER GAY
+10418 ; [.2836.0020.0008.10418] # DESERET CAPITAL LETTER GAY
+10441 ; [.2837.0020.0002.10441] # DESERET SMALL LETTER EF
+10419 ; [.2837.0020.0008.10419] # DESERET CAPITAL LETTER EF
+10442 ; [.2838.0020.0002.10442] # DESERET SMALL LETTER VEE
+1041A ; [.2838.0020.0008.1041A] # DESERET CAPITAL LETTER VEE
+10443 ; [.2839.0020.0002.10443] # DESERET SMALL LETTER ETH
+1041B ; [.2839.0020.0008.1041B] # DESERET CAPITAL LETTER ETH
+10444 ; [.283A.0020.0002.10444] # DESERET SMALL LETTER THEE
+1041C ; [.283A.0020.0008.1041C] # DESERET CAPITAL LETTER THEE
+10445 ; [.283B.0020.0002.10445] # DESERET SMALL LETTER ES
+1041D ; [.283B.0020.0008.1041D] # DESERET CAPITAL LETTER ES
+10446 ; [.283C.0020.0002.10446] # DESERET SMALL LETTER ZEE
+1041E ; [.283C.0020.0008.1041E] # DESERET CAPITAL LETTER ZEE
+10447 ; [.283D.0020.0002.10447] # DESERET SMALL LETTER ESH
+1041F ; [.283D.0020.0008.1041F] # DESERET CAPITAL LETTER ESH
+10448 ; [.283E.0020.0002.10448] # DESERET SMALL LETTER ZHEE
+10420 ; [.283E.0020.0008.10420] # DESERET CAPITAL LETTER ZHEE
+10449 ; [.283F.0020.0002.10449] # DESERET SMALL LETTER ER
+10421 ; [.283F.0020.0008.10421] # DESERET CAPITAL LETTER ER
+1044A ; [.2840.0020.0002.1044A] # DESERET SMALL LETTER EL
+10422 ; [.2840.0020.0008.10422] # DESERET CAPITAL LETTER EL
+1044B ; [.2841.0020.0002.1044B] # DESERET SMALL LETTER EM
+10423 ; [.2841.0020.0008.10423] # DESERET CAPITAL LETTER EM
+1044C ; [.2842.0020.0002.1044C] # DESERET SMALL LETTER EN
+10424 ; [.2842.0020.0008.10424] # DESERET CAPITAL LETTER EN
+1044D ; [.2843.0020.0002.1044D] # DESERET SMALL LETTER ENG
+10425 ; [.2843.0020.0008.10425] # DESERET CAPITAL LETTER ENG
+1044E ; [.2844.0020.0002.1044E] # DESERET SMALL LETTER OI
+10426 ; [.2844.0020.0008.10426] # DESERET CAPITAL LETTER OI
+1044F ; [.2845.0020.0002.1044F] # DESERET SMALL LETTER EW
+10427 ; [.2845.0020.0008.10427] # DESERET CAPITAL LETTER EW
+10450 ; [.2846.0020.0002.10450] # SHAVIAN LETTER PEEP
+10451 ; [.2847.0020.0002.10451] # SHAVIAN LETTER TOT
+10452 ; [.2848.0020.0002.10452] # SHAVIAN LETTER KICK
+10453 ; [.2849.0020.0002.10453] # SHAVIAN LETTER FEE
+10454 ; [.284A.0020.0002.10454] # SHAVIAN LETTER THIGH
+10455 ; [.284B.0020.0002.10455] # SHAVIAN LETTER SO
+10456 ; [.284C.0020.0002.10456] # SHAVIAN LETTER SURE
+10457 ; [.284D.0020.0002.10457] # SHAVIAN LETTER CHURCH
+10458 ; [.284E.0020.0002.10458] # SHAVIAN LETTER YEA
+10459 ; [.284F.0020.0002.10459] # SHAVIAN LETTER HUNG
+1045A ; [.2850.0020.0002.1045A] # SHAVIAN LETTER BIB
+1045B ; [.2851.0020.0002.1045B] # SHAVIAN LETTER DEAD
+1045C ; [.2852.0020.0002.1045C] # SHAVIAN LETTER GAG
+1045D ; [.2853.0020.0002.1045D] # SHAVIAN LETTER VOW
+1045E ; [.2854.0020.0002.1045E] # SHAVIAN LETTER THEY
+1045F ; [.2855.0020.0002.1045F] # SHAVIAN LETTER ZOO
+10460 ; [.2856.0020.0002.10460] # SHAVIAN LETTER MEASURE
+10461 ; [.2857.0020.0002.10461] # SHAVIAN LETTER JUDGE
+10462 ; [.2858.0020.0002.10462] # SHAVIAN LETTER WOE
+10463 ; [.2859.0020.0002.10463] # SHAVIAN LETTER HA-HA
+10464 ; [.285A.0020.0002.10464] # SHAVIAN LETTER LOLL
+10465 ; [.285B.0020.0002.10465] # SHAVIAN LETTER MIME
+10466 ; [.285C.0020.0002.10466] # SHAVIAN LETTER IF
+10467 ; [.285D.0020.0002.10467] # SHAVIAN LETTER EGG
+10468 ; [.285E.0020.0002.10468] # SHAVIAN LETTER ASH
+10469 ; [.285F.0020.0002.10469] # SHAVIAN LETTER ADO
+1046A ; [.2860.0020.0002.1046A] # SHAVIAN LETTER ON
+1046B ; [.2861.0020.0002.1046B] # SHAVIAN LETTER WOOL
+1046C ; [.2862.0020.0002.1046C] # SHAVIAN LETTER OUT
+1046D ; [.2863.0020.0002.1046D] # SHAVIAN LETTER AH
+1046E ; [.2864.0020.0002.1046E] # SHAVIAN LETTER ROAR
+1046F ; [.2865.0020.0002.1046F] # SHAVIAN LETTER NUN
+10470 ; [.2866.0020.0002.10470] # SHAVIAN LETTER EAT
+10471 ; [.2867.0020.0002.10471] # SHAVIAN LETTER AGE
+10472 ; [.2868.0020.0002.10472] # SHAVIAN LETTER ICE
+10473 ; [.2869.0020.0002.10473] # SHAVIAN LETTER UP
+10474 ; [.286A.0020.0002.10474] # SHAVIAN LETTER OAK
+10475 ; [.286B.0020.0002.10475] # SHAVIAN LETTER OOZE
+10476 ; [.286C.0020.0002.10476] # SHAVIAN LETTER OIL
+10477 ; [.286D.0020.0002.10477] # SHAVIAN LETTER AWE
+10478 ; [.286E.0020.0002.10478] # SHAVIAN LETTER ARE
+10479 ; [.286F.0020.0002.10479] # SHAVIAN LETTER OR
+1047A ; [.2870.0020.0002.1047A] # SHAVIAN LETTER AIR
+1047B ; [.2871.0020.0002.1047B] # SHAVIAN LETTER ERR
+1047C ; [.2872.0020.0002.1047C] # SHAVIAN LETTER ARRAY
+1047D ; [.2873.0020.0002.1047D] # SHAVIAN LETTER EAR
+1047E ; [.2874.0020.0002.1047E] # SHAVIAN LETTER IAN
+1047F ; [.2875.0020.0002.1047F] # SHAVIAN LETTER YEW
+10480 ; [.2876.0020.0002.10480] # OSMANYA LETTER ALEF
+10481 ; [.2877.0020.0002.10481] # OSMANYA LETTER BA
+10482 ; [.2878.0020.0002.10482] # OSMANYA LETTER TA
+10483 ; [.2879.0020.0002.10483] # OSMANYA LETTER JA
+10484 ; [.287A.0020.0002.10484] # OSMANYA LETTER XA
+10485 ; [.287B.0020.0002.10485] # OSMANYA LETTER KHA
+10486 ; [.287C.0020.0002.10486] # OSMANYA LETTER DEEL
+10487 ; [.287D.0020.0002.10487] # OSMANYA LETTER RA
+10488 ; [.287E.0020.0002.10488] # OSMANYA LETTER SA
+10489 ; [.287F.0020.0002.10489] # OSMANYA LETTER SHIIN
+1048A ; [.2880.0020.0002.1048A] # OSMANYA LETTER DHA
+1048B ; [.2881.0020.0002.1048B] # OSMANYA LETTER CAYN
+1048C ; [.2882.0020.0002.1048C] # OSMANYA LETTER GA
+1048D ; [.2883.0020.0002.1048D] # OSMANYA LETTER FA
+1048E ; [.2884.0020.0002.1048E] # OSMANYA LETTER QAAF
+1048F ; [.2885.0020.0002.1048F] # OSMANYA LETTER KAAF
+10490 ; [.2886.0020.0002.10490] # OSMANYA LETTER LAAN
+10491 ; [.2887.0020.0002.10491] # OSMANYA LETTER MIIN
+10492 ; [.2888.0020.0002.10492] # OSMANYA LETTER NUUN
+10493 ; [.2889.0020.0002.10493] # OSMANYA LETTER WAW
+10494 ; [.288A.0020.0002.10494] # OSMANYA LETTER HA
+10495 ; [.288B.0020.0002.10495] # OSMANYA LETTER YA
+10496 ; [.288C.0020.0002.10496] # OSMANYA LETTER A
+10497 ; [.288D.0020.0002.10497] # OSMANYA LETTER E
+10498 ; [.288E.0020.0002.10498] # OSMANYA LETTER I
+10499 ; [.288F.0020.0002.10499] # OSMANYA LETTER O
+1049A ; [.2890.0020.0002.1049A] # OSMANYA LETTER U
+1049B ; [.2891.0020.0002.1049B] # OSMANYA LETTER AA
+1049C ; [.2892.0020.0002.1049C] # OSMANYA LETTER EE
+1049D ; [.2893.0020.0002.1049D] # OSMANYA LETTER OO
+10000 ; [.2894.0020.0002.10000] # LINEAR B SYLLABLE B008 A
+10001 ; [.2895.0020.0002.10001] # LINEAR B SYLLABLE B038 E
+10002 ; [.2896.0020.0002.10002] # LINEAR B SYLLABLE B028 I
+10003 ; [.2897.0020.0002.10003] # LINEAR B SYLLABLE B061 O
+10004 ; [.2898.0020.0002.10004] # LINEAR B SYLLABLE B010 U
+10005 ; [.2899.0020.0002.10005] # LINEAR B SYLLABLE B001 DA
+10006 ; [.289A.0020.0002.10006] # LINEAR B SYLLABLE B045 DE
+10007 ; [.289B.0020.0002.10007] # LINEAR B SYLLABLE B007 DI
+10008 ; [.289C.0020.0002.10008] # LINEAR B SYLLABLE B014 DO
+10009 ; [.289D.0020.0002.10009] # LINEAR B SYLLABLE B051 DU
+1000A ; [.289E.0020.0002.1000A] # LINEAR B SYLLABLE B057 JA
+1000B ; [.289F.0020.0002.1000B] # LINEAR B SYLLABLE B046 JE
+1000D ; [.28A0.0020.0002.1000D] # LINEAR B SYLLABLE B036 JO
+1000E ; [.28A1.0020.0002.1000E] # LINEAR B SYLLABLE B065 JU
+1000F ; [.28A2.0020.0002.1000F] # LINEAR B SYLLABLE B077 KA
+10010 ; [.28A3.0020.0002.10010] # LINEAR B SYLLABLE B044 KE
+10011 ; [.28A4.0020.0002.10011] # LINEAR B SYLLABLE B067 KI
+10012 ; [.28A5.0020.0002.10012] # LINEAR B SYLLABLE B070 KO
+10013 ; [.28A6.0020.0002.10013] # LINEAR B SYLLABLE B081 KU
+10014 ; [.28A7.0020.0002.10014] # LINEAR B SYLLABLE B080 MA
+10015 ; [.28A8.0020.0002.10015] # LINEAR B SYLLABLE B013 ME
+10016 ; [.28A9.0020.0002.10016] # LINEAR B SYLLABLE B073 MI
+10017 ; [.28AA.0020.0002.10017] # LINEAR B SYLLABLE B015 MO
+10018 ; [.28AB.0020.0002.10018] # LINEAR B SYLLABLE B023 MU
+10019 ; [.28AC.0020.0002.10019] # LINEAR B SYLLABLE B006 NA
+1001A ; [.28AD.0020.0002.1001A] # LINEAR B SYLLABLE B024 NE
+1001B ; [.28AE.0020.0002.1001B] # LINEAR B SYLLABLE B030 NI
+1001C ; [.28AF.0020.0002.1001C] # LINEAR B SYLLABLE B052 NO
+1001D ; [.28B0.0020.0002.1001D] # LINEAR B SYLLABLE B055 NU
+1001E ; [.28B1.0020.0002.1001E] # LINEAR B SYLLABLE B003 PA
+1001F ; [.28B2.0020.0002.1001F] # LINEAR B SYLLABLE B072 PE
+10020 ; [.28B3.0020.0002.10020] # LINEAR B SYLLABLE B039 PI
+10021 ; [.28B4.0020.0002.10021] # LINEAR B SYLLABLE B011 PO
+10022 ; [.28B5.0020.0002.10022] # LINEAR B SYLLABLE B050 PU
+10023 ; [.28B6.0020.0002.10023] # LINEAR B SYLLABLE B016 QA
+10024 ; [.28B7.0020.0002.10024] # LINEAR B SYLLABLE B078 QE
+10025 ; [.28B8.0020.0002.10025] # LINEAR B SYLLABLE B021 QI
+10026 ; [.28B9.0020.0002.10026] # LINEAR B SYLLABLE B032 QO
+10028 ; [.28BA.0020.0002.10028] # LINEAR B SYLLABLE B060 RA
+10029 ; [.28BB.0020.0002.10029] # LINEAR B SYLLABLE B027 RE
+1002A ; [.28BC.0020.0002.1002A] # LINEAR B SYLLABLE B053 RI
+1002B ; [.28BD.0020.0002.1002B] # LINEAR B SYLLABLE B002 RO
+1002C ; [.28BE.0020.0002.1002C] # LINEAR B SYLLABLE B026 RU
+1002D ; [.28BF.0020.0002.1002D] # LINEAR B SYLLABLE B031 SA
+1002E ; [.28C0.0020.0002.1002E] # LINEAR B SYLLABLE B009 SE
+1002F ; [.28C1.0020.0002.1002F] # LINEAR B SYLLABLE B041 SI
+10030 ; [.28C2.0020.0002.10030] # LINEAR B SYLLABLE B012 SO
+10031 ; [.28C3.0020.0002.10031] # LINEAR B SYLLABLE B058 SU
+10032 ; [.28C4.0020.0002.10032] # LINEAR B SYLLABLE B059 TA
+10033 ; [.28C5.0020.0002.10033] # LINEAR B SYLLABLE B004 TE
+10034 ; [.28C6.0020.0002.10034] # LINEAR B SYLLABLE B037 TI
+10035 ; [.28C7.0020.0002.10035] # LINEAR B SYLLABLE B005 TO
+10036 ; [.28C8.0020.0002.10036] # LINEAR B SYLLABLE B069 TU
+10037 ; [.28C9.0020.0002.10037] # LINEAR B SYLLABLE B054 WA
+10038 ; [.28CA.0020.0002.10038] # LINEAR B SYLLABLE B075 WE
+10039 ; [.28CB.0020.0002.10039] # LINEAR B SYLLABLE B040 WI
+1003A ; [.28CC.0020.0002.1003A] # LINEAR B SYLLABLE B042 WO
+1003C ; [.28CD.0020.0002.1003C] # LINEAR B SYLLABLE B017 ZA
+1003D ; [.28CE.0020.0002.1003D] # LINEAR B SYLLABLE B074 ZE
+1003F ; [.28CF.0020.0002.1003F] # LINEAR B SYLLABLE B020 ZO
+10040 ; [.28D0.0020.0002.10040] # LINEAR B SYLLABLE B025 A2
+10041 ; [.28D1.0020.0002.10041] # LINEAR B SYLLABLE B043 A3
+10042 ; [.28D2.0020.0002.10042] # LINEAR B SYLLABLE B085 AU
+10043 ; [.28D3.0020.0002.10043] # LINEAR B SYLLABLE B071 DWE
+10044 ; [.28D4.0020.0002.10044] # LINEAR B SYLLABLE B090 DWO
+10045 ; [.28D5.0020.0002.10045] # LINEAR B SYLLABLE B048 NWA
+10046 ; [.28D6.0020.0002.10046] # LINEAR B SYLLABLE B029 PU2
+10047 ; [.28D7.0020.0002.10047] # LINEAR B SYLLABLE B062 PTE
+10048 ; [.28D8.0020.0002.10048] # LINEAR B SYLLABLE B076 RA2
+10049 ; [.28D9.0020.0002.10049] # LINEAR B SYLLABLE B033 RA3
+1004A ; [.28DA.0020.0002.1004A] # LINEAR B SYLLABLE B068 RO2
+1004B ; [.28DB.0020.0002.1004B] # LINEAR B SYLLABLE B066 TA2
+1004C ; [.28DC.0020.0002.1004C] # LINEAR B SYLLABLE B087 TWE
+1004D ; [.28DD.0020.0002.1004D] # LINEAR B SYLLABLE B091 TWO
+10050 ; [.28DE.0020.0002.10050] # LINEAR B SYMBOL B018
+10051 ; [.28DF.0020.0002.10051] # LINEAR B SYMBOL B019
+10052 ; [.28E0.0020.0002.10052] # LINEAR B SYMBOL B022
+10053 ; [.28E1.0020.0002.10053] # LINEAR B SYMBOL B034
+10054 ; [.28E2.0020.0002.10054] # LINEAR B SYMBOL B047
+10055 ; [.28E3.0020.0002.10055] # LINEAR B SYMBOL B049
+10056 ; [.28E4.0020.0002.10056] # LINEAR B SYMBOL B056
+10057 ; [.28E5.0020.0002.10057] # LINEAR B SYMBOL B063
+10058 ; [.28E6.0020.0002.10058] # LINEAR B SYMBOL B064
+10059 ; [.28E7.0020.0002.10059] # LINEAR B SYMBOL B079
+1005A ; [.28E8.0020.0002.1005A] # LINEAR B SYMBOL B082
+1005B ; [.28E9.0020.0002.1005B] # LINEAR B SYMBOL B083
+1005C ; [.28EA.0020.0002.1005C] # LINEAR B SYMBOL B086
+1005D ; [.28EB.0020.0002.1005D] # LINEAR B SYMBOL B089
+10080 ; [.28EC.0020.0002.10080] # LINEAR B IDEOGRAM B100 MAN
+10081 ; [.28ED.0020.0002.10081] # LINEAR B IDEOGRAM B102 WOMAN
+10082 ; [.28EE.0020.0002.10082] # LINEAR B IDEOGRAM B104 DEER
+10083 ; [.28EF.0020.0002.10083] # LINEAR B IDEOGRAM B105 EQUID
+10084 ; [.28F0.0020.0002.10084] # LINEAR B IDEOGRAM B105F MARE
+10085 ; [.28F1.0020.0002.10085] # LINEAR B IDEOGRAM B105M STALLION
+10086 ; [.28F2.0020.0002.10086] # LINEAR B IDEOGRAM B106F EWE
+10087 ; [.28F3.0020.0002.10087] # LINEAR B IDEOGRAM B106M RAM
+10088 ; [.28F4.0020.0002.10088] # LINEAR B IDEOGRAM B107F SHE-GOAT
+10089 ; [.28F5.0020.0002.10089] # LINEAR B IDEOGRAM B107M HE-GOAT
+1008A ; [.28F6.0020.0002.1008A] # LINEAR B IDEOGRAM B108F SOW
+1008B ; [.28F7.0020.0002.1008B] # LINEAR B IDEOGRAM B108M BOAR
+1008C ; [.28F8.0020.0002.1008C] # LINEAR B IDEOGRAM B109F COW
+1008D ; [.28F9.0020.0002.1008D] # LINEAR B IDEOGRAM B109M BULL
+1008E ; [.28FA.0020.0002.1008E] # LINEAR B IDEOGRAM B120 WHEAT
+1008F ; [.28FB.0020.0002.1008F] # LINEAR B IDEOGRAM B121 BARLEY
+10090 ; [.28FC.0020.0002.10090] # LINEAR B IDEOGRAM B122 OLIVE
+10091 ; [.28FD.0020.0002.10091] # LINEAR B IDEOGRAM B123 SPICE
+10092 ; [.28FE.0020.0002.10092] # LINEAR B IDEOGRAM B125 CYPERUS
+10093 ; [.28FF.0020.0002.10093] # LINEAR B MONOGRAM B127 KAPO
+10094 ; [.2900.0020.0002.10094] # LINEAR B MONOGRAM B128 KANAKO
+10095 ; [.2901.0020.0002.10095] # LINEAR B IDEOGRAM B130 OIL
+10096 ; [.2902.0020.0002.10096] # LINEAR B IDEOGRAM B131 WINE
+10097 ; [.2903.0020.0002.10097] # LINEAR B IDEOGRAM B132
+10098 ; [.2904.0020.0002.10098] # LINEAR B MONOGRAM B133 AREPA
+10099 ; [.2905.0020.0002.10099] # LINEAR B MONOGRAM B135 MERI
+1009A ; [.2906.0020.0002.1009A] # LINEAR B IDEOGRAM B140 BRONZE
+1009B ; [.2907.0020.0002.1009B] # LINEAR B IDEOGRAM B141 GOLD
+1009C ; [.2908.0020.0002.1009C] # LINEAR B IDEOGRAM B142
+1009D ; [.2909.0020.0002.1009D] # LINEAR B IDEOGRAM B145 WOOL
+1009E ; [.290A.0020.0002.1009E] # LINEAR B IDEOGRAM B146
+1009F ; [.290B.0020.0002.1009F] # LINEAR B IDEOGRAM B150
+100A0 ; [.290C.0020.0002.100A0] # LINEAR B IDEOGRAM B151 HORN
+100A1 ; [.290D.0020.0002.100A1] # LINEAR B IDEOGRAM B152
+100A2 ; [.290E.0020.0002.100A2] # LINEAR B IDEOGRAM B153
+100A3 ; [.290F.0020.0002.100A3] # LINEAR B IDEOGRAM B154
+100A4 ; [.2910.0020.0002.100A4] # LINEAR B MONOGRAM B156 TURO2
+100A5 ; [.2911.0020.0002.100A5] # LINEAR B IDEOGRAM B157
+100A6 ; [.2912.0020.0002.100A6] # LINEAR B IDEOGRAM B158
+100A7 ; [.2913.0020.0002.100A7] # LINEAR B IDEOGRAM B159 CLOTH
+100A8 ; [.2914.0020.0002.100A8] # LINEAR B IDEOGRAM B160
+100A9 ; [.2915.0020.0002.100A9] # LINEAR B IDEOGRAM B161
+100AA ; [.2916.0020.0002.100AA] # LINEAR B IDEOGRAM B162 GARMENT
+100AB ; [.2917.0020.0002.100AB] # LINEAR B IDEOGRAM B163 ARMOUR
+100AC ; [.2918.0020.0002.100AC] # LINEAR B IDEOGRAM B164
+100AD ; [.2919.0020.0002.100AD] # LINEAR B IDEOGRAM B165
+100AE ; [.291A.0020.0002.100AE] # LINEAR B IDEOGRAM B166
+100AF ; [.291B.0020.0002.100AF] # LINEAR B IDEOGRAM B167
+100B0 ; [.291C.0020.0002.100B0] # LINEAR B IDEOGRAM B168
+100B1 ; [.291D.0020.0002.100B1] # LINEAR B IDEOGRAM B169
+100B2 ; [.291E.0020.0002.100B2] # LINEAR B IDEOGRAM B170
+100B3 ; [.291F.0020.0002.100B3] # LINEAR B IDEOGRAM B171
+100B4 ; [.2920.0020.0002.100B4] # LINEAR B IDEOGRAM B172
+100B5 ; [.2921.0020.0002.100B5] # LINEAR B IDEOGRAM B173 MONTH
+100B6 ; [.2922.0020.0002.100B6] # LINEAR B IDEOGRAM B174
+100B7 ; [.2923.0020.0002.100B7] # LINEAR B IDEOGRAM B176 TREE
+100B8 ; [.2924.0020.0002.100B8] # LINEAR B IDEOGRAM B177
+100B9 ; [.2925.0020.0002.100B9] # LINEAR B IDEOGRAM B178
+100BA ; [.2926.0020.0002.100BA] # LINEAR B IDEOGRAM B179
+100BB ; [.2927.0020.0002.100BB] # LINEAR B IDEOGRAM B180
+100BC ; [.2928.0020.0002.100BC] # LINEAR B IDEOGRAM B181
+100BD ; [.2929.0020.0002.100BD] # LINEAR B IDEOGRAM B182
+100BE ; [.292A.0020.0002.100BE] # LINEAR B IDEOGRAM B183
+100BF ; [.292B.0020.0002.100BF] # LINEAR B IDEOGRAM B184
+100C0 ; [.292C.0020.0002.100C0] # LINEAR B IDEOGRAM B185
+100C1 ; [.292D.0020.0002.100C1] # LINEAR B IDEOGRAM B189
+100C2 ; [.292E.0020.0002.100C2] # LINEAR B IDEOGRAM B190
+100C3 ; [.292F.0020.0002.100C3] # LINEAR B IDEOGRAM B191 HELMET
+100C4 ; [.2930.0020.0002.100C4] # LINEAR B IDEOGRAM B220 FOOTSTOOL
+100C5 ; [.2931.0020.0002.100C5] # LINEAR B IDEOGRAM B225 BATHTUB
+100C6 ; [.2932.0020.0002.100C6] # LINEAR B IDEOGRAM B230 SPEAR
+100C7 ; [.2933.0020.0002.100C7] # LINEAR B IDEOGRAM B231 ARROW
+100C8 ; [.2934.0020.0002.100C8] # LINEAR B IDEOGRAM B232
+100C9 ; [.2935.0020.0002.100C9] # LINEAR B IDEOGRAM B233 SWORD
+100CA ; [.2936.0020.0002.100CA] # LINEAR B IDEOGRAM B234
+100CB ; [.2937.0020.0002.100CB] # LINEAR B IDEOGRAM B236
+100CC ; [.2938.0020.0002.100CC] # LINEAR B IDEOGRAM B240 WHEELED CHARIOT
+100CD ; [.2939.0020.0002.100CD] # LINEAR B IDEOGRAM B241 CHARIOT
+100CE ; [.293A.0020.0002.100CE] # LINEAR B IDEOGRAM B242 CHARIOT FRAME
+100CF ; [.293B.0020.0002.100CF] # LINEAR B IDEOGRAM B243 WHEEL
+100D0 ; [.293C.0020.0002.100D0] # LINEAR B IDEOGRAM B245
+100D1 ; [.293D.0020.0002.100D1] # LINEAR B IDEOGRAM B246
+100D2 ; [.293E.0020.0002.100D2] # LINEAR B MONOGRAM B247 DIPTE
+100D3 ; [.293F.0020.0002.100D3] # LINEAR B IDEOGRAM B248
+100D4 ; [.2940.0020.0002.100D4] # LINEAR B IDEOGRAM B249
+100D5 ; [.2941.0020.0002.100D5] # LINEAR B IDEOGRAM B251
+100D6 ; [.2942.0020.0002.100D6] # LINEAR B IDEOGRAM B252
+100D7 ; [.2943.0020.0002.100D7] # LINEAR B IDEOGRAM B253
+100D8 ; [.2944.0020.0002.100D8] # LINEAR B IDEOGRAM B254 DART
+100D9 ; [.2945.0020.0002.100D9] # LINEAR B IDEOGRAM B255
+100DA ; [.2946.0020.0002.100DA] # LINEAR B IDEOGRAM B256
+100DB ; [.2947.0020.0002.100DB] # LINEAR B IDEOGRAM B257
+100DC ; [.2948.0020.0002.100DC] # LINEAR B IDEOGRAM B258
+100DD ; [.2949.0020.0002.100DD] # LINEAR B IDEOGRAM B259
+100DE ; [.294A.0020.0002.100DE] # LINEAR B IDEOGRAM VESSEL B155
+100DF ; [.294B.0020.0002.100DF] # LINEAR B IDEOGRAM VESSEL B200
+100E0 ; [.294C.0020.0002.100E0] # LINEAR B IDEOGRAM VESSEL B201
+100E1 ; [.294D.0020.0002.100E1] # LINEAR B IDEOGRAM VESSEL B202
+100E2 ; [.294E.0020.0002.100E2] # LINEAR B IDEOGRAM VESSEL B203
+100E3 ; [.294F.0020.0002.100E3] # LINEAR B IDEOGRAM VESSEL B204
+100E4 ; [.2950.0020.0002.100E4] # LINEAR B IDEOGRAM VESSEL B205
+100E5 ; [.2951.0020.0002.100E5] # LINEAR B IDEOGRAM VESSEL B206
+100E6 ; [.2952.0020.0002.100E6] # LINEAR B IDEOGRAM VESSEL B207
+100E7 ; [.2953.0020.0002.100E7] # LINEAR B IDEOGRAM VESSEL B208
+100E8 ; [.2954.0020.0002.100E8] # LINEAR B IDEOGRAM VESSEL B209
+100E9 ; [.2955.0020.0002.100E9] # LINEAR B IDEOGRAM VESSEL B210
+100EA ; [.2956.0020.0002.100EA] # LINEAR B IDEOGRAM VESSEL B211
+100EB ; [.2957.0020.0002.100EB] # LINEAR B IDEOGRAM VESSEL B212
+100EC ; [.2958.0020.0002.100EC] # LINEAR B IDEOGRAM VESSEL B213
+100ED ; [.2959.0020.0002.100ED] # LINEAR B IDEOGRAM VESSEL B214
+100EE ; [.295A.0020.0002.100EE] # LINEAR B IDEOGRAM VESSEL B215
+100EF ; [.295B.0020.0002.100EF] # LINEAR B IDEOGRAM VESSEL B216
+100F0 ; [.295C.0020.0002.100F0] # LINEAR B IDEOGRAM VESSEL B217
+100F1 ; [.295D.0020.0002.100F1] # LINEAR B IDEOGRAM VESSEL B218
+100F2 ; [.295E.0020.0002.100F2] # LINEAR B IDEOGRAM VESSEL B219
+100F3 ; [.295F.0020.0002.100F3] # LINEAR B IDEOGRAM VESSEL B221
+100F4 ; [.2960.0020.0002.100F4] # LINEAR B IDEOGRAM VESSEL B222
+100F5 ; [.2961.0020.0002.100F5] # LINEAR B IDEOGRAM VESSEL B226
+100F6 ; [.2962.0020.0002.100F6] # LINEAR B IDEOGRAM VESSEL B227
+100F7 ; [.2963.0020.0002.100F7] # LINEAR B IDEOGRAM VESSEL B228
+100F8 ; [.2964.0020.0002.100F8] # LINEAR B IDEOGRAM VESSEL B229
+100F9 ; [.2965.0020.0002.100F9] # LINEAR B IDEOGRAM VESSEL B250
+100FA ; [.2966.0020.0002.100FA] # LINEAR B IDEOGRAM VESSEL B305
+10800 ; [.2967.0020.0002.10800] # CYPRIOT SYLLABLE A
+10801 ; [.2968.0020.0002.10801] # CYPRIOT SYLLABLE E
+10802 ; [.2969.0020.0002.10802] # CYPRIOT SYLLABLE I
+10803 ; [.296A.0020.0002.10803] # CYPRIOT SYLLABLE O
+10804 ; [.296B.0020.0002.10804] # CYPRIOT SYLLABLE U
+10805 ; [.296C.0020.0002.10805] # CYPRIOT SYLLABLE JA
+10808 ; [.296D.0020.0002.10808] # CYPRIOT SYLLABLE JO
+1080A ; [.296E.0020.0002.1080A] # CYPRIOT SYLLABLE KA
+1080B ; [.296F.0020.0002.1080B] # CYPRIOT SYLLABLE KE
+1080C ; [.2970.0020.0002.1080C] # CYPRIOT SYLLABLE KI
+1080D ; [.2971.0020.0002.1080D] # CYPRIOT SYLLABLE KO
+1080E ; [.2972.0020.0002.1080E] # CYPRIOT SYLLABLE KU
+1080F ; [.2973.0020.0002.1080F] # CYPRIOT SYLLABLE LA
+10810 ; [.2974.0020.0002.10810] # CYPRIOT SYLLABLE LE
+10811 ; [.2975.0020.0002.10811] # CYPRIOT SYLLABLE LI
+10812 ; [.2976.0020.0002.10812] # CYPRIOT SYLLABLE LO
+10813 ; [.2977.0020.0002.10813] # CYPRIOT SYLLABLE LU
+10814 ; [.2978.0020.0002.10814] # CYPRIOT SYLLABLE MA
+10815 ; [.2979.0020.0002.10815] # CYPRIOT SYLLABLE ME
+10816 ; [.297A.0020.0002.10816] # CYPRIOT SYLLABLE MI
+10817 ; [.297B.0020.0002.10817] # CYPRIOT SYLLABLE MO
+10818 ; [.297C.0020.0002.10818] # CYPRIOT SYLLABLE MU
+10819 ; [.297D.0020.0002.10819] # CYPRIOT SYLLABLE NA
+1081A ; [.297E.0020.0002.1081A] # CYPRIOT SYLLABLE NE
+1081B ; [.297F.0020.0002.1081B] # CYPRIOT SYLLABLE NI
+1081C ; [.2980.0020.0002.1081C] # CYPRIOT SYLLABLE NO
+1081D ; [.2981.0020.0002.1081D] # CYPRIOT SYLLABLE NU
+1081E ; [.2982.0020.0002.1081E] # CYPRIOT SYLLABLE PA
+1081F ; [.2983.0020.0002.1081F] # CYPRIOT SYLLABLE PE
+10820 ; [.2984.0020.0002.10820] # CYPRIOT SYLLABLE PI
+10821 ; [.2985.0020.0002.10821] # CYPRIOT SYLLABLE PO
+10822 ; [.2986.0020.0002.10822] # CYPRIOT SYLLABLE PU
+10823 ; [.2987.0020.0002.10823] # CYPRIOT SYLLABLE RA
+10824 ; [.2988.0020.0002.10824] # CYPRIOT SYLLABLE RE
+10825 ; [.2989.0020.0002.10825] # CYPRIOT SYLLABLE RI
+10826 ; [.298A.0020.0002.10826] # CYPRIOT SYLLABLE RO
+10827 ; [.298B.0020.0002.10827] # CYPRIOT SYLLABLE RU
+10828 ; [.298C.0020.0002.10828] # CYPRIOT SYLLABLE SA
+10829 ; [.298D.0020.0002.10829] # CYPRIOT SYLLABLE SE
+1082A ; [.298E.0020.0002.1082A] # CYPRIOT SYLLABLE SI
+1082B ; [.298F.0020.0002.1082B] # CYPRIOT SYLLABLE SO
+1082C ; [.2990.0020.0002.1082C] # CYPRIOT SYLLABLE SU
+1082D ; [.2991.0020.0002.1082D] # CYPRIOT SYLLABLE TA
+1082E ; [.2992.0020.0002.1082E] # CYPRIOT SYLLABLE TE
+1082F ; [.2993.0020.0002.1082F] # CYPRIOT SYLLABLE TI
+10830 ; [.2994.0020.0002.10830] # CYPRIOT SYLLABLE TO
+10831 ; [.2995.0020.0002.10831] # CYPRIOT SYLLABLE TU
+10832 ; [.2996.0020.0002.10832] # CYPRIOT SYLLABLE WA
+10833 ; [.2997.0020.0002.10833] # CYPRIOT SYLLABLE WE
+10834 ; [.2998.0020.0002.10834] # CYPRIOT SYLLABLE WI
+10835 ; [.2999.0020.0002.10835] # CYPRIOT SYLLABLE WO
+10837 ; [.299A.0020.0002.10837] # CYPRIOT SYLLABLE XA
+10838 ; [.299B.0020.0002.10838] # CYPRIOT SYLLABLE XE
+1083C ; [.299C.0020.0002.1083C] # CYPRIOT SYLLABLE ZA
+1083F ; [.299D.0020.0002.1083F] # CYPRIOT SYLLABLE ZO
+10380 ; [.299E.0020.0002.10380] # UGARITIC LETTER ALPA
+10381 ; [.299F.0020.0002.10381] # UGARITIC LETTER BETA
+10382 ; [.29A0.0020.0002.10382] # UGARITIC LETTER GAMLA
+10383 ; [.29A1.0020.0002.10383] # UGARITIC LETTER KHA
+10384 ; [.29A2.0020.0002.10384] # UGARITIC LETTER DELTA
+10385 ; [.29A3.0020.0002.10385] # UGARITIC LETTER HO
+10386 ; [.29A4.0020.0002.10386] # UGARITIC LETTER WO
+10387 ; [.29A5.0020.0002.10387] # UGARITIC LETTER ZETA
+10388 ; [.29A6.0020.0002.10388] # UGARITIC LETTER HOTA
+10389 ; [.29A7.0020.0002.10389] # UGARITIC LETTER TET
+1038A ; [.29A8.0020.0002.1038A] # UGARITIC LETTER YOD
+1038B ; [.29A9.0020.0002.1038B] # UGARITIC LETTER KAF
+1038C ; [.29AA.0020.0002.1038C] # UGARITIC LETTER SHIN
+1038D ; [.29AB.0020.0002.1038D] # UGARITIC LETTER LAMDA
+1038E ; [.29AC.0020.0002.1038E] # UGARITIC LETTER MEM
+1038F ; [.29AD.0020.0002.1038F] # UGARITIC LETTER DHAL
+10390 ; [.29AE.0020.0002.10390] # UGARITIC LETTER NUN
+10391 ; [.29AF.0020.0002.10391] # UGARITIC LETTER ZU
+10392 ; [.29B0.0020.0002.10392] # UGARITIC LETTER SAMKA
+10393 ; [.29B1.0020.0002.10393] # UGARITIC LETTER AIN
+10394 ; [.29B2.0020.0002.10394] # UGARITIC LETTER PU
+10395 ; [.29B3.0020.0002.10395] # UGARITIC LETTER SADE
+10396 ; [.29B4.0020.0002.10396] # UGARITIC LETTER QOPA
+10397 ; [.29B5.0020.0002.10397] # UGARITIC LETTER RASHA
+10398 ; [.29B6.0020.0002.10398] # UGARITIC LETTER THANNA
+10399 ; [.29B7.0020.0002.10399] # UGARITIC LETTER GHAIN
+1039A ; [.29B8.0020.0002.1039A] # UGARITIC LETTER TO
+1039B ; [.29B9.0020.0002.1039B] # UGARITIC LETTER I
+1039C ; [.29BA.0020.0002.1039C] # UGARITIC LETTER U
+1039D ; [.29BB.0020.0002.1039D] # UGARITIC LETTER SSU
+103A0 ; [.29BC.0020.0002.103A0] # OLD PERSIAN SIGN A
+103A1 ; [.29BD.0020.0002.103A1] # OLD PERSIAN SIGN I
+103A2 ; [.29BE.0020.0002.103A2] # OLD PERSIAN SIGN U
+103A3 ; [.29BF.0020.0002.103A3] # OLD PERSIAN SIGN KA
+103A4 ; [.29C0.0020.0002.103A4] # OLD PERSIAN SIGN KU
+103A5 ; [.29C1.0020.0002.103A5] # OLD PERSIAN SIGN GA
+103A6 ; [.29C2.0020.0002.103A6] # OLD PERSIAN SIGN GU
+103A7 ; [.29C3.0020.0002.103A7] # OLD PERSIAN SIGN XA
+103A8 ; [.29C4.0020.0002.103A8] # OLD PERSIAN SIGN CA
+103A9 ; [.29C5.0020.0002.103A9] # OLD PERSIAN SIGN JA
+103AA ; [.29C6.0020.0002.103AA] # OLD PERSIAN SIGN JI
+103AB ; [.29C7.0020.0002.103AB] # OLD PERSIAN SIGN TA
+103AC ; [.29C8.0020.0002.103AC] # OLD PERSIAN SIGN TU
+103AD ; [.29C9.0020.0002.103AD] # OLD PERSIAN SIGN DA
+103AE ; [.29CA.0020.0002.103AE] # OLD PERSIAN SIGN DI
+103AF ; [.29CB.0020.0002.103AF] # OLD PERSIAN SIGN DU
+103B0 ; [.29CC.0020.0002.103B0] # OLD PERSIAN SIGN THA
+103B1 ; [.29CD.0020.0002.103B1] # OLD PERSIAN SIGN PA
+103B2 ; [.29CE.0020.0002.103B2] # OLD PERSIAN SIGN BA
+103B3 ; [.29CF.0020.0002.103B3] # OLD PERSIAN SIGN FA
+103B4 ; [.29D0.0020.0002.103B4] # OLD PERSIAN SIGN NA
+103B5 ; [.29D1.0020.0002.103B5] # OLD PERSIAN SIGN NU
+103B6 ; [.29D2.0020.0002.103B6] # OLD PERSIAN SIGN MA
+103B7 ; [.29D3.0020.0002.103B7] # OLD PERSIAN SIGN MI
+103B8 ; [.29D4.0020.0002.103B8] # OLD PERSIAN SIGN MU
+103B9 ; [.29D5.0020.0002.103B9] # OLD PERSIAN SIGN YA
+103BA ; [.29D6.0020.0002.103BA] # OLD PERSIAN SIGN VA
+103BB ; [.29D7.0020.0002.103BB] # OLD PERSIAN SIGN VI
+103BC ; [.29D8.0020.0002.103BC] # OLD PERSIAN SIGN RA
+103BD ; [.29D9.0020.0002.103BD] # OLD PERSIAN SIGN RU
+103BE ; [.29DA.0020.0002.103BE] # OLD PERSIAN SIGN LA
+103BF ; [.29DB.0020.0002.103BF] # OLD PERSIAN SIGN SA
+103C0 ; [.29DC.0020.0002.103C0] # OLD PERSIAN SIGN ZA
+103C1 ; [.29DD.0020.0002.103C1] # OLD PERSIAN SIGN SHA
+103C2 ; [.29DE.0020.0002.103C2] # OLD PERSIAN SIGN SSA
+103C3 ; [.29DF.0020.0002.103C3] # OLD PERSIAN SIGN HA
+103C8 ; [.29E0.0020.0002.103C8] # OLD PERSIAN SIGN AURAMAZDAA
+103C9 ; [.29E1.0020.0002.103C9] # OLD PERSIAN SIGN AURAMAZDAA-2
+103CA ; [.29E2.0020.0002.103CA] # OLD PERSIAN SIGN AURAMAZDAAHA
+103CB ; [.29E3.0020.0002.103CB] # OLD PERSIAN SIGN XSHAAYATHIYA
+103CC ; [.29E4.0020.0002.103CC] # OLD PERSIAN SIGN DAHYAAUSH
+103CD ; [.29E5.0020.0002.103CD] # OLD PERSIAN SIGN DAHYAAUSH-2
+103CE ; [.29E6.0020.0002.103CE] # OLD PERSIAN SIGN BAGA
+103CF ; [.29E7.0020.0002.103CF] # OLD PERSIAN SIGN BUUMISH
+12000 ; [.29E8.0020.0002.12000] # CUNEIFORM SIGN A
+12001 ; [.29E9.0020.0002.12001] # CUNEIFORM SIGN A TIMES A
+12002 ; [.29EA.0020.0002.12002] # CUNEIFORM SIGN A TIMES BAD
+12003 ; [.29EB.0020.0002.12003] # CUNEIFORM SIGN A TIMES GAN2 TENU
+12004 ; [.29EC.0020.0002.12004] # CUNEIFORM SIGN A TIMES HA
+12005 ; [.29ED.0020.0002.12005] # CUNEIFORM SIGN A TIMES IGI
+12006 ; [.29EE.0020.0002.12006] # CUNEIFORM SIGN A TIMES LAGAR GUNU
+12007 ; [.29EF.0020.0002.12007] # CUNEIFORM SIGN A TIMES MUSH
+12008 ; [.29F0.0020.0002.12008] # CUNEIFORM SIGN A TIMES SAG
+12009 ; [.29F1.0020.0002.12009] # CUNEIFORM SIGN A2
+1200A ; [.29F2.0020.0002.1200A] # CUNEIFORM SIGN AB
+1200B ; [.29F3.0020.0002.1200B] # CUNEIFORM SIGN AB TIMES ASH2
+1200C ; [.29F4.0020.0002.1200C] # CUNEIFORM SIGN AB TIMES DUN3 GUNU
+1200D ; [.29F5.0020.0002.1200D] # CUNEIFORM SIGN AB TIMES GAL
+1200E ; [.29F6.0020.0002.1200E] # CUNEIFORM SIGN AB TIMES GAN2 TENU
+1200F ; [.29F7.0020.0002.1200F] # CUNEIFORM SIGN AB TIMES HA
+12010 ; [.29F8.0020.0002.12010] # CUNEIFORM SIGN AB TIMES IGI GUNU
+12011 ; [.29F9.0020.0002.12011] # CUNEIFORM SIGN AB TIMES IMIN
+12012 ; [.29FA.0020.0002.12012] # CUNEIFORM SIGN AB TIMES LAGAB
+12013 ; [.29FB.0020.0002.12013] # CUNEIFORM SIGN AB TIMES SHESH
+12014 ; [.29FC.0020.0002.12014] # CUNEIFORM SIGN AB TIMES U PLUS U PLUS U
+12015 ; [.29FD.0020.0002.12015] # CUNEIFORM SIGN AB GUNU
+12016 ; [.29FE.0020.0002.12016] # CUNEIFORM SIGN AB2
+12017 ; [.29FF.0020.0002.12017] # CUNEIFORM SIGN AB2 TIMES BALAG
+12018 ; [.2A00.0020.0002.12018] # CUNEIFORM SIGN AB2 TIMES GAN2 TENU
+12019 ; [.2A01.0020.0002.12019] # CUNEIFORM SIGN AB2 TIMES ME PLUS EN
+1201A ; [.2A02.0020.0002.1201A] # CUNEIFORM SIGN AB2 TIMES SHA3
+1201B ; [.2A03.0020.0002.1201B] # CUNEIFORM SIGN AB2 TIMES TAK4
+1201C ; [.2A04.0020.0002.1201C] # CUNEIFORM SIGN AD
+1201D ; [.2A05.0020.0002.1201D] # CUNEIFORM SIGN AK
+1201E ; [.2A06.0020.0002.1201E] # CUNEIFORM SIGN AK TIMES ERIN2
+1201F ; [.2A07.0020.0002.1201F] # CUNEIFORM SIGN AK TIMES SHITA PLUS GISH
+12020 ; [.2A08.0020.0002.12020] # CUNEIFORM SIGN AL
+12021 ; [.2A09.0020.0002.12021] # CUNEIFORM SIGN AL TIMES AL
+12022 ; [.2A0A.0020.0002.12022] # CUNEIFORM SIGN AL TIMES DIM2
+12023 ; [.2A0B.0020.0002.12023] # CUNEIFORM SIGN AL TIMES GISH
+12024 ; [.2A0C.0020.0002.12024] # CUNEIFORM SIGN AL TIMES HA
+12025 ; [.2A0D.0020.0002.12025] # CUNEIFORM SIGN AL TIMES KAD3
+12026 ; [.2A0E.0020.0002.12026] # CUNEIFORM SIGN AL TIMES KI
+12027 ; [.2A0F.0020.0002.12027] # CUNEIFORM SIGN AL TIMES SHE
+12028 ; [.2A10.0020.0002.12028] # CUNEIFORM SIGN AL TIMES USH
+12029 ; [.2A11.0020.0002.12029] # CUNEIFORM SIGN ALAN
+1202A ; [.2A12.0020.0002.1202A] # CUNEIFORM SIGN ALEPH
+1202B ; [.2A13.0020.0002.1202B] # CUNEIFORM SIGN AMAR
+1202C ; [.2A14.0020.0002.1202C] # CUNEIFORM SIGN AMAR TIMES SHE
+1202D ; [.2A15.0020.0002.1202D] # CUNEIFORM SIGN AN
+1202E ; [.2A16.0020.0002.1202E] # CUNEIFORM SIGN AN OVER AN
+1202F ; [.2A17.0020.0002.1202F] # CUNEIFORM SIGN AN THREE TIMES
+12030 ; [.2A18.0020.0002.12030] # CUNEIFORM SIGN AN PLUS NAGA OPPOSING AN PLUS NAGA
+12031 ; [.2A19.0020.0002.12031] # CUNEIFORM SIGN AN PLUS NAGA SQUARED
+12032 ; [.2A1A.0020.0002.12032] # CUNEIFORM SIGN ANSHE
+12033 ; [.2A1B.0020.0002.12033] # CUNEIFORM SIGN APIN
+12034 ; [.2A1C.0020.0002.12034] # CUNEIFORM SIGN ARAD
+12035 ; [.2A1D.0020.0002.12035] # CUNEIFORM SIGN ARAD TIMES KUR
+12036 ; [.2A1E.0020.0002.12036] # CUNEIFORM SIGN ARKAB
+12037 ; [.2A1F.0020.0002.12037] # CUNEIFORM SIGN ASAL2
+12038 ; [.2A20.0020.0002.12038] # CUNEIFORM SIGN ASH
+12039 ; [.2A21.0020.0002.12039] # CUNEIFORM SIGN ASH ZIDA TENU
+1203A ; [.2A22.0020.0002.1203A] # CUNEIFORM SIGN ASH KABA TENU
+1203B ; [.2A23.0020.0002.1203B] # CUNEIFORM SIGN ASH OVER ASH TUG2 OVER TUG2 TUG2 OVER TUG2 PAP
+1203C ; [.2A24.0020.0002.1203C] # CUNEIFORM SIGN ASH OVER ASH OVER ASH
+1203D ; [.2A25.0020.0002.1203D] # CUNEIFORM SIGN ASH OVER ASH OVER ASH CROSSING ASH OVER ASH OVER ASH
+1203E ; [.2A26.0020.0002.1203E] # CUNEIFORM SIGN ASH2
+1203F ; [.2A27.0020.0002.1203F] # CUNEIFORM SIGN ASHGAB
+12040 ; [.2A28.0020.0002.12040] # CUNEIFORM SIGN BA
+12041 ; [.2A29.0020.0002.12041] # CUNEIFORM SIGN BAD
+12042 ; [.2A2A.0020.0002.12042] # CUNEIFORM SIGN BAG3
+12043 ; [.2A2B.0020.0002.12043] # CUNEIFORM SIGN BAHAR2
+12044 ; [.2A2C.0020.0002.12044] # CUNEIFORM SIGN BAL
+12045 ; [.2A2D.0020.0002.12045] # CUNEIFORM SIGN BAL OVER BAL
+12046 ; [.2A2E.0020.0002.12046] # CUNEIFORM SIGN BALAG
+12047 ; [.2A2F.0020.0002.12047] # CUNEIFORM SIGN BAR
+12048 ; [.2A30.0020.0002.12048] # CUNEIFORM SIGN BARA2
+12049 ; [.2A31.0020.0002.12049] # CUNEIFORM SIGN BI
+1204A ; [.2A32.0020.0002.1204A] # CUNEIFORM SIGN BI TIMES A
+1204B ; [.2A33.0020.0002.1204B] # CUNEIFORM SIGN BI TIMES GAR
+1204C ; [.2A34.0020.0002.1204C] # CUNEIFORM SIGN BI TIMES IGI GUNU
+1204D ; [.2A35.0020.0002.1204D] # CUNEIFORM SIGN BU
+1204E ; [.2A36.0020.0002.1204E] # CUNEIFORM SIGN BU OVER BU AB
+1204F ; [.2A37.0020.0002.1204F] # CUNEIFORM SIGN BU OVER BU UN
+12050 ; [.2A38.0020.0002.12050] # CUNEIFORM SIGN BU CROSSING BU
+12051 ; [.2A39.0020.0002.12051] # CUNEIFORM SIGN BULUG
+12052 ; [.2A3A.0020.0002.12052] # CUNEIFORM SIGN BULUG OVER BULUG
+12053 ; [.2A3B.0020.0002.12053] # CUNEIFORM SIGN BUR
+12054 ; [.2A3C.0020.0002.12054] # CUNEIFORM SIGN BUR2
+12055 ; [.2A3D.0020.0002.12055] # CUNEIFORM SIGN DA
+12056 ; [.2A3E.0020.0002.12056] # CUNEIFORM SIGN DAG
+12057 ; [.2A3F.0020.0002.12057] # CUNEIFORM SIGN DAG KISIM5 TIMES A PLUS MASH
+12058 ; [.2A40.0020.0002.12058] # CUNEIFORM SIGN DAG KISIM5 TIMES AMAR
+12059 ; [.2A41.0020.0002.12059] # CUNEIFORM SIGN DAG KISIM5 TIMES BALAG
+1205A ; [.2A42.0020.0002.1205A] # CUNEIFORM SIGN DAG KISIM5 TIMES BI
+1205B ; [.2A43.0020.0002.1205B] # CUNEIFORM SIGN DAG KISIM5 TIMES GA
+1205C ; [.2A44.0020.0002.1205C] # CUNEIFORM SIGN DAG KISIM5 TIMES GA PLUS MASH
+1205D ; [.2A45.0020.0002.1205D] # CUNEIFORM SIGN DAG KISIM5 TIMES GI
+1205E ; [.2A46.0020.0002.1205E] # CUNEIFORM SIGN DAG KISIM5 TIMES GIR2
+1205F ; [.2A47.0020.0002.1205F] # CUNEIFORM SIGN DAG KISIM5 TIMES GUD
+12060 ; [.2A48.0020.0002.12060] # CUNEIFORM SIGN DAG KISIM5 TIMES HA
+12061 ; [.2A49.0020.0002.12061] # CUNEIFORM SIGN DAG KISIM5 TIMES IR
+12062 ; [.2A4A.0020.0002.12062] # CUNEIFORM SIGN DAG KISIM5 TIMES IR PLUS LU
+12063 ; [.2A4B.0020.0002.12063] # CUNEIFORM SIGN DAG KISIM5 TIMES KAK
+12064 ; [.2A4C.0020.0002.12064] # CUNEIFORM SIGN DAG KISIM5 TIMES LA
+12065 ; [.2A4D.0020.0002.12065] # CUNEIFORM SIGN DAG KISIM5 TIMES LU
+12066 ; [.2A4E.0020.0002.12066] # CUNEIFORM SIGN DAG KISIM5 TIMES LU PLUS MASH2
+12067 ; [.2A4F.0020.0002.12067] # CUNEIFORM SIGN DAG KISIM5 TIMES LUM
+12068 ; [.2A50.0020.0002.12068] # CUNEIFORM SIGN DAG KISIM5 TIMES NE
+12069 ; [.2A51.0020.0002.12069] # CUNEIFORM SIGN DAG KISIM5 TIMES PAP PLUS PAP
+1206A ; [.2A52.0020.0002.1206A] # CUNEIFORM SIGN DAG KISIM5 TIMES SI
+1206B ; [.2A53.0020.0002.1206B] # CUNEIFORM SIGN DAG KISIM5 TIMES TAK4
+1206C ; [.2A54.0020.0002.1206C] # CUNEIFORM SIGN DAG KISIM5 TIMES U2 PLUS GIR2
+1206D ; [.2A55.0020.0002.1206D] # CUNEIFORM SIGN DAG KISIM5 TIMES USH
+1206E ; [.2A56.0020.0002.1206E] # CUNEIFORM SIGN DAM
+1206F ; [.2A57.0020.0002.1206F] # CUNEIFORM SIGN DAR
+12070 ; [.2A58.0020.0002.12070] # CUNEIFORM SIGN DARA3
+12071 ; [.2A59.0020.0002.12071] # CUNEIFORM SIGN DARA4
+12072 ; [.2A5A.0020.0002.12072] # CUNEIFORM SIGN DI
+12073 ; [.2A5B.0020.0002.12073] # CUNEIFORM SIGN DIB
+12074 ; [.2A5C.0020.0002.12074] # CUNEIFORM SIGN DIM
+12075 ; [.2A5D.0020.0002.12075] # CUNEIFORM SIGN DIM TIMES SHE
+12076 ; [.2A5E.0020.0002.12076] # CUNEIFORM SIGN DIM2
+12077 ; [.2A5F.0020.0002.12077] # CUNEIFORM SIGN DIN
+12078 ; [.2A60.0020.0002.12078] # CUNEIFORM SIGN DIN KASKAL U GUNU DISH
+12079 ; [.2A61.0020.0002.12079] # CUNEIFORM SIGN DISH
+1207A ; [.2A62.0020.0002.1207A] # CUNEIFORM SIGN DU
+1207B ; [.2A63.0020.0002.1207B] # CUNEIFORM SIGN DU OVER DU
+1207C ; [.2A64.0020.0002.1207C] # CUNEIFORM SIGN DU GUNU
+1207D ; [.2A65.0020.0002.1207D] # CUNEIFORM SIGN DU SHESHIG
+1207E ; [.2A66.0020.0002.1207E] # CUNEIFORM SIGN DUB
+1207F ; [.2A67.0020.0002.1207F] # CUNEIFORM SIGN DUB TIMES ESH2
+12080 ; [.2A68.0020.0002.12080] # CUNEIFORM SIGN DUB2
+12081 ; [.2A69.0020.0002.12081] # CUNEIFORM SIGN DUG
+12082 ; [.2A6A.0020.0002.12082] # CUNEIFORM SIGN DUGUD
+12083 ; [.2A6B.0020.0002.12083] # CUNEIFORM SIGN DUH
+12084 ; [.2A6C.0020.0002.12084] # CUNEIFORM SIGN DUN
+12085 ; [.2A6D.0020.0002.12085] # CUNEIFORM SIGN DUN3
+12086 ; [.2A6E.0020.0002.12086] # CUNEIFORM SIGN DUN3 GUNU
+12087 ; [.2A6F.0020.0002.12087] # CUNEIFORM SIGN DUN3 GUNU GUNU
+12088 ; [.2A70.0020.0002.12088] # CUNEIFORM SIGN DUN4
+12089 ; [.2A71.0020.0002.12089] # CUNEIFORM SIGN DUR2
+1208A ; [.2A72.0020.0002.1208A] # CUNEIFORM SIGN E
+1208B ; [.2A73.0020.0002.1208B] # CUNEIFORM SIGN E TIMES PAP
+1208C ; [.2A74.0020.0002.1208C] # CUNEIFORM SIGN E OVER E NUN OVER NUN
+1208D ; [.2A75.0020.0002.1208D] # CUNEIFORM SIGN E2
+1208E ; [.2A76.0020.0002.1208E] # CUNEIFORM SIGN E2 TIMES A PLUS HA PLUS DA
+1208F ; [.2A77.0020.0002.1208F] # CUNEIFORM SIGN E2 TIMES GAR
+12090 ; [.2A78.0020.0002.12090] # CUNEIFORM SIGN E2 TIMES MI
+12091 ; [.2A79.0020.0002.12091] # CUNEIFORM SIGN E2 TIMES SAL
+12092 ; [.2A7A.0020.0002.12092] # CUNEIFORM SIGN E2 TIMES SHE
+12093 ; [.2A7B.0020.0002.12093] # CUNEIFORM SIGN E2 TIMES U
+12094 ; [.2A7C.0020.0002.12094] # CUNEIFORM SIGN EDIN
+12095 ; [.2A7D.0020.0002.12095] # CUNEIFORM SIGN EGIR
+12096 ; [.2A7E.0020.0002.12096] # CUNEIFORM SIGN EL
+12097 ; [.2A7F.0020.0002.12097] # CUNEIFORM SIGN EN
+12098 ; [.2A80.0020.0002.12098] # CUNEIFORM SIGN EN TIMES GAN2
+12099 ; [.2A81.0020.0002.12099] # CUNEIFORM SIGN EN TIMES GAN2 TENU
+1209A ; [.2A82.0020.0002.1209A] # CUNEIFORM SIGN EN TIMES ME
+1209B ; [.2A83.0020.0002.1209B] # CUNEIFORM SIGN EN CROSSING EN
+1209C ; [.2A84.0020.0002.1209C] # CUNEIFORM SIGN EN OPPOSING EN
+1209D ; [.2A85.0020.0002.1209D] # CUNEIFORM SIGN EN SQUARED
+1209E ; [.2A86.0020.0002.1209E] # CUNEIFORM SIGN EREN
+1209F ; [.2A87.0020.0002.1209F] # CUNEIFORM SIGN ERIN2
+120A0 ; [.2A88.0020.0002.120A0] # CUNEIFORM SIGN ESH2
+120A1 ; [.2A89.0020.0002.120A1] # CUNEIFORM SIGN EZEN
+120A2 ; [.2A8A.0020.0002.120A2] # CUNEIFORM SIGN EZEN TIMES A
+120A3 ; [.2A8B.0020.0002.120A3] # CUNEIFORM SIGN EZEN TIMES A PLUS LAL
+120A4 ; [.2A8C.0020.0002.120A4] # CUNEIFORM SIGN EZEN TIMES A PLUS LAL TIMES LAL
+120A5 ; [.2A8D.0020.0002.120A5] # CUNEIFORM SIGN EZEN TIMES AN
+120A6 ; [.2A8E.0020.0002.120A6] # CUNEIFORM SIGN EZEN TIMES BAD
+120A7 ; [.2A8F.0020.0002.120A7] # CUNEIFORM SIGN EZEN TIMES DUN3 GUNU
+120A8 ; [.2A90.0020.0002.120A8] # CUNEIFORM SIGN EZEN TIMES DUN3 GUNU GUNU
+120A9 ; [.2A91.0020.0002.120A9] # CUNEIFORM SIGN EZEN TIMES HA
+120AA ; [.2A92.0020.0002.120AA] # CUNEIFORM SIGN EZEN TIMES HA GUNU
+120AB ; [.2A93.0020.0002.120AB] # CUNEIFORM SIGN EZEN TIMES IGI GUNU
+120AC ; [.2A94.0020.0002.120AC] # CUNEIFORM SIGN EZEN TIMES KASKAL
+120AD ; [.2A95.0020.0002.120AD] # CUNEIFORM SIGN EZEN TIMES KASKAL SQUARED
+120AE ; [.2A96.0020.0002.120AE] # CUNEIFORM SIGN EZEN TIMES KU3
+120AF ; [.2A97.0020.0002.120AF] # CUNEIFORM SIGN EZEN TIMES LA
+120B0 ; [.2A98.0020.0002.120B0] # CUNEIFORM SIGN EZEN TIMES LAL TIMES LAL
+120B1 ; [.2A99.0020.0002.120B1] # CUNEIFORM SIGN EZEN TIMES LI
+120B2 ; [.2A9A.0020.0002.120B2] # CUNEIFORM SIGN EZEN TIMES LU
+120B3 ; [.2A9B.0020.0002.120B3] # CUNEIFORM SIGN EZEN TIMES U2
+120B4 ; [.2A9C.0020.0002.120B4] # CUNEIFORM SIGN EZEN TIMES UD
+120B5 ; [.2A9D.0020.0002.120B5] # CUNEIFORM SIGN GA
+120B6 ; [.2A9E.0020.0002.120B6] # CUNEIFORM SIGN GA GUNU
+120B7 ; [.2A9F.0020.0002.120B7] # CUNEIFORM SIGN GA2
+120B8 ; [.2AA0.0020.0002.120B8] # CUNEIFORM SIGN GA2 TIMES A PLUS DA PLUS HA
+120B9 ; [.2AA1.0020.0002.120B9] # CUNEIFORM SIGN GA2 TIMES A PLUS HA
+120BA ; [.2AA2.0020.0002.120BA] # CUNEIFORM SIGN GA2 TIMES A PLUS IGI
+120BB ; [.2AA3.0020.0002.120BB] # CUNEIFORM SIGN GA2 TIMES AB2 TENU PLUS TAB
+120BC ; [.2AA4.0020.0002.120BC] # CUNEIFORM SIGN GA2 TIMES AN
+120BD ; [.2AA5.0020.0002.120BD] # CUNEIFORM SIGN GA2 TIMES ASH
+120BE ; [.2AA6.0020.0002.120BE] # CUNEIFORM SIGN GA2 TIMES ASH2 PLUS GAL
+120BF ; [.2AA7.0020.0002.120BF] # CUNEIFORM SIGN GA2 TIMES BAD
+120C0 ; [.2AA8.0020.0002.120C0] # CUNEIFORM SIGN GA2 TIMES BAR PLUS RA
+120C1 ; [.2AA9.0020.0002.120C1] # CUNEIFORM SIGN GA2 TIMES BUR
+120C2 ; [.2AAA.0020.0002.120C2] # CUNEIFORM SIGN GA2 TIMES BUR PLUS RA
+120C3 ; [.2AAB.0020.0002.120C3] # CUNEIFORM SIGN GA2 TIMES DA
+120C4 ; [.2AAC.0020.0002.120C4] # CUNEIFORM SIGN GA2 TIMES DI
+120C5 ; [.2AAD.0020.0002.120C5] # CUNEIFORM SIGN GA2 TIMES DIM TIMES SHE
+120C6 ; [.2AAE.0020.0002.120C6] # CUNEIFORM SIGN GA2 TIMES DUB
+120C7 ; [.2AAF.0020.0002.120C7] # CUNEIFORM SIGN GA2 TIMES EL
+120C8 ; [.2AB0.0020.0002.120C8] # CUNEIFORM SIGN GA2 TIMES EL PLUS LA
+120C9 ; [.2AB1.0020.0002.120C9] # CUNEIFORM SIGN GA2 TIMES EN
+120CA ; [.2AB2.0020.0002.120CA] # CUNEIFORM SIGN GA2 TIMES EN TIMES GAN2 TENU
+120CB ; [.2AB3.0020.0002.120CB] # CUNEIFORM SIGN GA2 TIMES GAN2 TENU
+120CC ; [.2AB4.0020.0002.120CC] # CUNEIFORM SIGN GA2 TIMES GAR
+120CD ; [.2AB5.0020.0002.120CD] # CUNEIFORM SIGN GA2 TIMES GI
+120CE ; [.2AB6.0020.0002.120CE] # CUNEIFORM SIGN GA2 TIMES GI4
+120CF ; [.2AB7.0020.0002.120CF] # CUNEIFORM SIGN GA2 TIMES GI4 PLUS A
+120D0 ; [.2AB8.0020.0002.120D0] # CUNEIFORM SIGN GA2 TIMES GIR2 PLUS SU
+120D1 ; [.2AB9.0020.0002.120D1] # CUNEIFORM SIGN GA2 TIMES HA PLUS LU PLUS ESH2
+120D2 ; [.2ABA.0020.0002.120D2] # CUNEIFORM SIGN GA2 TIMES HAL
+120D3 ; [.2ABB.0020.0002.120D3] # CUNEIFORM SIGN GA2 TIMES HAL PLUS LA
+120D4 ; [.2ABC.0020.0002.120D4] # CUNEIFORM SIGN GA2 TIMES HI PLUS LI
+120D5 ; [.2ABD.0020.0002.120D5] # CUNEIFORM SIGN GA2 TIMES HUB2
+120D6 ; [.2ABE.0020.0002.120D6] # CUNEIFORM SIGN GA2 TIMES IGI GUNU
+120D7 ; [.2ABF.0020.0002.120D7] # CUNEIFORM SIGN GA2 TIMES ISH PLUS HU PLUS ASH
+120D8 ; [.2AC0.0020.0002.120D8] # CUNEIFORM SIGN GA2 TIMES KAK
+120D9 ; [.2AC1.0020.0002.120D9] # CUNEIFORM SIGN GA2 TIMES KASKAL
+120DA ; [.2AC2.0020.0002.120DA] # CUNEIFORM SIGN GA2 TIMES KID
+120DB ; [.2AC3.0020.0002.120DB] # CUNEIFORM SIGN GA2 TIMES KID PLUS LAL
+120DC ; [.2AC4.0020.0002.120DC] # CUNEIFORM SIGN GA2 TIMES KU3 PLUS AN
+120DD ; [.2AC5.0020.0002.120DD] # CUNEIFORM SIGN GA2 TIMES LA
+120DE ; [.2AC6.0020.0002.120DE] # CUNEIFORM SIGN GA2 TIMES ME PLUS EN
+120DF ; [.2AC7.0020.0002.120DF] # CUNEIFORM SIGN GA2 TIMES MI
+120E0 ; [.2AC8.0020.0002.120E0] # CUNEIFORM SIGN GA2 TIMES NUN
+120E1 ; [.2AC9.0020.0002.120E1] # CUNEIFORM SIGN GA2 TIMES NUN OVER NUN
+120E2 ; [.2ACA.0020.0002.120E2] # CUNEIFORM SIGN GA2 TIMES PA
+120E3 ; [.2ACB.0020.0002.120E3] # CUNEIFORM SIGN GA2 TIMES SAL
+120E4 ; [.2ACC.0020.0002.120E4] # CUNEIFORM SIGN GA2 TIMES SAR
+120E5 ; [.2ACD.0020.0002.120E5] # CUNEIFORM SIGN GA2 TIMES SHE
+120E6 ; [.2ACE.0020.0002.120E6] # CUNEIFORM SIGN GA2 TIMES SHE PLUS TUR
+120E7 ; [.2ACF.0020.0002.120E7] # CUNEIFORM SIGN GA2 TIMES SHID
+120E8 ; [.2AD0.0020.0002.120E8] # CUNEIFORM SIGN GA2 TIMES SUM
+120E9 ; [.2AD1.0020.0002.120E9] # CUNEIFORM SIGN GA2 TIMES TAK4
+120EA ; [.2AD2.0020.0002.120EA] # CUNEIFORM SIGN GA2 TIMES U
+120EB ; [.2AD3.0020.0002.120EB] # CUNEIFORM SIGN GA2 TIMES UD
+120EC ; [.2AD4.0020.0002.120EC] # CUNEIFORM SIGN GA2 TIMES UD PLUS DU
+120ED ; [.2AD5.0020.0002.120ED] # CUNEIFORM SIGN GA2 OVER GA2
+120EE ; [.2AD6.0020.0002.120EE] # CUNEIFORM SIGN GABA
+120EF ; [.2AD7.0020.0002.120EF] # CUNEIFORM SIGN GABA CROSSING GABA
+120F0 ; [.2AD8.0020.0002.120F0] # CUNEIFORM SIGN GAD
+120F1 ; [.2AD9.0020.0002.120F1] # CUNEIFORM SIGN GAD OVER GAD GAR OVER GAR
+120F2 ; [.2ADA.0020.0002.120F2] # CUNEIFORM SIGN GAL
+120F3 ; [.2ADB.0020.0002.120F3] # CUNEIFORM SIGN GAL GAD OVER GAD GAR OVER GAR
+120F4 ; [.2ADC.0020.0002.120F4] # CUNEIFORM SIGN GALAM
+120F5 ; [.2ADD.0020.0002.120F5] # CUNEIFORM SIGN GAM
+120F6 ; [.2ADE.0020.0002.120F6] # CUNEIFORM SIGN GAN
+120F7 ; [.2ADF.0020.0002.120F7] # CUNEIFORM SIGN GAN2
+120F8 ; [.2AE0.0020.0002.120F8] # CUNEIFORM SIGN GAN2 TENU
+120F9 ; [.2AE1.0020.0002.120F9] # CUNEIFORM SIGN GAN2 OVER GAN2
+120FA ; [.2AE2.0020.0002.120FA] # CUNEIFORM SIGN GAN2 CROSSING GAN2
+120FB ; [.2AE3.0020.0002.120FB] # CUNEIFORM SIGN GAR
+120FC ; [.2AE4.0020.0002.120FC] # CUNEIFORM SIGN GAR3
+120FD ; [.2AE5.0020.0002.120FD] # CUNEIFORM SIGN GASHAN
+120FE ; [.2AE6.0020.0002.120FE] # CUNEIFORM SIGN GESHTIN
+120FF ; [.2AE7.0020.0002.120FF] # CUNEIFORM SIGN GESHTIN TIMES KUR
+12100 ; [.2AE8.0020.0002.12100] # CUNEIFORM SIGN GI
+12101 ; [.2AE9.0020.0002.12101] # CUNEIFORM SIGN GI TIMES E
+12102 ; [.2AEA.0020.0002.12102] # CUNEIFORM SIGN GI TIMES U
+12103 ; [.2AEB.0020.0002.12103] # CUNEIFORM SIGN GI CROSSING GI
+12104 ; [.2AEC.0020.0002.12104] # CUNEIFORM SIGN GI4
+12105 ; [.2AED.0020.0002.12105] # CUNEIFORM SIGN GI4 OVER GI4
+12106 ; [.2AEE.0020.0002.12106] # CUNEIFORM SIGN GI4 CROSSING GI4
+12107 ; [.2AEF.0020.0002.12107] # CUNEIFORM SIGN GIDIM
+12108 ; [.2AF0.0020.0002.12108] # CUNEIFORM SIGN GIR2
+12109 ; [.2AF1.0020.0002.12109] # CUNEIFORM SIGN GIR2 GUNU
+1210A ; [.2AF2.0020.0002.1210A] # CUNEIFORM SIGN GIR3
+1210B ; [.2AF3.0020.0002.1210B] # CUNEIFORM SIGN GIR3 TIMES A PLUS IGI
+1210C ; [.2AF4.0020.0002.1210C] # CUNEIFORM SIGN GIR3 TIMES GAN2 TENU
+1210D ; [.2AF5.0020.0002.1210D] # CUNEIFORM SIGN GIR3 TIMES IGI
+1210E ; [.2AF6.0020.0002.1210E] # CUNEIFORM SIGN GIR3 TIMES LU PLUS IGI
+1210F ; [.2AF7.0020.0002.1210F] # CUNEIFORM SIGN GIR3 TIMES PA
+12110 ; [.2AF8.0020.0002.12110] # CUNEIFORM SIGN GISAL
+12111 ; [.2AF9.0020.0002.12111] # CUNEIFORM SIGN GISH
+12112 ; [.2AFA.0020.0002.12112] # CUNEIFORM SIGN GISH CROSSING GISH
+12113 ; [.2AFB.0020.0002.12113] # CUNEIFORM SIGN GISH TIMES BAD
+12114 ; [.2AFC.0020.0002.12114] # CUNEIFORM SIGN GISH TIMES TAK4
+12115 ; [.2AFD.0020.0002.12115] # CUNEIFORM SIGN GISH TENU
+12116 ; [.2AFE.0020.0002.12116] # CUNEIFORM SIGN GU
+12117 ; [.2AFF.0020.0002.12117] # CUNEIFORM SIGN GU CROSSING GU
+12118 ; [.2B00.0020.0002.12118] # CUNEIFORM SIGN GU2
+12119 ; [.2B01.0020.0002.12119] # CUNEIFORM SIGN GU2 TIMES KAK
+1211A ; [.2B02.0020.0002.1211A] # CUNEIFORM SIGN GU2 TIMES KAK TIMES IGI GUNU
+1211B ; [.2B03.0020.0002.1211B] # CUNEIFORM SIGN GU2 TIMES NUN
+1211C ; [.2B04.0020.0002.1211C] # CUNEIFORM SIGN GU2 TIMES SAL PLUS TUG2
+1211D ; [.2B05.0020.0002.1211D] # CUNEIFORM SIGN GU2 GUNU
+1211E ; [.2B06.0020.0002.1211E] # CUNEIFORM SIGN GUD
+1211F ; [.2B07.0020.0002.1211F] # CUNEIFORM SIGN GUD TIMES A PLUS KUR
+12120 ; [.2B08.0020.0002.12120] # CUNEIFORM SIGN GUD TIMES KUR
+12121 ; [.2B09.0020.0002.12121] # CUNEIFORM SIGN GUD OVER GUD LUGAL
+12122 ; [.2B0A.0020.0002.12122] # CUNEIFORM SIGN GUL
+12123 ; [.2B0B.0020.0002.12123] # CUNEIFORM SIGN GUM
+12124 ; [.2B0C.0020.0002.12124] # CUNEIFORM SIGN GUM TIMES SHE
+12125 ; [.2B0D.0020.0002.12125] # CUNEIFORM SIGN GUR
+12126 ; [.2B0E.0020.0002.12126] # CUNEIFORM SIGN GUR7
+12127 ; [.2B0F.0020.0002.12127] # CUNEIFORM SIGN GURUN
+12128 ; [.2B10.0020.0002.12128] # CUNEIFORM SIGN GURUSH
+12129 ; [.2B11.0020.0002.12129] # CUNEIFORM SIGN HA
+1212A ; [.2B12.0020.0002.1212A] # CUNEIFORM SIGN HA TENU
+1212B ; [.2B13.0020.0002.1212B] # CUNEIFORM SIGN HA GUNU
+1212C ; [.2B14.0020.0002.1212C] # CUNEIFORM SIGN HAL
+1212D ; [.2B15.0020.0002.1212D] # CUNEIFORM SIGN HI
+1212E ; [.2B16.0020.0002.1212E] # CUNEIFORM SIGN HI TIMES ASH
+1212F ; [.2B17.0020.0002.1212F] # CUNEIFORM SIGN HI TIMES ASH2
+12130 ; [.2B18.0020.0002.12130] # CUNEIFORM SIGN HI TIMES BAD
+12131 ; [.2B19.0020.0002.12131] # CUNEIFORM SIGN HI TIMES DISH
+12132 ; [.2B1A.0020.0002.12132] # CUNEIFORM SIGN HI TIMES GAD
+12133 ; [.2B1B.0020.0002.12133] # CUNEIFORM SIGN HI TIMES KIN
+12134 ; [.2B1C.0020.0002.12134] # CUNEIFORM SIGN HI TIMES NUN
+12135 ; [.2B1D.0020.0002.12135] # CUNEIFORM SIGN HI TIMES SHE
+12136 ; [.2B1E.0020.0002.12136] # CUNEIFORM SIGN HI TIMES U
+12137 ; [.2B1F.0020.0002.12137] # CUNEIFORM SIGN HU
+12138 ; [.2B20.0020.0002.12138] # CUNEIFORM SIGN HUB2
+12139 ; [.2B21.0020.0002.12139] # CUNEIFORM SIGN HUB2 TIMES AN
+1213A ; [.2B22.0020.0002.1213A] # CUNEIFORM SIGN HUB2 TIMES HAL
+1213B ; [.2B23.0020.0002.1213B] # CUNEIFORM SIGN HUB2 TIMES KASKAL
+1213C ; [.2B24.0020.0002.1213C] # CUNEIFORM SIGN HUB2 TIMES LISH
+1213D ; [.2B25.0020.0002.1213D] # CUNEIFORM SIGN HUB2 TIMES UD
+1213E ; [.2B26.0020.0002.1213E] # CUNEIFORM SIGN HUL2
+1213F ; [.2B27.0020.0002.1213F] # CUNEIFORM SIGN I
+12140 ; [.2B28.0020.0002.12140] # CUNEIFORM SIGN I A
+12141 ; [.2B29.0020.0002.12141] # CUNEIFORM SIGN IB
+12142 ; [.2B2A.0020.0002.12142] # CUNEIFORM SIGN IDIM
+12143 ; [.2B2B.0020.0002.12143] # CUNEIFORM SIGN IDIM OVER IDIM BUR
+12144 ; [.2B2C.0020.0002.12144] # CUNEIFORM SIGN IDIM OVER IDIM SQUARED
+12145 ; [.2B2D.0020.0002.12145] # CUNEIFORM SIGN IG
+12146 ; [.2B2E.0020.0002.12146] # CUNEIFORM SIGN IGI
+12147 ; [.2B2F.0020.0002.12147] # CUNEIFORM SIGN IGI DIB
+12148 ; [.2B30.0020.0002.12148] # CUNEIFORM SIGN IGI RI
+12149 ; [.2B31.0020.0002.12149] # CUNEIFORM SIGN IGI OVER IGI SHIR OVER SHIR UD OVER UD
+1214A ; [.2B32.0020.0002.1214A] # CUNEIFORM SIGN IGI GUNU
+1214B ; [.2B33.0020.0002.1214B] # CUNEIFORM SIGN IL
+1214C ; [.2B34.0020.0002.1214C] # CUNEIFORM SIGN IL TIMES GAN2 TENU
+1214D ; [.2B35.0020.0002.1214D] # CUNEIFORM SIGN IL2
+1214E ; [.2B36.0020.0002.1214E] # CUNEIFORM SIGN IM
+1214F ; [.2B37.0020.0002.1214F] # CUNEIFORM SIGN IM TIMES TAK4
+12150 ; [.2B38.0020.0002.12150] # CUNEIFORM SIGN IM CROSSING IM
+12151 ; [.2B39.0020.0002.12151] # CUNEIFORM SIGN IM OPPOSING IM
+12152 ; [.2B3A.0020.0002.12152] # CUNEIFORM SIGN IM SQUARED
+12153 ; [.2B3B.0020.0002.12153] # CUNEIFORM SIGN IMIN
+12154 ; [.2B3C.0020.0002.12154] # CUNEIFORM SIGN IN
+12155 ; [.2B3D.0020.0002.12155] # CUNEIFORM SIGN IR
+12156 ; [.2B3E.0020.0002.12156] # CUNEIFORM SIGN ISH
+12157 ; [.2B3F.0020.0002.12157] # CUNEIFORM SIGN KA
+12158 ; [.2B40.0020.0002.12158] # CUNEIFORM SIGN KA TIMES A
+12159 ; [.2B41.0020.0002.12159] # CUNEIFORM SIGN KA TIMES AD
+1215A ; [.2B42.0020.0002.1215A] # CUNEIFORM SIGN KA TIMES AD PLUS KU3
+1215B ; [.2B43.0020.0002.1215B] # CUNEIFORM SIGN KA TIMES ASH2
+1215C ; [.2B44.0020.0002.1215C] # CUNEIFORM SIGN KA TIMES BAD
+1215D ; [.2B45.0020.0002.1215D] # CUNEIFORM SIGN KA TIMES BALAG
+1215E ; [.2B46.0020.0002.1215E] # CUNEIFORM SIGN KA TIMES BAR
+1215F ; [.2B47.0020.0002.1215F] # CUNEIFORM SIGN KA TIMES BI
+12160 ; [.2B48.0020.0002.12160] # CUNEIFORM SIGN KA TIMES ERIN2
+12161 ; [.2B49.0020.0002.12161] # CUNEIFORM SIGN KA TIMES ESH2
+12162 ; [.2B4A.0020.0002.12162] # CUNEIFORM SIGN KA TIMES GA
+12163 ; [.2B4B.0020.0002.12163] # CUNEIFORM SIGN KA TIMES GAL
+12164 ; [.2B4C.0020.0002.12164] # CUNEIFORM SIGN KA TIMES GAN2 TENU
+12165 ; [.2B4D.0020.0002.12165] # CUNEIFORM SIGN KA TIMES GAR
+12166 ; [.2B4E.0020.0002.12166] # CUNEIFORM SIGN KA TIMES GAR PLUS SHA3 PLUS A
+12167 ; [.2B4F.0020.0002.12167] # CUNEIFORM SIGN KA TIMES GI
+12168 ; [.2B50.0020.0002.12168] # CUNEIFORM SIGN KA TIMES GIR2
+12169 ; [.2B51.0020.0002.12169] # CUNEIFORM SIGN KA TIMES GISH PLUS SAR
+1216A ; [.2B52.0020.0002.1216A] # CUNEIFORM SIGN KA TIMES GISH CROSSING GISH
+1216B ; [.2B53.0020.0002.1216B] # CUNEIFORM SIGN KA TIMES GU
+1216C ; [.2B54.0020.0002.1216C] # CUNEIFORM SIGN KA TIMES GUR7
+1216D ; [.2B55.0020.0002.1216D] # CUNEIFORM SIGN KA TIMES IGI
+1216E ; [.2B56.0020.0002.1216E] # CUNEIFORM SIGN KA TIMES IM
+1216F ; [.2B57.0020.0002.1216F] # CUNEIFORM SIGN KA TIMES KAK
+12170 ; [.2B58.0020.0002.12170] # CUNEIFORM SIGN KA TIMES KI
+12171 ; [.2B59.0020.0002.12171] # CUNEIFORM SIGN KA TIMES KID
+12172 ; [.2B5A.0020.0002.12172] # CUNEIFORM SIGN KA TIMES LI
+12173 ; [.2B5B.0020.0002.12173] # CUNEIFORM SIGN KA TIMES LU
+12174 ; [.2B5C.0020.0002.12174] # CUNEIFORM SIGN KA TIMES ME
+12175 ; [.2B5D.0020.0002.12175] # CUNEIFORM SIGN KA TIMES ME PLUS DU
+12176 ; [.2B5E.0020.0002.12176] # CUNEIFORM SIGN KA TIMES ME PLUS GI
+12177 ; [.2B5F.0020.0002.12177] # CUNEIFORM SIGN KA TIMES ME PLUS TE
+12178 ; [.2B60.0020.0002.12178] # CUNEIFORM SIGN KA TIMES MI
+12179 ; [.2B61.0020.0002.12179] # CUNEIFORM SIGN KA TIMES MI PLUS NUNUZ
+1217A ; [.2B62.0020.0002.1217A] # CUNEIFORM SIGN KA TIMES NE
+1217B ; [.2B63.0020.0002.1217B] # CUNEIFORM SIGN KA TIMES NUN
+1217C ; [.2B64.0020.0002.1217C] # CUNEIFORM SIGN KA TIMES PI
+1217D ; [.2B65.0020.0002.1217D] # CUNEIFORM SIGN KA TIMES RU
+1217E ; [.2B66.0020.0002.1217E] # CUNEIFORM SIGN KA TIMES SA
+1217F ; [.2B67.0020.0002.1217F] # CUNEIFORM SIGN KA TIMES SAR
+12180 ; [.2B68.0020.0002.12180] # CUNEIFORM SIGN KA TIMES SHA
+12181 ; [.2B69.0020.0002.12181] # CUNEIFORM SIGN KA TIMES SHE
+12182 ; [.2B6A.0020.0002.12182] # CUNEIFORM SIGN KA TIMES SHID
+12183 ; [.2B6B.0020.0002.12183] # CUNEIFORM SIGN KA TIMES SHU
+12184 ; [.2B6C.0020.0002.12184] # CUNEIFORM SIGN KA TIMES SIG
+12185 ; [.2B6D.0020.0002.12185] # CUNEIFORM SIGN KA TIMES SUHUR
+12186 ; [.2B6E.0020.0002.12186] # CUNEIFORM SIGN KA TIMES TAR
+12187 ; [.2B6F.0020.0002.12187] # CUNEIFORM SIGN KA TIMES U
+12188 ; [.2B70.0020.0002.12188] # CUNEIFORM SIGN KA TIMES U2
+12189 ; [.2B71.0020.0002.12189] # CUNEIFORM SIGN KA TIMES UD
+1218A ; [.2B72.0020.0002.1218A] # CUNEIFORM SIGN KA TIMES UMUM TIMES PA
+1218B ; [.2B73.0020.0002.1218B] # CUNEIFORM SIGN KA TIMES USH
+1218C ; [.2B74.0020.0002.1218C] # CUNEIFORM SIGN KA TIMES ZI
+1218D ; [.2B75.0020.0002.1218D] # CUNEIFORM SIGN KA2
+1218E ; [.2B76.0020.0002.1218E] # CUNEIFORM SIGN KA2 CROSSING KA2
+1218F ; [.2B77.0020.0002.1218F] # CUNEIFORM SIGN KAB
+12190 ; [.2B78.0020.0002.12190] # CUNEIFORM SIGN KAD2
+12191 ; [.2B79.0020.0002.12191] # CUNEIFORM SIGN KAD3
+12192 ; [.2B7A.0020.0002.12192] # CUNEIFORM SIGN KAD4
+12193 ; [.2B7B.0020.0002.12193] # CUNEIFORM SIGN KAD5
+12194 ; [.2B7C.0020.0002.12194] # CUNEIFORM SIGN KAD5 OVER KAD5
+12195 ; [.2B7D.0020.0002.12195] # CUNEIFORM SIGN KAK
+12196 ; [.2B7E.0020.0002.12196] # CUNEIFORM SIGN KAK TIMES IGI GUNU
+12197 ; [.2B7F.0020.0002.12197] # CUNEIFORM SIGN KAL
+12198 ; [.2B80.0020.0002.12198] # CUNEIFORM SIGN KAL TIMES BAD
+12199 ; [.2B81.0020.0002.12199] # CUNEIFORM SIGN KAL CROSSING KAL
+1219A ; [.2B82.0020.0002.1219A] # CUNEIFORM SIGN KAM2
+1219B ; [.2B83.0020.0002.1219B] # CUNEIFORM SIGN KAM4
+1219C ; [.2B84.0020.0002.1219C] # CUNEIFORM SIGN KASKAL
+1219D ; [.2B85.0020.0002.1219D] # CUNEIFORM SIGN KASKAL LAGAB TIMES U OVER LAGAB TIMES U
+1219E ; [.2B86.0020.0002.1219E] # CUNEIFORM SIGN KASKAL OVER KASKAL LAGAB TIMES U OVER LAGAB TIMES U
+1219F ; [.2B87.0020.0002.1219F] # CUNEIFORM SIGN KESH2
+121A0 ; [.2B88.0020.0002.121A0] # CUNEIFORM SIGN KI
+121A1 ; [.2B89.0020.0002.121A1] # CUNEIFORM SIGN KI TIMES BAD
+121A2 ; [.2B8A.0020.0002.121A2] # CUNEIFORM SIGN KI TIMES U
+121A3 ; [.2B8B.0020.0002.121A3] # CUNEIFORM SIGN KI TIMES UD
+121A4 ; [.2B8C.0020.0002.121A4] # CUNEIFORM SIGN KID
+121A5 ; [.2B8D.0020.0002.121A5] # CUNEIFORM SIGN KIN
+121A6 ; [.2B8E.0020.0002.121A6] # CUNEIFORM SIGN KISAL
+121A7 ; [.2B8F.0020.0002.121A7] # CUNEIFORM SIGN KISH
+121A8 ; [.2B90.0020.0002.121A8] # CUNEIFORM SIGN KISIM5
+121A9 ; [.2B91.0020.0002.121A9] # CUNEIFORM SIGN KISIM5 OVER KISIM5
+121AA ; [.2B92.0020.0002.121AA] # CUNEIFORM SIGN KU
+121AB ; [.2B93.0020.0002.121AB] # CUNEIFORM SIGN KU OVER HI TIMES ASH2 KU OVER HI TIMES ASH2
+121AC ; [.2B94.0020.0002.121AC] # CUNEIFORM SIGN KU3
+121AD ; [.2B95.0020.0002.121AD] # CUNEIFORM SIGN KU4
+121AE ; [.2B96.0020.0002.121AE] # CUNEIFORM SIGN KU4 VARIANT FORM
+121AF ; [.2B97.0020.0002.121AF] # CUNEIFORM SIGN KU7
+121B0 ; [.2B98.0020.0002.121B0] # CUNEIFORM SIGN KUL
+121B1 ; [.2B99.0020.0002.121B1] # CUNEIFORM SIGN KUL GUNU
+121B2 ; [.2B9A.0020.0002.121B2] # CUNEIFORM SIGN KUN
+121B3 ; [.2B9B.0020.0002.121B3] # CUNEIFORM SIGN KUR
+121B4 ; [.2B9C.0020.0002.121B4] # CUNEIFORM SIGN KUR OPPOSING KUR
+121B5 ; [.2B9D.0020.0002.121B5] # CUNEIFORM SIGN KUSHU2
+121B6 ; [.2B9E.0020.0002.121B6] # CUNEIFORM SIGN KWU318
+121B7 ; [.2B9F.0020.0002.121B7] # CUNEIFORM SIGN LA
+121B8 ; [.2BA0.0020.0002.121B8] # CUNEIFORM SIGN LAGAB
+121B9 ; [.2BA1.0020.0002.121B9] # CUNEIFORM SIGN LAGAB TIMES A
+121BA ; [.2BA2.0020.0002.121BA] # CUNEIFORM SIGN LAGAB TIMES A PLUS DA PLUS HA
+121BB ; [.2BA3.0020.0002.121BB] # CUNEIFORM SIGN LAGAB TIMES A PLUS GAR
+121BC ; [.2BA4.0020.0002.121BC] # CUNEIFORM SIGN LAGAB TIMES A PLUS LAL
+121BD ; [.2BA5.0020.0002.121BD] # CUNEIFORM SIGN LAGAB TIMES AL
+121BE ; [.2BA6.0020.0002.121BE] # CUNEIFORM SIGN LAGAB TIMES AN
+121BF ; [.2BA7.0020.0002.121BF] # CUNEIFORM SIGN LAGAB TIMES ASH ZIDA TENU
+121C0 ; [.2BA8.0020.0002.121C0] # CUNEIFORM SIGN LAGAB TIMES BAD
+121C1 ; [.2BA9.0020.0002.121C1] # CUNEIFORM SIGN LAGAB TIMES BI
+121C2 ; [.2BAA.0020.0002.121C2] # CUNEIFORM SIGN LAGAB TIMES DAR
+121C3 ; [.2BAB.0020.0002.121C3] # CUNEIFORM SIGN LAGAB TIMES EN
+121C4 ; [.2BAC.0020.0002.121C4] # CUNEIFORM SIGN LAGAB TIMES GA
+121C5 ; [.2BAD.0020.0002.121C5] # CUNEIFORM SIGN LAGAB TIMES GAR
+121C6 ; [.2BAE.0020.0002.121C6] # CUNEIFORM SIGN LAGAB TIMES GUD
+121C7 ; [.2BAF.0020.0002.121C7] # CUNEIFORM SIGN LAGAB TIMES GUD PLUS GUD
+121C8 ; [.2BB0.0020.0002.121C8] # CUNEIFORM SIGN LAGAB TIMES HA
+121C9 ; [.2BB1.0020.0002.121C9] # CUNEIFORM SIGN LAGAB TIMES HAL
+121CA ; [.2BB2.0020.0002.121CA] # CUNEIFORM SIGN LAGAB TIMES HI TIMES NUN
+121CB ; [.2BB3.0020.0002.121CB] # CUNEIFORM SIGN LAGAB TIMES IGI GUNU
+121CC ; [.2BB4.0020.0002.121CC] # CUNEIFORM SIGN LAGAB TIMES IM
+121CD ; [.2BB5.0020.0002.121CD] # CUNEIFORM SIGN LAGAB TIMES IM PLUS HA
+121CE ; [.2BB6.0020.0002.121CE] # CUNEIFORM SIGN LAGAB TIMES IM PLUS LU
+121CF ; [.2BB7.0020.0002.121CF] # CUNEIFORM SIGN LAGAB TIMES KI
+121D0 ; [.2BB8.0020.0002.121D0] # CUNEIFORM SIGN LAGAB TIMES KIN
+121D1 ; [.2BB9.0020.0002.121D1] # CUNEIFORM SIGN LAGAB TIMES KU3
+121D2 ; [.2BBA.0020.0002.121D2] # CUNEIFORM SIGN LAGAB TIMES KUL
+121D3 ; [.2BBB.0020.0002.121D3] # CUNEIFORM SIGN LAGAB TIMES KUL PLUS HI PLUS A
+121D4 ; [.2BBC.0020.0002.121D4] # CUNEIFORM SIGN LAGAB TIMES LAGAB
+121D5 ; [.2BBD.0020.0002.121D5] # CUNEIFORM SIGN LAGAB TIMES LISH
+121D6 ; [.2BBE.0020.0002.121D6] # CUNEIFORM SIGN LAGAB TIMES LU
+121D7 ; [.2BBF.0020.0002.121D7] # CUNEIFORM SIGN LAGAB TIMES LUL
+121D8 ; [.2BC0.0020.0002.121D8] # CUNEIFORM SIGN LAGAB TIMES ME
+121D9 ; [.2BC1.0020.0002.121D9] # CUNEIFORM SIGN LAGAB TIMES ME PLUS EN
+121DA ; [.2BC2.0020.0002.121DA] # CUNEIFORM SIGN LAGAB TIMES MUSH
+121DB ; [.2BC3.0020.0002.121DB] # CUNEIFORM SIGN LAGAB TIMES NE
+121DC ; [.2BC4.0020.0002.121DC] # CUNEIFORM SIGN LAGAB TIMES SHE PLUS SUM
+121DD ; [.2BC5.0020.0002.121DD] # CUNEIFORM SIGN LAGAB TIMES SHITA PLUS GISH PLUS ERIN2
+121DE ; [.2BC6.0020.0002.121DE] # CUNEIFORM SIGN LAGAB TIMES SHITA PLUS GISH TENU
+121DF ; [.2BC7.0020.0002.121DF] # CUNEIFORM SIGN LAGAB TIMES SHU2
+121E0 ; [.2BC8.0020.0002.121E0] # CUNEIFORM SIGN LAGAB TIMES SHU2 PLUS SHU2
+121E1 ; [.2BC9.0020.0002.121E1] # CUNEIFORM SIGN LAGAB TIMES SUM
+121E2 ; [.2BCA.0020.0002.121E2] # CUNEIFORM SIGN LAGAB TIMES TAG
+121E3 ; [.2BCB.0020.0002.121E3] # CUNEIFORM SIGN LAGAB TIMES TAK4
+121E4 ; [.2BCC.0020.0002.121E4] # CUNEIFORM SIGN LAGAB TIMES TE PLUS A PLUS SU PLUS NA
+121E5 ; [.2BCD.0020.0002.121E5] # CUNEIFORM SIGN LAGAB TIMES U
+121E6 ; [.2BCE.0020.0002.121E6] # CUNEIFORM SIGN LAGAB TIMES U PLUS A
+121E7 ; [.2BCF.0020.0002.121E7] # CUNEIFORM SIGN LAGAB TIMES U PLUS U PLUS U
+121E8 ; [.2BD0.0020.0002.121E8] # CUNEIFORM SIGN LAGAB TIMES U2 PLUS ASH
+121E9 ; [.2BD1.0020.0002.121E9] # CUNEIFORM SIGN LAGAB TIMES UD
+121EA ; [.2BD2.0020.0002.121EA] # CUNEIFORM SIGN LAGAB TIMES USH
+121EB ; [.2BD3.0020.0002.121EB] # CUNEIFORM SIGN LAGAB SQUARED
+121EC ; [.2BD4.0020.0002.121EC] # CUNEIFORM SIGN LAGAR
+121ED ; [.2BD5.0020.0002.121ED] # CUNEIFORM SIGN LAGAR TIMES SHE
+121EE ; [.2BD6.0020.0002.121EE] # CUNEIFORM SIGN LAGAR TIMES SHE PLUS SUM
+121EF ; [.2BD7.0020.0002.121EF] # CUNEIFORM SIGN LAGAR GUNU
+121F0 ; [.2BD8.0020.0002.121F0] # CUNEIFORM SIGN LAGAR GUNU OVER LAGAR GUNU SHE
+121F1 ; [.2BD9.0020.0002.121F1] # CUNEIFORM SIGN LAHSHU
+121F2 ; [.2BDA.0020.0002.121F2] # CUNEIFORM SIGN LAL
+121F3 ; [.2BDB.0020.0002.121F3] # CUNEIFORM SIGN LAL TIMES LAL
+121F4 ; [.2BDC.0020.0002.121F4] # CUNEIFORM SIGN LAM
+121F5 ; [.2BDD.0020.0002.121F5] # CUNEIFORM SIGN LAM TIMES KUR
+121F6 ; [.2BDE.0020.0002.121F6] # CUNEIFORM SIGN LAM TIMES KUR PLUS RU
+121F7 ; [.2BDF.0020.0002.121F7] # CUNEIFORM SIGN LI
+121F8 ; [.2BE0.0020.0002.121F8] # CUNEIFORM SIGN LIL
+121F9 ; [.2BE1.0020.0002.121F9] # CUNEIFORM SIGN LIMMU2
+121FA ; [.2BE2.0020.0002.121FA] # CUNEIFORM SIGN LISH
+121FB ; [.2BE3.0020.0002.121FB] # CUNEIFORM SIGN LU
+121FC ; [.2BE4.0020.0002.121FC] # CUNEIFORM SIGN LU TIMES BAD
+121FD ; [.2BE5.0020.0002.121FD] # CUNEIFORM SIGN LU2
+121FE ; [.2BE6.0020.0002.121FE] # CUNEIFORM SIGN LU2 TIMES AL
+121FF ; [.2BE7.0020.0002.121FF] # CUNEIFORM SIGN LU2 TIMES BAD
+12200 ; [.2BE8.0020.0002.12200] # CUNEIFORM SIGN LU2 TIMES ESH2
+12201 ; [.2BE9.0020.0002.12201] # CUNEIFORM SIGN LU2 TIMES ESH2 TENU
+12202 ; [.2BEA.0020.0002.12202] # CUNEIFORM SIGN LU2 TIMES GAN2 TENU
+12203 ; [.2BEB.0020.0002.12203] # CUNEIFORM SIGN LU2 TIMES HI TIMES BAD
+12204 ; [.2BEC.0020.0002.12204] # CUNEIFORM SIGN LU2 TIMES IM
+12205 ; [.2BED.0020.0002.12205] # CUNEIFORM SIGN LU2 TIMES KAD2
+12206 ; [.2BEE.0020.0002.12206] # CUNEIFORM SIGN LU2 TIMES KAD3
+12207 ; [.2BEF.0020.0002.12207] # CUNEIFORM SIGN LU2 TIMES KAD3 PLUS ASH
+12208 ; [.2BF0.0020.0002.12208] # CUNEIFORM SIGN LU2 TIMES KI
+12209 ; [.2BF1.0020.0002.12209] # CUNEIFORM SIGN LU2 TIMES LA PLUS ASH
+1220A ; [.2BF2.0020.0002.1220A] # CUNEIFORM SIGN LU2 TIMES LAGAB
+1220B ; [.2BF3.0020.0002.1220B] # CUNEIFORM SIGN LU2 TIMES ME PLUS EN
+1220C ; [.2BF4.0020.0002.1220C] # CUNEIFORM SIGN LU2 TIMES NE
+1220D ; [.2BF5.0020.0002.1220D] # CUNEIFORM SIGN LU2 TIMES NU
+1220E ; [.2BF6.0020.0002.1220E] # CUNEIFORM SIGN LU2 TIMES SI PLUS ASH
+1220F ; [.2BF7.0020.0002.1220F] # CUNEIFORM SIGN LU2 TIMES SIK2 PLUS BU
+12210 ; [.2BF8.0020.0002.12210] # CUNEIFORM SIGN LU2 TIMES TUG2
+12211 ; [.2BF9.0020.0002.12211] # CUNEIFORM SIGN LU2 TENU
+12212 ; [.2BFA.0020.0002.12212] # CUNEIFORM SIGN LU2 CROSSING LU2
+12213 ; [.2BFB.0020.0002.12213] # CUNEIFORM SIGN LU2 OPPOSING LU2
+12214 ; [.2BFC.0020.0002.12214] # CUNEIFORM SIGN LU2 SQUARED
+12215 ; [.2BFD.0020.0002.12215] # CUNEIFORM SIGN LU2 SHESHIG
+12216 ; [.2BFE.0020.0002.12216] # CUNEIFORM SIGN LU3
+12217 ; [.2BFF.0020.0002.12217] # CUNEIFORM SIGN LUGAL
+12218 ; [.2C00.0020.0002.12218] # CUNEIFORM SIGN LUGAL OVER LUGAL
+12219 ; [.2C01.0020.0002.12219] # CUNEIFORM SIGN LUGAL OPPOSING LUGAL
+1221A ; [.2C02.0020.0002.1221A] # CUNEIFORM SIGN LUGAL SHESHIG
+1221B ; [.2C03.0020.0002.1221B] # CUNEIFORM SIGN LUH
+1221C ; [.2C04.0020.0002.1221C] # CUNEIFORM SIGN LUL
+1221D ; [.2C05.0020.0002.1221D] # CUNEIFORM SIGN LUM
+1221E ; [.2C06.0020.0002.1221E] # CUNEIFORM SIGN LUM OVER LUM
+1221F ; [.2C07.0020.0002.1221F] # CUNEIFORM SIGN LUM OVER LUM GAR OVER GAR
+12220 ; [.2C08.0020.0002.12220] # CUNEIFORM SIGN MA
+12221 ; [.2C09.0020.0002.12221] # CUNEIFORM SIGN MA TIMES TAK4
+12222 ; [.2C0A.0020.0002.12222] # CUNEIFORM SIGN MA GUNU
+12223 ; [.2C0B.0020.0002.12223] # CUNEIFORM SIGN MA2
+12224 ; [.2C0C.0020.0002.12224] # CUNEIFORM SIGN MAH
+12225 ; [.2C0D.0020.0002.12225] # CUNEIFORM SIGN MAR
+12226 ; [.2C0E.0020.0002.12226] # CUNEIFORM SIGN MASH
+12227 ; [.2C0F.0020.0002.12227] # CUNEIFORM SIGN MASH2
+12228 ; [.2C10.0020.0002.12228] # CUNEIFORM SIGN ME
+12229 ; [.2C11.0020.0002.12229] # CUNEIFORM SIGN MES
+1222A ; [.2C12.0020.0002.1222A] # CUNEIFORM SIGN MI
+1222B ; [.2C13.0020.0002.1222B] # CUNEIFORM SIGN MIN
+1222C ; [.2C14.0020.0002.1222C] # CUNEIFORM SIGN MU
+1222D ; [.2C15.0020.0002.1222D] # CUNEIFORM SIGN MU OVER MU
+1222E ; [.2C16.0020.0002.1222E] # CUNEIFORM SIGN MUG
+1222F ; [.2C17.0020.0002.1222F] # CUNEIFORM SIGN MUG GUNU
+12230 ; [.2C18.0020.0002.12230] # CUNEIFORM SIGN MUNSUB
+12231 ; [.2C19.0020.0002.12231] # CUNEIFORM SIGN MURGU2
+12232 ; [.2C1A.0020.0002.12232] # CUNEIFORM SIGN MUSH
+12233 ; [.2C1B.0020.0002.12233] # CUNEIFORM SIGN MUSH TIMES A
+12234 ; [.2C1C.0020.0002.12234] # CUNEIFORM SIGN MUSH TIMES KUR
+12235 ; [.2C1D.0020.0002.12235] # CUNEIFORM SIGN MUSH TIMES ZA
+12236 ; [.2C1E.0020.0002.12236] # CUNEIFORM SIGN MUSH OVER MUSH
+12237 ; [.2C1F.0020.0002.12237] # CUNEIFORM SIGN MUSH OVER MUSH TIMES A PLUS NA
+12238 ; [.2C20.0020.0002.12238] # CUNEIFORM SIGN MUSH CROSSING MUSH
+12239 ; [.2C21.0020.0002.12239] # CUNEIFORM SIGN MUSH3
+1223A ; [.2C22.0020.0002.1223A] # CUNEIFORM SIGN MUSH3 TIMES A
+1223B ; [.2C23.0020.0002.1223B] # CUNEIFORM SIGN MUSH3 TIMES A PLUS DI
+1223C ; [.2C24.0020.0002.1223C] # CUNEIFORM SIGN MUSH3 TIMES DI
+1223D ; [.2C25.0020.0002.1223D] # CUNEIFORM SIGN MUSH3 GUNU
+1223E ; [.2C26.0020.0002.1223E] # CUNEIFORM SIGN NA
+1223F ; [.2C27.0020.0002.1223F] # CUNEIFORM SIGN NA2
+12240 ; [.2C28.0020.0002.12240] # CUNEIFORM SIGN NAGA
+12241 ; [.2C29.0020.0002.12241] # CUNEIFORM SIGN NAGA INVERTED
+12242 ; [.2C2A.0020.0002.12242] # CUNEIFORM SIGN NAGA TIMES SHU TENU
+12243 ; [.2C2B.0020.0002.12243] # CUNEIFORM SIGN NAGA OPPOSING NAGA
+12244 ; [.2C2C.0020.0002.12244] # CUNEIFORM SIGN NAGAR
+12245 ; [.2C2D.0020.0002.12245] # CUNEIFORM SIGN NAM NUTILLU
+12246 ; [.2C2E.0020.0002.12246] # CUNEIFORM SIGN NAM
+12247 ; [.2C2F.0020.0002.12247] # CUNEIFORM SIGN NAM2
+12248 ; [.2C30.0020.0002.12248] # CUNEIFORM SIGN NE
+12249 ; [.2C31.0020.0002.12249] # CUNEIFORM SIGN NE TIMES A
+1224A ; [.2C32.0020.0002.1224A] # CUNEIFORM SIGN NE TIMES UD
+1224B ; [.2C33.0020.0002.1224B] # CUNEIFORM SIGN NE SHESHIG
+1224C ; [.2C34.0020.0002.1224C] # CUNEIFORM SIGN NI
+1224D ; [.2C35.0020.0002.1224D] # CUNEIFORM SIGN NI TIMES E
+1224E ; [.2C36.0020.0002.1224E] # CUNEIFORM SIGN NI2
+1224F ; [.2C37.0020.0002.1224F] # CUNEIFORM SIGN NIM
+12250 ; [.2C38.0020.0002.12250] # CUNEIFORM SIGN NIM TIMES GAN2 TENU
+12251 ; [.2C39.0020.0002.12251] # CUNEIFORM SIGN NIM TIMES GAR PLUS GAN2 TENU
+12252 ; [.2C3A.0020.0002.12252] # CUNEIFORM SIGN NINDA2
+12253 ; [.2C3B.0020.0002.12253] # CUNEIFORM SIGN NINDA2 TIMES AN
+12254 ; [.2C3C.0020.0002.12254] # CUNEIFORM SIGN NINDA2 TIMES ASH
+12255 ; [.2C3D.0020.0002.12255] # CUNEIFORM SIGN NINDA2 TIMES ASH PLUS ASH
+12256 ; [.2C3E.0020.0002.12256] # CUNEIFORM SIGN NINDA2 TIMES GUD
+12257 ; [.2C3F.0020.0002.12257] # CUNEIFORM SIGN NINDA2 TIMES ME PLUS GAN2 TENU
+12258 ; [.2C40.0020.0002.12258] # CUNEIFORM SIGN NINDA2 TIMES NE
+12259 ; [.2C41.0020.0002.12259] # CUNEIFORM SIGN NINDA2 TIMES NUN
+1225A ; [.2C42.0020.0002.1225A] # CUNEIFORM SIGN NINDA2 TIMES SHE
+1225B ; [.2C43.0020.0002.1225B] # CUNEIFORM SIGN NINDA2 TIMES SHE PLUS A AN
+1225C ; [.2C44.0020.0002.1225C] # CUNEIFORM SIGN NINDA2 TIMES SHE PLUS ASH
+1225D ; [.2C45.0020.0002.1225D] # CUNEIFORM SIGN NINDA2 TIMES SHE PLUS ASH PLUS ASH
+1225E ; [.2C46.0020.0002.1225E] # CUNEIFORM SIGN NINDA2 TIMES U2 PLUS ASH
+1225F ; [.2C47.0020.0002.1225F] # CUNEIFORM SIGN NINDA2 TIMES USH
+12260 ; [.2C48.0020.0002.12260] # CUNEIFORM SIGN NISAG
+12261 ; [.2C49.0020.0002.12261] # CUNEIFORM SIGN NU
+12262 ; [.2C4A.0020.0002.12262] # CUNEIFORM SIGN NU11
+12263 ; [.2C4B.0020.0002.12263] # CUNEIFORM SIGN NUN
+12264 ; [.2C4C.0020.0002.12264] # CUNEIFORM SIGN NUN LAGAR TIMES GAR
+12265 ; [.2C4D.0020.0002.12265] # CUNEIFORM SIGN NUN LAGAR TIMES MASH
+12266 ; [.2C4E.0020.0002.12266] # CUNEIFORM SIGN NUN LAGAR TIMES SAL
+12267 ; [.2C4F.0020.0002.12267] # CUNEIFORM SIGN NUN LAGAR TIMES SAL OVER NUN LAGAR TIMES SAL
+12268 ; [.2C50.0020.0002.12268] # CUNEIFORM SIGN NUN LAGAR TIMES USH
+12269 ; [.2C51.0020.0002.12269] # CUNEIFORM SIGN NUN TENU
+1226A ; [.2C52.0020.0002.1226A] # CUNEIFORM SIGN NUN OVER NUN
+1226B ; [.2C53.0020.0002.1226B] # CUNEIFORM SIGN NUN CROSSING NUN
+1226C ; [.2C54.0020.0002.1226C] # CUNEIFORM SIGN NUN CROSSING NUN LAGAR OVER LAGAR
+1226D ; [.2C55.0020.0002.1226D] # CUNEIFORM SIGN NUNUZ
+1226E ; [.2C56.0020.0002.1226E] # CUNEIFORM SIGN NUNUZ AB2 TIMES ASHGAB
+1226F ; [.2C57.0020.0002.1226F] # CUNEIFORM SIGN NUNUZ AB2 TIMES BI
+12270 ; [.2C58.0020.0002.12270] # CUNEIFORM SIGN NUNUZ AB2 TIMES DUG
+12271 ; [.2C59.0020.0002.12271] # CUNEIFORM SIGN NUNUZ AB2 TIMES GUD
+12272 ; [.2C5A.0020.0002.12272] # CUNEIFORM SIGN NUNUZ AB2 TIMES IGI GUNU
+12273 ; [.2C5B.0020.0002.12273] # CUNEIFORM SIGN NUNUZ AB2 TIMES KAD3
+12274 ; [.2C5C.0020.0002.12274] # CUNEIFORM SIGN NUNUZ AB2 TIMES LA
+12275 ; [.2C5D.0020.0002.12275] # CUNEIFORM SIGN NUNUZ AB2 TIMES NE
+12276 ; [.2C5E.0020.0002.12276] # CUNEIFORM SIGN NUNUZ AB2 TIMES SILA3
+12277 ; [.2C5F.0020.0002.12277] # CUNEIFORM SIGN NUNUZ AB2 TIMES U2
+12278 ; [.2C60.0020.0002.12278] # CUNEIFORM SIGN NUNUZ KISIM5 TIMES BI
+12279 ; [.2C61.0020.0002.12279] # CUNEIFORM SIGN NUNUZ KISIM5 TIMES BI U
+1227A ; [.2C62.0020.0002.1227A] # CUNEIFORM SIGN PA
+1227B ; [.2C63.0020.0002.1227B] # CUNEIFORM SIGN PAD
+1227C ; [.2C64.0020.0002.1227C] # CUNEIFORM SIGN PAN
+1227D ; [.2C65.0020.0002.1227D] # CUNEIFORM SIGN PAP
+1227E ; [.2C66.0020.0002.1227E] # CUNEIFORM SIGN PESH2
+1227F ; [.2C67.0020.0002.1227F] # CUNEIFORM SIGN PI
+12280 ; [.2C68.0020.0002.12280] # CUNEIFORM SIGN PI TIMES A
+12281 ; [.2C69.0020.0002.12281] # CUNEIFORM SIGN PI TIMES AB
+12282 ; [.2C6A.0020.0002.12282] # CUNEIFORM SIGN PI TIMES BI
+12283 ; [.2C6B.0020.0002.12283] # CUNEIFORM SIGN PI TIMES BU
+12284 ; [.2C6C.0020.0002.12284] # CUNEIFORM SIGN PI TIMES E
+12285 ; [.2C6D.0020.0002.12285] # CUNEIFORM SIGN PI TIMES I
+12286 ; [.2C6E.0020.0002.12286] # CUNEIFORM SIGN PI TIMES IB
+12287 ; [.2C6F.0020.0002.12287] # CUNEIFORM SIGN PI TIMES U
+12288 ; [.2C70.0020.0002.12288] # CUNEIFORM SIGN PI TIMES U2
+12289 ; [.2C71.0020.0002.12289] # CUNEIFORM SIGN PI CROSSING PI
+1228A ; [.2C72.0020.0002.1228A] # CUNEIFORM SIGN PIRIG
+1228B ; [.2C73.0020.0002.1228B] # CUNEIFORM SIGN PIRIG TIMES KAL
+1228C ; [.2C74.0020.0002.1228C] # CUNEIFORM SIGN PIRIG TIMES UD
+1228D ; [.2C75.0020.0002.1228D] # CUNEIFORM SIGN PIRIG TIMES ZA
+1228E ; [.2C76.0020.0002.1228E] # CUNEIFORM SIGN PIRIG OPPOSING PIRIG
+1228F ; [.2C77.0020.0002.1228F] # CUNEIFORM SIGN RA
+12290 ; [.2C78.0020.0002.12290] # CUNEIFORM SIGN RAB
+12291 ; [.2C79.0020.0002.12291] # CUNEIFORM SIGN RI
+12292 ; [.2C7A.0020.0002.12292] # CUNEIFORM SIGN RU
+12293 ; [.2C7B.0020.0002.12293] # CUNEIFORM SIGN SA
+12294 ; [.2C7C.0020.0002.12294] # CUNEIFORM SIGN SAG NUTILLU
+12295 ; [.2C7D.0020.0002.12295] # CUNEIFORM SIGN SAG
+12296 ; [.2C7E.0020.0002.12296] # CUNEIFORM SIGN SAG TIMES A
+12297 ; [.2C7F.0020.0002.12297] # CUNEIFORM SIGN SAG TIMES DU
+12298 ; [.2C80.0020.0002.12298] # CUNEIFORM SIGN SAG TIMES DUB
+12299 ; [.2C81.0020.0002.12299] # CUNEIFORM SIGN SAG TIMES HA
+1229A ; [.2C82.0020.0002.1229A] # CUNEIFORM SIGN SAG TIMES KAK
+1229B ; [.2C83.0020.0002.1229B] # CUNEIFORM SIGN SAG TIMES KUR
+1229C ; [.2C84.0020.0002.1229C] # CUNEIFORM SIGN SAG TIMES LUM
+1229D ; [.2C85.0020.0002.1229D] # CUNEIFORM SIGN SAG TIMES MI
+1229E ; [.2C86.0020.0002.1229E] # CUNEIFORM SIGN SAG TIMES NUN
+1229F ; [.2C87.0020.0002.1229F] # CUNEIFORM SIGN SAG TIMES SAL
+122A0 ; [.2C88.0020.0002.122A0] # CUNEIFORM SIGN SAG TIMES SHID
+122A1 ; [.2C89.0020.0002.122A1] # CUNEIFORM SIGN SAG TIMES TAB
+122A2 ; [.2C8A.0020.0002.122A2] # CUNEIFORM SIGN SAG TIMES U2
+122A3 ; [.2C8B.0020.0002.122A3] # CUNEIFORM SIGN SAG TIMES UB
+122A4 ; [.2C8C.0020.0002.122A4] # CUNEIFORM SIGN SAG TIMES UM
+122A5 ; [.2C8D.0020.0002.122A5] # CUNEIFORM SIGN SAG TIMES UR
+122A6 ; [.2C8E.0020.0002.122A6] # CUNEIFORM SIGN SAG TIMES USH
+122A7 ; [.2C8F.0020.0002.122A7] # CUNEIFORM SIGN SAG OVER SAG
+122A8 ; [.2C90.0020.0002.122A8] # CUNEIFORM SIGN SAG GUNU
+122A9 ; [.2C91.0020.0002.122A9] # CUNEIFORM SIGN SAL
+122AA ; [.2C92.0020.0002.122AA] # CUNEIFORM SIGN SAL LAGAB TIMES ASH2
+122AB ; [.2C93.0020.0002.122AB] # CUNEIFORM SIGN SANGA2
+122AC ; [.2C94.0020.0002.122AC] # CUNEIFORM SIGN SAR
+122AD ; [.2C95.0020.0002.122AD] # CUNEIFORM SIGN SHA
+122AE ; [.2C96.0020.0002.122AE] # CUNEIFORM SIGN SHA3
+122AF ; [.2C97.0020.0002.122AF] # CUNEIFORM SIGN SHA3 TIMES A
+122B0 ; [.2C98.0020.0002.122B0] # CUNEIFORM SIGN SHA3 TIMES BAD
+122B1 ; [.2C99.0020.0002.122B1] # CUNEIFORM SIGN SHA3 TIMES GISH
+122B2 ; [.2C9A.0020.0002.122B2] # CUNEIFORM SIGN SHA3 TIMES NE
+122B3 ; [.2C9B.0020.0002.122B3] # CUNEIFORM SIGN SHA3 TIMES SHU2
+122B4 ; [.2C9C.0020.0002.122B4] # CUNEIFORM SIGN SHA3 TIMES TUR
+122B5 ; [.2C9D.0020.0002.122B5] # CUNEIFORM SIGN SHA3 TIMES U
+122B6 ; [.2C9E.0020.0002.122B6] # CUNEIFORM SIGN SHA3 TIMES U PLUS A
+122B7 ; [.2C9F.0020.0002.122B7] # CUNEIFORM SIGN SHA6
+122B8 ; [.2CA0.0020.0002.122B8] # CUNEIFORM SIGN SHAB6
+122B9 ; [.2CA1.0020.0002.122B9] # CUNEIFORM SIGN SHAR2
+122BA ; [.2CA2.0020.0002.122BA] # CUNEIFORM SIGN SHE
+122BB ; [.2CA3.0020.0002.122BB] # CUNEIFORM SIGN SHE HU
+122BC ; [.2CA4.0020.0002.122BC] # CUNEIFORM SIGN SHE OVER SHE GAD OVER GAD GAR OVER GAR
+122BD ; [.2CA5.0020.0002.122BD] # CUNEIFORM SIGN SHE OVER SHE TAB OVER TAB GAR OVER GAR
+122BE ; [.2CA6.0020.0002.122BE] # CUNEIFORM SIGN SHEG9
+122BF ; [.2CA7.0020.0002.122BF] # CUNEIFORM SIGN SHEN
+122C0 ; [.2CA8.0020.0002.122C0] # CUNEIFORM SIGN SHESH
+122C1 ; [.2CA9.0020.0002.122C1] # CUNEIFORM SIGN SHESH2
+122C2 ; [.2CAA.0020.0002.122C2] # CUNEIFORM SIGN SHESHLAM
+122C3 ; [.2CAB.0020.0002.122C3] # CUNEIFORM SIGN SHID
+122C4 ; [.2CAC.0020.0002.122C4] # CUNEIFORM SIGN SHID TIMES A
+122C5 ; [.2CAD.0020.0002.122C5] # CUNEIFORM SIGN SHID TIMES IM
+122C6 ; [.2CAE.0020.0002.122C6] # CUNEIFORM SIGN SHIM
+122C7 ; [.2CAF.0020.0002.122C7] # CUNEIFORM SIGN SHIM TIMES A
+122C8 ; [.2CB0.0020.0002.122C8] # CUNEIFORM SIGN SHIM TIMES BAL
+122C9 ; [.2CB1.0020.0002.122C9] # CUNEIFORM SIGN SHIM TIMES BULUG
+122CA ; [.2CB2.0020.0002.122CA] # CUNEIFORM SIGN SHIM TIMES DIN
+122CB ; [.2CB3.0020.0002.122CB] # CUNEIFORM SIGN SHIM TIMES GAR
+122CC ; [.2CB4.0020.0002.122CC] # CUNEIFORM SIGN SHIM TIMES IGI
+122CD ; [.2CB5.0020.0002.122CD] # CUNEIFORM SIGN SHIM TIMES IGI GUNU
+122CE ; [.2CB6.0020.0002.122CE] # CUNEIFORM SIGN SHIM TIMES KUSHU2
+122CF ; [.2CB7.0020.0002.122CF] # CUNEIFORM SIGN SHIM TIMES LUL
+122D0 ; [.2CB8.0020.0002.122D0] # CUNEIFORM SIGN SHIM TIMES MUG
+122D1 ; [.2CB9.0020.0002.122D1] # CUNEIFORM SIGN SHIM TIMES SAL
+122D2 ; [.2CBA.0020.0002.122D2] # CUNEIFORM SIGN SHINIG
+122D3 ; [.2CBB.0020.0002.122D3] # CUNEIFORM SIGN SHIR
+122D4 ; [.2CBC.0020.0002.122D4] # CUNEIFORM SIGN SHIR TENU
+122D5 ; [.2CBD.0020.0002.122D5] # CUNEIFORM SIGN SHIR OVER SHIR BUR OVER BUR
+122D6 ; [.2CBE.0020.0002.122D6] # CUNEIFORM SIGN SHITA
+122D7 ; [.2CBF.0020.0002.122D7] # CUNEIFORM SIGN SHU
+122D8 ; [.2CC0.0020.0002.122D8] # CUNEIFORM SIGN SHU OVER INVERTED SHU
+122D9 ; [.2CC1.0020.0002.122D9] # CUNEIFORM SIGN SHU2
+122DA ; [.2CC2.0020.0002.122DA] # CUNEIFORM SIGN SHUBUR
+122DB ; [.2CC3.0020.0002.122DB] # CUNEIFORM SIGN SI
+122DC ; [.2CC4.0020.0002.122DC] # CUNEIFORM SIGN SI GUNU
+122DD ; [.2CC5.0020.0002.122DD] # CUNEIFORM SIGN SIG
+122DE ; [.2CC6.0020.0002.122DE] # CUNEIFORM SIGN SIG4
+122DF ; [.2CC7.0020.0002.122DF] # CUNEIFORM SIGN SIG4 OVER SIG4 SHU2
+122E0 ; [.2CC8.0020.0002.122E0] # CUNEIFORM SIGN SIK2
+122E1 ; [.2CC9.0020.0002.122E1] # CUNEIFORM SIGN SILA3
+122E2 ; [.2CCA.0020.0002.122E2] # CUNEIFORM SIGN SU
+122E3 ; [.2CCB.0020.0002.122E3] # CUNEIFORM SIGN SU OVER SU
+122E4 ; [.2CCC.0020.0002.122E4] # CUNEIFORM SIGN SUD
+122E5 ; [.2CCD.0020.0002.122E5] # CUNEIFORM SIGN SUD2
+122E6 ; [.2CCE.0020.0002.122E6] # CUNEIFORM SIGN SUHUR
+122E7 ; [.2CCF.0020.0002.122E7] # CUNEIFORM SIGN SUM
+122E8 ; [.2CD0.0020.0002.122E8] # CUNEIFORM SIGN SUMASH
+122E9 ; [.2CD1.0020.0002.122E9] # CUNEIFORM SIGN SUR
+122EA ; [.2CD2.0020.0002.122EA] # CUNEIFORM SIGN SUR9
+122EB ; [.2CD3.0020.0002.122EB] # CUNEIFORM SIGN TA
+122EC ; [.2CD4.0020.0002.122EC] # CUNEIFORM SIGN TA ASTERISK
+122ED ; [.2CD5.0020.0002.122ED] # CUNEIFORM SIGN TA TIMES HI
+122EE ; [.2CD6.0020.0002.122EE] # CUNEIFORM SIGN TA TIMES MI
+122EF ; [.2CD7.0020.0002.122EF] # CUNEIFORM SIGN TA GUNU
+122F0 ; [.2CD8.0020.0002.122F0] # CUNEIFORM SIGN TAB
+122F1 ; [.2CD9.0020.0002.122F1] # CUNEIFORM SIGN TAB OVER TAB NI OVER NI DISH OVER DISH
+122F2 ; [.2CDA.0020.0002.122F2] # CUNEIFORM SIGN TAB SQUARED
+122F3 ; [.2CDB.0020.0002.122F3] # CUNEIFORM SIGN TAG
+122F4 ; [.2CDC.0020.0002.122F4] # CUNEIFORM SIGN TAG TIMES BI
+122F5 ; [.2CDD.0020.0002.122F5] # CUNEIFORM SIGN TAG TIMES GUD
+122F6 ; [.2CDE.0020.0002.122F6] # CUNEIFORM SIGN TAG TIMES SHE
+122F7 ; [.2CDF.0020.0002.122F7] # CUNEIFORM SIGN TAG TIMES SHU
+122F8 ; [.2CE0.0020.0002.122F8] # CUNEIFORM SIGN TAG TIMES TUG2
+122F9 ; [.2CE1.0020.0002.122F9] # CUNEIFORM SIGN TAG TIMES UD
+122FA ; [.2CE2.0020.0002.122FA] # CUNEIFORM SIGN TAK4
+122FB ; [.2CE3.0020.0002.122FB] # CUNEIFORM SIGN TAR
+122FC ; [.2CE4.0020.0002.122FC] # CUNEIFORM SIGN TE
+122FD ; [.2CE5.0020.0002.122FD] # CUNEIFORM SIGN TE GUNU
+122FE ; [.2CE6.0020.0002.122FE] # CUNEIFORM SIGN TI
+122FF ; [.2CE7.0020.0002.122FF] # CUNEIFORM SIGN TI TENU
+12300 ; [.2CE8.0020.0002.12300] # CUNEIFORM SIGN TIL
+12301 ; [.2CE9.0020.0002.12301] # CUNEIFORM SIGN TIR
+12302 ; [.2CEA.0020.0002.12302] # CUNEIFORM SIGN TIR TIMES TAK4
+12303 ; [.2CEB.0020.0002.12303] # CUNEIFORM SIGN TIR OVER TIR
+12304 ; [.2CEC.0020.0002.12304] # CUNEIFORM SIGN TIR OVER TIR GAD OVER GAD GAR OVER GAR
+12305 ; [.2CED.0020.0002.12305] # CUNEIFORM SIGN TU
+12306 ; [.2CEE.0020.0002.12306] # CUNEIFORM SIGN TUG2
+12307 ; [.2CEF.0020.0002.12307] # CUNEIFORM SIGN TUK
+12308 ; [.2CF0.0020.0002.12308] # CUNEIFORM SIGN TUM
+12309 ; [.2CF1.0020.0002.12309] # CUNEIFORM SIGN TUR
+1230A ; [.2CF2.0020.0002.1230A] # CUNEIFORM SIGN TUR OVER TUR ZA OVER ZA
+1230B ; [.2CF3.0020.0002.1230B] # CUNEIFORM SIGN U
+1230C ; [.2CF4.0020.0002.1230C] # CUNEIFORM SIGN U GUD
+1230D ; [.2CF5.0020.0002.1230D] # CUNEIFORM SIGN U U U
+1230E ; [.2CF6.0020.0002.1230E] # CUNEIFORM SIGN U OVER U PA OVER PA GAR OVER GAR
+1230F ; [.2CF7.0020.0002.1230F] # CUNEIFORM SIGN U OVER U SUR OVER SUR
+12310 ; [.2CF8.0020.0002.12310] # CUNEIFORM SIGN U OVER U U REVERSED OVER U REVERSED
+12311 ; [.2CF9.0020.0002.12311] # CUNEIFORM SIGN U2
+12312 ; [.2CFA.0020.0002.12312] # CUNEIFORM SIGN UB
+12313 ; [.2CFB.0020.0002.12313] # CUNEIFORM SIGN UD
+12314 ; [.2CFC.0020.0002.12314] # CUNEIFORM SIGN UD KUSHU2
+12315 ; [.2CFD.0020.0002.12315] # CUNEIFORM SIGN UD TIMES BAD
+12316 ; [.2CFE.0020.0002.12316] # CUNEIFORM SIGN UD TIMES MI
+12317 ; [.2CFF.0020.0002.12317] # CUNEIFORM SIGN UD TIMES U PLUS U PLUS U
+12318 ; [.2D00.0020.0002.12318] # CUNEIFORM SIGN UD TIMES U PLUS U PLUS U GUNU
+12319 ; [.2D01.0020.0002.12319] # CUNEIFORM SIGN UD GUNU
+1231A ; [.2D02.0020.0002.1231A] # CUNEIFORM SIGN UD SHESHIG
+1231B ; [.2D03.0020.0002.1231B] # CUNEIFORM SIGN UD SHESHIG TIMES BAD
+1231C ; [.2D04.0020.0002.1231C] # CUNEIFORM SIGN UDUG
+1231D ; [.2D05.0020.0002.1231D] # CUNEIFORM SIGN UM
+1231E ; [.2D06.0020.0002.1231E] # CUNEIFORM SIGN UM TIMES LAGAB
+1231F ; [.2D07.0020.0002.1231F] # CUNEIFORM SIGN UM TIMES ME PLUS DA
+12320 ; [.2D08.0020.0002.12320] # CUNEIFORM SIGN UM TIMES SHA3
+12321 ; [.2D09.0020.0002.12321] # CUNEIFORM SIGN UM TIMES U
+12322 ; [.2D0A.0020.0002.12322] # CUNEIFORM SIGN UMBIN
+12323 ; [.2D0B.0020.0002.12323] # CUNEIFORM SIGN UMUM
+12324 ; [.2D0C.0020.0002.12324] # CUNEIFORM SIGN UMUM TIMES KASKAL
+12325 ; [.2D0D.0020.0002.12325] # CUNEIFORM SIGN UMUM TIMES PA
+12326 ; [.2D0E.0020.0002.12326] # CUNEIFORM SIGN UN
+12327 ; [.2D0F.0020.0002.12327] # CUNEIFORM SIGN UN GUNU
+12328 ; [.2D10.0020.0002.12328] # CUNEIFORM SIGN UR
+12329 ; [.2D11.0020.0002.12329] # CUNEIFORM SIGN UR CROSSING UR
+1232A ; [.2D12.0020.0002.1232A] # CUNEIFORM SIGN UR SHESHIG
+1232B ; [.2D13.0020.0002.1232B] # CUNEIFORM SIGN UR2
+1232C ; [.2D14.0020.0002.1232C] # CUNEIFORM SIGN UR2 TIMES A PLUS HA
+1232D ; [.2D15.0020.0002.1232D] # CUNEIFORM SIGN UR2 TIMES A PLUS NA
+1232E ; [.2D16.0020.0002.1232E] # CUNEIFORM SIGN UR2 TIMES AL
+1232F ; [.2D17.0020.0002.1232F] # CUNEIFORM SIGN UR2 TIMES HA
+12330 ; [.2D18.0020.0002.12330] # CUNEIFORM SIGN UR2 TIMES NUN
+12331 ; [.2D19.0020.0002.12331] # CUNEIFORM SIGN UR2 TIMES U2
+12332 ; [.2D1A.0020.0002.12332] # CUNEIFORM SIGN UR2 TIMES U2 PLUS ASH
+12333 ; [.2D1B.0020.0002.12333] # CUNEIFORM SIGN UR2 TIMES U2 PLUS BI
+12334 ; [.2D1C.0020.0002.12334] # CUNEIFORM SIGN UR4
+12335 ; [.2D1D.0020.0002.12335] # CUNEIFORM SIGN URI
+12336 ; [.2D1E.0020.0002.12336] # CUNEIFORM SIGN URI3
+12337 ; [.2D1F.0020.0002.12337] # CUNEIFORM SIGN URU
+12338 ; [.2D20.0020.0002.12338] # CUNEIFORM SIGN URU TIMES A
+12339 ; [.2D21.0020.0002.12339] # CUNEIFORM SIGN URU TIMES ASHGAB
+1233A ; [.2D22.0020.0002.1233A] # CUNEIFORM SIGN URU TIMES BAR
+1233B ; [.2D23.0020.0002.1233B] # CUNEIFORM SIGN URU TIMES DUN
+1233C ; [.2D24.0020.0002.1233C] # CUNEIFORM SIGN URU TIMES GA
+1233D ; [.2D25.0020.0002.1233D] # CUNEIFORM SIGN URU TIMES GAL
+1233E ; [.2D26.0020.0002.1233E] # CUNEIFORM SIGN URU TIMES GAN2 TENU
+1233F ; [.2D27.0020.0002.1233F] # CUNEIFORM SIGN URU TIMES GAR
+12340 ; [.2D28.0020.0002.12340] # CUNEIFORM SIGN URU TIMES GU
+12341 ; [.2D29.0020.0002.12341] # CUNEIFORM SIGN URU TIMES HA
+12342 ; [.2D2A.0020.0002.12342] # CUNEIFORM SIGN URU TIMES IGI
+12343 ; [.2D2B.0020.0002.12343] # CUNEIFORM SIGN URU TIMES IM
+12344 ; [.2D2C.0020.0002.12344] # CUNEIFORM SIGN URU TIMES ISH
+12345 ; [.2D2D.0020.0002.12345] # CUNEIFORM SIGN URU TIMES KI
+12346 ; [.2D2E.0020.0002.12346] # CUNEIFORM SIGN URU TIMES LUM
+12347 ; [.2D2F.0020.0002.12347] # CUNEIFORM SIGN URU TIMES MIN
+12348 ; [.2D30.0020.0002.12348] # CUNEIFORM SIGN URU TIMES PA
+12349 ; [.2D31.0020.0002.12349] # CUNEIFORM SIGN URU TIMES SHE
+1234A ; [.2D32.0020.0002.1234A] # CUNEIFORM SIGN URU TIMES SIG4
+1234B ; [.2D33.0020.0002.1234B] # CUNEIFORM SIGN URU TIMES TU
+1234C ; [.2D34.0020.0002.1234C] # CUNEIFORM SIGN URU TIMES U PLUS GUD
+1234D ; [.2D35.0020.0002.1234D] # CUNEIFORM SIGN URU TIMES UD
+1234E ; [.2D36.0020.0002.1234E] # CUNEIFORM SIGN URU TIMES URUDA
+1234F ; [.2D37.0020.0002.1234F] # CUNEIFORM SIGN URUDA
+12350 ; [.2D38.0020.0002.12350] # CUNEIFORM SIGN URUDA TIMES U
+12351 ; [.2D39.0020.0002.12351] # CUNEIFORM SIGN USH
+12352 ; [.2D3A.0020.0002.12352] # CUNEIFORM SIGN USH TIMES A
+12353 ; [.2D3B.0020.0002.12353] # CUNEIFORM SIGN USH TIMES KU
+12354 ; [.2D3C.0020.0002.12354] # CUNEIFORM SIGN USH TIMES KUR
+12355 ; [.2D3D.0020.0002.12355] # CUNEIFORM SIGN USH TIMES TAK4
+12356 ; [.2D3E.0020.0002.12356] # CUNEIFORM SIGN USHX
+12357 ; [.2D3F.0020.0002.12357] # CUNEIFORM SIGN USH2
+12358 ; [.2D40.0020.0002.12358] # CUNEIFORM SIGN USHUMX
+12359 ; [.2D41.0020.0002.12359] # CUNEIFORM SIGN UTUKI
+1235A ; [.2D42.0020.0002.1235A] # CUNEIFORM SIGN UZ3
+1235B ; [.2D43.0020.0002.1235B] # CUNEIFORM SIGN UZ3 TIMES KASKAL
+1235C ; [.2D44.0020.0002.1235C] # CUNEIFORM SIGN UZU
+1235D ; [.2D45.0020.0002.1235D] # CUNEIFORM SIGN ZA
+1235E ; [.2D46.0020.0002.1235E] # CUNEIFORM SIGN ZA TENU
+1235F ; [.2D47.0020.0002.1235F] # CUNEIFORM SIGN ZA SQUARED TIMES KUR
+12360 ; [.2D48.0020.0002.12360] # CUNEIFORM SIGN ZAG
+12361 ; [.2D49.0020.0002.12361] # CUNEIFORM SIGN ZAMX
+12362 ; [.2D4A.0020.0002.12362] # CUNEIFORM SIGN ZE2
+12363 ; [.2D4B.0020.0002.12363] # CUNEIFORM SIGN ZI
+12364 ; [.2D4C.0020.0002.12364] # CUNEIFORM SIGN ZI OVER ZI
+12365 ; [.2D4D.0020.0002.12365] # CUNEIFORM SIGN ZI3
+12366 ; [.2D4E.0020.0002.12366] # CUNEIFORM SIGN ZIB
+12367 ; [.2D4F.0020.0002.12367] # CUNEIFORM SIGN ZIB KABA TENU
+12368 ; [.2D50.0020.0002.12368] # CUNEIFORM SIGN ZIG
+12369 ; [.2D51.0020.0002.12369] # CUNEIFORM SIGN ZIZ2
+1236A ; [.2D52.0020.0002.1236A] # CUNEIFORM SIGN ZU
+1236B ; [.2D53.0020.0002.1236B] # CUNEIFORM SIGN ZU5
+1236C ; [.2D54.0020.0002.1236C] # CUNEIFORM SIGN ZU5 TIMES A
+1236D ; [.2D55.0020.0002.1236D] # CUNEIFORM SIGN ZUBUR
+1236E ; [.2D56.0020.0002.1236E] # CUNEIFORM SIGN ZUM
+2F00 ; [.FB40.0020.0004.4E00][.CE00.0000.0000.4E00] # KANGXI RADICAL ONE; QQK
+3220 ; [*02B1.0020.0004.3220][.FB40.0020.0004.4E00][.CE00.0000.0000.4E00][*02B2.0020.001F.3220] # PARENTHESIZED IDEOGRAPH ONE; QQKN
+3280 ; [.FB40.0020.0006.4E00][.CE00.0000.0000.4E00] # CIRCLED IDEOGRAPH ONE; QQK
+3192 ; [.FB40.0020.0014.4E00][.CE00.0000.0000.4E00] # IDEOGRAPHIC ANNOTATION ONE MARK; QQK
+319C ; [.FB40.0020.0014.4E01][.CE01.0000.0000.4E01] # IDEOGRAPHIC ANNOTATION FOURTH MARK; QQK
+3226 ; [*02B1.0020.0004.3226][.FB40.0020.0004.4E03][.CE03.0000.0000.4E03][*02B2.0020.001F.3226] # PARENTHESIZED IDEOGRAPH SEVEN; QQKN
+3286 ; [.FB40.0020.0006.4E03][.CE03.0000.0000.4E03] # CIRCLED IDEOGRAPH SEVEN; QQK
+3222 ; [*02B1.0020.0004.3222][.FB40.0020.0004.4E09][.CE09.0000.0000.4E09][*02B2.0020.001F.3222] # PARENTHESIZED IDEOGRAPH THREE; QQKN
+3282 ; [.FB40.0020.0006.4E09][.CE09.0000.0000.4E09] # CIRCLED IDEOGRAPH THREE; QQK
+3194 ; [.FB40.0020.0014.4E09][.CE09.0000.0000.4E09] # IDEOGRAPHIC ANNOTATION THREE MARK; QQK
+32A4 ; [.FB40.0020.0006.4E0A][.CE0A.0000.0000.4E0A] # CIRCLED IDEOGRAPH HIGH; QQK
+3196 ; [.FB40.0020.0014.4E0A][.CE0A.0000.0000.4E0A] # IDEOGRAPHIC ANNOTATION TOP MARK; QQK
+32A6 ; [.FB40.0020.0006.4E0B][.CE0B.0000.0000.4E0B] # CIRCLED IDEOGRAPH LOW; QQK
+3198 ; [.FB40.0020.0014.4E0B][.CE0B.0000.0000.4E0B] # IDEOGRAPHIC ANNOTATION BOTTOM MARK; QQK
+F967 ; [.FB40.0020.0002.4E0D][.CE0D.0000.0000.4E0D] # CJK COMPATIBILITY IDEOGRAPH-F967; QQC
+319B ; [.FB40.0020.0014.4E19][.CE19.0000.0000.4E19] # IDEOGRAPHIC ANNOTATION THIRD MARK; QQK
+FA70 ; [.FB40.0020.0002.4E26][.CE26.0000.0000.4E26] # CJK COMPATIBILITY IDEOGRAPH-FA70; QQC
+2F01 ; [.FB40.0020.0004.4E28][.CE28.0000.0000.4E28] # KANGXI RADICAL LINE; QQK
+2EA6 ; [.FB40.0020.0004.4E2C][.CE2C.0000.0000.4E2C] # CJK RADICAL SIMPLIFIED HALF TREE TRUNK; QQK
+32A5 ; [.FB40.0020.0006.4E2D][.CE2D.0000.0000.4E2D] # CIRCLED IDEOGRAPH CENTRE; QQK
+3197 ; [.FB40.0020.0014.4E2D][.CE2D.0000.0000.4E2D] # IDEOGRAPHIC ANNOTATION MIDDLE MARK; QQK
+F905 ; [.FB40.0020.0002.4E32][.CE32.0000.0000.4E32] # CJK COMPATIBILITY IDEOGRAPH-F905; QQC
+2F02 ; [.FB40.0020.0004.4E36][.CE36.0000.0000.4E36] # KANGXI RADICAL DOT; QQK
+2E80 ; [.FB40.0020.0004.4E36][.CE36.0000.0000.4E36][.0000.0199.001F.2E80] # CJK RADICAL REPEAT; QQKN
+2F801 ; [.FB40.0020.0002.4E38][.CE38.0000.0000.4E38] # CJK COMPATIBILITY IDEOGRAPH-2F801; QQC
+F95E ; [.FB40.0020.0002.4E39][.CE39.0000.0000.4E39] # CJK COMPATIBILITY IDEOGRAPH-F95E; QQC
+2F800 ; [.FB40.0020.0002.4E3D][.CE3D.0000.0000.4E3D] # CJK COMPATIBILITY IDEOGRAPH-2F800; QQC
+2F03 ; [.FB40.0020.0004.4E3F][.CE3F.0000.0000.4E3F] # KANGXI RADICAL SLASH; QQK
+2F802 ; [.FB40.0020.0002.4E41][.CE41.0000.0000.4E41] # CJK COMPATIBILITY IDEOGRAPH-2F802; QQC
+2F04 ; [.FB40.0020.0004.4E59][.CE59.0000.0000.4E59] # KANGXI RADICAL SECOND; QQK
+319A ; [.FB40.0020.0014.4E59][.CE59.0000.0000.4E59] # IDEOGRAPHIC ANNOTATION SECOND MARK; QQK
+2E84 ; [.FB40.0020.0004.4E59][.CE59.0000.0000.4E59][.0000.0199.001F.2E84] # CJK RADICAL SECOND THREE; QQKN
+2E83 ; [.FB40.0020.0004.4E5A][.CE5A.0000.0000.4E5A] # CJK RADICAL SECOND TWO; QQK
+2E82 ; [.FB40.0020.0004.4E5B][.CE5B.0000.0000.4E5B] # CJK RADICAL SECOND ONE; QQK
+3228 ; [*02B1.0020.0004.3228][.FB40.0020.0004.4E5D][.CE5D.0000.0000.4E5D][*02B2.0020.001F.3228] # PARENTHESIZED IDEOGRAPH NINE; QQKN
+3288 ; [.FB40.0020.0006.4E5D][.CE5D.0000.0000.4E5D] # CIRCLED IDEOGRAPH NINE; QQK
+F91B ; [.FB40.0020.0002.4E82][.CE82.0000.0000.4E82] # CJK COMPATIBILITY IDEOGRAPH-F91B; QQC
+2F05 ; [.FB40.0020.0004.4E85][.CE85.0000.0000.4E85] # KANGXI RADICAL HOOK; QQK
+F9BA ; [.FB40.0020.0002.4E86][.CE86.0000.0000.4E86] # CJK COMPATIBILITY IDEOGRAPH-F9BA; QQC
+2F06 ; [.FB40.0020.0004.4E8C][.CE8C.0000.0000.4E8C] # KANGXI RADICAL TWO; QQK
+3221 ; [*02B1.0020.0004.3221][.FB40.0020.0004.4E8C][.CE8C.0000.0000.4E8C][*02B2.0020.001F.3221] # PARENTHESIZED IDEOGRAPH TWO; QQKN
+3281 ; [.FB40.0020.0006.4E8C][.CE8C.0000.0000.4E8C] # CIRCLED IDEOGRAPH TWO; QQK
+3193 ; [.FB40.0020.0014.4E8C][.CE8C.0000.0000.4E8C] # IDEOGRAPHIC ANNOTATION TWO MARK; QQK
+3224 ; [*02B1.0020.0004.3224][.FB40.0020.0004.4E94][.CE94.0000.0000.4E94][*02B2.0020.001F.3224] # PARENTHESIZED IDEOGRAPH FIVE; QQKN
+3284 ; [.FB40.0020.0006.4E94][.CE94.0000.0000.4E94] # CIRCLED IDEOGRAPH FIVE; QQK
+2F07 ; [.FB40.0020.0004.4EA0][.CEA0.0000.0000.4EA0] # KANGXI RADICAL LID; QQK
+F977 ; [.FB40.0020.0002.4EAE][.CEAE.0000.0000.4EAE] # CJK COMPATIBILITY IDEOGRAPH-F977; QQC
+2F08 ; [.FB40.0020.0004.4EBA][.CEBA.0000.0000.4EBA] # KANGXI RADICAL MAN; QQK
+319F ; [.FB40.0020.0014.4EBA][.CEBA.0000.0000.4EBA] # IDEOGRAPHIC ANNOTATION MAN MARK; QQK
+2E85 ; [.FB40.0020.0004.4EBB][.CEBB.0000.0000.4EBB] # CJK RADICAL PERSON; QQK
+F9FD ; [.FB40.0020.0002.4EC0][.CEC0.0000.0000.4EC0] # CJK COMPATIBILITY IDEOGRAPH-F9FD; QQC
+2F819 ; [.FB40.0020.0002.4ECC][.CECC.0000.0000.4ECC] # CJK COMPATIBILITY IDEOGRAPH-2F819; QQC
+3239 ; [*02B1.0020.0004.3239][.FB40.0020.0004.4EE3][.CEE3.0000.0000.4EE3][*02B2.0020.001F.3239] # PARENTHESIZED IDEOGRAPH REPRESENT; QQKN
+F9A8 ; [.FB40.0020.0002.4EE4][.CEE4.0000.0000.4EE4] # CJK COMPATIBILITY IDEOGRAPH-F9A8; QQC
+323D ; [*02B1.0020.0004.323D][.FB40.0020.0004.4F01][.CF01.0000.0000.4F01][*02B2.0020.001F.323D] # PARENTHESIZED IDEOGRAPH ENTERPRISE; QQKN
+32AD ; [.FB40.0020.0006.4F01][.CF01.0000.0000.4F01] # CIRCLED IDEOGRAPH ENTERPRISE; QQK
+3241 ; [*02B1.0020.0004.3241][.FB40.0020.0004.4F11][.CF11.0000.0000.4F11][*02B2.0020.001F.3241] # PARENTHESIZED IDEOGRAPH REST; QQKN
+32A1 ; [.FB40.0020.0006.4F11][.CF11.0000.0000.4F11] # CIRCLED IDEOGRAPH REST; QQK
+2F804 ; [.FB40.0020.0002.4F60][.CF60.0000.0000.4F60] # CJK COMPATIBILITY IDEOGRAPH-2F804; QQC
+FA73 ; [.FB40.0020.0002.4F80][.CF80.0000.0000.4F80] # CJK COMPATIBILITY IDEOGRAPH-FA73; QQC
+F92D ; [.FB40.0020.0002.4F86][.CF86.0000.0000.4F86] # CJK COMPATIBILITY IDEOGRAPH-F92D; QQC
+F9B5 ; [.FB40.0020.0002.4F8B][.CF8B.0000.0000.4F8B] # CJK COMPATIBILITY IDEOGRAPH-F9B5; QQC
+FA30 ; [.FB40.0020.0002.4FAE][.CFAE.0000.0000.4FAE] # CJK COMPATIBILITY IDEOGRAPH-FA30; QQC
+2F805 ; [.FB40.0020.0002.4FAE][.CFAE.0000.0000.4FAE] # CJK COMPATIBILITY IDEOGRAPH-2F805; QQC
+2F806 ; [.FB40.0020.0002.4FBB][.CFBB.0000.0000.4FBB] # CJK COMPATIBILITY IDEOGRAPH-2F806; QQC
+F965 ; [.FB40.0020.0002.4FBF][.CFBF.0000.0000.4FBF] # CJK COMPATIBILITY IDEOGRAPH-F965; QQC
+2F807 ; [.FB40.0020.0002.5002][.D002.0000.0000.5002] # CJK COMPATIBILITY IDEOGRAPH-2F807; QQC
+F9D4 ; [.FB40.0020.0002.502B][.D02B.0000.0000.502B] # CJK COMPATIBILITY IDEOGRAPH-F9D4; QQC
+2F808 ; [.FB40.0020.0002.507A][.D07A.0000.0000.507A] # CJK COMPATIBILITY IDEOGRAPH-2F808; QQC
+2F809 ; [.FB40.0020.0002.5099][.D099.0000.0000.5099] # CJK COMPATIBILITY IDEOGRAPH-2F809; QQC
+2F80B ; [.FB40.0020.0002.50CF][.D0CF.0000.0000.50CF] # CJK COMPATIBILITY IDEOGRAPH-2F80B; QQC
+F9BB ; [.FB40.0020.0002.50DA][.D0DA.0000.0000.50DA] # CJK COMPATIBILITY IDEOGRAPH-F9BB; QQC
+FA31 ; [.FB40.0020.0002.50E7][.D0E7.0000.0000.50E7] # CJK COMPATIBILITY IDEOGRAPH-FA31; QQC
+2F80A ; [.FB40.0020.0002.50E7][.D0E7.0000.0000.50E7] # CJK COMPATIBILITY IDEOGRAPH-2F80A; QQC
+329D ; [.FB40.0020.0006.512A][.D12A.0000.0000.512A] # CIRCLED IDEOGRAPH EXCELLENT; QQK
+2F09 ; [.FB40.0020.0004.513F][.D13F.0000.0000.513F] # KANGXI RADICAL LEGS; QQK
+FA0C ; [.FB40.0020.0002.5140][.D140.0000.0000.5140] # CJK COMPATIBILITY IDEOGRAPH-FA0C; QQC
+FA74 ; [.FB40.0020.0002.5145][.D145.0000.0000.5145] # CJK COMPATIBILITY IDEOGRAPH-FA74; QQC
+FA32 ; [.FB40.0020.0002.514D][.D14D.0000.0000.514D] # CJK COMPATIBILITY IDEOGRAPH-FA32; QQC
+2F80E ; [.FB40.0020.0002.514D][.D14D.0000.0000.514D] # CJK COMPATIBILITY IDEOGRAPH-2F80E; QQC
+2F80F ; [.FB40.0020.0002.5154][.D154.0000.0000.5154] # CJK COMPATIBILITY IDEOGRAPH-2F80F; QQC
+2F810 ; [.FB40.0020.0002.5164][.D164.0000.0000.5164] # CJK COMPATIBILITY IDEOGRAPH-2F810; QQC
+2F0A ; [.FB40.0020.0004.5165][.D165.0000.0000.5165] # KANGXI RADICAL ENTER; QQK
+2F814 ; [.FB40.0020.0002.5167][.D167.0000.0000.5167] # CJK COMPATIBILITY IDEOGRAPH-2F814; QQC
+FA72 ; [.FB40.0020.0002.5168][.D168.0000.0000.5168] # CJK COMPATIBILITY IDEOGRAPH-FA72; QQC
+F978 ; [.FB40.0020.0002.5169][.D169.0000.0000.5169] # CJK COMPATIBILITY IDEOGRAPH-F978; QQC
+2F0B ; [.FB40.0020.0004.516B][.D16B.0000.0000.516B] # KANGXI RADICAL EIGHT; QQK
+3227 ; [*02B1.0020.0004.3227][.FB40.0020.0004.516B][.D16B.0000.0000.516B][*02B2.0020.001F.3227] # PARENTHESIZED IDEOGRAPH EIGHT; QQKN
+3287 ; [.FB40.0020.0006.516B][.D16B.0000.0000.516B] # CIRCLED IDEOGRAPH EIGHT; QQK
+F9D1 ; [.FB40.0020.0002.516D][.D16D.0000.0000.516D] # CJK COMPATIBILITY IDEOGRAPH-F9D1; QQC
+3225 ; [*02B1.0020.0004.3225][.FB40.0020.0004.516D][.D16D.0000.0000.516D][*02B2.0020.001F.3225] # PARENTHESIZED IDEOGRAPH SIX; QQKN
+3285 ; [.FB40.0020.0006.516D][.D16D.0000.0000.516D] # CIRCLED IDEOGRAPH SIX; QQK
+2F811 ; [.FB40.0020.0002.5177][.D177.0000.0000.5177] # CJK COMPATIBILITY IDEOGRAPH-2F811; QQC
+FA75 ; [.FB40.0020.0002.5180][.D180.0000.0000.5180] # CJK COMPATIBILITY IDEOGRAPH-FA75; QQC
+2F0C ; [.FB40.0020.0004.5182][.D182.0000.0000.5182] # KANGXI RADICAL DOWN BOX; QQK
+2E86 ; [.FB40.0020.0004.5182][.D182.0000.0000.5182][.0000.0199.001F.2E86] # CJK RADICAL BOX; QQKN
+2F815 ; [.FB40.0020.0002.518D][.D18D.0000.0000.518D] # CJK COMPATIBILITY IDEOGRAPH-2F815; QQC
+2F8D2 ; [.FB40.0020.0002.5192][.D192.0000.0000.5192] # CJK COMPATIBILITY IDEOGRAPH-2F8D2; QQC
+2F8D3 ; [.FB40.0020.0002.5195][.D195.0000.0000.5195] # CJK COMPATIBILITY IDEOGRAPH-2F8D3; QQC
+2F0D ; [.FB40.0020.0004.5196][.D196.0000.0000.5196] # KANGXI RADICAL COVER; QQK
+2F817 ; [.FB40.0020.0002.5197][.D197.0000.0000.5197] # CJK COMPATIBILITY IDEOGRAPH-2F817; QQC
+32A2 ; [.FB40.0020.0006.5199][.D199.0000.0000.5199] # CIRCLED IDEOGRAPH COPY; QQK
+2F818 ; [.FB40.0020.0002.51A4][.D1A4.0000.0000.51A4] # CJK COMPATIBILITY IDEOGRAPH-2F818; QQC
+2F0E ; [.FB40.0020.0004.51AB][.D1AB.0000.0000.51AB] # KANGXI RADICAL ICE; QQK
+2F81A ; [.FB40.0020.0002.51AC][.D1AC.0000.0000.51AC] # CJK COMPATIBILITY IDEOGRAPH-2F81A; QQC
+FA71 ; [.FB40.0020.0002.51B5][.D1B5.0000.0000.51B5] # CJK COMPATIBILITY IDEOGRAPH-FA71; QQC
+2F81B ; [.FB40.0020.0002.51B5][.D1B5.0000.0000.51B5] # CJK COMPATIBILITY IDEOGRAPH-2F81B; QQC
+F92E ; [.FB40.0020.0002.51B7][.D1B7.0000.0000.51B7] # CJK COMPATIBILITY IDEOGRAPH-F92E; QQC
+F979 ; [.FB40.0020.0002.51C9][.D1C9.0000.0000.51C9] # CJK COMPATIBILITY IDEOGRAPH-F979; QQC
+F955 ; [.FB40.0020.0002.51CC][.D1CC.0000.0000.51CC] # CJK COMPATIBILITY IDEOGRAPH-F955; QQC
+F954 ; [.FB40.0020.0002.51DC][.D1DC.0000.0000.51DC] # CJK COMPATIBILITY IDEOGRAPH-F954; QQC
+FA15 ; [.FB40.0020.0002.51DE][.D1DE.0000.0000.51DE] # CJK COMPATIBILITY IDEOGRAPH-FA15; QQC
+2F0F ; [.FB40.0020.0004.51E0][.D1E0.0000.0000.51E0] # KANGXI RADICAL TABLE; QQK
+2E87 ; [.FB40.0020.0004.51E0][.D1E0.0000.0000.51E0][.0000.0199.001F.2E87] # CJK RADICAL TABLE; QQKN
+2F81D ; [.FB40.0020.0002.51F5][.D1F5.0000.0000.51F5] # CJK COMPATIBILITY IDEOGRAPH-2F81D; QQC
+2F10 ; [.FB40.0020.0004.51F5][.D1F5.0000.0000.51F5] # KANGXI RADICAL OPEN BOX; QQK
+2F11 ; [.FB40.0020.0004.5200][.D200.0000.0000.5200] # KANGXI RADICAL KNIFE; QQK
+2E88 ; [.FB40.0020.0004.5200][.D200.0000.0000.5200][.0000.0199.001F.2E88] # CJK RADICAL KNIFE ONE; QQKN
+2E89 ; [.FB40.0020.0004.5202][.D202.0000.0000.5202] # CJK RADICAL KNIFE TWO; QQK
+2F81E ; [.FB40.0020.0002.5203][.D203.0000.0000.5203] # CJK COMPATIBILITY IDEOGRAPH-2F81E; QQC
+FA00 ; [.FB40.0020.0002.5207][.D207.0000.0000.5207] # CJK COMPATIBILITY IDEOGRAPH-FA00; QQC
+2F850 ; [.FB40.0020.0002.5207][.D207.0000.0000.5207] # CJK COMPATIBILITY IDEOGRAPH-2F850; QQC
+F99C ; [.FB40.0020.0002.5217][.D217.0000.0000.5217] # CJK COMPATIBILITY IDEOGRAPH-F99C; QQC
+F9DD ; [.FB40.0020.0002.5229][.D229.0000.0000.5229] # CJK COMPATIBILITY IDEOGRAPH-F9DD; QQC
+F9FF ; [.FB40.0020.0002.523A][.D23A.0000.0000.523A] # CJK COMPATIBILITY IDEOGRAPH-F9FF; QQC
+2F820 ; [.FB40.0020.0002.523B][.D23B.0000.0000.523B] # CJK COMPATIBILITY IDEOGRAPH-2F820; QQC
+2F821 ; [.FB40.0020.0002.5246][.D246.0000.0000.5246] # CJK COMPATIBILITY IDEOGRAPH-2F821; QQC
+2F822 ; [.FB40.0020.0002.5272][.D272.0000.0000.5272] # CJK COMPATIBILITY IDEOGRAPH-2F822; QQC
+2F823 ; [.FB40.0020.0002.5277][.D277.0000.0000.5277] # CJK COMPATIBILITY IDEOGRAPH-2F823; QQC
+F9C7 ; [.FB40.0020.0002.5289][.D289.0000.0000.5289] # CJK COMPATIBILITY IDEOGRAPH-F9C7; QQC
+F98A ; [.FB40.0020.0002.529B][.D29B.0000.0000.529B] # CJK COMPATIBILITY IDEOGRAPH-F98A; QQC
+2F12 ; [.FB40.0020.0004.529B][.D29B.0000.0000.529B] # KANGXI RADICAL POWER; QQK
+F99D ; [.FB40.0020.0002.52A3][.D2A3.0000.0000.52A3] # CJK COMPATIBILITY IDEOGRAPH-F99D; QQC
+2F992 ; [.FB40.0020.0002.52B3][.D2B3.0000.0000.52B3] # CJK COMPATIBILITY IDEOGRAPH-2F992; QQC
+3238 ; [*02B1.0020.0004.3238][.FB40.0020.0004.52B4][.D2B4.0000.0000.52B4][*02B2.0020.001F.3238] # PARENTHESIZED IDEOGRAPH LABOR; QQKN
+3298 ; [.FB40.0020.0006.52B4][.D2B4.0000.0000.52B4] # CIRCLED IDEOGRAPH LABOR; QQK
+FA76 ; [.FB40.0020.0002.52C7][.D2C7.0000.0000.52C7] # CJK COMPATIBILITY IDEOGRAPH-FA76; QQC
+2F825 ; [.FB40.0020.0002.52C7][.D2C7.0000.0000.52C7] # CJK COMPATIBILITY IDEOGRAPH-2F825; QQC
+FA33 ; [.FB40.0020.0002.52C9][.D2C9.0000.0000.52C9] # CJK COMPATIBILITY IDEOGRAPH-FA33; QQC
+2F826 ; [.FB40.0020.0002.52C9][.D2C9.0000.0000.52C9] # CJK COMPATIBILITY IDEOGRAPH-2F826; QQC
+F952 ; [.FB40.0020.0002.52D2][.D2D2.0000.0000.52D2] # CJK COMPATIBILITY IDEOGRAPH-F952; QQC
+F92F ; [.FB40.0020.0002.52DE][.D2DE.0000.0000.52DE] # CJK COMPATIBILITY IDEOGRAPH-F92F; QQC
+FA34 ; [.FB40.0020.0002.52E4][.D2E4.0000.0000.52E4] # CJK COMPATIBILITY IDEOGRAPH-FA34; QQC
+2F827 ; [.FB40.0020.0002.52E4][.D2E4.0000.0000.52E4] # CJK COMPATIBILITY IDEOGRAPH-2F827; QQC
+F97F ; [.FB40.0020.0002.52F5][.D2F5.0000.0000.52F5] # CJK COMPATIBILITY IDEOGRAPH-F97F; QQC
+2F13 ; [.FB40.0020.0004.52F9][.D2F9.0000.0000.52F9] # KANGXI RADICAL WRAP; QQK
+FA77 ; [.FB40.0020.0002.52FA][.D2FA.0000.0000.52FA] # CJK COMPATIBILITY IDEOGRAPH-FA77; QQC
+2F828 ; [.FB40.0020.0002.52FA][.D2FA.0000.0000.52FA] # CJK COMPATIBILITY IDEOGRAPH-2F828; QQC
+2F829 ; [.FB40.0020.0002.5305][.D305.0000.0000.5305] # CJK COMPATIBILITY IDEOGRAPH-2F829; QQC
+2F82A ; [.FB40.0020.0002.5306][.D306.0000.0000.5306] # CJK COMPATIBILITY IDEOGRAPH-2F82A; QQC
+2F14 ; [.FB40.0020.0004.5315][.D315.0000.0000.5315] # KANGXI RADICAL SPOON; QQK
+F963 ; [.FB40.0020.0002.5317][.D317.0000.0000.5317] # CJK COMPATIBILITY IDEOGRAPH-F963; QQC
+2F82B ; [.FB40.0020.0002.5317][.D317.0000.0000.5317] # CJK COMPATIBILITY IDEOGRAPH-2F82B; QQC
+2F15 ; [.FB40.0020.0004.531A][.D31A.0000.0000.531A] # KANGXI RADICAL RIGHT OPEN BOX; QQK
+2F16 ; [.FB40.0020.0004.5338][.D338.0000.0000.5338] # KANGXI RADICAL HIDING ENCLOSURE; QQK
+32A9 ; [.FB40.0020.0006.533B][.D33B.0000.0000.533B] # CIRCLED IDEOGRAPH MEDICINE; QQK
+F9EB ; [.FB40.0020.0002.533F][.D33F.0000.0000.533F] # CJK COMPATIBILITY IDEOGRAPH-F9EB; QQC
+2F17 ; [.FB40.0020.0004.5341][.D341.0000.0000.5341] # KANGXI RADICAL TEN; QQK
+3038 ; [.FB40.0020.0004.5341][.D341.0000.0000.5341] # HANGZHOU NUMERAL TEN; QQK
+3229 ; [*02B1.0020.0004.3229][.FB40.0020.0004.5341][.D341.0000.0000.5341][*02B2.0020.001F.3229] # PARENTHESIZED IDEOGRAPH TEN; QQKN
+3289 ; [.FB40.0020.0006.5341][.D341.0000.0000.5341] # CIRCLED IDEOGRAPH TEN; QQK
+3039 ; [.FB40.0020.0004.5344][.D344.0000.0000.5344] # HANGZHOU NUMERAL TWENTY; QQK
+303A ; [.FB40.0020.0004.5345][.D345.0000.0000.5345] # HANGZHOU NUMERAL THIRTY; QQK
+2F82C ; [.FB40.0020.0002.5349][.D349.0000.0000.5349] # CJK COMPATIBILITY IDEOGRAPH-2F82C; QQC
+FA35 ; [.FB40.0020.0002.5351][.D351.0000.0000.5351] # CJK COMPATIBILITY IDEOGRAPH-FA35; QQC
+2F82D ; [.FB40.0020.0002.5351][.D351.0000.0000.5351] # CJK COMPATIBILITY IDEOGRAPH-2F82D; QQC
+323F ; [*02B1.0020.0004.323F][.FB40.0020.0004.5354][.D354.0000.0000.5354][*02B2.0020.001F.323F] # PARENTHESIZED IDEOGRAPH ALLIANCE; QQKN
+32AF ; [.FB40.0020.0006.5354][.D354.0000.0000.5354] # CIRCLED IDEOGRAPH ALLIANCE; QQK
+2F82E ; [.FB40.0020.0002.535A][.D35A.0000.0000.535A] # CJK COMPATIBILITY IDEOGRAPH-2F82E; QQC
+2F18 ; [.FB40.0020.0004.535C][.D35C.0000.0000.535C] # KANGXI RADICAL DIVINATION; QQK
+2E8A ; [.FB40.0020.0004.535C][.D35C.0000.0000.535C][.0000.0199.001F.2E8A] # CJK RADICAL DIVINATION; QQKN
+2F19 ; [.FB40.0020.0004.5369][.D369.0000.0000.5369] # KANGXI RADICAL SEAL; QQK
+2E8B ; [.FB40.0020.0004.5369][.D369.0000.0000.5369][.0000.0199.001F.2E8B] # CJK RADICAL SEAL; QQKN
+329E ; [.FB40.0020.0006.5370][.D370.0000.0000.5370] # CIRCLED IDEOGRAPH PRINT; QQK
+2F82F ; [.FB40.0020.0002.5373][.D373.0000.0000.5373] # CJK COMPATIBILITY IDEOGRAPH-2F82F; QQC
+F91C ; [.FB40.0020.0002.5375][.D375.0000.0000.5375] # CJK COMPATIBILITY IDEOGRAPH-F91C; QQC
+2F830 ; [.FB40.0020.0002.537D][.D37D.0000.0000.537D] # CJK COMPATIBILITY IDEOGRAPH-2F830; QQC
+2F831 ; [.FB40.0020.0002.537F][.D37F.0000.0000.537F] # CJK COMPATIBILITY IDEOGRAPH-2F831; QQC
+2F832 ; [.FB40.0020.0002.537F][.D37F.0000.0000.537F] # CJK COMPATIBILITY IDEOGRAPH-2F832; QQC
+2F833 ; [.FB40.0020.0002.537F][.D37F.0000.0000.537F] # CJK COMPATIBILITY IDEOGRAPH-2F833; QQC
+2F1A ; [.FB40.0020.0004.5382][.D382.0000.0000.5382] # KANGXI RADICAL CLIFF; QQK
+2E81 ; [.FB40.0020.0004.5382][.D382.0000.0000.5382][.0000.0199.001F.2E81] # CJK RADICAL CLIFF; QQKN
+2F1B ; [.FB40.0020.0004.53B6][.D3B6.0000.0000.53B6] # KANGXI RADICAL PRIVATE; QQK
+F96B ; [.FB40.0020.0002.53C3][.D3C3.0000.0000.53C3] # CJK COMPATIBILITY IDEOGRAPH-F96B; QQC
+2F1C ; [.FB40.0020.0004.53C8][.D3C8.0000.0000.53C8] # KANGXI RADICAL AGAIN; QQK
+2F836 ; [.FB40.0020.0002.53CA][.D3CA.0000.0000.53CA] # CJK COMPATIBILITY IDEOGRAPH-2F836; QQC
+2F837 ; [.FB40.0020.0002.53DF][.D3DF.0000.0000.53DF] # CJK COMPATIBILITY IDEOGRAPH-2F837; QQC
+2F1D ; [.FB40.0020.0004.53E3][.D3E3.0000.0000.53E3] # KANGXI RADICAL MOUTH; QQK
+F906 ; [.FB40.0020.0002.53E5][.D3E5.0000.0000.53E5] # CJK COMPATIBILITY IDEOGRAPH-F906; QQC
+2F839 ; [.FB40.0020.0002.53EB][.D3EB.0000.0000.53EB] # CJK COMPATIBILITY IDEOGRAPH-2F839; QQC
+2F83A ; [.FB40.0020.0002.53F1][.D3F1.0000.0000.53F1] # CJK COMPATIBILITY IDEOGRAPH-2F83A; QQC
+32A8 ; [.FB40.0020.0006.53F3][.D3F3.0000.0000.53F3] # CIRCLED IDEOGRAPH RIGHT; QQK
+2F83B ; [.FB40.0020.0002.5406][.D406.0000.0000.5406] # CJK COMPATIBILITY IDEOGRAPH-2F83B; QQC
+3234 ; [*02B1.0020.0004.3234][.FB40.0020.0004.540D][.D40D.0000.0000.540D][*02B2.0020.001F.3234] # PARENTHESIZED IDEOGRAPH NAME; QQKN
+3294 ; [.FB40.0020.0006.540D][.D40D.0000.0000.540D] # CIRCLED IDEOGRAPH NAME; QQK
+F9DE ; [.FB40.0020.0002.540F][.D40F.0000.0000.540F] # CJK COMPATIBILITY IDEOGRAPH-F9DE; QQC
+F9ED ; [.FB40.0020.0002.541D][.D41D.0000.0000.541D] # CJK COMPATIBILITY IDEOGRAPH-F9ED; QQC
+2F83D ; [.FB40.0020.0002.5438][.D438.0000.0000.5438] # CJK COMPATIBILITY IDEOGRAPH-2F83D; QQC
+F980 ; [.FB40.0020.0002.5442][.D442.0000.0000.5442] # CJK COMPATIBILITY IDEOGRAPH-F980; QQC
+2F83E ; [.FB40.0020.0002.5448][.D448.0000.0000.5448] # CJK COMPATIBILITY IDEOGRAPH-2F83E; QQC
+2F83F ; [.FB40.0020.0002.5468][.D468.0000.0000.5468] # CJK COMPATIBILITY IDEOGRAPH-2F83F; QQC
+323A ; [*02B1.0020.0004.323A][.FB40.0020.0004.547C][.D47C.0000.0000.547C][*02B2.0020.001F.323A] # PARENTHESIZED IDEOGRAPH CALL; QQKN
+2F83C ; [.FB40.0020.0002.549E][.D49E.0000.0000.549E] # CJK COMPATIBILITY IDEOGRAPH-2F83C; QQC
+2F840 ; [.FB40.0020.0002.54A2][.D4A2.0000.0000.54A2] # CJK COMPATIBILITY IDEOGRAPH-2F840; QQC
+F99E ; [.FB40.0020.0002.54BD][.D4BD.0000.0000.54BD] # CJK COMPATIBILITY IDEOGRAPH-F99E; QQC
+2F841 ; [.FB40.0020.0002.54F6][.D4F6.0000.0000.54F6] # CJK COMPATIBILITY IDEOGRAPH-2F841; QQC
+2F842 ; [.FB40.0020.0002.5510][.D510.0000.0000.5510] # CJK COMPATIBILITY IDEOGRAPH-2F842; QQC
+2F843 ; [.FB40.0020.0002.5553][.D553.0000.0000.5553] # CJK COMPATIBILITY IDEOGRAPH-2F843; QQC
+FA79 ; [.FB40.0020.0002.5555][.D555.0000.0000.5555] # CJK COMPATIBILITY IDEOGRAPH-FA79; QQC
+2F844 ; [.FB40.0020.0002.5563][.D563.0000.0000.5563] # CJK COMPATIBILITY IDEOGRAPH-2F844; QQC
+2F845 ; [.FB40.0020.0002.5584][.D584.0000.0000.5584] # CJK COMPATIBILITY IDEOGRAPH-2F845; QQC
+2F846 ; [.FB40.0020.0002.5584][.D584.0000.0000.5584] # CJK COMPATIBILITY IDEOGRAPH-2F846; QQC
+F90B ; [.FB40.0020.0002.5587][.D587.0000.0000.5587] # CJK COMPATIBILITY IDEOGRAPH-F90B; QQC
+FA7A ; [.FB40.0020.0002.5599][.D599.0000.0000.5599] # CJK COMPATIBILITY IDEOGRAPH-FA7A; QQC
+2F847 ; [.FB40.0020.0002.5599][.D599.0000.0000.5599] # CJK COMPATIBILITY IDEOGRAPH-2F847; QQC
+FA36 ; [.FB40.0020.0002.559D][.D59D.0000.0000.559D] # CJK COMPATIBILITY IDEOGRAPH-FA36; QQC
+FA78 ; [.FB40.0020.0002.559D][.D59D.0000.0000.559D] # CJK COMPATIBILITY IDEOGRAPH-FA78; QQC
+2F848 ; [.FB40.0020.0002.55AB][.D5AB.0000.0000.55AB] # CJK COMPATIBILITY IDEOGRAPH-2F848; QQC
+2F849 ; [.FB40.0020.0002.55B3][.D5B3.0000.0000.55B3] # CJK COMPATIBILITY IDEOGRAPH-2F849; QQC
+FA0D ; [.FB40.0020.0002.55C0][.D5C0.0000.0000.55C0] # CJK COMPATIBILITY IDEOGRAPH-FA0D; QQC
+2F84A ; [.FB40.0020.0002.55C2][.D5C2.0000.0000.55C2] # CJK COMPATIBILITY IDEOGRAPH-2F84A; QQC
+FA7B ; [.FB40.0020.0002.55E2][.D5E2.0000.0000.55E2] # CJK COMPATIBILITY IDEOGRAPH-FA7B; QQC
+FA37 ; [.FB40.0020.0002.5606][.D606.0000.0000.5606] # CJK COMPATIBILITY IDEOGRAPH-FA37; QQC
+2F84C ; [.FB40.0020.0002.5606][.D606.0000.0000.5606] # CJK COMPATIBILITY IDEOGRAPH-2F84C; QQC
+2F84E ; [.FB40.0020.0002.5651][.D651.0000.0000.5651] # CJK COMPATIBILITY IDEOGRAPH-2F84E; QQC
+FA38 ; [.FB40.0020.0002.5668][.D668.0000.0000.5668] # CJK COMPATIBILITY IDEOGRAPH-FA38; QQC
+2F84F ; [.FB40.0020.0002.5674][.D674.0000.0000.5674] # CJK COMPATIBILITY IDEOGRAPH-2F84F; QQC
+2F1E ; [.FB40.0020.0004.56D7][.D6D7.0000.0000.56D7] # KANGXI RADICAL ENCLOSURE; QQK
+3223 ; [*02B1.0020.0004.3223][.FB40.0020.0004.56DB][.D6DB.0000.0000.56DB][*02B2.0020.001F.3223] # PARENTHESIZED IDEOGRAPH FOUR; QQKN
+3283 ; [.FB40.0020.0006.56DB][.D6DB.0000.0000.56DB] # CIRCLED IDEOGRAPH FOUR; QQK
+3195 ; [.FB40.0020.0014.56DB][.D6DB.0000.0000.56DB] # IDEOGRAPHIC ANNOTATION FOUR MARK; QQK
+F9A9 ; [.FB40.0020.0002.56F9][.D6F9.0000.0000.56F9] # CJK COMPATIBILITY IDEOGRAPH-F9A9; QQC
+2F84B ; [.FB40.0020.0002.5716][.D716.0000.0000.5716] # CJK COMPATIBILITY IDEOGRAPH-2F84B; QQC
+2F84D ; [.FB40.0020.0002.5717][.D717.0000.0000.5717] # CJK COMPATIBILITY IDEOGRAPH-2F84D; QQC
+2F1F ; [.FB40.0020.0004.571F][.D71F.0000.0000.571F] # KANGXI RADICAL EARTH; QQK
+322F ; [*02B1.0020.0004.322F][.FB40.0020.0004.571F][.D71F.0000.0000.571F][*02B2.0020.001F.322F] # PARENTHESIZED IDEOGRAPH EARTH; QQKN
+328F ; [.FB40.0020.0006.571F][.D71F.0000.0000.571F] # CIRCLED IDEOGRAPH EARTH; QQK
+319E ; [.FB40.0020.0014.5730][.D730.0000.0000.5730] # IDEOGRAPHIC ANNOTATION EARTH MARK; QQK
+2F855 ; [.FB40.0020.0002.578B][.D78B.0000.0000.578B] # CJK COMPATIBILITY IDEOGRAPH-2F855; QQC
+2F852 ; [.FB40.0020.0002.57CE][.D7CE.0000.0000.57CE] # CJK COMPATIBILITY IDEOGRAPH-2F852; QQC
+2F853 ; [.FB40.0020.0002.57F4][.D7F4.0000.0000.57F4] # CJK COMPATIBILITY IDEOGRAPH-2F853; QQC
+2F854 ; [.FB40.0020.0002.580D][.D80D.0000.0000.580D] # CJK COMPATIBILITY IDEOGRAPH-2F854; QQC
+2F857 ; [.FB40.0020.0002.5831][.D831.0000.0000.5831] # CJK COMPATIBILITY IDEOGRAPH-2F857; QQC
+2F856 ; [.FB40.0020.0002.5832][.D832.0000.0000.5832] # CJK COMPATIBILITY IDEOGRAPH-2F856; QQC
+FA39 ; [.FB40.0020.0002.5840][.D840.0000.0000.5840] # CJK COMPATIBILITY IDEOGRAPH-FA39; QQC
+FA10 ; [.FB40.0020.0002.585A][.D85A.0000.0000.585A] # CJK COMPATIBILITY IDEOGRAPH-FA10; QQC
+FA7C ; [.FB40.0020.0002.585A][.D85A.0000.0000.585A] # CJK COMPATIBILITY IDEOGRAPH-FA7C; QQC
+F96C ; [.FB40.0020.0002.585E][.D85E.0000.0000.585E] # CJK COMPATIBILITY IDEOGRAPH-F96C; QQC
+FA3A ; [.FB40.0020.0002.58A8][.D8A8.0000.0000.58A8] # CJK COMPATIBILITY IDEOGRAPH-FA3A; QQC
+2F858 ; [.FB40.0020.0002.58AC][.D8AC.0000.0000.58AC] # CJK COMPATIBILITY IDEOGRAPH-2F858; QQC
+FA7D ; [.FB40.0020.0002.58B3][.D8B3.0000.0000.58B3] # CJK COMPATIBILITY IDEOGRAPH-FA7D; QQC
+F94A ; [.FB40.0020.0002.58D8][.D8D8.0000.0000.58D8] # CJK COMPATIBILITY IDEOGRAPH-F94A; QQC
+F942 ; [.FB40.0020.0002.58DF][.D8DF.0000.0000.58DF] # CJK COMPATIBILITY IDEOGRAPH-F942; QQC
+2F20 ; [.FB40.0020.0004.58EB][.D8EB.0000.0000.58EB] # KANGXI RADICAL SCHOLAR; QQK
+2F851 ; [.FB40.0020.0002.58EE][.D8EE.0000.0000.58EE] # CJK COMPATIBILITY IDEOGRAPH-2F851; QQC
+2F85A ; [.FB40.0020.0002.58F2][.D8F2.0000.0000.58F2] # CJK COMPATIBILITY IDEOGRAPH-2F85A; QQC
+2F85B ; [.FB40.0020.0002.58F7][.D8F7.0000.0000.58F7] # CJK COMPATIBILITY IDEOGRAPH-2F85B; QQC
+2F21 ; [.FB40.0020.0004.5902][.D902.0000.0000.5902] # KANGXI RADICAL GO; QQK
+2F85C ; [.FB40.0020.0002.5906][.D906.0000.0000.5906] # CJK COMPATIBILITY IDEOGRAPH-2F85C; QQC
+2F22 ; [.FB40.0020.0004.590A][.D90A.0000.0000.590A] # KANGXI RADICAL GO SLOWLY; QQK
+2F23 ; [.FB40.0020.0004.5915][.D915.0000.0000.5915] # KANGXI RADICAL EVENING; QQK
+2F85D ; [.FB40.0020.0002.591A][.D91A.0000.0000.591A] # CJK COMPATIBILITY IDEOGRAPH-2F85D; QQC
+32B0 ; [.FB40.0020.0006.591C][.D91C.0000.0000.591C] # CIRCLED IDEOGRAPH NIGHT; QQK
+2F85E ; [.FB40.0020.0002.5922][.D922.0000.0000.5922] # CJK COMPATIBILITY IDEOGRAPH-2F85E; QQC
+2F24 ; [.FB40.0020.0004.5927][.D927.0000.0000.5927] # KANGXI RADICAL BIG; QQK
+337D ; [.FB40.0020.001C.5927][.D927.0000.0000.5927][.FB40.0020.001F.6B63][.EB63.0000.0000.6B63] # SQUARE ERA NAME TAISYOU; QQKN
+319D ; [.FB40.0020.0014.5929][.D929.0000.0000.5929] # IDEOGRAPHIC ANNOTATION HEAVEN MARK; QQK
+FA7E ; [.FB40.0020.0002.5944][.D944.0000.0000.5944] # CJK COMPATIBILITY IDEOGRAPH-FA7E; QQC
+F90C ; [.FB40.0020.0002.5948][.D948.0000.0000.5948] # CJK COMPATIBILITY IDEOGRAPH-F90C; QQC
+F909 ; [.FB40.0020.0002.5951][.D951.0000.0000.5951] # CJK COMPATIBILITY IDEOGRAPH-F909; QQC
+FA7F ; [.FB40.0020.0002.5954][.D954.0000.0000.5954] # CJK COMPATIBILITY IDEOGRAPH-FA7F; QQC
+2F85F ; [.FB40.0020.0002.5962][.D962.0000.0000.5962] # CJK COMPATIBILITY IDEOGRAPH-2F85F; QQC
+F981 ; [.FB40.0020.0002.5973][.D973.0000.0000.5973] # CJK COMPATIBILITY IDEOGRAPH-F981; QQC
+2F25 ; [.FB40.0020.0004.5973][.D973.0000.0000.5973] # KANGXI RADICAL WOMAN; QQK
+329B ; [.FB40.0020.0006.5973][.D973.0000.0000.5973] # CIRCLED IDEOGRAPH FEMALE; QQK
+2F865 ; [.FB40.0020.0002.59D8][.D9D8.0000.0000.59D8] # CJK COMPATIBILITY IDEOGRAPH-2F865; QQC
+2F862 ; [.FB40.0020.0002.59EC][.D9EC.0000.0000.59EC] # CJK COMPATIBILITY IDEOGRAPH-2F862; QQC
+2F863 ; [.FB40.0020.0002.5A1B][.DA1B.0000.0000.5A1B] # CJK COMPATIBILITY IDEOGRAPH-2F863; QQC
+2F864 ; [.FB40.0020.0002.5A27][.DA27.0000.0000.5A27] # CJK COMPATIBILITY IDEOGRAPH-2F864; QQC
+FA80 ; [.FB40.0020.0002.5A62][.DA62.0000.0000.5A62] # CJK COMPATIBILITY IDEOGRAPH-FA80; QQC
+2F866 ; [.FB40.0020.0002.5A66][.DA66.0000.0000.5A66] # CJK COMPATIBILITY IDEOGRAPH-2F866; QQC
+2F986 ; [.FB40.0020.0002.5AB5][.DAB5.0000.0000.5AB5] # CJK COMPATIBILITY IDEOGRAPH-2F986; QQC
+2F869 ; [.FB40.0020.0002.5B08][.DB08.0000.0000.5B08] # CJK COMPATIBILITY IDEOGRAPH-2F869; QQC
+FA81 ; [.FB40.0020.0002.5B28][.DB28.0000.0000.5B28] # CJK COMPATIBILITY IDEOGRAPH-FA81; QQC
+2F86A ; [.FB40.0020.0002.5B3E][.DB3E.0000.0000.5B3E] # CJK COMPATIBILITY IDEOGRAPH-2F86A; QQC
+2F86B ; [.FB40.0020.0002.5B3E][.DB3E.0000.0000.5B3E] # CJK COMPATIBILITY IDEOGRAPH-2F86B; QQC
+2F26 ; [.FB40.0020.0004.5B50][.DB50.0000.0000.5B50] # KANGXI RADICAL CHILD; QQK
+323B ; [*02B1.0020.0004.323B][.FB40.0020.0004.5B66][.DB66.0000.0000.5B66][*02B2.0020.001F.323B] # PARENTHESIZED IDEOGRAPH STUDY; QQKN
+32AB ; [.FB40.0020.0006.5B66][.DB66.0000.0000.5B66] # CIRCLED IDEOGRAPH STUDY; QQK
+2F27 ; [.FB40.0020.0004.5B80][.DB80.0000.0000.5B80] # KANGXI RADICAL ROOF; QQK
+FA04 ; [.FB40.0020.0002.5B85][.DB85.0000.0000.5B85] # CJK COMPATIBILITY IDEOGRAPH-FA04; QQC
+32AA ; [.FB40.0020.0006.5B97][.DB97.0000.0000.5B97] # CIRCLED IDEOGRAPH RELIGION; QQK
+2F86D ; [.FB40.0020.0002.5BC3][.DBC3.0000.0000.5BC3] # CJK COMPATIBILITY IDEOGRAPH-2F86D; QQC
+2F86E ; [.FB40.0020.0002.5BD8][.DBD8.0000.0000.5BD8] # CJK COMPATIBILITY IDEOGRAPH-2F86E; QQC
+F95F ; [.FB40.0020.0002.5BE7][.DBE7.0000.0000.5BE7] # CJK COMPATIBILITY IDEOGRAPH-F95F; QQC
+F9AA ; [.FB40.0020.0002.5BE7][.DBE7.0000.0000.5BE7] # CJK COMPATIBILITY IDEOGRAPH-F9AA; QQC
+2F86F ; [.FB40.0020.0002.5BE7][.DBE7.0000.0000.5BE7] # CJK COMPATIBILITY IDEOGRAPH-2F86F; QQC
+F9BC ; [.FB40.0020.0002.5BEE][.DBEE.0000.0000.5BEE] # CJK COMPATIBILITY IDEOGRAPH-F9BC; QQC
+2F870 ; [.FB40.0020.0002.5BF3][.DBF3.0000.0000.5BF3] # CJK COMPATIBILITY IDEOGRAPH-2F870; QQC
+2F28 ; [.FB40.0020.0004.5BF8][.DBF8.0000.0000.5BF8] # KANGXI RADICAL INCH; QQK
+2F872 ; [.FB40.0020.0002.5BFF][.DBFF.0000.0000.5BFF] # CJK COMPATIBILITY IDEOGRAPH-2F872; QQC
+2F873 ; [.FB40.0020.0002.5C06][.DC06.0000.0000.5C06] # CJK COMPATIBILITY IDEOGRAPH-2F873; QQC
+2F29 ; [.FB40.0020.0004.5C0F][.DC0F.0000.0000.5C0F] # KANGXI RADICAL SMALL; QQK
+2E8C ; [.FB40.0020.0004.5C0F][.DC0F.0000.0000.5C0F][.0000.0199.001F.2E8C] # CJK RADICAL SMALL ONE; QQKN
+2E8D ; [.FB40.0020.0004.5C0F][.DC0F.0000.0000.5C0F][.0000.019A.001F.2E8D] # CJK RADICAL SMALL TWO; QQKN
+2F875 ; [.FB40.0020.0002.5C22][.DC22.0000.0000.5C22] # CJK COMPATIBILITY IDEOGRAPH-2F875; QQC
+2E90 ; [.FB40.0020.0004.5C22][.DC22.0000.0000.5C22] # CJK RADICAL LAME THREE; QQK
+2F2A ; [.FB40.0020.0004.5C22][.DC22.0000.0000.5C22] # KANGXI RADICAL LAME; QQK
+2E8E ; [.FB40.0020.0004.5C22][.DC22.0000.0000.5C22][.0000.0199.001F.2E8E] # CJK RADICAL LAME ONE; QQKN
+2E8F ; [.FB40.0020.0004.5C23][.DC23.0000.0000.5C23] # CJK RADICAL LAME TWO; QQK
+2E91 ; [.FB40.0020.0004.5C23][.DC23.0000.0000.5C23][.0000.0199.001F.2E91] # CJK RADICAL LAME FOUR; QQKN
+2F2B ; [.FB40.0020.0004.5C38][.DC38.0000.0000.5C38] # KANGXI RADICAL CORPSE; QQK
+F9BD ; [.FB40.0020.0002.5C3F][.DC3F.0000.0000.5C3F] # CJK COMPATIBILITY IDEOGRAPH-F9BD; QQC
+2F877 ; [.FB40.0020.0002.5C60][.DC60.0000.0000.5C60] # CJK COMPATIBILITY IDEOGRAPH-2F877; QQC
+F94B ; [.FB40.0020.0002.5C62][.DC62.0000.0000.5C62] # CJK COMPATIBILITY IDEOGRAPH-F94B; QQC
+FA3B ; [.FB40.0020.0002.5C64][.DC64.0000.0000.5C64] # CJK COMPATIBILITY IDEOGRAPH-FA3B; QQC
+F9DF ; [.FB40.0020.0002.5C65][.DC65.0000.0000.5C65] # CJK COMPATIBILITY IDEOGRAPH-F9DF; QQC
+FA3C ; [.FB40.0020.0002.5C6E][.DC6E.0000.0000.5C6E] # CJK COMPATIBILITY IDEOGRAPH-FA3C; QQC
+2F878 ; [.FB40.0020.0002.5C6E][.DC6E.0000.0000.5C6E] # CJK COMPATIBILITY IDEOGRAPH-2F878; QQC
+2F2C ; [.FB40.0020.0004.5C6E][.DC6E.0000.0000.5C6E] # KANGXI RADICAL SPROUT; QQK
+2F2D ; [.FB40.0020.0004.5C71][.DC71.0000.0000.5C71] # KANGXI RADICAL MOUNTAIN; QQK
+2F87A ; [.FB40.0020.0002.5C8D][.DC8D.0000.0000.5C8D] # CJK COMPATIBILITY IDEOGRAPH-2F87A; QQC
+2F879 ; [.FB40.0020.0002.5CC0][.DCC0.0000.0000.5CC0] # CJK COMPATIBILITY IDEOGRAPH-2F879; QQC
+F9D5 ; [.FB40.0020.0002.5D19][.DD19.0000.0000.5D19] # CJK COMPATIBILITY IDEOGRAPH-F9D5; QQC
+2F87C ; [.FB40.0020.0002.5D43][.DD43.0000.0000.5D43] # CJK COMPATIBILITY IDEOGRAPH-2F87C; QQC
+F921 ; [.FB40.0020.0002.5D50][.DD50.0000.0000.5D50] # CJK COMPATIBILITY IDEOGRAPH-F921; QQC
+2F87F ; [.FB40.0020.0002.5D6B][.DD6B.0000.0000.5D6B] # CJK COMPATIBILITY IDEOGRAPH-2F87F; QQC
+2F87E ; [.FB40.0020.0002.5D6E][.DD6E.0000.0000.5D6E] # CJK COMPATIBILITY IDEOGRAPH-2F87E; QQC
+2F880 ; [.FB40.0020.0002.5D7C][.DD7C.0000.0000.5D7C] # CJK COMPATIBILITY IDEOGRAPH-2F880; QQC
+2F9F4 ; [.FB40.0020.0002.5DB2][.DDB2.0000.0000.5DB2] # CJK COMPATIBILITY IDEOGRAPH-2F9F4; QQC
+F9AB ; [.FB40.0020.0002.5DBA][.DDBA.0000.0000.5DBA] # CJK COMPATIBILITY IDEOGRAPH-F9AB; QQC
+2F2E ; [.FB40.0020.0004.5DDB][.DDDB.0000.0000.5DDB] # KANGXI RADICAL RIVER; QQK
+2F881 ; [.FB40.0020.0002.5DE1][.DDE1.0000.0000.5DE1] # CJK COMPATIBILITY IDEOGRAPH-2F881; QQC
+2F882 ; [.FB40.0020.0002.5DE2][.DDE2.0000.0000.5DE2] # CJK COMPATIBILITY IDEOGRAPH-2F882; QQC
+2F2F ; [.FB40.0020.0004.5DE5][.DDE5.0000.0000.5DE5] # KANGXI RADICAL WORK; QQK
+32A7 ; [.FB40.0020.0006.5DE6][.DDE6.0000.0000.5DE6] # CIRCLED IDEOGRAPH LEFT; QQK
+2F30 ; [.FB40.0020.0004.5DF1][.DDF1.0000.0000.5DF1] # KANGXI RADICAL ONESELF; QQK
+2E92 ; [.FB40.0020.0004.5DF3][.DDF3.0000.0000.5DF3] # CJK RADICAL SNAKE; QQK
+2F884 ; [.FB40.0020.0002.5DFD][.DDFD.0000.0000.5DFD] # CJK COMPATIBILITY IDEOGRAPH-2F884; QQC
+2F31 ; [.FB40.0020.0004.5DFE][.DDFE.0000.0000.5DFE] # KANGXI RADICAL TURBAN; QQK
+2F885 ; [.FB40.0020.0002.5E28][.DE28.0000.0000.5E28] # CJK COMPATIBILITY IDEOGRAPH-2F885; QQC
+2F886 ; [.FB40.0020.0002.5E3D][.DE3D.0000.0000.5E3D] # CJK COMPATIBILITY IDEOGRAPH-2F886; QQC
+2F887 ; [.FB40.0020.0002.5E69][.DE69.0000.0000.5E69] # CJK COMPATIBILITY IDEOGRAPH-2F887; QQC
+2F32 ; [.FB40.0020.0004.5E72][.DE72.0000.0000.5E72] # KANGXI RADICAL DRY; QQK
+337B ; [.FB40.0020.001C.5E73][.DE73.0000.0000.5E73][.FB40.0020.001F.6210][.E210.0000.0000.6210] # SQUARE ERA NAME HEISEI; QQKN
+F98E ; [.FB40.0020.0002.5E74][.DE74.0000.0000.5E74] # CJK COMPATIBILITY IDEOGRAPH-F98E; QQC
+2E93 ; [.FB40.0020.0004.5E7A][.DE7A.0000.0000.5E7A] # CJK RADICAL THREAD; QQK
+2F33 ; [.FB40.0020.0004.5E7A][.DE7A.0000.0000.5E7A] # KANGXI RADICAL SHORT THREAD; QQK
+2F34 ; [.FB40.0020.0004.5E7F][.DE7F.0000.0000.5E7F] # KANGXI RADICAL DOTTED CLIFF; QQK
+FA01 ; [.FB40.0020.0002.5EA6][.DEA6.0000.0000.5EA6] # CJK COMPATIBILITY IDEOGRAPH-FA01; QQC
+2F88B ; [.FB40.0020.0002.5EB0][.DEB0.0000.0000.5EB0] # CJK COMPATIBILITY IDEOGRAPH-2F88B; QQC
+2F88C ; [.FB40.0020.0002.5EB3][.DEB3.0000.0000.5EB3] # CJK COMPATIBILITY IDEOGRAPH-2F88C; QQC
+2F88D ; [.FB40.0020.0002.5EB6][.DEB6.0000.0000.5EB6] # CJK COMPATIBILITY IDEOGRAPH-2F88D; QQC
+F9A2 ; [.FB40.0020.0002.5EC9][.DEC9.0000.0000.5EC9] # CJK COMPATIBILITY IDEOGRAPH-F9A2; QQC
+F928 ; [.FB40.0020.0002.5ECA][.DECA.0000.0000.5ECA] # CJK COMPATIBILITY IDEOGRAPH-F928; QQC
+2F88E ; [.FB40.0020.0002.5ECA][.DECA.0000.0000.5ECA] # CJK COMPATIBILITY IDEOGRAPH-2F88E; QQC
+FA82 ; [.FB40.0020.0002.5ED2][.DED2.0000.0000.5ED2] # CJK COMPATIBILITY IDEOGRAPH-FA82; QQC
+FA0B ; [.FB40.0020.0002.5ED3][.DED3.0000.0000.5ED3] # CJK COMPATIBILITY IDEOGRAPH-FA0B; QQC
+FA83 ; [.FB40.0020.0002.5ED9][.DED9.0000.0000.5ED9] # CJK COMPATIBILITY IDEOGRAPH-FA83; QQC
+F982 ; [.FB40.0020.0002.5EEC][.DEEC.0000.0000.5EEC] # CJK COMPATIBILITY IDEOGRAPH-F982; QQC
+2F35 ; [.FB40.0020.0004.5EF4][.DEF4.0000.0000.5EF4] # KANGXI RADICAL LONG STRIDE; QQK
+2F890 ; [.FB40.0020.0002.5EFE][.DEFE.0000.0000.5EFE] # CJK COMPATIBILITY IDEOGRAPH-2F890; QQC
+2F36 ; [.FB40.0020.0004.5EFE][.DEFE.0000.0000.5EFE] # KANGXI RADICAL TWO HANDS; QQK
+F943 ; [.FB40.0020.0002.5F04][.DF04.0000.0000.5F04] # CJK COMPATIBILITY IDEOGRAPH-F943; QQC
+2F37 ; [.FB40.0020.0004.5F0B][.DF0B.0000.0000.5F0B] # KANGXI RADICAL SHOOT; QQK
+2F38 ; [.FB40.0020.0004.5F13][.DF13.0000.0000.5F13] # KANGXI RADICAL BOW; QQK
+2F894 ; [.FB40.0020.0002.5F22][.DF22.0000.0000.5F22] # CJK COMPATIBILITY IDEOGRAPH-2F894; QQC
+2F895 ; [.FB40.0020.0002.5F22][.DF22.0000.0000.5F22] # CJK COMPATIBILITY IDEOGRAPH-2F895; QQC
+2F39 ; [.FB40.0020.0004.5F50][.DF50.0000.0000.5F50] # KANGXI RADICAL SNOUT; QQK
+2E95 ; [.FB40.0020.0004.5F50][.DF50.0000.0000.5F50][.0000.0199.001F.2E95] # CJK RADICAL SNOUT TWO; QQKN
+2E94 ; [.FB40.0020.0004.5F51][.DF51.0000.0000.5F51] # CJK RADICAL SNOUT ONE; QQK
+2F874 ; [.FB40.0020.0002.5F53][.DF53.0000.0000.5F53] # CJK COMPATIBILITY IDEOGRAPH-2F874; QQC
+2F3A ; [.FB40.0020.0004.5F61][.DF61.0000.0000.5F61] # KANGXI RADICAL BRISTLE; QQK
+2F899 ; [.FB40.0020.0002.5F62][.DF62.0000.0000.5F62] # CJK COMPATIBILITY IDEOGRAPH-2F899; QQC
+FA84 ; [.FB40.0020.0002.5F69][.DF69.0000.0000.5F69] # CJK COMPATIBILITY IDEOGRAPH-FA84; QQC
+2F89A ; [.FB40.0020.0002.5F6B][.DF6B.0000.0000.5F6B] # CJK COMPATIBILITY IDEOGRAPH-2F89A; QQC
+2F3B ; [.FB40.0020.0004.5F73][.DF73.0000.0000.5F73] # KANGXI RADICAL STEP; QQK
+F9D8 ; [.FB40.0020.0002.5F8B][.DF8B.0000.0000.5F8B] # CJK COMPATIBILITY IDEOGRAPH-F9D8; QQC
+2F89C ; [.FB40.0020.0002.5F9A][.DF9A.0000.0000.5F9A] # CJK COMPATIBILITY IDEOGRAPH-2F89C; QQC
+F966 ; [.FB40.0020.0002.5FA9][.DFA9.0000.0000.5FA9] # CJK COMPATIBILITY IDEOGRAPH-F966; QQC
+FA85 ; [.FB40.0020.0002.5FAD][.DFAD.0000.0000.5FAD] # CJK COMPATIBILITY IDEOGRAPH-FA85; QQC
+2F3C ; [.FB40.0020.0004.5FC3][.DFC3.0000.0000.5FC3] # KANGXI RADICAL HEART; QQK
+2E97 ; [.FB40.0020.0004.5FC3][.DFC3.0000.0000.5FC3][.0000.0199.001F.2E97] # CJK RADICAL HEART TWO; QQKN
+2E96 ; [.FB40.0020.0004.5FC4][.DFC4.0000.0000.5FC4] # CJK RADICAL HEART ONE; QQK
+2F89D ; [.FB40.0020.0002.5FCD][.DFCD.0000.0000.5FCD] # CJK COMPATIBILITY IDEOGRAPH-2F89D; QQC
+2F89E ; [.FB40.0020.0002.5FD7][.DFD7.0000.0000.5FD7] # CJK COMPATIBILITY IDEOGRAPH-2F89E; QQC
+F9A3 ; [.FB40.0020.0002.5FF5][.DFF5.0000.0000.5FF5] # CJK COMPATIBILITY IDEOGRAPH-F9A3; QQC
+2F89F ; [.FB40.0020.0002.5FF9][.DFF9.0000.0000.5FF9] # CJK COMPATIBILITY IDEOGRAPH-2F89F; QQC
+F960 ; [.FB40.0020.0002.6012][.E012.0000.0000.6012] # CJK COMPATIBILITY IDEOGRAPH-F960; QQC
+F9AC ; [.FB40.0020.0002.601C][.E01C.0000.0000.601C] # CJK COMPATIBILITY IDEOGRAPH-F9AC; QQC
+2F8A0 ; [.FB40.0020.0002.6081][.E081.0000.0000.6081] # CJK COMPATIBILITY IDEOGRAPH-2F8A0; QQC
+FA3D ; [.FB40.0020.0002.6094][.E094.0000.0000.6094] # CJK COMPATIBILITY IDEOGRAPH-FA3D; QQC
+2F8A3 ; [.FB40.0020.0002.6094][.E094.0000.0000.6094] # CJK COMPATIBILITY IDEOGRAPH-2F8A3; QQC
+2F8A5 ; [.FB40.0020.0002.60C7][.E0C7.0000.0000.60C7] # CJK COMPATIBILITY IDEOGRAPH-2F8A5; QQC
+FA86 ; [.FB40.0020.0002.60D8][.E0D8.0000.0000.60D8] # CJK COMPATIBILITY IDEOGRAPH-FA86; QQC
+F9B9 ; [.FB40.0020.0002.60E1][.E0E1.0000.0000.60E1] # CJK COMPATIBILITY IDEOGRAPH-F9B9; QQC
+FA88 ; [.FB40.0020.0002.6108][.E108.0000.0000.6108] # CJK COMPATIBILITY IDEOGRAPH-FA88; QQC
+F9D9 ; [.FB40.0020.0002.6144][.E144.0000.0000.6144] # CJK COMPATIBILITY IDEOGRAPH-F9D9; QQC
+2F8A6 ; [.FB40.0020.0002.6148][.E148.0000.0000.6148] # CJK COMPATIBILITY IDEOGRAPH-2F8A6; QQC
+2F8A7 ; [.FB40.0020.0002.614C][.E14C.0000.0000.614C] # CJK COMPATIBILITY IDEOGRAPH-2F8A7; QQC
+2F8A9 ; [.FB40.0020.0002.614C][.E14C.0000.0000.614C] # CJK COMPATIBILITY IDEOGRAPH-2F8A9; QQC
+FA87 ; [.FB40.0020.0002.614E][.E14E.0000.0000.614E] # CJK COMPATIBILITY IDEOGRAPH-FA87; QQC
+2F8A8 ; [.FB40.0020.0002.614E][.E14E.0000.0000.614E] # CJK COMPATIBILITY IDEOGRAPH-2F8A8; QQC
+FA8A ; [.FB40.0020.0002.6160][.E160.0000.0000.6160] # CJK COMPATIBILITY IDEOGRAPH-FA8A; QQC
+FA3E ; [.FB40.0020.0002.6168][.E168.0000.0000.6168] # CJK COMPATIBILITY IDEOGRAPH-FA3E; QQC
+2F8AA ; [.FB40.0020.0002.617A][.E17A.0000.0000.617A] # CJK COMPATIBILITY IDEOGRAPH-2F8AA; QQC
+FA3F ; [.FB40.0020.0002.618E][.E18E.0000.0000.618E] # CJK COMPATIBILITY IDEOGRAPH-FA3F; QQC
+FA89 ; [.FB40.0020.0002.618E][.E18E.0000.0000.618E] # CJK COMPATIBILITY IDEOGRAPH-FA89; QQC
+2F8AB ; [.FB40.0020.0002.618E][.E18E.0000.0000.618E] # CJK COMPATIBILITY IDEOGRAPH-2F8AB; QQC
+F98F ; [.FB40.0020.0002.6190][.E190.0000.0000.6190] # CJK COMPATIBILITY IDEOGRAPH-F98F; QQC
+2F8AD ; [.FB40.0020.0002.61A4][.E1A4.0000.0000.61A4] # CJK COMPATIBILITY IDEOGRAPH-2F8AD; QQC
+2F8AE ; [.FB40.0020.0002.61AF][.E1AF.0000.0000.61AF] # CJK COMPATIBILITY IDEOGRAPH-2F8AE; QQC
+2F8AC ; [.FB40.0020.0002.61B2][.E1B2.0000.0000.61B2] # CJK COMPATIBILITY IDEOGRAPH-2F8AC; QQC
+2F8AF ; [.FB40.0020.0002.61DE][.E1DE.0000.0000.61DE] # CJK COMPATIBILITY IDEOGRAPH-2F8AF; QQC
+FA40 ; [.FB40.0020.0002.61F2][.E1F2.0000.0000.61F2] # CJK COMPATIBILITY IDEOGRAPH-FA40; QQC
+FA8B ; [.FB40.0020.0002.61F2][.E1F2.0000.0000.61F2] # CJK COMPATIBILITY IDEOGRAPH-FA8B; QQC
+2F8B0 ; [.FB40.0020.0002.61F2][.E1F2.0000.0000.61F2] # CJK COMPATIBILITY IDEOGRAPH-2F8B0; QQC
+F90D ; [.FB40.0020.0002.61F6][.E1F6.0000.0000.61F6] # CJK COMPATIBILITY IDEOGRAPH-F90D; QQC
+2F8B1 ; [.FB40.0020.0002.61F6][.E1F6.0000.0000.61F6] # CJK COMPATIBILITY IDEOGRAPH-2F8B1; QQC
+F990 ; [.FB40.0020.0002.6200][.E200.0000.0000.6200] # CJK COMPATIBILITY IDEOGRAPH-F990; QQC
+2F3D ; [.FB40.0020.0004.6208][.E208.0000.0000.6208] # KANGXI RADICAL HALBERD; QQK
+2F8B2 ; [.FB40.0020.0002.6210][.E210.0000.0000.6210] # CJK COMPATIBILITY IDEOGRAPH-2F8B2; QQC
+2F8B3 ; [.FB40.0020.0002.621B][.E21B.0000.0000.621B] # CJK COMPATIBILITY IDEOGRAPH-2F8B3; QQC
+F9D2 ; [.FB40.0020.0002.622E][.E22E.0000.0000.622E] # CJK COMPATIBILITY IDEOGRAPH-F9D2; QQC
+FA8C ; [.FB40.0020.0002.6234][.E234.0000.0000.6234] # CJK COMPATIBILITY IDEOGRAPH-FA8C; QQC
+2F3E ; [.FB40.0020.0004.6236][.E236.0000.0000.6236] # KANGXI RADICAL DOOR; QQK
+2F3F ; [.FB40.0020.0004.624B][.E24B.0000.0000.624B] # KANGXI RADICAL HAND; QQK
+2E98 ; [.FB40.0020.0004.624C][.E24C.0000.0000.624C] # CJK RADICAL HAND; QQK
+2F8B4 ; [.FB40.0020.0002.625D][.E25D.0000.0000.625D] # CJK COMPATIBILITY IDEOGRAPH-2F8B4; QQC
+2F8B5 ; [.FB40.0020.0002.62B1][.E2B1.0000.0000.62B1] # CJK COMPATIBILITY IDEOGRAPH-2F8B5; QQC
+F925 ; [.FB40.0020.0002.62C9][.E2C9.0000.0000.62C9] # CJK COMPATIBILITY IDEOGRAPH-F925; QQC
+F95B ; [.FB40.0020.0002.62CF][.E2CF.0000.0000.62CF] # CJK COMPATIBILITY IDEOGRAPH-F95B; QQC
+FA02 ; [.FB40.0020.0002.62D3][.E2D3.0000.0000.62D3] # CJK COMPATIBILITY IDEOGRAPH-FA02; QQC
+2F8B6 ; [.FB40.0020.0002.62D4][.E2D4.0000.0000.62D4] # CJK COMPATIBILITY IDEOGRAPH-2F8B6; QQC
+2F8BA ; [.FB40.0020.0002.62FC][.E2FC.0000.0000.62FC] # CJK COMPATIBILITY IDEOGRAPH-2F8BA; QQC
+F973 ; [.FB40.0020.0002.62FE][.E2FE.0000.0000.62FE] # CJK COMPATIBILITY IDEOGRAPH-F973; QQC
+2F8B9 ; [.FB40.0020.0002.633D][.E33D.0000.0000.633D] # CJK COMPATIBILITY IDEOGRAPH-2F8B9; QQC
+2F8B7 ; [.FB40.0020.0002.6350][.E350.0000.0000.6350] # CJK COMPATIBILITY IDEOGRAPH-2F8B7; QQC
+2F8BB ; [.FB40.0020.0002.6368][.E368.0000.0000.6368] # CJK COMPATIBILITY IDEOGRAPH-2F8BB; QQC
+F9A4 ; [.FB40.0020.0002.637B][.E37B.0000.0000.637B] # CJK COMPATIBILITY IDEOGRAPH-F9A4; QQC
+2F8BC ; [.FB40.0020.0002.6383][.E383.0000.0000.6383] # CJK COMPATIBILITY IDEOGRAPH-2F8BC; QQC
+F975 ; [.FB40.0020.0002.63A0][.E3A0.0000.0000.63A0] # CJK COMPATIBILITY IDEOGRAPH-F975; QQC
+2F8C1 ; [.FB40.0020.0002.63A9][.E3A9.0000.0000.63A9] # CJK COMPATIBILITY IDEOGRAPH-2F8C1; QQC
+FA8D ; [.FB40.0020.0002.63C4][.E3C4.0000.0000.63C4] # CJK COMPATIBILITY IDEOGRAPH-FA8D; QQC
+2F8C0 ; [.FB40.0020.0002.63C5][.E3C5.0000.0000.63C5] # CJK COMPATIBILITY IDEOGRAPH-2F8C0; QQC
+2F8BD ; [.FB40.0020.0002.63E4][.E3E4.0000.0000.63E4] # CJK COMPATIBILITY IDEOGRAPH-2F8BD; QQC
+FA8E ; [.FB40.0020.0002.641C][.E41C.0000.0000.641C] # CJK COMPATIBILITY IDEOGRAPH-FA8E; QQC
+2F8BF ; [.FB40.0020.0002.6422][.E422.0000.0000.6422] # CJK COMPATIBILITY IDEOGRAPH-2F8BF; QQC
+FA8F ; [.FB40.0020.0002.6452][.E452.0000.0000.6452] # CJK COMPATIBILITY IDEOGRAPH-FA8F; QQC
+2F8C3 ; [.FB40.0020.0002.6469][.E469.0000.0000.6469] # CJK COMPATIBILITY IDEOGRAPH-2F8C3; QQC
+2F8C6 ; [.FB40.0020.0002.6477][.E477.0000.0000.6477] # CJK COMPATIBILITY IDEOGRAPH-2F8C6; QQC
+2F8C4 ; [.FB40.0020.0002.647E][.E47E.0000.0000.647E] # CJK COMPATIBILITY IDEOGRAPH-2F8C4; QQC
+F991 ; [.FB40.0020.0002.649A][.E49A.0000.0000.649A] # CJK COMPATIBILITY IDEOGRAPH-F991; QQC
+2F8C5 ; [.FB40.0020.0002.649D][.E49D.0000.0000.649D] # CJK COMPATIBILITY IDEOGRAPH-2F8C5; QQC
+F930 ; [.FB40.0020.0002.64C4][.E4C4.0000.0000.64C4] # CJK COMPATIBILITY IDEOGRAPH-F930; QQC
+2F40 ; [.FB40.0020.0004.652F][.E52F.0000.0000.652F] # KANGXI RADICAL BRANCH; QQK
+2F41 ; [.FB40.0020.0004.6534][.E534.0000.0000.6534] # KANGXI RADICAL RAP; QQK
+2E99 ; [.FB40.0020.0004.6535][.E535.0000.0000.6535] # CJK RADICAL RAP; QQK
+FA41 ; [.FB40.0020.0002.654F][.E54F.0000.0000.654F] # CJK COMPATIBILITY IDEOGRAPH-FA41; QQC
+2F8C8 ; [.FB40.0020.0002.654F][.E54F.0000.0000.654F] # CJK COMPATIBILITY IDEOGRAPH-2F8C8; QQC
+FA90 ; [.FB40.0020.0002.6556][.E556.0000.0000.6556] # CJK COMPATIBILITY IDEOGRAPH-FA90; QQC
+2F8C9 ; [.FB40.0020.0002.656C][.E56C.0000.0000.656C] # CJK COMPATIBILITY IDEOGRAPH-2F8C9; QQC
+F969 ; [.FB40.0020.0002.6578][.E578.0000.0000.6578] # CJK COMPATIBILITY IDEOGRAPH-F969; QQC
+2F42 ; [.FB40.0020.0004.6587][.E587.0000.0000.6587] # KANGXI RADICAL SCRIPT; QQK
+2F43 ; [.FB40.0020.0004.6597][.E597.0000.0000.6597] # KANGXI RADICAL DIPPER; QQK
+F9BE ; [.FB40.0020.0002.6599][.E599.0000.0000.6599] # CJK COMPATIBILITY IDEOGRAPH-F9BE; QQC
+2F44 ; [.FB40.0020.0004.65A4][.E5A4.0000.0000.65A4] # KANGXI RADICAL AXE; QQK
+2F45 ; [.FB40.0020.0004.65B9][.E5B9.0000.0000.65B9] # KANGXI RADICAL SQUARE; QQK
+F983 ; [.FB40.0020.0002.65C5][.E5C5.0000.0000.65C5] # CJK COMPATIBILITY IDEOGRAPH-F983; QQC
+2F46 ; [.FB40.0020.0004.65E0][.E5E0.0000.0000.65E0] # KANGXI RADICAL NOT; QQK
+2E9B ; [.FB40.0020.0004.65E1][.E5E1.0000.0000.65E1] # CJK RADICAL CHOKE; QQK
+FA42 ; [.FB40.0020.0002.65E2][.E5E2.0000.0000.65E2] # CJK COMPATIBILITY IDEOGRAPH-FA42; QQC
+2F8CB ; [.FB40.0020.0002.65E3][.E5E3.0000.0000.65E3] # CJK COMPATIBILITY IDEOGRAPH-2F8CB; QQC
+2F47 ; [.FB40.0020.0004.65E5][.E5E5.0000.0000.65E5] # KANGXI RADICAL SUN; QQK
+3230 ; [*02B1.0020.0004.3230][.FB40.0020.0004.65E5][.E5E5.0000.0000.65E5][*02B2.0020.001F.3230] # PARENTHESIZED IDEOGRAPH SUN; QQKN
+3290 ; [.FB40.0020.0006.65E5][.E5E5.0000.0000.65E5] # CIRCLED IDEOGRAPH SUN; QQK
+2E9C ; [.FB40.0020.0004.65E5][.E5E5.0000.0000.65E5][.0000.0199.001F.2E9C] # CJK RADICAL SUN; QQKN
+337E ; [.FB40.0020.001C.660E][.E60E.0000.0000.660E][.FB40.0020.001F.6CBB][.ECBB.0000.0000.6CBB] # SQUARE ERA NAME MEIZI; QQKN
+F9E0 ; [.FB40.0020.0002.6613][.E613.0000.0000.6613] # CJK COMPATIBILITY IDEOGRAPH-F9E0; QQC
+337C ; [.FB40.0020.001C.662D][.E62D.0000.0000.662D][.FB40.0020.001F.548C][.D48C.0000.0000.548C] # SQUARE ERA NAME SYOUWA; QQKN
+2F8CD ; [.FB40.0020.0002.6649][.E649.0000.0000.6649] # CJK COMPATIBILITY IDEOGRAPH-2F8CD; QQC
+FA12 ; [.FB40.0020.0002.6674][.E674.0000.0000.6674] # CJK COMPATIBILITY IDEOGRAPH-FA12; QQC
+FA91 ; [.FB40.0020.0002.6674][.E674.0000.0000.6674] # CJK COMPATIBILITY IDEOGRAPH-FA91; QQC
+F9C5 ; [.FB40.0020.0002.6688][.E688.0000.0000.6688] # CJK COMPATIBILITY IDEOGRAPH-F9C5; QQC
+FA43 ; [.FB40.0020.0002.6691][.E691.0000.0000.6691] # CJK COMPATIBILITY IDEOGRAPH-FA43; QQC
+2F8CF ; [.FB40.0020.0002.6691][.E691.0000.0000.6691] # CJK COMPATIBILITY IDEOGRAPH-2F8CF; QQC
+2F8D5 ; [.FB40.0020.0002.669C][.E69C.0000.0000.669C] # CJK COMPATIBILITY IDEOGRAPH-2F8D5; QQC
+FA06 ; [.FB40.0020.0002.66B4][.E6B4.0000.0000.66B4] # CJK COMPATIBILITY IDEOGRAPH-FA06; QQC
+F98B ; [.FB40.0020.0002.66C6][.E6C6.0000.0000.66C6] # CJK COMPATIBILITY IDEOGRAPH-F98B; QQC
+2F48 ; [.FB40.0020.0004.66F0][.E6F0.0000.0000.66F0] # KANGXI RADICAL SAY; QQK
+F901 ; [.FB40.0020.0002.66F4][.E6F4.0000.0000.66F4] # CJK COMPATIBILITY IDEOGRAPH-F901; QQC
+2F8CC ; [.FB40.0020.0002.66F8][.E6F8.0000.0000.66F8] # CJK COMPATIBILITY IDEOGRAPH-2F8CC; QQC
+2F8D4 ; [.FB40.0020.0002.6700][.E700.0000.0000.6700] # CJK COMPATIBILITY IDEOGRAPH-2F8D4; QQC
+2F49 ; [.FB40.0020.0004.6708][.E708.0000.0000.6708] # KANGXI RADICAL MOON; QQK
+322A ; [*02B1.0020.0004.322A][.FB40.0020.0004.6708][.E708.0000.0000.6708][*02B2.0020.001F.322A] # PARENTHESIZED IDEOGRAPH MOON; QQKN
+328A ; [.FB40.0020.0006.6708][.E708.0000.0000.6708] # CIRCLED IDEOGRAPH MOON; QQK
+2E9D ; [.FB40.0020.0004.6708][.E708.0000.0000.6708][.0000.0199.001F.2E9D] # CJK RADICAL MOON; QQKN
+3232 ; [*02B1.0020.0004.3232][.FB40.0020.0004.6709][.E709.0000.0000.6709][*02B2.0020.001F.3232] # PARENTHESIZED IDEOGRAPH HAVE; QQKN
+3292 ; [.FB40.0020.0006.6709][.E709.0000.0000.6709] # CIRCLED IDEOGRAPH HAVE; QQK
+F929 ; [.FB40.0020.0002.6717][.E717.0000.0000.6717] # CJK COMPATIBILITY IDEOGRAPH-F929; QQC
+FA92 ; [.FB40.0020.0002.6717][.E717.0000.0000.6717] # CJK COMPATIBILITY IDEOGRAPH-FA92; QQC
+2F8D8 ; [.FB40.0020.0002.6717][.E717.0000.0000.6717] # CJK COMPATIBILITY IDEOGRAPH-2F8D8; QQC
+FA93 ; [.FB40.0020.0002.671B][.E71B.0000.0000.671B] # CJK COMPATIBILITY IDEOGRAPH-FA93; QQC
+2F8D9 ; [.FB40.0020.0002.671B][.E71B.0000.0000.671B] # CJK COMPATIBILITY IDEOGRAPH-2F8D9; QQC
+2F8DA ; [.FB40.0020.0002.6721][.E721.0000.0000.6721] # CJK COMPATIBILITY IDEOGRAPH-2F8DA; QQC
+2F4A ; [.FB40.0020.0004.6728][.E728.0000.0000.6728] # KANGXI RADICAL TREE; QQK
+322D ; [*02B1.0020.0004.322D][.FB40.0020.0004.6728][.E728.0000.0000.6728][*02B2.0020.001F.322D] # PARENTHESIZED IDEOGRAPH WOOD; QQKN
+328D ; [.FB40.0020.0006.6728][.E728.0000.0000.6728] # CIRCLED IDEOGRAPH WOOD; QQK
+F9E1 ; [.FB40.0020.0002.674E][.E74E.0000.0000.674E] # CJK COMPATIBILITY IDEOGRAPH-F9E1; QQC
+2F8DC ; [.FB40.0020.0002.6753][.E753.0000.0000.6753] # CJK COMPATIBILITY IDEOGRAPH-2F8DC; QQC
+FA94 ; [.FB40.0020.0002.6756][.E756.0000.0000.6756] # CJK COMPATIBILITY IDEOGRAPH-FA94; QQC
+2F8DB ; [.FB40.0020.0002.675E][.E75E.0000.0000.675E] # CJK COMPATIBILITY IDEOGRAPH-2F8DB; QQC
+F9C8 ; [.FB40.0020.0002.677B][.E77B.0000.0000.677B] # CJK COMPATIBILITY IDEOGRAPH-F9C8; QQC
+2F8E0 ; [.FB40.0020.0002.6785][.E785.0000.0000.6785] # CJK COMPATIBILITY IDEOGRAPH-2F8E0; QQC
+F9F4 ; [.FB40.0020.0002.6797][.E797.0000.0000.6797] # CJK COMPATIBILITY IDEOGRAPH-F9F4; QQC
+F9C9 ; [.FB40.0020.0002.67F3][.E7F3.0000.0000.67F3] # CJK COMPATIBILITY IDEOGRAPH-F9C9; QQC
+2F8DF ; [.FB40.0020.0002.67FA][.E7FA.0000.0000.67FA] # CJK COMPATIBILITY IDEOGRAPH-2F8DF; QQC
+F9DA ; [.FB40.0020.0002.6817][.E817.0000.0000.6817] # CJK COMPATIBILITY IDEOGRAPH-F9DA; QQC
+2F8E5 ; [.FB40.0020.0002.681F][.E81F.0000.0000.681F] # CJK COMPATIBILITY IDEOGRAPH-2F8E5; QQC
+3231 ; [*02B1.0020.0004.3231][.FB40.0020.0004.682A][.E82A.0000.0000.682A][*02B2.0020.001F.3231] # PARENTHESIZED IDEOGRAPH STOCK; QQKN
+3291 ; [.FB40.0020.0006.682A][.E82A.0000.0000.682A] # CIRCLED IDEOGRAPH STOCK; QQK
+337F ; [.FB40.0020.001C.682A][.E82A.0000.0000.682A][.FB40.0020.001F.5F0F][.DF0F.0000.0000.5F0F][.FB40.0020.001F.4F1A][.CF1A.0000.0000.4F1A][.FB40.0020.001F.793E][.F93E.0000.0000.793E] # SQUARE CORPORATION; QQKN
+2F8E1 ; [.FB40.0020.0002.6852][.E852.0000.0000.6852] # CJK COMPATIBILITY IDEOGRAPH-2F8E1; QQC
+F97A ; [.FB40.0020.0002.6881][.E881.0000.0000.6881] # CJK COMPATIBILITY IDEOGRAPH-F97A; QQC
+FA44 ; [.FB40.0020.0002.6885][.E885.0000.0000.6885] # CJK COMPATIBILITY IDEOGRAPH-FA44; QQC
+2F8E2 ; [.FB40.0020.0002.6885][.E885.0000.0000.6885] # CJK COMPATIBILITY IDEOGRAPH-2F8E2; QQC
+2F8E4 ; [.FB40.0020.0002.688E][.E88E.0000.0000.688E] # CJK COMPATIBILITY IDEOGRAPH-2F8E4; QQC
+F9E2 ; [.FB40.0020.0002.68A8][.E8A8.0000.0000.68A8] # CJK COMPATIBILITY IDEOGRAPH-F9E2; QQC
+2F8E6 ; [.FB40.0020.0002.6914][.E914.0000.0000.6914] # CJK COMPATIBILITY IDEOGRAPH-2F8E6; QQC
+2F8E8 ; [.FB40.0020.0002.6942][.E942.0000.0000.6942] # CJK COMPATIBILITY IDEOGRAPH-2F8E8; QQC
+2F8E9 ; [.FB40.0020.0002.69A3][.E9A3.0000.0000.69A3] # CJK COMPATIBILITY IDEOGRAPH-2F8E9; QQC
+2F8EA ; [.FB40.0020.0002.69EA][.E9EA.0000.0000.69EA] # CJK COMPATIBILITY IDEOGRAPH-2F8EA; QQC
+F914 ; [.FB40.0020.0002.6A02][.EA02.0000.0000.6A02] # CJK COMPATIBILITY IDEOGRAPH-F914; QQC
+F95C ; [.FB40.0020.0002.6A02][.EA02.0000.0000.6A02] # CJK COMPATIBILITY IDEOGRAPH-F95C; QQC
+F9BF ; [.FB40.0020.0002.6A02][.EA02.0000.0000.6A02] # CJK COMPATIBILITY IDEOGRAPH-F9BF; QQC
+F94C ; [.FB40.0020.0002.6A13][.EA13.0000.0000.6A13] # CJK COMPATIBILITY IDEOGRAPH-F94C; QQC
+2F8EB ; [.FB40.0020.0002.6AA8][.EAA8.0000.0000.6AA8] # CJK COMPATIBILITY IDEOGRAPH-2F8EB; QQC
+F931 ; [.FB40.0020.0002.6AD3][.EAD3.0000.0000.6AD3] # CJK COMPATIBILITY IDEOGRAPH-F931; QQC
+2F8ED ; [.FB40.0020.0002.6ADB][.EADB.0000.0000.6ADB] # CJK COMPATIBILITY IDEOGRAPH-2F8ED; QQC
+F91D ; [.FB40.0020.0002.6B04][.EB04.0000.0000.6B04] # CJK COMPATIBILITY IDEOGRAPH-F91D; QQC
+2F4B ; [.FB40.0020.0004.6B20][.EB20.0000.0000.6B20] # KANGXI RADICAL LACK; QQK
+2F8EF ; [.FB40.0020.0002.6B21][.EB21.0000.0000.6B21] # CJK COMPATIBILITY IDEOGRAPH-2F8EF; QQC
+2F8F1 ; [.FB40.0020.0002.6B54][.EB54.0000.0000.6B54] # CJK COMPATIBILITY IDEOGRAPH-2F8F1; QQC
+2F4C ; [.FB40.0020.0004.6B62][.EB62.0000.0000.6B62] # KANGXI RADICAL STOP; QQK
+32A3 ; [.FB40.0020.0006.6B63][.EB63.0000.0000.6B63] # CIRCLED IDEOGRAPH CORRECT; QQK
+2F8F3 ; [.FB40.0020.0002.6B72][.EB72.0000.0000.6B72] # CJK COMPATIBILITY IDEOGRAPH-2F8F3; QQC
+F98C ; [.FB40.0020.0002.6B77][.EB77.0000.0000.6B77] # CJK COMPATIBILITY IDEOGRAPH-F98C; QQC
+FA95 ; [.FB40.0020.0002.6B79][.EB79.0000.0000.6B79] # CJK COMPATIBILITY IDEOGRAPH-FA95; QQC
+2F4D ; [.FB40.0020.0004.6B79][.EB79.0000.0000.6B79] # KANGXI RADICAL DEATH; QQK
+2E9E ; [.FB40.0020.0004.6B7A][.EB7A.0000.0000.6B7A][.0000.0199.001F.2E9E] # CJK RADICAL DEATH; QQKN
+2F8F4 ; [.FB40.0020.0002.6B9F][.EB9F.0000.0000.6B9F] # CJK COMPATIBILITY IDEOGRAPH-2F8F4; QQC
+F9A5 ; [.FB40.0020.0002.6BAE][.EBAE.0000.0000.6BAE] # CJK COMPATIBILITY IDEOGRAPH-F9A5; QQC
+2F4E ; [.FB40.0020.0004.6BB3][.EBB3.0000.0000.6BB3] # KANGXI RADICAL WEAPON; QQK
+F970 ; [.FB40.0020.0002.6BBA][.EBBA.0000.0000.6BBA] # CJK COMPATIBILITY IDEOGRAPH-F970; QQC
+FA96 ; [.FB40.0020.0002.6BBA][.EBBA.0000.0000.6BBA] # CJK COMPATIBILITY IDEOGRAPH-FA96; QQC
+2F8F5 ; [.FB40.0020.0002.6BBA][.EBBA.0000.0000.6BBA] # CJK COMPATIBILITY IDEOGRAPH-2F8F5; QQC
+2F8F6 ; [.FB40.0020.0002.6BBB][.EBBB.0000.0000.6BBB] # CJK COMPATIBILITY IDEOGRAPH-2F8F6; QQC
+2F4F ; [.FB40.0020.0004.6BCB][.EBCB.0000.0000.6BCB] # KANGXI RADICAL DO NOT; QQK
+2E9F ; [.FB40.0020.0004.6BCD][.EBCD.0000.0000.6BCD] # CJK RADICAL MOTHER; QQK
+2F50 ; [.FB40.0020.0004.6BD4][.EBD4.0000.0000.6BD4] # KANGXI RADICAL COMPARE; QQK
+2F51 ; [.FB40.0020.0004.6BDB][.EBDB.0000.0000.6BDB] # KANGXI RADICAL FUR; QQK
+2F52 ; [.FB40.0020.0004.6C0F][.EC0F.0000.0000.6C0F] # KANGXI RADICAL CLAN; QQK
+2EA0 ; [.FB40.0020.0004.6C11][.EC11.0000.0000.6C11] # CJK RADICAL CIVILIAN; QQK
+2F53 ; [.FB40.0020.0004.6C14][.EC14.0000.0000.6C14] # KANGXI RADICAL STEAM; QQK
+2F54 ; [.FB40.0020.0004.6C34][.EC34.0000.0000.6C34] # KANGXI RADICAL WATER; QQK
+322C ; [*02B1.0020.0004.322C][.FB40.0020.0004.6C34][.EC34.0000.0000.6C34][*02B2.0020.001F.322C] # PARENTHESIZED IDEOGRAPH WATER; QQKN
+328C ; [.FB40.0020.0006.6C34][.EC34.0000.0000.6C34] # CIRCLED IDEOGRAPH WATER; QQK
+2EA1 ; [.FB40.0020.0004.6C35][.EC35.0000.0000.6C35] # CJK RADICAL WATER ONE; QQK
+2EA2 ; [.FB40.0020.0004.6C3A][.EC3A.0000.0000.6C3A] # CJK RADICAL WATER TWO; QQK
+2F8FA ; [.FB40.0020.0002.6C4E][.EC4E.0000.0000.6C4E] # CJK COMPATIBILITY IDEOGRAPH-2F8FA; QQC
+2F8FE ; [.FB40.0020.0002.6C67][.EC67.0000.0000.6C67] # CJK COMPATIBILITY IDEOGRAPH-2F8FE; QQC
+F972 ; [.FB40.0020.0002.6C88][.EC88.0000.0000.6C88] # CJK COMPATIBILITY IDEOGRAPH-F972; QQC
+2F8FC ; [.FB40.0020.0002.6CBF][.ECBF.0000.0000.6CBF] # CJK COMPATIBILITY IDEOGRAPH-2F8FC; QQC
+F968 ; [.FB40.0020.0002.6CCC][.ECCC.0000.0000.6CCC] # CJK COMPATIBILITY IDEOGRAPH-F968; QQC
+2F8FD ; [.FB40.0020.0002.6CCD][.ECCD.0000.0000.6CCD] # CJK COMPATIBILITY IDEOGRAPH-2F8FD; QQC
+F9E3 ; [.FB40.0020.0002.6CE5][.ECE5.0000.0000.6CE5] # CJK COMPATIBILITY IDEOGRAPH-F9E3; QQC
+329F ; [.FB40.0020.0006.6CE8][.ECE8.0000.0000.6CE8] # CIRCLED IDEOGRAPH ATTENTION; QQK
+2F8FF ; [.FB40.0020.0002.6D16][.ED16.0000.0000.6D16] # CJK COMPATIBILITY IDEOGRAPH-2F8FF; QQC
+F915 ; [.FB40.0020.0002.6D1B][.ED1B.0000.0000.6D1B] # CJK COMPATIBILITY IDEOGRAPH-F915; QQC
+FA05 ; [.FB40.0020.0002.6D1E][.ED1E.0000.0000.6D1E] # CJK COMPATIBILITY IDEOGRAPH-FA05; QQC
+2F907 ; [.FB40.0020.0002.6D34][.ED34.0000.0000.6D34] # CJK COMPATIBILITY IDEOGRAPH-2F907; QQC
+2F900 ; [.FB40.0020.0002.6D3E][.ED3E.0000.0000.6D3E] # CJK COMPATIBILITY IDEOGRAPH-2F900; QQC
+F9CA ; [.FB40.0020.0002.6D41][.ED41.0000.0000.6D41] # CJK COMPATIBILITY IDEOGRAPH-F9CA; QQC
+FA97 ; [.FB40.0020.0002.6D41][.ED41.0000.0000.6D41] # CJK COMPATIBILITY IDEOGRAPH-FA97; QQC
+2F902 ; [.FB40.0020.0002.6D41][.ED41.0000.0000.6D41] # CJK COMPATIBILITY IDEOGRAPH-2F902; QQC
+2F903 ; [.FB40.0020.0002.6D69][.ED69.0000.0000.6D69] # CJK COMPATIBILITY IDEOGRAPH-2F903; QQC
+F92A ; [.FB40.0020.0002.6D6A][.ED6A.0000.0000.6D6A] # CJK COMPATIBILITY IDEOGRAPH-F92A; QQC
+FA45 ; [.FB40.0020.0002.6D77][.ED77.0000.0000.6D77] # CJK COMPATIBILITY IDEOGRAPH-FA45; QQC
+2F901 ; [.FB40.0020.0002.6D77][.ED77.0000.0000.6D77] # CJK COMPATIBILITY IDEOGRAPH-2F901; QQC
+2F904 ; [.FB40.0020.0002.6D78][.ED78.0000.0000.6D78] # CJK COMPATIBILITY IDEOGRAPH-2F904; QQC
+2F905 ; [.FB40.0020.0002.6D85][.ED85.0000.0000.6D85] # CJK COMPATIBILITY IDEOGRAPH-2F905; QQC
+F9F5 ; [.FB40.0020.0002.6DCB][.EDCB.0000.0000.6DCB] # CJK COMPATIBILITY IDEOGRAPH-F9F5; QQC
+F94D ; [.FB40.0020.0002.6DDA][.EDDA.0000.0000.6DDA] # CJK COMPATIBILITY IDEOGRAPH-F94D; QQC
+F9D6 ; [.FB40.0020.0002.6DEA][.EDEA.0000.0000.6DEA] # CJK COMPATIBILITY IDEOGRAPH-F9D6; QQC
+2F90E ; [.FB40.0020.0002.6DF9][.EDF9.0000.0000.6DF9] # CJK COMPATIBILITY IDEOGRAPH-2F90E; QQC
+FA46 ; [.FB40.0020.0002.6E1A][.EE1A.0000.0000.6E1A] # CJK COMPATIBILITY IDEOGRAPH-FA46; QQC
+2F908 ; [.FB40.0020.0002.6E2F][.EE2F.0000.0000.6E2F] # CJK COMPATIBILITY IDEOGRAPH-2F908; QQC
+2F909 ; [.FB40.0020.0002.6E6E][.EE6E.0000.0000.6E6E] # CJK COMPATIBILITY IDEOGRAPH-2F909; QQC
+F9CB ; [.FB40.0020.0002.6E9C][.EE9C.0000.0000.6E9C] # CJK COMPATIBILITY IDEOGRAPH-F9CB; QQC
+F9EC ; [.FB40.0020.0002.6EBA][.EEBA.0000.0000.6EBA] # CJK COMPATIBILITY IDEOGRAPH-F9EC; QQC
+2F90C ; [.FB40.0020.0002.6EC7][.EEC7.0000.0000.6EC7] # CJK COMPATIBILITY IDEOGRAPH-2F90C; QQC
+FA99 ; [.FB40.0020.0002.6ECB][.EECB.0000.0000.6ECB] # CJK COMPATIBILITY IDEOGRAPH-FA99; QQC
+2F90B ; [.FB40.0020.0002.6ECB][.EECB.0000.0000.6ECB] # CJK COMPATIBILITY IDEOGRAPH-2F90B; QQC
+F904 ; [.FB40.0020.0002.6ED1][.EED1.0000.0000.6ED1] # CJK COMPATIBILITY IDEOGRAPH-F904; QQC
+FA98 ; [.FB40.0020.0002.6EDB][.EEDB.0000.0000.6EDB] # CJK COMPATIBILITY IDEOGRAPH-FA98; QQC
+F94E ; [.FB40.0020.0002.6F0F][.EF0F.0000.0000.6F0F] # CJK COMPATIBILITY IDEOGRAPH-F94E; QQC
+FA47 ; [.FB40.0020.0002.6F22][.EF22.0000.0000.6F22] # CJK COMPATIBILITY IDEOGRAPH-FA47; QQC
+FA9A ; [.FB40.0020.0002.6F22][.EF22.0000.0000.6F22] # CJK COMPATIBILITY IDEOGRAPH-FA9A; QQC
+F992 ; [.FB40.0020.0002.6F23][.EF23.0000.0000.6F23] # CJK COMPATIBILITY IDEOGRAPH-F992; QQC
+2F90F ; [.FB40.0020.0002.6F6E][.EF6E.0000.0000.6F6E] # CJK COMPATIBILITY IDEOGRAPH-2F90F; QQC
+2F912 ; [.FB40.0020.0002.6FC6][.EFC6.0000.0000.6FC6] # CJK COMPATIBILITY IDEOGRAPH-2F912; QQC
+F922 ; [.FB40.0020.0002.6FEB][.EFEB.0000.0000.6FEB] # CJK COMPATIBILITY IDEOGRAPH-F922; QQC
+F984 ; [.FB40.0020.0002.6FFE][.EFFE.0000.0000.6FFE] # CJK COMPATIBILITY IDEOGRAPH-F984; QQC
+2F915 ; [.FB40.0020.0002.701B][.F01B.0000.0000.701B] # CJK COMPATIBILITY IDEOGRAPH-2F915; QQC
+FA9B ; [.FB40.0020.0002.701E][.F01E.0000.0000.701E] # CJK COMPATIBILITY IDEOGRAPH-FA9B; QQC
+2F914 ; [.FB40.0020.0002.701E][.F01E.0000.0000.701E] # CJK COMPATIBILITY IDEOGRAPH-2F914; QQC
+2F913 ; [.FB40.0020.0002.7039][.F039.0000.0000.7039] # CJK COMPATIBILITY IDEOGRAPH-2F913; QQC
+2F917 ; [.FB40.0020.0002.704A][.F04A.0000.0000.704A] # CJK COMPATIBILITY IDEOGRAPH-2F917; QQC
+2F55 ; [.FB40.0020.0004.706B][.F06B.0000.0000.706B] # KANGXI RADICAL FIRE; QQK
+322B ; [*02B1.0020.0004.322B][.FB40.0020.0004.706B][.F06B.0000.0000.706B][*02B2.0020.001F.322B] # PARENTHESIZED IDEOGRAPH FIRE; QQKN
+328B ; [.FB40.0020.0006.706B][.F06B.0000.0000.706B] # CIRCLED IDEOGRAPH FIRE; QQK
+2EA3 ; [.FB40.0020.0004.706C][.F06C.0000.0000.706C] # CJK RADICAL FIRE; QQK
+2F835 ; [.FB40.0020.0002.7070][.F070.0000.0000.7070] # CJK COMPATIBILITY IDEOGRAPH-2F835; QQC
+2F919 ; [.FB40.0020.0002.7077][.F077.0000.0000.7077] # CJK COMPATIBILITY IDEOGRAPH-2F919; QQC
+2F918 ; [.FB40.0020.0002.707D][.F07D.0000.0000.707D] # CJK COMPATIBILITY IDEOGRAPH-2F918; QQC
+F9FB ; [.FB40.0020.0002.7099][.F099.0000.0000.7099] # CJK COMPATIBILITY IDEOGRAPH-F9FB; QQC
+2F91A ; [.FB40.0020.0002.70AD][.F0AD.0000.0000.70AD] # CJK COMPATIBILITY IDEOGRAPH-2F91A; QQC
+F99F ; [.FB40.0020.0002.70C8][.F0C8.0000.0000.70C8] # CJK COMPATIBILITY IDEOGRAPH-F99F; QQC
+F916 ; [.FB40.0020.0002.70D9][.F0D9.0000.0000.70D9] # CJK COMPATIBILITY IDEOGRAPH-F916; QQC
+2F91C ; [.FB40.0020.0002.7145][.F145.0000.0000.7145] # CJK COMPATIBILITY IDEOGRAPH-2F91C; QQC
+F993 ; [.FB40.0020.0002.7149][.F149.0000.0000.7149] # CJK COMPATIBILITY IDEOGRAPH-F993; QQC
+FA48 ; [.FB40.0020.0002.716E][.F16E.0000.0000.716E] # CJK COMPATIBILITY IDEOGRAPH-FA48; QQC
+FA9C ; [.FB40.0020.0002.716E][.F16E.0000.0000.716E] # CJK COMPATIBILITY IDEOGRAPH-FA9C; QQC
+2F91E ; [.FB40.0020.0002.719C][.F19C.0000.0000.719C] # CJK COMPATIBILITY IDEOGRAPH-2F91E; QQC
+F9C0 ; [.FB40.0020.0002.71CE][.F1CE.0000.0000.71CE] # CJK COMPATIBILITY IDEOGRAPH-F9C0; QQC
+F9EE ; [.FB40.0020.0002.71D0][.F1D0.0000.0000.71D0] # CJK COMPATIBILITY IDEOGRAPH-F9EE; QQC
+F932 ; [.FB40.0020.0002.7210][.F210.0000.0000.7210] # CJK COMPATIBILITY IDEOGRAPH-F932; QQC
+F91E ; [.FB40.0020.0002.721B][.F21B.0000.0000.721B] # CJK COMPATIBILITY IDEOGRAPH-F91E; QQC
+2F920 ; [.FB40.0020.0002.7228][.F228.0000.0000.7228] # CJK COMPATIBILITY IDEOGRAPH-2F920; QQC
+2F56 ; [.FB40.0020.0004.722A][.F22A.0000.0000.722A] # KANGXI RADICAL CLAW; QQK
+FA49 ; [.FB40.0020.0002.722B][.F22B.0000.0000.722B] # CJK COMPATIBILITY IDEOGRAPH-FA49; QQC
+2EA4 ; [.FB40.0020.0004.722B][.F22B.0000.0000.722B] # CJK RADICAL PAW ONE; QQK
+2EA5 ; [.FB40.0020.0004.722B][.F22B.0000.0000.722B][.0000.0199.001F.2EA5] # CJK RADICAL PAW TWO; QQKN
+FA9E ; [.FB40.0020.0002.7235][.F235.0000.0000.7235] # CJK COMPATIBILITY IDEOGRAPH-FA9E; QQC
+2F921 ; [.FB40.0020.0002.7235][.F235.0000.0000.7235] # CJK COMPATIBILITY IDEOGRAPH-2F921; QQC
+2F57 ; [.FB40.0020.0004.7236][.F236.0000.0000.7236] # KANGXI RADICAL FATHER; QQK
+2F58 ; [.FB40.0020.0004.723B][.F23B.0000.0000.723B] # KANGXI RADICAL DOUBLE X; QQK
+2F59 ; [.FB40.0020.0004.723F][.F23F.0000.0000.723F] # KANGXI RADICAL HALF TREE TRUNK; QQK
+2F5A ; [.FB40.0020.0004.7247][.F247.0000.0000.7247] # KANGXI RADICAL SLICE; QQK
+2F922 ; [.FB40.0020.0002.7250][.F250.0000.0000.7250] # CJK COMPATIBILITY IDEOGRAPH-2F922; QQC
+2F5B ; [.FB40.0020.0004.7259][.F259.0000.0000.7259] # KANGXI RADICAL FANG; QQK
+2F5C ; [.FB40.0020.0004.725B][.F25B.0000.0000.725B] # KANGXI RADICAL COW; QQK
+2EA7 ; [.FB40.0020.0004.725B][.F25B.0000.0000.725B][.0000.0199.001F.2EA7] # CJK RADICAL COW; QQKN
+F946 ; [.FB40.0020.0002.7262][.F262.0000.0000.7262] # CJK COMPATIBILITY IDEOGRAPH-F946; QQC
+3235 ; [*02B1.0020.0004.3235][.FB40.0020.0004.7279][.F279.0000.0000.7279][*02B2.0020.001F.3235] # PARENTHESIZED IDEOGRAPH SPECIAL; QQKN
+3295 ; [.FB40.0020.0006.7279][.F279.0000.0000.7279] # CIRCLED IDEOGRAPH SPECIAL; QQK
+2F924 ; [.FB40.0020.0002.7280][.F280.0000.0000.7280] # CJK COMPATIBILITY IDEOGRAPH-2F924; QQC
+2F925 ; [.FB40.0020.0002.7295][.F295.0000.0000.7295] # CJK COMPATIBILITY IDEOGRAPH-2F925; QQC
+2F5D ; [.FB40.0020.0004.72AC][.F2AC.0000.0000.72AC] # KANGXI RADICAL DOG; QQK
+2EA8 ; [.FB40.0020.0004.72AD][.F2AD.0000.0000.72AD] # CJK RADICAL DOG; QQK
+FA9F ; [.FB40.0020.0002.72AF][.F2AF.0000.0000.72AF] # CJK COMPATIBILITY IDEOGRAPH-FA9F; QQC
+F9FA ; [.FB40.0020.0002.72C0][.F2C0.0000.0000.72C0] # CJK COMPATIBILITY IDEOGRAPH-F9FA; QQC
+F92B ; [.FB40.0020.0002.72FC][.F2FC.0000.0000.72FC] # CJK COMPATIBILITY IDEOGRAPH-F92B; QQC
+FA16 ; [.FB40.0020.0002.732A][.F32A.0000.0000.732A] # CJK COMPATIBILITY IDEOGRAPH-FA16; QQC
+FAA0 ; [.FB40.0020.0002.732A][.F32A.0000.0000.732A] # CJK COMPATIBILITY IDEOGRAPH-FAA0; QQC
+F9A7 ; [.FB40.0020.0002.7375][.F375.0000.0000.7375] # CJK COMPATIBILITY IDEOGRAPH-F9A7; QQC
+2F928 ; [.FB40.0020.0002.737A][.F37A.0000.0000.737A] # CJK COMPATIBILITY IDEOGRAPH-2F928; QQC
+2F5E ; [.FB40.0020.0004.7384][.F384.0000.0000.7384] # KANGXI RADICAL PROFOUND; QQK
+F961 ; [.FB40.0020.0002.7387][.F387.0000.0000.7387] # CJK COMPATIBILITY IDEOGRAPH-F961; QQC
+F9DB ; [.FB40.0020.0002.7387][.F387.0000.0000.7387] # CJK COMPATIBILITY IDEOGRAPH-F9DB; QQC
+2F5F ; [.FB40.0020.0004.7389][.F389.0000.0000.7389] # KANGXI RADICAL JADE; QQK
+2F929 ; [.FB40.0020.0002.738B][.F38B.0000.0000.738B] # CJK COMPATIBILITY IDEOGRAPH-2F929; QQC
+2EA9 ; [.FB40.0020.0004.738B][.F38B.0000.0000.738B][.0000.0199.001F.2EA9] # CJK RADICAL JADE; QQKN
+2F92B ; [.FB40.0020.0002.73A5][.F3A5.0000.0000.73A5] # CJK COMPATIBILITY IDEOGRAPH-2F92B; QQC
+F9AD ; [.FB40.0020.0002.73B2][.F3B2.0000.0000.73B2] # CJK COMPATIBILITY IDEOGRAPH-F9AD; QQC
+F917 ; [.FB40.0020.0002.73DE][.F3DE.0000.0000.73DE] # CJK COMPATIBILITY IDEOGRAPH-F917; QQC
+F9E4 ; [.FB40.0020.0002.7406][.F406.0000.0000.7406] # CJK COMPATIBILITY IDEOGRAPH-F9E4; QQC
+F9CC ; [.FB40.0020.0002.7409][.F409.0000.0000.7409] # CJK COMPATIBILITY IDEOGRAPH-F9CC; QQC
+FA4A ; [.FB40.0020.0002.7422][.F422.0000.0000.7422] # CJK COMPATIBILITY IDEOGRAPH-FA4A; QQC
+2F92E ; [.FB40.0020.0002.7447][.F447.0000.0000.7447] # CJK COMPATIBILITY IDEOGRAPH-2F92E; QQC
+2F92F ; [.FB40.0020.0002.745C][.F45C.0000.0000.745C] # CJK COMPATIBILITY IDEOGRAPH-2F92F; QQC
+F9AE ; [.FB40.0020.0002.7469][.F469.0000.0000.7469] # CJK COMPATIBILITY IDEOGRAPH-F9AE; QQC
+FAA1 ; [.FB40.0020.0002.7471][.F471.0000.0000.7471] # CJK COMPATIBILITY IDEOGRAPH-FAA1; QQC
+2F930 ; [.FB40.0020.0002.7471][.F471.0000.0000.7471] # CJK COMPATIBILITY IDEOGRAPH-2F930; QQC
+2F931 ; [.FB40.0020.0002.7485][.F485.0000.0000.7485] # CJK COMPATIBILITY IDEOGRAPH-2F931; QQC
+F994 ; [.FB40.0020.0002.7489][.F489.0000.0000.7489] # CJK COMPATIBILITY IDEOGRAPH-F994; QQC
+F9EF ; [.FB40.0020.0002.7498][.F498.0000.0000.7498] # CJK COMPATIBILITY IDEOGRAPH-F9EF; QQC
+2F932 ; [.FB40.0020.0002.74CA][.F4CA.0000.0000.74CA] # CJK COMPATIBILITY IDEOGRAPH-2F932; QQC
+2F60 ; [.FB40.0020.0004.74DC][.F4DC.0000.0000.74DC] # KANGXI RADICAL MELON; QQK
+2F61 ; [.FB40.0020.0004.74E6][.F4E6.0000.0000.74E6] # KANGXI RADICAL TILE; QQK
+FAA2 ; [.FB40.0020.0002.7506][.F506.0000.0000.7506] # CJK COMPATIBILITY IDEOGRAPH-FAA2; QQC
+2F62 ; [.FB40.0020.0004.7518][.F518.0000.0000.7518] # KANGXI RADICAL SWEET; QQK
+2F63 ; [.FB40.0020.0004.751F][.F51F.0000.0000.751F] # KANGXI RADICAL LIFE; QQK
+2F934 ; [.FB40.0020.0002.7524][.F524.0000.0000.7524] # CJK COMPATIBILITY IDEOGRAPH-2F934; QQC
+2F64 ; [.FB40.0020.0004.7528][.F528.0000.0000.7528] # KANGXI RADICAL USE; QQK
+2F65 ; [.FB40.0020.0004.7530][.F530.0000.0000.7530] # KANGXI RADICAL FIELD; QQK
+3199 ; [.FB40.0020.0014.7532][.F532.0000.0000.7532] # IDEOGRAPHIC ANNOTATION FIRST MARK; QQK
+329A ; [.FB40.0020.0006.7537][.F537.0000.0000.7537] # CIRCLED IDEOGRAPH MALE; QQK
+FAA3 ; [.FB40.0020.0002.753B][.F53B.0000.0000.753B] # CJK COMPATIBILITY IDEOGRAPH-FAA3; QQC
+2F936 ; [.FB40.0020.0002.753E][.F53E.0000.0000.753E] # CJK COMPATIBILITY IDEOGRAPH-2F936; QQC
+F9CD ; [.FB40.0020.0002.7559][.F559.0000.0000.7559] # CJK COMPATIBILITY IDEOGRAPH-F9CD; QQC
+F976 ; [.FB40.0020.0002.7565][.F565.0000.0000.7565] # CJK COMPATIBILITY IDEOGRAPH-F976; QQC
+F962 ; [.FB40.0020.0002.7570][.F570.0000.0000.7570] # CJK COMPATIBILITY IDEOGRAPH-F962; QQC
+2F938 ; [.FB40.0020.0002.7570][.F570.0000.0000.7570] # CJK COMPATIBILITY IDEOGRAPH-2F938; QQC
+2F66 ; [.FB40.0020.0004.758B][.F58B.0000.0000.758B] # KANGXI RADICAL BOLT OF CLOTH; QQK
+2EAA ; [.FB40.0020.0004.758B][.F58B.0000.0000.758B][.0000.0199.001F.2EAA] # CJK RADICAL BOLT OF CLOTH; QQKN
+2F67 ; [.FB40.0020.0004.7592][.F592.0000.0000.7592] # KANGXI RADICAL SICKNESS; QQK
+F9E5 ; [.FB40.0020.0002.75E2][.F5E2.0000.0000.75E2] # CJK COMPATIBILITY IDEOGRAPH-F9E5; QQC
+2F93A ; [.FB40.0020.0002.7610][.F610.0000.0000.7610] # CJK COMPATIBILITY IDEOGRAPH-2F93A; QQC
+FAA4 ; [.FB40.0020.0002.761D][.F61D.0000.0000.761D] # CJK COMPATIBILITY IDEOGRAPH-FAA4; QQC
+FAA5 ; [.FB40.0020.0002.761F][.F61F.0000.0000.761F] # CJK COMPATIBILITY IDEOGRAPH-FAA5; QQC
+F9C1 ; [.FB40.0020.0002.7642][.F642.0000.0000.7642] # CJK COMPATIBILITY IDEOGRAPH-F9C1; QQC
+F90E ; [.FB40.0020.0002.7669][.F669.0000.0000.7669] # CJK COMPATIBILITY IDEOGRAPH-F90E; QQC
+2F68 ; [.FB40.0020.0004.7676][.F676.0000.0000.7676] # KANGXI RADICAL DOTTED TENT; QQK
+2F69 ; [.FB40.0020.0004.767D][.F67D.0000.0000.767D] # KANGXI RADICAL WHITE; QQK
+2F6A ; [.FB40.0020.0004.76AE][.F6AE.0000.0000.76AE] # KANGXI RADICAL SKIN; QQK
+2F6B ; [.FB40.0020.0004.76BF][.F6BF.0000.0000.76BF] # KANGXI RADICAL DISH; QQK
+FA17 ; [.FB40.0020.0002.76CA][.F6CA.0000.0000.76CA] # CJK COMPATIBILITY IDEOGRAPH-FA17; QQC
+FAA6 ; [.FB40.0020.0002.76CA][.F6CA.0000.0000.76CA] # CJK COMPATIBILITY IDEOGRAPH-FAA6; QQC
+FAA7 ; [.FB40.0020.0002.76DB][.F6DB.0000.0000.76DB] # CJK COMPATIBILITY IDEOGRAPH-FAA7; QQC
+323C ; [*02B1.0020.0004.323C][.FB40.0020.0004.76E3][.F6E3.0000.0000.76E3][*02B2.0020.001F.323C] # PARENTHESIZED IDEOGRAPH SUPERVISE; QQKN
+32AC ; [.FB40.0020.0006.76E3][.F6E3.0000.0000.76E3] # CIRCLED IDEOGRAPH SUPERVISE; QQK
+F933 ; [.FB40.0020.0002.76E7][.F6E7.0000.0000.76E7] # CJK COMPATIBILITY IDEOGRAPH-F933; QQC
+2F6C ; [.FB40.0020.0004.76EE][.F6EE.0000.0000.76EE] # KANGXI RADICAL EYE; QQK
+2EAB ; [.FB40.0020.0004.76EE][.F6EE.0000.0000.76EE][.0000.0199.001F.2EAB] # CJK RADICAL EYE; QQKN
+FAA8 ; [.FB40.0020.0002.76F4][.F6F4.0000.0000.76F4] # CJK COMPATIBILITY IDEOGRAPH-FAA8; QQC
+2F940 ; [.FB40.0020.0002.76F4][.F6F4.0000.0000.76F4] # CJK COMPATIBILITY IDEOGRAPH-2F940; QQC
+F96D ; [.FB40.0020.0002.7701][.F701.0000.0000.7701] # CJK COMPATIBILITY IDEOGRAPH-F96D; QQC
+2F945 ; [.FB40.0020.0002.771E][.F71E.0000.0000.771E] # CJK COMPATIBILITY IDEOGRAPH-2F945; QQC
+2F946 ; [.FB40.0020.0002.771F][.F71F.0000.0000.771F] # CJK COMPATIBILITY IDEOGRAPH-2F946; QQC
+2F947 ; [.FB40.0020.0002.771F][.F71F.0000.0000.771F] # CJK COMPATIBILITY IDEOGRAPH-2F947; QQC
+FAAA ; [.FB40.0020.0002.7740][.F740.0000.0000.7740] # CJK COMPATIBILITY IDEOGRAPH-FAAA; QQC
+FAA9 ; [.FB40.0020.0002.774A][.F74A.0000.0000.774A] # CJK COMPATIBILITY IDEOGRAPH-FAA9; QQC
+2F948 ; [.FB40.0020.0002.774A][.F74A.0000.0000.774A] # CJK COMPATIBILITY IDEOGRAPH-2F948; QQC
+2F94A ; [.FB40.0020.0002.778B][.F78B.0000.0000.778B] # CJK COMPATIBILITY IDEOGRAPH-2F94A; QQC
+FA9D ; [.FB40.0020.0002.77A7][.F7A7.0000.0000.77A7] # CJK COMPATIBILITY IDEOGRAPH-FA9D; QQC
+2F6D ; [.FB40.0020.0004.77DB][.F7DB.0000.0000.77DB] # KANGXI RADICAL SPEAR; QQK
+2F6E ; [.FB40.0020.0004.77E2][.F7E2.0000.0000.77E2] # KANGXI RADICAL ARROW; QQK
+2F6F ; [.FB40.0020.0004.77F3][.F7F3.0000.0000.77F3] # KANGXI RADICAL STONE; QQK
+2F94E ; [.FB40.0020.0002.784E][.F84E.0000.0000.784E] # CJK COMPATIBILITY IDEOGRAPH-2F94E; QQC
+F9CE ; [.FB40.0020.0002.786B][.F86B.0000.0000.786B] # CJK COMPATIBILITY IDEOGRAPH-F9CE; QQC
+F93B ; [.FB40.0020.0002.788C][.F88C.0000.0000.788C] # CJK COMPATIBILITY IDEOGRAPH-F93B; QQC
+2F94F ; [.FB40.0020.0002.788C][.F88C.0000.0000.788C] # CJK COMPATIBILITY IDEOGRAPH-2F94F; QQC
+FA4B ; [.FB40.0020.0002.7891][.F891.0000.0000.7891] # CJK COMPATIBILITY IDEOGRAPH-FA4B; QQC
+F947 ; [.FB40.0020.0002.78CA][.F8CA.0000.0000.78CA] # CJK COMPATIBILITY IDEOGRAPH-F947; QQC
+FAAB ; [.FB40.0020.0002.78CC][.F8CC.0000.0000.78CC] # CJK COMPATIBILITY IDEOGRAPH-FAAB; QQC
+2F950 ; [.FB40.0020.0002.78CC][.F8CC.0000.0000.78CC] # CJK COMPATIBILITY IDEOGRAPH-2F950; QQC
+F964 ; [.FB40.0020.0002.78FB][.F8FB.0000.0000.78FB] # CJK COMPATIBILITY IDEOGRAPH-F964; QQC
+F985 ; [.FB40.0020.0002.792A][.F92A.0000.0000.792A] # CJK COMPATIBILITY IDEOGRAPH-F985; QQC
+2F70 ; [.FB40.0020.0004.793A][.F93A.0000.0000.793A] # KANGXI RADICAL SPIRIT; QQK
+2EAC ; [.FB40.0020.0004.793A][.F93A.0000.0000.793A][.0000.0199.001F.2EAC] # CJK RADICAL SPIRIT ONE; QQKN
+2EAD ; [.FB40.0020.0004.793B][.F93B.0000.0000.793B] # CJK RADICAL SPIRIT TWO; QQK
+FA18 ; [.FB40.0020.0002.793C][.F93C.0000.0000.793C] # CJK COMPATIBILITY IDEOGRAPH-FA18; QQC
+FA4C ; [.FB40.0020.0002.793E][.F93E.0000.0000.793E] # CJK COMPATIBILITY IDEOGRAPH-FA4C; QQC
+3233 ; [*02B1.0020.0004.3233][.FB40.0020.0004.793E][.F93E.0000.0000.793E][*02B2.0020.001F.3233] # PARENTHESIZED IDEOGRAPH SOCIETY; QQKN
+3293 ; [.FB40.0020.0006.793E][.F93E.0000.0000.793E] # CIRCLED IDEOGRAPH SOCIETY; QQK
+FA4E ; [.FB40.0020.0002.7948][.F948.0000.0000.7948] # CJK COMPATIBILITY IDEOGRAPH-FA4E; QQC
+FA4D ; [.FB40.0020.0002.7949][.F949.0000.0000.7949] # CJK COMPATIBILITY IDEOGRAPH-FA4D; QQC
+FA4F ; [.FB40.0020.0002.7950][.F950.0000.0000.7950] # CJK COMPATIBILITY IDEOGRAPH-FA4F; QQC
+FA50 ; [.FB40.0020.0002.7956][.F956.0000.0000.7956] # CJK COMPATIBILITY IDEOGRAPH-FA50; QQC
+2F953 ; [.FB40.0020.0002.7956][.F956.0000.0000.7956] # CJK COMPATIBILITY IDEOGRAPH-2F953; QQC
+FA51 ; [.FB40.0020.0002.795D][.F95D.0000.0000.795D] # CJK COMPATIBILITY IDEOGRAPH-FA51; QQC
+3237 ; [*02B1.0020.0004.3237][.FB40.0020.0004.795D][.F95D.0000.0000.795D][*02B2.0020.001F.3237] # PARENTHESIZED IDEOGRAPH CONGRATULATION; QQKN
+3297 ; [.FB40.0020.0006.795D][.F95D.0000.0000.795D] # CIRCLED IDEOGRAPH CONGRATULATION; QQK
+FA19 ; [.FB40.0020.0002.795E][.F95E.0000.0000.795E] # CJK COMPATIBILITY IDEOGRAPH-FA19; QQC
+FA1A ; [.FB40.0020.0002.7965][.F965.0000.0000.7965] # CJK COMPATIBILITY IDEOGRAPH-FA1A; QQC
+3240 ; [*02B1.0020.0004.3240][.FB40.0020.0004.796D][.F96D.0000.0000.796D][*02B2.0020.001F.3240] # PARENTHESIZED IDEOGRAPH FESTIVAL; QQKN
+F93C ; [.FB40.0020.0002.797F][.F97F.0000.0000.797F] # CJK COMPATIBILITY IDEOGRAPH-F93C; QQC
+FA52 ; [.FB40.0020.0002.798D][.F98D.0000.0000.798D] # CJK COMPATIBILITY IDEOGRAPH-FA52; QQC
+FA53 ; [.FB40.0020.0002.798E][.F98E.0000.0000.798E] # CJK COMPATIBILITY IDEOGRAPH-FA53; QQC
+FA1B ; [.FB40.0020.0002.798F][.F98F.0000.0000.798F] # CJK COMPATIBILITY IDEOGRAPH-FA1B; QQC
+2F956 ; [.FB40.0020.0002.798F][.F98F.0000.0000.798F] # CJK COMPATIBILITY IDEOGRAPH-2F956; QQC
+F9B6 ; [.FB40.0020.0002.79AE][.F9AE.0000.0000.79AE] # CJK COMPATIBILITY IDEOGRAPH-F9B6; QQC
+2F71 ; [.FB40.0020.0004.79B8][.F9B8.0000.0000.79B8] # KANGXI RADICAL TRACK; QQK
+2F72 ; [.FB40.0020.0004.79BE][.F9BE.0000.0000.79BE] # KANGXI RADICAL GRAIN; QQK
+F995 ; [.FB40.0020.0002.79CA][.F9CA.0000.0000.79CA] # CJK COMPATIBILITY IDEOGRAPH-F995; QQC
+3299 ; [.FB40.0020.0006.79D8][.F9D8.0000.0000.79D8] # CIRCLED IDEOGRAPH SECRET; QQK
+2F957 ; [.FB40.0020.0002.79EB][.F9EB.0000.0000.79EB] # CJK COMPATIBILITY IDEOGRAPH-2F957; QQC
+F956 ; [.FB40.0020.0002.7A1C][.FA1C.0000.0000.7A1C] # CJK COMPATIBILITY IDEOGRAPH-F956; QQC
+FA54 ; [.FB40.0020.0002.7A40][.FA40.0000.0000.7A40] # CJK COMPATIBILITY IDEOGRAPH-FA54; QQC
+2F959 ; [.FB40.0020.0002.7A40][.FA40.0000.0000.7A40] # CJK COMPATIBILITY IDEOGRAPH-2F959; QQC
+2F95A ; [.FB40.0020.0002.7A4A][.FA4A.0000.0000.7A4A] # CJK COMPATIBILITY IDEOGRAPH-2F95A; QQC
+2F95B ; [.FB40.0020.0002.7A4F][.FA4F.0000.0000.7A4F] # CJK COMPATIBILITY IDEOGRAPH-2F95B; QQC
+2F73 ; [.FB40.0020.0004.7A74][.FA74.0000.0000.7A74] # KANGXI RADICAL CAVE; QQK
+FA55 ; [.FB40.0020.0002.7A81][.FA81.0000.0000.7A81] # CJK COMPATIBILITY IDEOGRAPH-FA55; QQC
+FAAC ; [.FB40.0020.0002.7AB1][.FAB1.0000.0000.7AB1] # CJK COMPATIBILITY IDEOGRAPH-FAAC; QQC
+F9F7 ; [.FB40.0020.0002.7ACB][.FACB.0000.0000.7ACB] # CJK COMPATIBILITY IDEOGRAPH-F9F7; QQC
+2F74 ; [.FB40.0020.0004.7ACB][.FACB.0000.0000.7ACB] # KANGXI RADICAL STAND; QQK
+2F95F ; [.FB40.0020.0002.7AEE][.FAEE.0000.0000.7AEE] # CJK COMPATIBILITY IDEOGRAPH-2F95F; QQC
+2F75 ; [.FB40.0020.0004.7AF9][.FAF9.0000.0000.7AF9] # KANGXI RADICAL BAMBOO; QQK
+2EAE ; [.FB40.0020.0004.7AF9][.FAF9.0000.0000.7AF9][.0000.0199.001F.2EAE] # CJK RADICAL BAMBOO; QQKN
+F9F8 ; [.FB40.0020.0002.7B20][.FB20.0000.0000.7B20] # CJK COMPATIBILITY IDEOGRAPH-F9F8; QQC
+FA56 ; [.FB40.0020.0002.7BC0][.FBC0.0000.0000.7BC0] # CJK COMPATIBILITY IDEOGRAPH-FA56; QQC
+FAAD ; [.FB40.0020.0002.7BC0][.FBC0.0000.0000.7BC0] # CJK COMPATIBILITY IDEOGRAPH-FAAD; QQC
+2F962 ; [.FB40.0020.0002.7BC6][.FBC6.0000.0000.7BC6] # CJK COMPATIBILITY IDEOGRAPH-2F962; QQC
+2F963 ; [.FB40.0020.0002.7BC9][.FBC9.0000.0000.7BC9] # CJK COMPATIBILITY IDEOGRAPH-2F963; QQC
+F9A6 ; [.FB40.0020.0002.7C3E][.FC3E.0000.0000.7C3E] # CJK COMPATIBILITY IDEOGRAPH-F9A6; QQC
+F944 ; [.FB40.0020.0002.7C60][.FC60.0000.0000.7C60] # CJK COMPATIBILITY IDEOGRAPH-F944; QQC
+2F76 ; [.FB40.0020.0004.7C73][.FC73.0000.0000.7C73] # KANGXI RADICAL RICE; QQK
+FAAE ; [.FB40.0020.0002.7C7B][.FC7B.0000.0000.7C7B] # CJK COMPATIBILITY IDEOGRAPH-FAAE; QQC
+F9F9 ; [.FB40.0020.0002.7C92][.FC92.0000.0000.7C92] # CJK COMPATIBILITY IDEOGRAPH-F9F9; QQC
+FA1D ; [.FB40.0020.0002.7CBE][.FCBE.0000.0000.7CBE] # CJK COMPATIBILITY IDEOGRAPH-FA1D; QQC
+2F966 ; [.FB40.0020.0002.7CD2][.FCD2.0000.0000.7CD2] # CJK COMPATIBILITY IDEOGRAPH-2F966; QQC
+FA03 ; [.FB40.0020.0002.7CD6][.FCD6.0000.0000.7CD6] # CJK COMPATIBILITY IDEOGRAPH-FA03; QQC
+2F969 ; [.FB40.0020.0002.7CE3][.FCE3.0000.0000.7CE3] # CJK COMPATIBILITY IDEOGRAPH-2F969; QQC
+F97B ; [.FB40.0020.0002.7CE7][.FCE7.0000.0000.7CE7] # CJK COMPATIBILITY IDEOGRAPH-F97B; QQC
+2F968 ; [.FB40.0020.0002.7CE8][.FCE8.0000.0000.7CE8] # CJK COMPATIBILITY IDEOGRAPH-2F968; QQC
+2F77 ; [.FB40.0020.0004.7CF8][.FCF8.0000.0000.7CF8] # KANGXI RADICAL SILK; QQK
+2EAF ; [.FB40.0020.0004.7CF9][.FCF9.0000.0000.7CF9] # CJK RADICAL SILK; QQK
+2F96A ; [.FB40.0020.0002.7D00][.FD00.0000.0000.7D00] # CJK COMPATIBILITY IDEOGRAPH-2F96A; QQC
+F9CF ; [.FB40.0020.0002.7D10][.FD10.0000.0000.7D10] # CJK COMPATIBILITY IDEOGRAPH-F9CF; QQC
+F96A ; [.FB40.0020.0002.7D22][.FD22.0000.0000.7D22] # CJK COMPATIBILITY IDEOGRAPH-F96A; QQC
+F94F ; [.FB40.0020.0002.7D2F][.FD2F.0000.0000.7D2F] # CJK COMPATIBILITY IDEOGRAPH-F94F; QQC
+FAAF ; [.FB40.0020.0002.7D5B][.FD5B.0000.0000.7D5B] # CJK COMPATIBILITY IDEOGRAPH-FAAF; QQC
+2F96C ; [.FB40.0020.0002.7D63][.FD63.0000.0000.7D63] # CJK COMPATIBILITY IDEOGRAPH-2F96C; QQC
+F93D ; [.FB40.0020.0002.7DA0][.FDA0.0000.0000.7DA0] # CJK COMPATIBILITY IDEOGRAPH-F93D; QQC
+F957 ; [.FB40.0020.0002.7DBE][.FDBE.0000.0000.7DBE] # CJK COMPATIBILITY IDEOGRAPH-F957; QQC
+2F96E ; [.FB40.0020.0002.7DC7][.FDC7.0000.0000.7DC7] # CJK COMPATIBILITY IDEOGRAPH-2F96E; QQC
+F996 ; [.FB40.0020.0002.7DF4][.FDF4.0000.0000.7DF4] # CJK COMPATIBILITY IDEOGRAPH-F996; QQC
+FA57 ; [.FB40.0020.0002.7DF4][.FDF4.0000.0000.7DF4] # CJK COMPATIBILITY IDEOGRAPH-FA57; QQC
+FAB0 ; [.FB40.0020.0002.7DF4][.FDF4.0000.0000.7DF4] # CJK COMPATIBILITY IDEOGRAPH-FAB0; QQC
+2F96F ; [.FB40.0020.0002.7E02][.FE02.0000.0000.7E02] # CJK COMPATIBILITY IDEOGRAPH-2F96F; QQC
+FA58 ; [.FB40.0020.0002.7E09][.FE09.0000.0000.7E09] # CJK COMPATIBILITY IDEOGRAPH-FA58; QQC
+F950 ; [.FB40.0020.0002.7E37][.FE37.0000.0000.7E37] # CJK COMPATIBILITY IDEOGRAPH-F950; QQC
+FA59 ; [.FB40.0020.0002.7E41][.FE41.0000.0000.7E41] # CJK COMPATIBILITY IDEOGRAPH-FA59; QQC
+2F970 ; [.FB40.0020.0002.7E45][.FE45.0000.0000.7E45] # CJK COMPATIBILITY IDEOGRAPH-2F970; QQC
+2EB0 ; [.FB40.0020.0004.7E9F][.FE9F.0000.0000.7E9F] # CJK RADICAL C-SIMPLIFIED SILK; QQK
+2F78 ; [.FB40.0020.0004.7F36][.FF36.0000.0000.7F36] # KANGXI RADICAL JAR; QQK
+FAB1 ; [.FB40.0020.0002.7F3E][.FF3E.0000.0000.7F3E] # CJK COMPATIBILITY IDEOGRAPH-FAB1; QQC
+2F79 ; [.FB40.0020.0004.7F51][.FF51.0000.0000.7F51] # KANGXI RADICAL NET; QQK
+2EB2 ; [.FB40.0020.0004.7F52][.FF52.0000.0000.7F52] # CJK RADICAL NET TWO; QQK
+2EB5 ; [.FB40.0020.0004.7F52][.FF52.0000.0000.7F52][.0000.0199.001F.2EB5] # CJK RADICAL MESH; QQKN
+2EB1 ; [.FB40.0020.0004.7F53][.FF53.0000.0000.7F53] # CJK RADICAL NET ONE; QQK
+2EB3 ; [.FB40.0020.0004.7F53][.FF53.0000.0000.7F53][.0000.0199.001F.2EB3] # CJK RADICAL NET THREE; QQKN
+2EB4 ; [.FB40.0020.0004.7F53][.FF53.0000.0000.7F53][.0000.019A.001F.2EB4] # CJK RADICAL NET FOUR; QQKN
+FA5A ; [.FB40.0020.0002.7F72][.FF72.0000.0000.7F72] # CJK COMPATIBILITY IDEOGRAPH-FA5A; QQC
+F9E6 ; [.FB40.0020.0002.7F79][.FF79.0000.0000.7F79] # CJK COMPATIBILITY IDEOGRAPH-F9E6; QQC
+2F976 ; [.FB40.0020.0002.7F7A][.FF7A.0000.0000.7F7A] # CJK COMPATIBILITY IDEOGRAPH-2F976; QQC
+F90F ; [.FB40.0020.0002.7F85][.FF85.0000.0000.7F85] # CJK COMPATIBILITY IDEOGRAPH-F90F; QQC
+2F7A ; [.FB40.0020.0004.7F8A][.FF8A.0000.0000.7F8A] # KANGXI RADICAL SHEEP; QQK
+2EB6 ; [.FB40.0020.0004.7F8A][.FF8A.0000.0000.7F8A][.0000.0199.001F.2EB6] # CJK RADICAL SHEEP; QQKN
+2EB7 ; [.FB40.0020.0004.7F8A][.FF8A.0000.0000.7F8A][.0000.019A.001F.2EB7] # CJK RADICAL RAM; QQKN
+2EB8 ; [.FB40.0020.0004.7F8B][.FF8B.0000.0000.7F8B] # CJK RADICAL EWE; QQK
+2F978 ; [.FB40.0020.0002.7F95][.FF95.0000.0000.7F95] # CJK COMPATIBILITY IDEOGRAPH-2F978; QQC
+F9AF ; [.FB40.0020.0002.7F9A][.FF9A.0000.0000.7F9A] # CJK COMPATIBILITY IDEOGRAPH-F9AF; QQC
+FA1E ; [.FB40.0020.0002.7FBD][.FFBD.0000.0000.7FBD] # CJK COMPATIBILITY IDEOGRAPH-FA1E; QQC
+2F7B ; [.FB40.0020.0004.7FBD][.FFBD.0000.0000.7FBD] # KANGXI RADICAL FEATHER; QQK
+2F979 ; [.FB40.0020.0002.7FFA][.FFFA.0000.0000.7FFA] # CJK COMPATIBILITY IDEOGRAPH-2F979; QQC
+F934 ; [.FB41.0020.0002.8001][.8001.0000.0000.8001] # CJK COMPATIBILITY IDEOGRAPH-F934; QQC
+2F7C ; [.FB41.0020.0004.8001][.8001.0000.0000.8001] # KANGXI RADICAL OLD; QQK
+2EB9 ; [.FB41.0020.0004.8002][.8002.0000.0000.8002] # CJK RADICAL OLD; QQK
+FA5B ; [.FB41.0020.0002.8005][.8005.0000.0000.8005] # CJK COMPATIBILITY IDEOGRAPH-FA5B; QQC
+FAB2 ; [.FB41.0020.0002.8005][.8005.0000.0000.8005] # CJK COMPATIBILITY IDEOGRAPH-FAB2; QQC
+2F97A ; [.FB41.0020.0002.8005][.8005.0000.0000.8005] # CJK COMPATIBILITY IDEOGRAPH-2F97A; QQC
+2F7D ; [.FB41.0020.0004.800C][.800C.0000.0000.800C] # KANGXI RADICAL AND; QQK
+2F7E ; [.FB41.0020.0004.8012][.8012.0000.0000.8012] # KANGXI RADICAL PLOW; QQK
+2F7F ; [.FB41.0020.0004.8033][.8033.0000.0000.8033] # KANGXI RADICAL EAR; QQK
+F9B0 ; [.FB41.0020.0002.8046][.8046.0000.0000.8046] # CJK COMPATIBILITY IDEOGRAPH-F9B0; QQC
+2F97D ; [.FB41.0020.0002.8060][.8060.0000.0000.8060] # CJK COMPATIBILITY IDEOGRAPH-2F97D; QQC
+F997 ; [.FB41.0020.0002.806F][.806F.0000.0000.806F] # CJK COMPATIBILITY IDEOGRAPH-F997; QQC
+2F97F ; [.FB41.0020.0002.8070][.8070.0000.0000.8070] # CJK COMPATIBILITY IDEOGRAPH-2F97F; QQC
+F945 ; [.FB41.0020.0002.807E][.807E.0000.0000.807E] # CJK COMPATIBILITY IDEOGRAPH-F945; QQC
+2F80 ; [.FB41.0020.0004.807F][.807F.0000.0000.807F] # KANGXI RADICAL BRUSH; QQK
+2EBB ; [.FB41.0020.0004.807F][.807F.0000.0000.807F][.0000.0199.001F.2EBB] # CJK RADICAL BRUSH TWO; QQKN
+2EBA ; [.FB41.0020.0004.8080][.8080.0000.0000.8080] # CJK RADICAL BRUSH ONE; QQK
+2F81 ; [.FB41.0020.0004.8089][.8089.0000.0000.8089] # KANGXI RADICAL MEAT; QQK
+2EBC ; [.FB41.0020.0004.8089][.8089.0000.0000.8089][.0000.0199.001F.2EBC] # CJK RADICAL MEAT; QQKN
+F953 ; [.FB41.0020.0002.808B][.808B.0000.0000.808B] # CJK COMPATIBILITY IDEOGRAPH-F953; QQC
+2F8D6 ; [.FB41.0020.0002.80AD][.80AD.0000.0000.80AD] # CJK COMPATIBILITY IDEOGRAPH-2F8D6; QQC
+2F982 ; [.FB41.0020.0002.80B2][.80B2.0000.0000.80B2] # CJK COMPATIBILITY IDEOGRAPH-2F982; QQC
+2F983 ; [.FB41.0020.0002.8103][.8103.0000.0000.8103] # CJK COMPATIBILITY IDEOGRAPH-2F983; QQC
+2F985 ; [.FB41.0020.0002.813E][.813E.0000.0000.813E] # CJK COMPATIBILITY IDEOGRAPH-2F985; QQC
+F926 ; [.FB41.0020.0002.81D8][.81D8.0000.0000.81D8] # CJK COMPATIBILITY IDEOGRAPH-F926; QQC
+2F82 ; [.FB41.0020.0004.81E3][.81E3.0000.0000.81E3] # KANGXI RADICAL MINISTER; QQK
+F9F6 ; [.FB41.0020.0002.81E8][.81E8.0000.0000.81E8] # CJK COMPATIBILITY IDEOGRAPH-F9F6; QQC
+2F83 ; [.FB41.0020.0004.81EA][.81EA.0000.0000.81EA] # KANGXI RADICAL SELF; QQK
+3242 ; [*02B1.0020.0004.3242][.FB41.0020.0004.81EA][.81EA.0000.0000.81EA][*02B2.0020.001F.3242] # PARENTHESIZED IDEOGRAPH SELF; QQKN
+FA5C ; [.FB41.0020.0002.81ED][.81ED.0000.0000.81ED] # CJK COMPATIBILITY IDEOGRAPH-FA5C; QQC
+2F84 ; [.FB41.0020.0004.81F3][.81F3.0000.0000.81F3] # KANGXI RADICAL ARRIVE; QQK
+3243 ; [*02B1.0020.0004.3243][.FB41.0020.0004.81F3][.81F3.0000.0000.81F3][*02B2.0020.001F.3243] # PARENTHESIZED IDEOGRAPH REACH; QQKN
+2F85 ; [.FB41.0020.0004.81FC][.81FC.0000.0000.81FC] # KANGXI RADICAL MORTAR; QQK
+2EBD ; [.FB41.0020.0004.81FC][.81FC.0000.0000.81FC][.0000.0199.001F.2EBD] # CJK RADICAL MORTAR; QQKN
+2F893 ; [.FB41.0020.0002.8201][.8201.0000.0000.8201] # CJK COMPATIBILITY IDEOGRAPH-2F893; QQC
+2F98B ; [.FB41.0020.0002.8201][.8201.0000.0000.8201] # CJK COMPATIBILITY IDEOGRAPH-2F98B; QQC
+2F98C ; [.FB41.0020.0002.8204][.8204.0000.0000.8204] # CJK COMPATIBILITY IDEOGRAPH-2F98C; QQC
+2F86 ; [.FB41.0020.0004.820C][.820C.0000.0000.820C] # KANGXI RADICAL TONGUE; QQK
+2F87 ; [.FB41.0020.0004.821B][.821B.0000.0000.821B] # KANGXI RADICAL OPPOSE; QQK
+2F88 ; [.FB41.0020.0004.821F][.821F.0000.0000.821F] # KANGXI RADICAL BOAT; QQK
+2F89 ; [.FB41.0020.0004.826E][.826E.0000.0000.826E] # KANGXI RADICAL STOPPING; QQK
+F97C ; [.FB41.0020.0002.826F][.826F.0000.0000.826F] # CJK COMPATIBILITY IDEOGRAPH-F97C; QQC
+2F8A ; [.FB41.0020.0004.8272][.8272.0000.0000.8272] # KANGXI RADICAL COLOR; QQK
+2F8B ; [.FB41.0020.0004.8278][.8278.0000.0000.8278] # KANGXI RADICAL GRASS; QQK
+FA5D ; [.FB41.0020.0002.8279][.8279.0000.0000.8279] # CJK COMPATIBILITY IDEOGRAPH-FA5D; QQC
+FA5E ; [.FB41.0020.0002.8279][.8279.0000.0000.8279] # CJK COMPATIBILITY IDEOGRAPH-FA5E; QQC
+2EBE ; [.FB41.0020.0004.8279][.8279.0000.0000.8279] # CJK RADICAL GRASS ONE; QQK
+2EBF ; [.FB41.0020.0004.8279][.8279.0000.0000.8279][.0000.0199.001F.2EBF] # CJK RADICAL GRASS TWO; QQKN
+2EC0 ; [.FB41.0020.0004.8279][.8279.0000.0000.8279][.0000.019A.001F.2EC0] # CJK RADICAL GRASS THREE; QQKN
+2F990 ; [.FB41.0020.0002.828B][.828B.0000.0000.828B] # CJK COMPATIBILITY IDEOGRAPH-2F990; QQC
+2F98F ; [.FB41.0020.0002.8291][.8291.0000.0000.8291] # CJK COMPATIBILITY IDEOGRAPH-2F98F; QQC
+2F991 ; [.FB41.0020.0002.829D][.829D.0000.0000.829D] # CJK COMPATIBILITY IDEOGRAPH-2F991; QQC
+2F993 ; [.FB41.0020.0002.82B1][.82B1.0000.0000.82B1] # CJK COMPATIBILITY IDEOGRAPH-2F993; QQC
+2F994 ; [.FB41.0020.0002.82B3][.82B3.0000.0000.82B3] # CJK COMPATIBILITY IDEOGRAPH-2F994; QQC
+2F995 ; [.FB41.0020.0002.82BD][.82BD.0000.0000.82BD] # CJK COMPATIBILITY IDEOGRAPH-2F995; QQC
+F974 ; [.FB41.0020.0002.82E5][.82E5.0000.0000.82E5] # CJK COMPATIBILITY IDEOGRAPH-F974; QQC
+2F998 ; [.FB41.0020.0002.82E5][.82E5.0000.0000.82E5] # CJK COMPATIBILITY IDEOGRAPH-2F998; QQC
+2F996 ; [.FB41.0020.0002.82E6][.82E6.0000.0000.82E6] # CJK COMPATIBILITY IDEOGRAPH-2F996; QQC
+2F999 ; [.FB41.0020.0002.831D][.831D.0000.0000.831D] # CJK COMPATIBILITY IDEOGRAPH-2F999; QQC
+2F99C ; [.FB41.0020.0002.8323][.8323.0000.0000.8323] # CJK COMPATIBILITY IDEOGRAPH-2F99C; QQC
+F9FE ; [.FB41.0020.0002.8336][.8336.0000.0000.8336] # CJK COMPATIBILITY IDEOGRAPH-F9FE; QQC
+FAB3 ; [.FB41.0020.0002.8352][.8352.0000.0000.8352] # CJK COMPATIBILITY IDEOGRAPH-FAB3; QQC
+2F9A0 ; [.FB41.0020.0002.8353][.8353.0000.0000.8353] # CJK COMPATIBILITY IDEOGRAPH-2F9A0; QQC
+2F99A ; [.FB41.0020.0002.8363][.8363.0000.0000.8363] # CJK COMPATIBILITY IDEOGRAPH-2F99A; QQC
+2F99B ; [.FB41.0020.0002.83AD][.83AD.0000.0000.83AD] # CJK COMPATIBILITY IDEOGRAPH-2F99B; QQC
+2F99D ; [.FB41.0020.0002.83BD][.83BD.0000.0000.83BD] # CJK COMPATIBILITY IDEOGRAPH-2F99D; QQC
+F93E ; [.FB41.0020.0002.83C9][.83C9.0000.0000.83C9] # CJK COMPATIBILITY IDEOGRAPH-F93E; QQC
+2F9A1 ; [.FB41.0020.0002.83CA][.83CA.0000.0000.83CA] # CJK COMPATIBILITY IDEOGRAPH-2F9A1; QQC
+2F9A2 ; [.FB41.0020.0002.83CC][.83CC.0000.0000.83CC] # CJK COMPATIBILITY IDEOGRAPH-2F9A2; QQC
+2F9A3 ; [.FB41.0020.0002.83DC][.83DC.0000.0000.83DC] # CJK COMPATIBILITY IDEOGRAPH-2F9A3; QQC
+2F99E ; [.FB41.0020.0002.83E7][.83E7.0000.0000.83E7] # CJK COMPATIBILITY IDEOGRAPH-2F99E; QQC
+FAB4 ; [.FB41.0020.0002.83EF][.83EF.0000.0000.83EF] # CJK COMPATIBILITY IDEOGRAPH-FAB4; QQC
+F958 ; [.FB41.0020.0002.83F1][.83F1.0000.0000.83F1] # CJK COMPATIBILITY IDEOGRAPH-F958; QQC
+F918 ; [.FB41.0020.0002.843D][.843D.0000.0000.843D] # CJK COMPATIBILITY IDEOGRAPH-F918; QQC
+F96E ; [.FB41.0020.0002.8449][.8449.0000.0000.8449] # CJK COMPATIBILITY IDEOGRAPH-F96E; QQC
+FA5F ; [.FB41.0020.0002.8457][.8457.0000.0000.8457] # CJK COMPATIBILITY IDEOGRAPH-FA5F; QQC
+2F99F ; [.FB41.0020.0002.8457][.8457.0000.0000.8457] # CJK COMPATIBILITY IDEOGRAPH-2F99F; QQC
+F999 ; [.FB41.0020.0002.84EE][.84EE.0000.0000.84EE] # CJK COMPATIBILITY IDEOGRAPH-F999; QQC
+2F9A8 ; [.FB41.0020.0002.84F1][.84F1.0000.0000.84F1] # CJK COMPATIBILITY IDEOGRAPH-2F9A8; QQC
+2F9A9 ; [.FB41.0020.0002.84F3][.84F3.0000.0000.84F3] # CJK COMPATIBILITY IDEOGRAPH-2F9A9; QQC
+F9C2 ; [.FB41.0020.0002.84FC][.84FC.0000.0000.84FC] # CJK COMPATIBILITY IDEOGRAPH-F9C2; QQC
+2F9AA ; [.FB41.0020.0002.8516][.8516.0000.0000.8516] # CJK COMPATIBILITY IDEOGRAPH-2F9AA; QQC
+2F9AC ; [.FB41.0020.0002.8564][.8564.0000.0000.8564] # CJK COMPATIBILITY IDEOGRAPH-2F9AC; QQC
+F923 ; [.FB41.0020.0002.85CD][.85CD.0000.0000.85CD] # CJK COMPATIBILITY IDEOGRAPH-F923; QQC
+F9F0 ; [.FB41.0020.0002.85FA][.85FA.0000.0000.85FA] # CJK COMPATIBILITY IDEOGRAPH-F9F0; QQC
+F935 ; [.FB41.0020.0002.8606][.8606.0000.0000.8606] # CJK COMPATIBILITY IDEOGRAPH-F935; QQC
+FA20 ; [.FB41.0020.0002.8612][.8612.0000.0000.8612] # CJK COMPATIBILITY IDEOGRAPH-FA20; QQC
+F91F ; [.FB41.0020.0002.862D][.862D.0000.0000.862D] # CJK COMPATIBILITY IDEOGRAPH-F91F; QQC
+F910 ; [.FB41.0020.0002.863F][.863F.0000.0000.863F] # CJK COMPATIBILITY IDEOGRAPH-F910; QQC
+2F8C ; [.FB41.0020.0004.864D][.864D.0000.0000.864D] # KANGXI RADICAL TIGER; QQK
+2EC1 ; [.FB41.0020.0004.864E][.864E.0000.0000.864E] # CJK RADICAL TIGER; QQK
+2F9B3 ; [.FB41.0020.0002.8650][.8650.0000.0000.8650] # CJK COMPATIBILITY IDEOGRAPH-2F9B3; QQC
+F936 ; [.FB41.0020.0002.865C][.865C.0000.0000.865C] # CJK COMPATIBILITY IDEOGRAPH-F936; QQC
+2F9B4 ; [.FB41.0020.0002.865C][.865C.0000.0000.865C] # CJK COMPATIBILITY IDEOGRAPH-2F9B4; QQC
+2F9B5 ; [.FB41.0020.0002.8667][.8667.0000.0000.8667] # CJK COMPATIBILITY IDEOGRAPH-2F9B5; QQC
+2F9B6 ; [.FB41.0020.0002.8669][.8669.0000.0000.8669] # CJK COMPATIBILITY IDEOGRAPH-2F9B6; QQC
+2F8D ; [.FB41.0020.0004.866B][.866B.0000.0000.866B] # KANGXI RADICAL INSECT; QQK
+2F9B8 ; [.FB41.0020.0002.8688][.8688.0000.0000.8688] # CJK COMPATIBILITY IDEOGRAPH-2F9B8; QQC
+2F9B7 ; [.FB41.0020.0002.86A9][.86A9.0000.0000.86A9] # CJK COMPATIBILITY IDEOGRAPH-2F9B7; QQC
+2F9BA ; [.FB41.0020.0002.86E2][.86E2.0000.0000.86E2] # CJK COMPATIBILITY IDEOGRAPH-2F9BA; QQC
+2F9B9 ; [.FB41.0020.0002.870E][.870E.0000.0000.870E] # CJK COMPATIBILITY IDEOGRAPH-2F9B9; QQC
+2F9BC ; [.FB41.0020.0002.8728][.8728.0000.0000.8728] # CJK COMPATIBILITY IDEOGRAPH-2F9BC; QQC
+2F9BD ; [.FB41.0020.0002.876B][.876B.0000.0000.876B] # CJK COMPATIBILITY IDEOGRAPH-2F9BD; QQC
+FAB5 ; [.FB41.0020.0002.8779][.8779.0000.0000.8779] # CJK COMPATIBILITY IDEOGRAPH-FAB5; QQC
+2F9BB ; [.FB41.0020.0002.8779][.8779.0000.0000.8779] # CJK COMPATIBILITY IDEOGRAPH-2F9BB; QQC
+2F9BE ; [.FB41.0020.0002.8786][.8786.0000.0000.8786] # CJK COMPATIBILITY IDEOGRAPH-2F9BE; QQC
+F911 ; [.FB41.0020.0002.87BA][.87BA.0000.0000.87BA] # CJK COMPATIBILITY IDEOGRAPH-F911; QQC
+2F9C0 ; [.FB41.0020.0002.87E1][.87E1.0000.0000.87E1] # CJK COMPATIBILITY IDEOGRAPH-2F9C0; QQC
+2F9C1 ; [.FB41.0020.0002.8801][.8801.0000.0000.8801] # CJK COMPATIBILITY IDEOGRAPH-2F9C1; QQC
+F927 ; [.FB41.0020.0002.881F][.881F.0000.0000.881F] # CJK COMPATIBILITY IDEOGRAPH-F927; QQC
+2F8E ; [.FB41.0020.0004.8840][.8840.0000.0000.8840] # KANGXI RADICAL BLOOD; QQK
+FA08 ; [.FB41.0020.0002.884C][.884C.0000.0000.884C] # CJK COMPATIBILITY IDEOGRAPH-FA08; QQC
+2F8F ; [.FB41.0020.0004.884C][.884C.0000.0000.884C] # KANGXI RADICAL WALK ENCLOSURE; QQK
+2F9C3 ; [.FB41.0020.0002.8860][.8860.0000.0000.8860] # CJK COMPATIBILITY IDEOGRAPH-2F9C3; QQC
+2F9C4 ; [.FB41.0020.0002.8863][.8863.0000.0000.8863] # CJK COMPATIBILITY IDEOGRAPH-2F9C4; QQC
+2F90 ; [.FB41.0020.0004.8863][.8863.0000.0000.8863] # KANGXI RADICAL CLOTHES; QQK
+2EC2 ; [.FB41.0020.0004.8864][.8864.0000.0000.8864] # CJK RADICAL CLOTHES; QQK
+F9A0 ; [.FB41.0020.0002.88C2][.88C2.0000.0000.88C2] # CJK COMPATIBILITY IDEOGRAPH-F9A0; QQC
+F9E7 ; [.FB41.0020.0002.88CF][.88CF.0000.0000.88CF] # CJK COMPATIBILITY IDEOGRAPH-F9E7; QQC
+2F9C6 ; [.FB41.0020.0002.88D7][.88D7.0000.0000.88D7] # CJK COMPATIBILITY IDEOGRAPH-2F9C6; QQC
+2F9C7 ; [.FB41.0020.0002.88DE][.88DE.0000.0000.88DE] # CJK COMPATIBILITY IDEOGRAPH-2F9C7; QQC
+F9E8 ; [.FB41.0020.0002.88E1][.88E1.0000.0000.88E1] # CJK COMPATIBILITY IDEOGRAPH-F9E8; QQC
+F912 ; [.FB41.0020.0002.88F8][.88F8.0000.0000.88F8] # CJK COMPATIBILITY IDEOGRAPH-F912; QQC
+2F9C9 ; [.FB41.0020.0002.88FA][.88FA.0000.0000.88FA] # CJK COMPATIBILITY IDEOGRAPH-2F9C9; QQC
+FA60 ; [.FB41.0020.0002.8910][.8910.0000.0000.8910] # CJK COMPATIBILITY IDEOGRAPH-FA60; QQC
+FAB6 ; [.FB41.0020.0002.8941][.8941.0000.0000.8941] # CJK COMPATIBILITY IDEOGRAPH-FAB6; QQC
+F924 ; [.FB41.0020.0002.8964][.8964.0000.0000.8964] # CJK COMPATIBILITY IDEOGRAPH-F924; QQC
+2F91 ; [.FB41.0020.0004.897E][.897E.0000.0000.897E] # KANGXI RADICAL WEST; QQK
+2EC4 ; [.FB41.0020.0004.897F][.897F.0000.0000.897F] # CJK RADICAL WEST TWO; QQK
+2EC3 ; [.FB41.0020.0004.8980][.8980.0000.0000.8980] # CJK RADICAL WEST ONE; QQK
+FAB7 ; [.FB41.0020.0002.8986][.8986.0000.0000.8986] # CJK COMPATIBILITY IDEOGRAPH-FAB7; QQC
+FA0A ; [.FB41.0020.0002.898B][.898B.0000.0000.898B] # CJK COMPATIBILITY IDEOGRAPH-FA0A; QQC
+2F92 ; [.FB41.0020.0004.898B][.898B.0000.0000.898B] # KANGXI RADICAL SEE; QQK
+FA61 ; [.FB41.0020.0002.8996][.8996.0000.0000.8996] # CJK COMPATIBILITY IDEOGRAPH-FA61; QQC
+FAB8 ; [.FB41.0020.0002.8996][.8996.0000.0000.8996] # CJK COMPATIBILITY IDEOGRAPH-FAB8; QQC
+2EC5 ; [.FB41.0020.0004.89C1][.89C1.0000.0000.89C1] # CJK RADICAL C-SIMPLIFIED SEE; QQK
+2EC6 ; [.FB41.0020.0004.89D2][.89D2.0000.0000.89D2] # CJK RADICAL SIMPLIFIED HORN; QQK
+2F93 ; [.FB41.0020.0004.89D2][.89D2.0000.0000.89D2] # KANGXI RADICAL HORN; QQK
+2EC7 ; [.FB41.0020.0004.89D2][.89D2.0000.0000.89D2][.0000.0199.001F.2EC7] # CJK RADICAL HORN; QQKN
+2F94 ; [.FB41.0020.0004.8A00][.8A00.0000.0000.8A00] # KANGXI RADICAL SPEECH; QQK
+2F9CF ; [.FB41.0020.0002.8AA0][.8AA0.0000.0000.8AA0] # CJK COMPATIBILITY IDEOGRAPH-2F9CF; QQC
+F96F ; [.FB41.0020.0002.8AAA][.8AAA.0000.0000.8AAA] # CJK COMPATIBILITY IDEOGRAPH-F96F; QQC
+F9A1 ; [.FB41.0020.0002.8AAA][.8AAA.0000.0000.8AAA] # CJK COMPATIBILITY IDEOGRAPH-F9A1; QQC
+FAB9 ; [.FB41.0020.0002.8ABF][.8ABF.0000.0000.8ABF] # CJK COMPATIBILITY IDEOGRAPH-FAB9; QQC
+FABB ; [.FB41.0020.0002.8ACB][.8ACB.0000.0000.8ACB] # CJK COMPATIBILITY IDEOGRAPH-FABB; QQC
+F97D ; [.FB41.0020.0002.8AD2][.8AD2.0000.0000.8AD2] # CJK COMPATIBILITY IDEOGRAPH-F97D; QQC
+F941 ; [.FB41.0020.0002.8AD6][.8AD6.0000.0000.8AD6] # CJK COMPATIBILITY IDEOGRAPH-F941; QQC
+FABE ; [.FB41.0020.0002.8AED][.8AED.0000.0000.8AED] # CJK COMPATIBILITY IDEOGRAPH-FABE; QQC
+2F9D0 ; [.FB41.0020.0002.8AED][.8AED.0000.0000.8AED] # CJK COMPATIBILITY IDEOGRAPH-2F9D0; QQC
+FA22 ; [.FB41.0020.0002.8AF8][.8AF8.0000.0000.8AF8] # CJK COMPATIBILITY IDEOGRAPH-FA22; QQC
+FABA ; [.FB41.0020.0002.8AF8][.8AF8.0000.0000.8AF8] # CJK COMPATIBILITY IDEOGRAPH-FABA; QQC
+F95D ; [.FB41.0020.0002.8AFE][.8AFE.0000.0000.8AFE] # CJK COMPATIBILITY IDEOGRAPH-F95D; QQC
+FABD ; [.FB41.0020.0002.8AFE][.8AFE.0000.0000.8AFE] # CJK COMPATIBILITY IDEOGRAPH-FABD; QQC
+FA62 ; [.FB41.0020.0002.8B01][.8B01.0000.0000.8B01] # CJK COMPATIBILITY IDEOGRAPH-FA62; QQC
+FABC ; [.FB41.0020.0002.8B01][.8B01.0000.0000.8B01] # CJK COMPATIBILITY IDEOGRAPH-FABC; QQC
+FA63 ; [.FB41.0020.0002.8B39][.8B39.0000.0000.8B39] # CJK COMPATIBILITY IDEOGRAPH-FA63; QQC
+FABF ; [.FB41.0020.0002.8B39][.8B39.0000.0000.8B39] # CJK COMPATIBILITY IDEOGRAPH-FABF; QQC
+F9FC ; [.FB41.0020.0002.8B58][.8B58.0000.0000.8B58] # CJK COMPATIBILITY IDEOGRAPH-F9FC; QQC
+F95A ; [.FB41.0020.0002.8B80][.8B80.0000.0000.8B80] # CJK COMPATIBILITY IDEOGRAPH-F95A; QQC
+FAC0 ; [.FB41.0020.0002.8B8A][.8B8A.0000.0000.8B8A] # CJK COMPATIBILITY IDEOGRAPH-FAC0; QQC
+2F9D1 ; [.FB41.0020.0002.8B8A][.8B8A.0000.0000.8B8A] # CJK COMPATIBILITY IDEOGRAPH-2F9D1; QQC
+2EC8 ; [.FB41.0020.0004.8BA0][.8BA0.0000.0000.8BA0] # CJK RADICAL C-SIMPLIFIED SPEECH; QQK
+2F95 ; [.FB41.0020.0004.8C37][.8C37.0000.0000.8C37] # KANGXI RADICAL VALLEY; QQK
+2F96 ; [.FB41.0020.0004.8C46][.8C46.0000.0000.8C46] # KANGXI RADICAL BEAN; QQK
+F900 ; [.FB41.0020.0002.8C48][.8C48.0000.0000.8C48] # CJK COMPATIBILITY IDEOGRAPH-F900; QQC
+2F9D2 ; [.FB41.0020.0002.8C55][.8C55.0000.0000.8C55] # CJK COMPATIBILITY IDEOGRAPH-2F9D2; QQC
+2F97 ; [.FB41.0020.0004.8C55][.8C55.0000.0000.8C55] # KANGXI RADICAL PIG; QQK
+2F98 ; [.FB41.0020.0004.8C78][.8C78.0000.0000.8C78] # KANGXI RADICAL BADGER; QQK
+2F99 ; [.FB41.0020.0004.8C9D][.8C9D.0000.0000.8C9D] # KANGXI RADICAL SHELL; QQK
+3236 ; [*02B1.0020.0004.3236][.FB41.0020.0004.8CA1][.8CA1.0000.0000.8CA1][*02B2.0020.001F.3236] # PARENTHESIZED IDEOGRAPH FINANCIAL; QQKN
+3296 ; [.FB41.0020.0006.8CA1][.8CA1.0000.0000.8CA1] # CIRCLED IDEOGRAPH FINANCIAL; QQK
+2F9D4 ; [.FB41.0020.0002.8CAB][.8CAB.0000.0000.8CAB] # CJK COMPATIBILITY IDEOGRAPH-2F9D4; QQC
+2F9D5 ; [.FB41.0020.0002.8CC1][.8CC1.0000.0000.8CC1] # CJK COMPATIBILITY IDEOGRAPH-2F9D5; QQC
+F948 ; [.FB41.0020.0002.8CC2][.8CC2.0000.0000.8CC2] # CJK COMPATIBILITY IDEOGRAPH-F948; QQC
+323E ; [*02B1.0020.0004.323E][.FB41.0020.0004.8CC7][.8CC7.0000.0000.8CC7][*02B2.0020.001F.323E] # PARENTHESIZED IDEOGRAPH RESOURCE; QQKN
+32AE ; [.FB41.0020.0006.8CC7][.8CC7.0000.0000.8CC7] # CIRCLED IDEOGRAPH RESOURCE; QQK
+F903 ; [.FB41.0020.0002.8CC8][.8CC8.0000.0000.8CC8] # CJK COMPATIBILITY IDEOGRAPH-F903; QQC
+FA64 ; [.FB41.0020.0002.8CD3][.8CD3.0000.0000.8CD3] # CJK COMPATIBILITY IDEOGRAPH-FA64; QQC
+FA65 ; [.FB41.0020.0002.8D08][.8D08.0000.0000.8D08] # CJK COMPATIBILITY IDEOGRAPH-FA65; QQC
+FAC1 ; [.FB41.0020.0002.8D08][.8D08.0000.0000.8D08] # CJK COMPATIBILITY IDEOGRAPH-FAC1; QQC
+2F9D6 ; [.FB41.0020.0002.8D1B][.8D1B.0000.0000.8D1B] # CJK COMPATIBILITY IDEOGRAPH-2F9D6; QQC
+2EC9 ; [.FB41.0020.0004.8D1D][.8D1D.0000.0000.8D1D] # CJK RADICAL C-SIMPLIFIED SHELL; QQK
+2F9A ; [.FB41.0020.0004.8D64][.8D64.0000.0000.8D64] # KANGXI RADICAL RED; QQK
+2F9B ; [.FB41.0020.0004.8D70][.8D70.0000.0000.8D70] # KANGXI RADICAL RUN; QQK
+2F9D7 ; [.FB41.0020.0002.8D77][.8D77.0000.0000.8D77] # CJK COMPATIBILITY IDEOGRAPH-2F9D7; QQC
+2F9C ; [.FB41.0020.0004.8DB3][.8DB3.0000.0000.8DB3] # KANGXI RADICAL FOOT; QQK
+2ECA ; [.FB41.0020.0004.8DB3][.8DB3.0000.0000.8DB3][.0000.0199.001F.2ECA] # CJK RADICAL FOOT; QQKN
+2F9DB ; [.FB41.0020.0002.8DBC][.8DBC.0000.0000.8DBC] # CJK COMPATIBILITY IDEOGRAPH-2F9DB; QQC
+2F9DA ; [.FB41.0020.0002.8DCB][.8DCB.0000.0000.8DCB] # CJK COMPATIBILITY IDEOGRAPH-2F9DA; QQC
+F937 ; [.FB41.0020.0002.8DEF][.8DEF.0000.0000.8DEF] # CJK COMPATIBILITY IDEOGRAPH-F937; QQC
+2F9DC ; [.FB41.0020.0002.8DF0][.8DF0.0000.0000.8DF0] # CJK COMPATIBILITY IDEOGRAPH-2F9DC; QQC
+2F9D ; [.FB41.0020.0004.8EAB][.8EAB.0000.0000.8EAB] # KANGXI RADICAL BODY; QQK
+F902 ; [.FB41.0020.0002.8ECA][.8ECA.0000.0000.8ECA] # CJK COMPATIBILITY IDEOGRAPH-F902; QQC
+2F9E ; [.FB41.0020.0004.8ECA][.8ECA.0000.0000.8ECA] # KANGXI RADICAL CART; QQK
+2F9DE ; [.FB41.0020.0002.8ED4][.8ED4.0000.0000.8ED4] # CJK COMPATIBILITY IDEOGRAPH-2F9DE; QQC
+F998 ; [.FB41.0020.0002.8F26][.8F26.0000.0000.8F26] # CJK COMPATIBILITY IDEOGRAPH-F998; QQC
+F9D7 ; [.FB41.0020.0002.8F2A][.8F2A.0000.0000.8F2A] # CJK COMPATIBILITY IDEOGRAPH-F9D7; QQC
+FAC2 ; [.FB41.0020.0002.8F38][.8F38.0000.0000.8F38] # CJK COMPATIBILITY IDEOGRAPH-FAC2; QQC
+2F9DF ; [.FB41.0020.0002.8F38][.8F38.0000.0000.8F38] # CJK COMPATIBILITY IDEOGRAPH-2F9DF; QQC
+FA07 ; [.FB41.0020.0002.8F3B][.8F3B.0000.0000.8F3B] # CJK COMPATIBILITY IDEOGRAPH-FA07; QQC
+F98D ; [.FB41.0020.0002.8F62][.8F62.0000.0000.8F62] # CJK COMPATIBILITY IDEOGRAPH-F98D; QQC
+2ECB ; [.FB41.0020.0004.8F66][.8F66.0000.0000.8F66] # CJK RADICAL C-SIMPLIFIED CART; QQK
+2F9F ; [.FB41.0020.0004.8F9B][.8F9B.0000.0000.8F9B] # KANGXI RADICAL BITTER; QQK
+2F98D ; [.FB41.0020.0002.8F9E][.8F9E.0000.0000.8F9E] # CJK COMPATIBILITY IDEOGRAPH-2F98D; QQC
+F971 ; [.FB41.0020.0002.8FB0][.8FB0.0000.0000.8FB0] # CJK COMPATIBILITY IDEOGRAPH-F971; QQC
+2FA0 ; [.FB41.0020.0004.8FB0][.8FB0.0000.0000.8FB0] # KANGXI RADICAL MORNING; QQK
+2FA1 ; [.FB41.0020.0004.8FB5][.8FB5.0000.0000.8FB5] # KANGXI RADICAL WALK; QQK
+FA66 ; [.FB41.0020.0002.8FB6][.8FB6.0000.0000.8FB6] # CJK COMPATIBILITY IDEOGRAPH-FA66; QQC
+2ECC ; [.FB41.0020.0004.8FB6][.8FB6.0000.0000.8FB6] # CJK RADICAL SIMPLIFIED WALK; QQK
+2ECD ; [.FB41.0020.0004.8FB6][.8FB6.0000.0000.8FB6][.0000.0199.001F.2ECD] # CJK RADICAL WALK ONE; QQKN
+2ECE ; [.FB41.0020.0004.8FB6][.8FB6.0000.0000.8FB6][.0000.019A.001F.2ECE] # CJK RADICAL WALK TWO; QQKN
+F99A ; [.FB41.0020.0002.9023][.9023.0000.0000.9023] # CJK COMPATIBILITY IDEOGRAPH-F99A; QQC
+FA25 ; [.FB41.0020.0002.9038][.9038.0000.0000.9038] # CJK COMPATIBILITY IDEOGRAPH-FA25; QQC
+FA67 ; [.FB41.0020.0002.9038][.9038.0000.0000.9038] # CJK COMPATIBILITY IDEOGRAPH-FA67; QQC
+329C ; [.FB41.0020.0006.9069][.9069.0000.0000.9069] # CIRCLED IDEOGRAPH SUITABLE; QQK
+FAC3 ; [.FB41.0020.0002.9072][.9072.0000.0000.9072] # CJK COMPATIBILITY IDEOGRAPH-FAC3; QQC
+F9C3 ; [.FB41.0020.0002.907C][.907C.0000.0000.907C] # CJK COMPATIBILITY IDEOGRAPH-F9C3; QQC
+F913 ; [.FB41.0020.0002.908F][.908F.0000.0000.908F] # CJK COMPATIBILITY IDEOGRAPH-F913; QQC
+2FA2 ; [.FB41.0020.0004.9091][.9091.0000.0000.9091] # KANGXI RADICAL CITY; QQK
+2ECF ; [.FB41.0020.0004.9091][.9091.0000.0000.9091][.0000.0199.001F.2ECF] # CJK RADICAL CITY; QQKN
+2F9E2 ; [.FB41.0020.0002.9094][.9094.0000.0000.9094] # CJK COMPATIBILITY IDEOGRAPH-2F9E2; QQC
+F92C ; [.FB41.0020.0002.90CE][.90CE.0000.0000.90CE] # CJK COMPATIBILITY IDEOGRAPH-F92C; QQC
+2F9E3 ; [.FB41.0020.0002.90F1][.90F1.0000.0000.90F1] # CJK COMPATIBILITY IDEOGRAPH-2F9E3; QQC
+FA26 ; [.FB41.0020.0002.90FD][.90FD.0000.0000.90FD] # CJK COMPATIBILITY IDEOGRAPH-FA26; QQC
+2F9E4 ; [.FB41.0020.0002.9111][.9111.0000.0000.9111] # CJK COMPATIBILITY IDEOGRAPH-2F9E4; QQC
+2F9E6 ; [.FB41.0020.0002.911B][.911B.0000.0000.911B] # CJK COMPATIBILITY IDEOGRAPH-2F9E6; QQC
+2FA3 ; [.FB41.0020.0004.9149][.9149.0000.0000.9149] # KANGXI RADICAL WINE; QQK
+F919 ; [.FB41.0020.0002.916A][.916A.0000.0000.916A] # CJK COMPATIBILITY IDEOGRAPH-F919; QQC
+FAC4 ; [.FB41.0020.0002.9199][.9199.0000.0000.9199] # CJK COMPATIBILITY IDEOGRAPH-FAC4; QQC
+F9B7 ; [.FB41.0020.0002.91B4][.91B4.0000.0000.91B4] # CJK COMPATIBILITY IDEOGRAPH-F9B7; QQC
+2FA4 ; [.FB41.0020.0004.91C6][.91C6.0000.0000.91C6] # KANGXI RADICAL DISTINGUISH; QQK
+F9E9 ; [.FB41.0020.0002.91CC][.91CC.0000.0000.91CC] # CJK COMPATIBILITY IDEOGRAPH-F9E9; QQC
+2FA5 ; [.FB41.0020.0004.91CC][.91CC.0000.0000.91CC] # KANGXI RADICAL VILLAGE; QQK
+F97E ; [.FB41.0020.0002.91CF][.91CF.0000.0000.91CF] # CJK COMPATIBILITY IDEOGRAPH-F97E; QQC
+F90A ; [.FB41.0020.0002.91D1][.91D1.0000.0000.91D1] # CJK COMPATIBILITY IDEOGRAPH-F90A; QQC
+2FA6 ; [.FB41.0020.0004.91D1][.91D1.0000.0000.91D1] # KANGXI RADICAL GOLD; QQK
+322E ; [*02B1.0020.0004.322E][.FB41.0020.0004.91D1][.91D1.0000.0000.91D1][*02B2.0020.001F.322E] # PARENTHESIZED IDEOGRAPH METAL; QQKN
+328E ; [.FB41.0020.0006.91D1][.91D1.0000.0000.91D1] # CIRCLED IDEOGRAPH METAL; QQK
+F9B1 ; [.FB41.0020.0002.9234][.9234.0000.0000.9234] # CJK COMPATIBILITY IDEOGRAPH-F9B1; QQC
+2F9E7 ; [.FB41.0020.0002.9238][.9238.0000.0000.9238] # CJK COMPATIBILITY IDEOGRAPH-2F9E7; QQC
+FAC5 ; [.FB41.0020.0002.9276][.9276.0000.0000.9276] # CJK COMPATIBILITY IDEOGRAPH-FAC5; QQC
+2F9EA ; [.FB41.0020.0002.927C][.927C.0000.0000.927C] # CJK COMPATIBILITY IDEOGRAPH-2F9EA; QQC
+2F9E8 ; [.FB41.0020.0002.92D7][.92D7.0000.0000.92D7] # CJK COMPATIBILITY IDEOGRAPH-2F9E8; QQC
+2F9E9 ; [.FB41.0020.0002.92D8][.92D8.0000.0000.92D8] # CJK COMPATIBILITY IDEOGRAPH-2F9E9; QQC
+F93F ; [.FB41.0020.0002.9304][.9304.0000.0000.9304] # CJK COMPATIBILITY IDEOGRAPH-F93F; QQC
+F99B ; [.FB41.0020.0002.934A][.934A.0000.0000.934A] # CJK COMPATIBILITY IDEOGRAPH-F99B; QQC
+2F9EB ; [.FB41.0020.0002.93F9][.93F9.0000.0000.93F9] # CJK COMPATIBILITY IDEOGRAPH-2F9EB; QQC
+2F9EC ; [.FB41.0020.0002.9415][.9415.0000.0000.9415] # CJK COMPATIBILITY IDEOGRAPH-2F9EC; QQC
+2ED0 ; [.FB41.0020.0004.9485][.9485.0000.0000.9485] # CJK RADICAL C-SIMPLIFIED GOLD; QQK
+2ED1 ; [.FB41.0020.0004.9577][.9577.0000.0000.9577] # CJK RADICAL LONG ONE; QQK
+2FA7 ; [.FB41.0020.0004.9577][.9577.0000.0000.9577] # KANGXI RADICAL LONG; QQK
+2ED2 ; [.FB41.0020.0004.9578][.9578.0000.0000.9578] # CJK RADICAL LONG TWO; QQK
+2ED3 ; [.FB41.0020.0004.957F][.957F.0000.0000.957F] # CJK RADICAL C-SIMPLIFIED LONG; QQK
+2FA8 ; [.FB41.0020.0004.9580][.9580.0000.0000.9580] # KANGXI RADICAL GATE; QQK
+2F9EE ; [.FB41.0020.0002.958B][.958B.0000.0000.958B] # CJK COMPATIBILITY IDEOGRAPH-2F9EE; QQC
+F986 ; [.FB41.0020.0002.95AD][.95AD.0000.0000.95AD] # CJK COMPATIBILITY IDEOGRAPH-F986; QQC
+2F9F0 ; [.FB41.0020.0002.95B7][.95B7.0000.0000.95B7] # CJK COMPATIBILITY IDEOGRAPH-2F9F0; QQC
+2ED4 ; [.FB41.0020.0004.95E8][.95E8.0000.0000.95E8] # CJK RADICAL C-SIMPLIFIED GATE; QQK
+2FA9 ; [.FB41.0020.0004.961C][.961C.0000.0000.961C] # KANGXI RADICAL MOUND; QQK
+2ED5 ; [.FB41.0020.0004.961C][.961C.0000.0000.961C][.0000.0199.001F.2ED5] # CJK RADICAL MOUND ONE; QQKN
+2ED6 ; [.FB41.0020.0004.961D][.961D.0000.0000.961D] # CJK RADICAL MOUND TWO; QQK
+F9C6 ; [.FB41.0020.0002.962E][.962E.0000.0000.962E] # CJK COMPATIBILITY IDEOGRAPH-F9C6; QQC
+F951 ; [.FB41.0020.0002.964B][.964B.0000.0000.964B] # CJK COMPATIBILITY IDEOGRAPH-F951; QQC
+FA09 ; [.FB41.0020.0002.964D][.964D.0000.0000.964D] # CJK COMPATIBILITY IDEOGRAPH-FA09; QQC
+F959 ; [.FB41.0020.0002.9675][.9675.0000.0000.9675] # CJK COMPATIBILITY IDEOGRAPH-F959; QQC
+F9D3 ; [.FB41.0020.0002.9678][.9678.0000.0000.9678] # CJK COMPATIBILITY IDEOGRAPH-F9D3; QQC
+FAC6 ; [.FB41.0020.0002.967C][.967C.0000.0000.967C] # CJK COMPATIBILITY IDEOGRAPH-FAC6; QQC
+F9DC ; [.FB41.0020.0002.9686][.9686.0000.0000.9686] # CJK COMPATIBILITY IDEOGRAPH-F9DC; QQC
+F9F1 ; [.FB41.0020.0002.96A3][.96A3.0000.0000.96A3] # CJK COMPATIBILITY IDEOGRAPH-F9F1; QQC
+2FAA ; [.FB41.0020.0004.96B6][.96B6.0000.0000.96B6] # KANGXI RADICAL SLAVE; QQK
+F9B8 ; [.FB41.0020.0002.96B8][.96B8.0000.0000.96B8] # CJK COMPATIBILITY IDEOGRAPH-F9B8; QQC
+2FAB ; [.FB41.0020.0004.96B9][.96B9.0000.0000.96B9] # KANGXI RADICAL SHORT TAILED BIRD; QQK
+2F9F3 ; [.FB41.0020.0002.96C3][.96C3.0000.0000.96C3] # CJK COMPATIBILITY IDEOGRAPH-2F9F3; QQC
+F9EA ; [.FB41.0020.0002.96E2][.96E2.0000.0000.96E2] # CJK COMPATIBILITY IDEOGRAPH-F9EA; QQC
+FA68 ; [.FB41.0020.0002.96E3][.96E3.0000.0000.96E3] # CJK COMPATIBILITY IDEOGRAPH-FA68; QQC
+FAC7 ; [.FB41.0020.0002.96E3][.96E3.0000.0000.96E3] # CJK COMPATIBILITY IDEOGRAPH-FAC7; QQC
+2FAC ; [.FB41.0020.0004.96E8][.96E8.0000.0000.96E8] # KANGXI RADICAL RAIN; QQK
+2ED7 ; [.FB41.0020.0004.96E8][.96E8.0000.0000.96E8][.0000.0199.001F.2ED7] # CJK RADICAL RAIN; QQKN
+F9B2 ; [.FB41.0020.0002.96F6][.96F6.0000.0000.96F6] # CJK COMPATIBILITY IDEOGRAPH-F9B2; QQC
+F949 ; [.FB41.0020.0002.96F7][.96F7.0000.0000.96F7] # CJK COMPATIBILITY IDEOGRAPH-F949; QQC
+2F9F5 ; [.FB41.0020.0002.9723][.9723.0000.0000.9723] # CJK COMPATIBILITY IDEOGRAPH-2F9F5; QQC
+F938 ; [.FB41.0020.0002.9732][.9732.0000.0000.9732] # CJK COMPATIBILITY IDEOGRAPH-F938; QQC
+F9B3 ; [.FB41.0020.0002.9748][.9748.0000.0000.9748] # CJK COMPATIBILITY IDEOGRAPH-F9B3; QQC
+2FAD ; [.FB41.0020.0004.9751][.9751.0000.0000.9751] # KANGXI RADICAL BLUE; QQK
+2ED8 ; [.FB41.0020.0004.9752][.9752.0000.0000.9752] # CJK RADICAL BLUE; QQK
+FA1C ; [.FB41.0020.0002.9756][.9756.0000.0000.9756] # CJK COMPATIBILITY IDEOGRAPH-FA1C; QQC
+FAC8 ; [.FB41.0020.0002.9756][.9756.0000.0000.9756] # CJK COMPATIBILITY IDEOGRAPH-FAC8; QQC
+2FAE ; [.FB41.0020.0004.975E][.975E.0000.0000.975E] # KANGXI RADICAL WRONG; QQK
+2FAF ; [.FB41.0020.0004.9762][.9762.0000.0000.9762] # KANGXI RADICAL FACE; QQK
+2FB0 ; [.FB41.0020.0004.9769][.9769.0000.0000.9769] # KANGXI RADICAL LEATHER; QQK
+2FB1 ; [.FB41.0020.0004.97CB][.97CB.0000.0000.97CB] # KANGXI RADICAL TANNED LEATHER; QQK
+FAC9 ; [.FB41.0020.0002.97DB][.97DB.0000.0000.97DB] # CJK COMPATIBILITY IDEOGRAPH-FAC9; QQC
+2F9FA ; [.FB41.0020.0002.97E0][.97E0.0000.0000.97E0] # CJK COMPATIBILITY IDEOGRAPH-2F9FA; QQC
+2ED9 ; [.FB41.0020.0004.97E6][.97E6.0000.0000.97E6] # CJK RADICAL C-SIMPLIFIED TANNED LEATHER; QQK
+2FB2 ; [.FB41.0020.0004.97ED][.97ED.0000.0000.97ED] # KANGXI RADICAL LEEK; QQK
+2FB3 ; [.FB41.0020.0004.97F3][.97F3.0000.0000.97F3] # KANGXI RADICAL SOUND; QQK
+FA69 ; [.FB41.0020.0002.97FF][.97FF.0000.0000.97FF] # CJK COMPATIBILITY IDEOGRAPH-FA69; QQC
+FACA ; [.FB41.0020.0002.97FF][.97FF.0000.0000.97FF] # CJK COMPATIBILITY IDEOGRAPH-FACA; QQC
+2FB4 ; [.FB41.0020.0004.9801][.9801.0000.0000.9801] # KANGXI RADICAL LEAF; QQK
+32A0 ; [.FB41.0020.0006.9805][.9805.0000.0000.9805] # CIRCLED IDEOGRAPH ITEM; QQK
+FACB ; [.FB41.0020.0002.980B][.980B.0000.0000.980B] # CJK COMPATIBILITY IDEOGRAPH-FACB; QQC
+2F9FE ; [.FB41.0020.0002.980B][.980B.0000.0000.980B] # CJK COMPATIBILITY IDEOGRAPH-2F9FE; QQC
+2F9FF ; [.FB41.0020.0002.980B][.980B.0000.0000.980B] # CJK COMPATIBILITY IDEOGRAPH-2F9FF; QQC
+F9B4 ; [.FB41.0020.0002.9818][.9818.0000.0000.9818] # CJK COMPATIBILITY IDEOGRAPH-F9B4; QQC
+2FA00 ; [.FB41.0020.0002.9829][.9829.0000.0000.9829] # CJK COMPATIBILITY IDEOGRAPH-2FA00; QQC
+FA6A ; [.FB41.0020.0002.983B][.983B.0000.0000.983B] # CJK COMPATIBILITY IDEOGRAPH-FA6A; QQC
+FACC ; [.FB41.0020.0002.983B][.983B.0000.0000.983B] # CJK COMPATIBILITY IDEOGRAPH-FACC; QQC
+F9D0 ; [.FB41.0020.0002.985E][.985E.0000.0000.985E] # CJK COMPATIBILITY IDEOGRAPH-F9D0; QQC
+2EDA ; [.FB41.0020.0004.9875][.9875.0000.0000.9875] # CJK RADICAL C-SIMPLIFIED LEAF; QQK
+2FB5 ; [.FB41.0020.0004.98A8][.98A8.0000.0000.98A8] # KANGXI RADICAL WIND; QQK
+2EDB ; [.FB41.0020.0004.98CE][.98CE.0000.0000.98CE] # CJK RADICAL C-SIMPLIFIED WIND; QQK
+2FB6 ; [.FB41.0020.0004.98DB][.98DB.0000.0000.98DB] # KANGXI RADICAL FLY; QQK
+2EDC ; [.FB41.0020.0004.98DE][.98DE.0000.0000.98DE] # CJK RADICAL C-SIMPLIFIED FLY; QQK
+2EDD ; [.FB41.0020.0004.98DF][.98DF.0000.0000.98DF] # CJK RADICAL EAT ONE; QQK
+2FB7 ; [.FB41.0020.0004.98DF][.98DF.0000.0000.98DF] # KANGXI RADICAL EAT; QQK
+2EDF ; [.FB41.0020.0004.98E0][.98E0.0000.0000.98E0] # CJK RADICAL EAT THREE; QQK
+2EDE ; [.FB41.0020.0004.98E0][.98E0.0000.0000.98E0][.0000.0199.001F.2EDE] # CJK RADICAL EAT TWO; QQKN
+2FA02 ; [.FB41.0020.0002.98E2][.98E2.0000.0000.98E2] # CJK COMPATIBILITY IDEOGRAPH-2FA02; QQC
+FA2A ; [.FB41.0020.0002.98EF][.98EF.0000.0000.98EF] # CJK COMPATIBILITY IDEOGRAPH-FA2A; QQC
+FA2B ; [.FB41.0020.0002.98FC][.98FC.0000.0000.98FC] # CJK COMPATIBILITY IDEOGRAPH-FA2B; QQC
+FA2C ; [.FB41.0020.0002.9928][.9928.0000.0000.9928] # CJK COMPATIBILITY IDEOGRAPH-FA2C; QQC
+2FA04 ; [.FB41.0020.0002.9929][.9929.0000.0000.9929] # CJK COMPATIBILITY IDEOGRAPH-2FA04; QQC
+2EE0 ; [.FB41.0020.0004.9963][.9963.0000.0000.9963] # CJK RADICAL C-SIMPLIFIED EAT; QQK
+2FB8 ; [.FB41.0020.0004.9996][.9996.0000.0000.9996] # KANGXI RADICAL HEAD; QQK
+2EE1 ; [.FB41.0020.0004.9996][.9996.0000.0000.9996][.0000.0199.001F.2EE1] # CJK RADICAL HEAD; QQKN
+2FB9 ; [.FB41.0020.0004.9999][.9999.0000.0000.9999] # KANGXI RADICAL FRAGRANT; QQK
+2FA05 ; [.FB41.0020.0002.99A7][.99A7.0000.0000.99A7] # CJK COMPATIBILITY IDEOGRAPH-2FA05; QQC
+2FBA ; [.FB41.0020.0004.99AC][.99AC.0000.0000.99AC] # KANGXI RADICAL HORSE; QQK
+2FA06 ; [.FB41.0020.0002.99C2][.99C2.0000.0000.99C2] # CJK COMPATIBILITY IDEOGRAPH-2FA06; QQC
+F91A ; [.FB41.0020.0002.99F1][.99F1.0000.0000.99F1] # CJK COMPATIBILITY IDEOGRAPH-F91A; QQC
+2FA07 ; [.FB41.0020.0002.99FE][.99FE.0000.0000.99FE] # CJK COMPATIBILITY IDEOGRAPH-2FA07; QQC
+F987 ; [.FB41.0020.0002.9A6A][.9A6A.0000.0000.9A6A] # CJK COMPATIBILITY IDEOGRAPH-F987; QQC
+2EE2 ; [.FB41.0020.0004.9A6C][.9A6C.0000.0000.9A6C] # CJK RADICAL C-SIMPLIFIED HORSE; QQK
+2FBB ; [.FB41.0020.0004.9AA8][.9AA8.0000.0000.9AA8] # KANGXI RADICAL BONE; QQK
+2EE3 ; [.FB41.0020.0004.9AA8][.9AA8.0000.0000.9AA8][.0000.0199.001F.2EE3] # CJK RADICAL BONE; QQKN
+2FBC ; [.FB41.0020.0004.9AD8][.9AD8.0000.0000.9AD8] # KANGXI RADICAL TALL; QQK
+2FBD ; [.FB41.0020.0004.9ADF][.9ADF.0000.0000.9ADF] # KANGXI RADICAL HAIR; QQK
+FACD ; [.FB41.0020.0002.9B12][.9B12.0000.0000.9B12] # CJK COMPATIBILITY IDEOGRAPH-FACD; QQC
+2FA0A ; [.FB41.0020.0002.9B12][.9B12.0000.0000.9B12] # CJK COMPATIBILITY IDEOGRAPH-2FA0A; QQC
+2FBE ; [.FB41.0020.0004.9B25][.9B25.0000.0000.9B25] # KANGXI RADICAL FIGHT; QQK
+2FBF ; [.FB41.0020.0004.9B2F][.9B2F.0000.0000.9B2F] # KANGXI RADICAL SACRIFICIAL WINE; QQK
+2FC0 ; [.FB41.0020.0004.9B32][.9B32.0000.0000.9B32] # KANGXI RADICAL CAULDRON; QQK
+2FC1 ; [.FB41.0020.0004.9B3C][.9B3C.0000.0000.9B3C] # KANGXI RADICAL GHOST; QQK
+2EE4 ; [.FB41.0020.0004.9B3C][.9B3C.0000.0000.9B3C][.0000.0199.001F.2EE4] # CJK RADICAL GHOST; QQKN
+2FC2 ; [.FB41.0020.0004.9B5A][.9B5A.0000.0000.9B5A] # KANGXI RADICAL FISH; QQK
+F939 ; [.FB41.0020.0002.9B6F][.9B6F.0000.0000.9B6F] # CJK COMPATIBILITY IDEOGRAPH-F939; QQC
+2FA0B ; [.FB41.0020.0002.9C40][.9C40.0000.0000.9C40] # CJK COMPATIBILITY IDEOGRAPH-2FA0B; QQC
+F9F2 ; [.FB41.0020.0002.9C57][.9C57.0000.0000.9C57] # CJK COMPATIBILITY IDEOGRAPH-F9F2; QQC
+2EE5 ; [.FB41.0020.0004.9C7C][.9C7C.0000.0000.9C7C] # CJK RADICAL C-SIMPLIFIED FISH; QQK
+2FC3 ; [.FB41.0020.0004.9CE5][.9CE5.0000.0000.9CE5] # KANGXI RADICAL BIRD; QQK
+2FA0C ; [.FB41.0020.0002.9CFD][.9CFD.0000.0000.9CFD] # CJK COMPATIBILITY IDEOGRAPH-2FA0C; QQC
+2FA0F ; [.FB41.0020.0002.9D67][.9D67.0000.0000.9D67] # CJK COMPATIBILITY IDEOGRAPH-2FA0F; QQC
+FA2D ; [.FB41.0020.0002.9DB4][.9DB4.0000.0000.9DB4] # CJK COMPATIBILITY IDEOGRAPH-FA2D; QQC
+F93A ; [.FB41.0020.0002.9DFA][.9DFA.0000.0000.9DFA] # CJK COMPATIBILITY IDEOGRAPH-F93A; QQC
+F920 ; [.FB41.0020.0002.9E1E][.9E1E.0000.0000.9E1E] # CJK COMPATIBILITY IDEOGRAPH-F920; QQC
+2EE6 ; [.FB41.0020.0004.9E1F][.9E1F.0000.0000.9E1F] # CJK RADICAL C-SIMPLIFIED BIRD; QQK
+2FC4 ; [.FB41.0020.0004.9E75][.9E75.0000.0000.9E75] # KANGXI RADICAL SALT; QQK
+2EE7 ; [.FB41.0020.0004.9E75][.9E75.0000.0000.9E75][.0000.0199.001F.2EE7] # CJK RADICAL C-SIMPLIFIED SALT; QQKN
+F940 ; [.FB41.0020.0002.9E7F][.9E7F.0000.0000.9E7F] # CJK COMPATIBILITY IDEOGRAPH-F940; QQC
+2FC5 ; [.FB41.0020.0004.9E7F][.9E7F.0000.0000.9E7F] # KANGXI RADICAL DEER; QQK
+F988 ; [.FB41.0020.0002.9E97][.9E97.0000.0000.9E97] # CJK COMPATIBILITY IDEOGRAPH-F988; QQC
+F9F3 ; [.FB41.0020.0002.9E9F][.9E9F.0000.0000.9E9F] # CJK COMPATIBILITY IDEOGRAPH-F9F3; QQC
+2FC6 ; [.FB41.0020.0004.9EA5][.9EA5.0000.0000.9EA5] # KANGXI RADICAL WHEAT; QQK
+2EE8 ; [.FB41.0020.0004.9EA6][.9EA6.0000.0000.9EA6] # CJK RADICAL SIMPLIFIED WHEAT; QQK
+2FA15 ; [.FB41.0020.0002.9EBB][.9EBB.0000.0000.9EBB] # CJK COMPATIBILITY IDEOGRAPH-2FA15; QQC
+2FC7 ; [.FB41.0020.0004.9EBB][.9EBB.0000.0000.9EBB] # KANGXI RADICAL HEMP; QQK
+2FC8 ; [.FB41.0020.0004.9EC3][.9EC3.0000.0000.9EC3] # KANGXI RADICAL YELLOW; QQK
+2EE9 ; [.FB41.0020.0004.9EC4][.9EC4.0000.0000.9EC4] # CJK RADICAL SIMPLIFIED YELLOW; QQK
+2FC9 ; [.FB41.0020.0004.9ECD][.9ECD.0000.0000.9ECD] # KANGXI RADICAL MILLET; QQK
+F989 ; [.FB41.0020.0002.9ECE][.9ECE.0000.0000.9ECE] # CJK COMPATIBILITY IDEOGRAPH-F989; QQC
+2FCA ; [.FB41.0020.0004.9ED1][.9ED1.0000.0000.9ED1] # KANGXI RADICAL BLACK; QQK
+2FA17 ; [.FB41.0020.0002.9EF9][.9EF9.0000.0000.9EF9] # CJK COMPATIBILITY IDEOGRAPH-2FA17; QQC
+2FCB ; [.FB41.0020.0004.9EF9][.9EF9.0000.0000.9EF9] # KANGXI RADICAL EMBROIDERY; QQK
+2FCC ; [.FB41.0020.0004.9EFD][.9EFD.0000.0000.9EFD] # KANGXI RADICAL FROG; QQK
+2FA18 ; [.FB41.0020.0002.9EFE][.9EFE.0000.0000.9EFE] # CJK COMPATIBILITY IDEOGRAPH-2FA18; QQC
+2EEA ; [.FB41.0020.0004.9EFE][.9EFE.0000.0000.9EFE] # CJK RADICAL C-SIMPLIFIED FROG; QQK
+2FA19 ; [.FB41.0020.0002.9F05][.9F05.0000.0000.9F05] # CJK COMPATIBILITY IDEOGRAPH-2FA19; QQC
+2FCD ; [.FB41.0020.0004.9F0E][.9F0E.0000.0000.9F0E] # KANGXI RADICAL TRIPOD; QQK
+2FA1A ; [.FB41.0020.0002.9F0F][.9F0F.0000.0000.9F0F] # CJK COMPATIBILITY IDEOGRAPH-2FA1A; QQC
+2FCE ; [.FB41.0020.0004.9F13][.9F13.0000.0000.9F13] # KANGXI RADICAL DRUM; QQK
+2FA1B ; [.FB41.0020.0002.9F16][.9F16.0000.0000.9F16] # CJK COMPATIBILITY IDEOGRAPH-2FA1B; QQC
+2FCF ; [.FB41.0020.0004.9F20][.9F20.0000.0000.9F20] # KANGXI RADICAL RAT; QQK
+2FA1C ; [.FB41.0020.0002.9F3B][.9F3B.0000.0000.9F3B] # CJK COMPATIBILITY IDEOGRAPH-2FA1C; QQC
+2FD0 ; [.FB41.0020.0004.9F3B][.9F3B.0000.0000.9F3B] # KANGXI RADICAL NOSE; QQK
+FAD8 ; [.FB41.0020.0002.9F43][.9F43.0000.0000.9F43] # CJK COMPATIBILITY IDEOGRAPH-FAD8; QQC
+2FD1 ; [.FB41.0020.0004.9F4A][.9F4A.0000.0000.9F4A] # KANGXI RADICAL EVEN; QQK
+2EEB ; [.FB41.0020.0004.9F4A][.9F4A.0000.0000.9F4A][.0000.0199.001F.2EEB] # CJK RADICAL J-SIMPLIFIED EVEN; QQKN
+2EEC ; [.FB41.0020.0004.9F50][.9F50.0000.0000.9F50] # CJK RADICAL C-SIMPLIFIED EVEN; QQK
+2FD2 ; [.FB41.0020.0004.9F52][.9F52.0000.0000.9F52] # KANGXI RADICAL TOOTH; QQK
+2EED ; [.FB41.0020.0004.9F52][.9F52.0000.0000.9F52][.0000.0199.001F.2EED] # CJK RADICAL J-SIMPLIFIED TOOTH; QQKN
+2EEE ; [.FB41.0020.0004.9F7F][.9F7F.0000.0000.9F7F] # CJK RADICAL C-SIMPLIFIED TOOTH; QQK
+F9C4 ; [.FB41.0020.0002.9F8D][.9F8D.0000.0000.9F8D] # CJK COMPATIBILITY IDEOGRAPH-F9C4; QQC
+2FD3 ; [.FB41.0020.0004.9F8D][.9F8D.0000.0000.9F8D] # KANGXI RADICAL DRAGON; QQK
+2EEF ; [.FB41.0020.0004.9F8D][.9F8D.0000.0000.9F8D][.0000.0199.001F.2EEF] # CJK RADICAL J-SIMPLIFIED DRAGON; QQKN
+FAD9 ; [.FB41.0020.0002.9F8E][.9F8E.0000.0000.9F8E] # CJK COMPATIBILITY IDEOGRAPH-FAD9; QQC
+2EF0 ; [.FB41.0020.0004.9F99][.9F99.0000.0000.9F99] # CJK RADICAL C-SIMPLIFIED DRAGON; QQK
+F907 ; [.FB41.0020.0002.9F9C][.9F9C.0000.0000.9F9C] # CJK COMPATIBILITY IDEOGRAPH-F907; QQC
+F908 ; [.FB41.0020.0002.9F9C][.9F9C.0000.0000.9F9C] # CJK COMPATIBILITY IDEOGRAPH-F908; QQC
+FACE ; [.FB41.0020.0002.9F9C][.9F9C.0000.0000.9F9C] # CJK COMPATIBILITY IDEOGRAPH-FACE; QQC
+2FD4 ; [.FB41.0020.0004.9F9C][.9F9C.0000.0000.9F9C] # KANGXI RADICAL TURTLE; QQK
+2EF1 ; [.FB41.0020.0004.9F9C][.9F9C.0000.0000.9F9C][.0000.0199.001F.2EF1] # CJK RADICAL TURTLE; QQKN
+2EF2 ; [.FB41.0020.0004.9F9C][.9F9C.0000.0000.9F9C][.0000.019A.001F.2EF2] # CJK RADICAL J-SIMPLIFIED TURTLE; QQKN
+2EF3 ; [.FB41.0020.0004.9F9F][.9F9F.0000.0000.9F9F] # CJK RADICAL C-SIMPLIFIED TURTLE; QQK
+2FD5 ; [.FB41.0020.0004.9FA0][.9FA0.0000.0000.9FA0] # KANGXI RADICAL FLUTE; QQK
+FA0E ; [.FB41.0020.0002.FA0E][.FA0E.0000.0000.FA0E] # CJK COMPATIBILITY IDEOGRAPH-FA0E
+FA0F ; [.FB41.0020.0002.FA0F][.FA0F.0000.0000.FA0F] # CJK COMPATIBILITY IDEOGRAPH-FA0F
+FA11 ; [.FB41.0020.0002.FA11][.FA11.0000.0000.FA11] # CJK COMPATIBILITY IDEOGRAPH-FA11
+FA13 ; [.FB41.0020.0002.FA13][.FA13.0000.0000.FA13] # CJK COMPATIBILITY IDEOGRAPH-FA13
+FA14 ; [.FB41.0020.0002.FA14][.FA14.0000.0000.FA14] # CJK COMPATIBILITY IDEOGRAPH-FA14
+FA1F ; [.FB41.0020.0002.FA1F][.FA1F.0000.0000.FA1F] # CJK COMPATIBILITY IDEOGRAPH-FA1F
+FA21 ; [.FB41.0020.0002.FA21][.FA21.0000.0000.FA21] # CJK COMPATIBILITY IDEOGRAPH-FA21
+FA23 ; [.FB41.0020.0002.FA23][.FA23.0000.0000.FA23] # CJK COMPATIBILITY IDEOGRAPH-FA23
+FA24 ; [.FB41.0020.0002.FA24][.FA24.0000.0000.FA24] # CJK COMPATIBILITY IDEOGRAPH-FA24
+FA27 ; [.FB41.0020.0002.FA27][.FA27.0000.0000.FA27] # CJK COMPATIBILITY IDEOGRAPH-FA27
+FA28 ; [.FB41.0020.0002.FA28][.FA28.0000.0000.FA28] # CJK COMPATIBILITY IDEOGRAPH-FA28
+FA29 ; [.FB41.0020.0002.FA29][.FA29.0000.0000.FA29] # CJK COMPATIBILITY IDEOGRAPH-FA29
+2F80C ; [.FB80.0020.0002.349E][.B49E.0000.0000.349E] # CJK COMPATIBILITY IDEOGRAPH-2F80C; QQC
+2F813 ; [.FB80.0020.0002.34B9][.B4B9.0000.0000.34B9] # CJK COMPATIBILITY IDEOGRAPH-2F813; QQC
+2F9CA ; [.FB80.0020.0002.34BB][.B4BB.0000.0000.34BB] # CJK COMPATIBILITY IDEOGRAPH-2F9CA; QQC
+2F81F ; [.FB80.0020.0002.34DF][.B4DF.0000.0000.34DF] # CJK COMPATIBILITY IDEOGRAPH-2F81F; QQC
+2F824 ; [.FB80.0020.0002.3515][.B515.0000.0000.3515] # CJK COMPATIBILITY IDEOGRAPH-2F824; QQC
+2F867 ; [.FB80.0020.0002.36EE][.B6EE.0000.0000.36EE] # CJK COMPATIBILITY IDEOGRAPH-2F867; QQC
+2F868 ; [.FB80.0020.0002.36FC][.B6FC.0000.0000.36FC] # CJK COMPATIBILITY IDEOGRAPH-2F868; QQC
+2F876 ; [.FB80.0020.0002.3781][.B781.0000.0000.3781] # CJK COMPATIBILITY IDEOGRAPH-2F876; QQC
+2F883 ; [.FB80.0020.0002.382F][.B82F.0000.0000.382F] # CJK COMPATIBILITY IDEOGRAPH-2F883; QQC
+2F888 ; [.FB80.0020.0002.3862][.B862.0000.0000.3862] # CJK COMPATIBILITY IDEOGRAPH-2F888; QQC
+2F88A ; [.FB80.0020.0002.387C][.B87C.0000.0000.387C] # CJK COMPATIBILITY IDEOGRAPH-2F88A; QQC
+2F896 ; [.FB80.0020.0002.38C7][.B8C7.0000.0000.38C7] # CJK COMPATIBILITY IDEOGRAPH-2F896; QQC
+2F89B ; [.FB80.0020.0002.38E3][.B8E3.0000.0000.38E3] # CJK COMPATIBILITY IDEOGRAPH-2F89B; QQC
+2F8A2 ; [.FB80.0020.0002.391C][.B91C.0000.0000.391C] # CJK COMPATIBILITY IDEOGRAPH-2F8A2; QQC
+2F8A1 ; [.FB80.0020.0002.393A][.B93A.0000.0000.393A] # CJK COMPATIBILITY IDEOGRAPH-2F8A1; QQC
+2F8C2 ; [.FB80.0020.0002.3A2E][.BA2E.0000.0000.3A2E] # CJK COMPATIBILITY IDEOGRAPH-2F8C2; QQC
+2F8C7 ; [.FB80.0020.0002.3A6C][.BA6C.0000.0000.3A6C] # CJK COMPATIBILITY IDEOGRAPH-2F8C7; QQC
+2F8D1 ; [.FB80.0020.0002.3AE4][.BAE4.0000.0000.3AE4] # CJK COMPATIBILITY IDEOGRAPH-2F8D1; QQC
+2F8D0 ; [.FB80.0020.0002.3B08][.BB08.0000.0000.3B08] # CJK COMPATIBILITY IDEOGRAPH-2F8D0; QQC
+2F8CE ; [.FB80.0020.0002.3B19][.BB19.0000.0000.3B19] # CJK COMPATIBILITY IDEOGRAPH-2F8CE; QQC
+2F8DE ; [.FB80.0020.0002.3B49][.BB49.0000.0000.3B49] # CJK COMPATIBILITY IDEOGRAPH-2F8DE; QQC
+FAD2 ; [.FB80.0020.0002.3B9D][.BB9D.0000.0000.3B9D] # CJK COMPATIBILITY IDEOGRAPH-FAD2; QQC
+2F8E7 ; [.FB80.0020.0002.3B9D][.BB9D.0000.0000.3B9D] # CJK COMPATIBILITY IDEOGRAPH-2F8E7; QQC
+2F8EE ; [.FB80.0020.0002.3C18][.BC18.0000.0000.3C18] # CJK COMPATIBILITY IDEOGRAPH-2F8EE; QQC
+2F8F2 ; [.FB80.0020.0002.3C4E][.BC4E.0000.0000.3C4E] # CJK COMPATIBILITY IDEOGRAPH-2F8F2; QQC
+2F90A ; [.FB80.0020.0002.3D33][.BD33.0000.0000.3D33] # CJK COMPATIBILITY IDEOGRAPH-2F90A; QQC
+2F916 ; [.FB80.0020.0002.3D96][.BD96.0000.0000.3D96] # CJK COMPATIBILITY IDEOGRAPH-2F916; QQC
+2F92A ; [.FB80.0020.0002.3EAC][.BEAC.0000.0000.3EAC] # CJK COMPATIBILITY IDEOGRAPH-2F92A; QQC
+2F92C ; [.FB80.0020.0002.3EB8][.BEB8.0000.0000.3EB8] # CJK COMPATIBILITY IDEOGRAPH-2F92C; QQC
+2F92D ; [.FB80.0020.0002.3EB8][.BEB8.0000.0000.3EB8] # CJK COMPATIBILITY IDEOGRAPH-2F92D; QQC
+2F933 ; [.FB80.0020.0002.3F1B][.BF1B.0000.0000.3F1B] # CJK COMPATIBILITY IDEOGRAPH-2F933; QQC
+2F93E ; [.FB80.0020.0002.3FFC][.BFFC.0000.0000.3FFC] # CJK COMPATIBILITY IDEOGRAPH-2F93E; QQC
+2F93F ; [.FB80.0020.0002.4008][.C008.0000.0000.4008] # CJK COMPATIBILITY IDEOGRAPH-2F93F; QQC
+FAD3 ; [.FB80.0020.0002.4018][.C018.0000.0000.4018] # CJK COMPATIBILITY IDEOGRAPH-FAD3; QQC
+FAD4 ; [.FB80.0020.0002.4039][.C039.0000.0000.4039] # CJK COMPATIBILITY IDEOGRAPH-FAD4; QQC
+2F949 ; [.FB80.0020.0002.4039][.C039.0000.0000.4039] # CJK COMPATIBILITY IDEOGRAPH-2F949; QQC
+2F94B ; [.FB80.0020.0002.4046][.C046.0000.0000.4046] # CJK COMPATIBILITY IDEOGRAPH-2F94B; QQC
+2F94C ; [.FB80.0020.0002.4096][.C096.0000.0000.4096] # CJK COMPATIBILITY IDEOGRAPH-2F94C; QQC
+2F951 ; [.FB80.0020.0002.40E3][.C0E3.0000.0000.40E3] # CJK COMPATIBILITY IDEOGRAPH-2F951; QQC
+2F958 ; [.FB80.0020.0002.412F][.C12F.0000.0000.412F] # CJK COMPATIBILITY IDEOGRAPH-2F958; QQC
+2F960 ; [.FB80.0020.0002.4202][.C202.0000.0000.4202] # CJK COMPATIBILITY IDEOGRAPH-2F960; QQC
+2F964 ; [.FB80.0020.0002.4227][.C227.0000.0000.4227] # CJK COMPATIBILITY IDEOGRAPH-2F964; QQC
+2F967 ; [.FB80.0020.0002.42A0][.C2A0.0000.0000.42A0] # CJK COMPATIBILITY IDEOGRAPH-2F967; QQC
+2F96D ; [.FB80.0020.0002.4301][.C301.0000.0000.4301] # CJK COMPATIBILITY IDEOGRAPH-2F96D; QQC
+2F971 ; [.FB80.0020.0002.4334][.C334.0000.0000.4334] # CJK COMPATIBILITY IDEOGRAPH-2F971; QQC
+2F974 ; [.FB80.0020.0002.4359][.C359.0000.0000.4359] # CJK COMPATIBILITY IDEOGRAPH-2F974; QQC
+2F981 ; [.FB80.0020.0002.43D5][.C3D5.0000.0000.43D5] # CJK COMPATIBILITY IDEOGRAPH-2F981; QQC
+2F8D7 ; [.FB80.0020.0002.43D9][.C3D9.0000.0000.43D9] # CJK COMPATIBILITY IDEOGRAPH-2F8D7; QQC
+2F984 ; [.FB80.0020.0002.440B][.C40B.0000.0000.440B] # CJK COMPATIBILITY IDEOGRAPH-2F984; QQC
+2F98E ; [.FB80.0020.0002.446B][.C46B.0000.0000.446B] # CJK COMPATIBILITY IDEOGRAPH-2F98E; QQC
+2F9A7 ; [.FB80.0020.0002.452B][.C52B.0000.0000.452B] # CJK COMPATIBILITY IDEOGRAPH-2F9A7; QQC
+2F9AE ; [.FB80.0020.0002.455D][.C55D.0000.0000.455D] # CJK COMPATIBILITY IDEOGRAPH-2F9AE; QQC
+2F9AF ; [.FB80.0020.0002.4561][.C561.0000.0000.4561] # CJK COMPATIBILITY IDEOGRAPH-2F9AF; QQC
+2F9B2 ; [.FB80.0020.0002.456B][.C56B.0000.0000.456B] # CJK COMPATIBILITY IDEOGRAPH-2F9B2; QQC
+2F9BF ; [.FB80.0020.0002.45D7][.C5D7.0000.0000.45D7] # CJK COMPATIBILITY IDEOGRAPH-2F9BF; QQC
+2F9C2 ; [.FB80.0020.0002.45F9][.C5F9.0000.0000.45F9] # CJK COMPATIBILITY IDEOGRAPH-2F9C2; QQC
+2F9C8 ; [.FB80.0020.0002.4635][.C635.0000.0000.4635] # CJK COMPATIBILITY IDEOGRAPH-2F9C8; QQC
+2F9CD ; [.FB80.0020.0002.46BE][.C6BE.0000.0000.46BE] # CJK COMPATIBILITY IDEOGRAPH-2F9CD; QQC
+2F9CE ; [.FB80.0020.0002.46C7][.C6C7.0000.0000.46C7] # CJK COMPATIBILITY IDEOGRAPH-2F9CE; QQC
+2F9EF ; [.FB80.0020.0002.4995][.C995.0000.0000.4995] # CJK COMPATIBILITY IDEOGRAPH-2F9EF; QQC
+2F9F2 ; [.FB80.0020.0002.49E6][.C9E6.0000.0000.49E6] # CJK COMPATIBILITY IDEOGRAPH-2F9F2; QQC
+2F9F8 ; [.FB80.0020.0002.4A6E][.CA6E.0000.0000.4A6E] # CJK COMPATIBILITY IDEOGRAPH-2F9F8; QQC
+2F9F9 ; [.FB80.0020.0002.4A76][.CA76.0000.0000.4A76] # CJK COMPATIBILITY IDEOGRAPH-2F9F9; QQC
+2F9FC ; [.FB80.0020.0002.4AB2][.CAB2.0000.0000.4AB2] # CJK COMPATIBILITY IDEOGRAPH-2F9FC; QQC
+2FA03 ; [.FB80.0020.0002.4B33][.CB33.0000.0000.4B33] # CJK COMPATIBILITY IDEOGRAPH-2FA03; QQC
+2FA08 ; [.FB80.0020.0002.4BCE][.CBCE.0000.0000.4BCE] # CJK COMPATIBILITY IDEOGRAPH-2FA08; QQC
+2FA0D ; [.FB80.0020.0002.4CCE][.CCCE.0000.0000.4CCE] # CJK COMPATIBILITY IDEOGRAPH-2FA0D; QQC
+2FA0E ; [.FB80.0020.0002.4CED][.CCED.0000.0000.4CED] # CJK COMPATIBILITY IDEOGRAPH-2FA0E; QQC
+2FA11 ; [.FB80.0020.0002.4CF8][.CCF8.0000.0000.4CF8] # CJK COMPATIBILITY IDEOGRAPH-2FA11; QQC
+2FA16 ; [.FB80.0020.0002.4D56][.CD56.0000.0000.4D56] # CJK COMPATIBILITY IDEOGRAPH-2FA16; QQC
+2F803 ; [.FB84.0020.0002.20122][.8122.0000.0000.20122] # CJK COMPATIBILITY IDEOGRAPH-2F803; QQC
+2F812 ; [.FB84.0020.0002.2051C][.851C.0000.0000.2051C] # CJK COMPATIBILITY IDEOGRAPH-2F812; QQC
+2F91B ; [.FB84.0020.0002.20525][.8525.0000.0000.20525] # CJK COMPATIBILITY IDEOGRAPH-2F91B; QQC
+2F816 ; [.FB84.0020.0002.2054B][.854B.0000.0000.2054B] # CJK COMPATIBILITY IDEOGRAPH-2F816; QQC
+2F80D ; [.FB84.0020.0002.2063A][.863A.0000.0000.2063A] # CJK COMPATIBILITY IDEOGRAPH-2F80D; QQC
+2F9D9 ; [.FB84.0020.0002.20804][.8804.0000.0000.20804] # CJK COMPATIBILITY IDEOGRAPH-2F9D9; QQC
+2F9DD ; [.FB84.0020.0002.208DE][.88DE.0000.0000.208DE] # CJK COMPATIBILITY IDEOGRAPH-2F9DD; QQC
+2F834 ; [.FB84.0020.0002.20A2C][.8A2C.0000.0000.20A2C] # CJK COMPATIBILITY IDEOGRAPH-2F834; QQC
+2F838 ; [.FB84.0020.0002.20B63][.8B63.0000.0000.20B63] # CJK COMPATIBILITY IDEOGRAPH-2F838; QQC
+2F859 ; [.FB84.0020.0002.214E4][.94E4.0000.0000.214E4] # CJK COMPATIBILITY IDEOGRAPH-2F859; QQC
+2F860 ; [.FB84.0020.0002.216A8][.96A8.0000.0000.216A8] # CJK COMPATIBILITY IDEOGRAPH-2F860; QQC
+2F861 ; [.FB84.0020.0002.216EA][.96EA.0000.0000.216EA] # CJK COMPATIBILITY IDEOGRAPH-2F861; QQC
+2F86C ; [.FB84.0020.0002.219C8][.99C8.0000.0000.219C8] # CJK COMPATIBILITY IDEOGRAPH-2F86C; QQC
+2F871 ; [.FB84.0020.0002.21B18][.9B18.0000.0000.21B18] # CJK COMPATIBILITY IDEOGRAPH-2F871; QQC
+2F8F8 ; [.FB84.0020.0002.21D0B][.9D0B.0000.0000.21D0B] # CJK COMPATIBILITY IDEOGRAPH-2F8F8; QQC
+2F87B ; [.FB84.0020.0002.21DE4][.9DE4.0000.0000.21DE4] # CJK COMPATIBILITY IDEOGRAPH-2F87B; QQC
+2F87D ; [.FB84.0020.0002.21DE6][.9DE6.0000.0000.21DE6] # CJK COMPATIBILITY IDEOGRAPH-2F87D; QQC
+2F889 ; [.FB84.0020.0002.22183][.A183.0000.0000.22183] # CJK COMPATIBILITY IDEOGRAPH-2F889; QQC
+2F939 ; [.FB84.0020.0002.2219F][.A19F.0000.0000.2219F] # CJK COMPATIBILITY IDEOGRAPH-2F939; QQC
+2F891 ; [.FB84.0020.0002.22331][.A331.0000.0000.22331] # CJK COMPATIBILITY IDEOGRAPH-2F891; QQC
+2F892 ; [.FB84.0020.0002.22331][.A331.0000.0000.22331] # CJK COMPATIBILITY IDEOGRAPH-2F892; QQC
+2F8A4 ; [.FB84.0020.0002.226D4][.A6D4.0000.0000.226D4] # CJK COMPATIBILITY IDEOGRAPH-2F8A4; QQC
+FAD0 ; [.FB84.0020.0002.22844][.A844.0000.0000.22844] # CJK COMPATIBILITY IDEOGRAPH-FAD0; QQC
+FACF ; [.FB84.0020.0002.2284A][.A84A.0000.0000.2284A] # CJK COMPATIBILITY IDEOGRAPH-FACF; QQC
+2F8B8 ; [.FB84.0020.0002.22B0C][.AB0C.0000.0000.22B0C] # CJK COMPATIBILITY IDEOGRAPH-2F8B8; QQC
+2F8BE ; [.FB84.0020.0002.22BF1][.ABF1.0000.0000.22BF1] # CJK COMPATIBILITY IDEOGRAPH-2F8BE; QQC
+2F8CA ; [.FB84.0020.0002.2300A][.B00A.0000.0000.2300A] # CJK COMPATIBILITY IDEOGRAPH-2F8CA; QQC
+2F897 ; [.FB84.0020.0002.232B8][.B2B8.0000.0000.232B8] # CJK COMPATIBILITY IDEOGRAPH-2F897; QQC
+2F980 ; [.FB84.0020.0002.2335F][.B35F.0000.0000.2335F] # CJK COMPATIBILITY IDEOGRAPH-2F980; QQC
+2F989 ; [.FB84.0020.0002.23393][.B393.0000.0000.23393] # CJK COMPATIBILITY IDEOGRAPH-2F989; QQC
+2F98A ; [.FB84.0020.0002.2339C][.B39C.0000.0000.2339C] # CJK COMPATIBILITY IDEOGRAPH-2F98A; QQC
+2F8DD ; [.FB84.0020.0002.233C3][.B3C3.0000.0000.233C3] # CJK COMPATIBILITY IDEOGRAPH-2F8DD; QQC
+FAD1 ; [.FB84.0020.0002.233D5][.B3D5.0000.0000.233D5] # CJK COMPATIBILITY IDEOGRAPH-FAD1; QQC
+2F8E3 ; [.FB84.0020.0002.2346D][.B46D.0000.0000.2346D] # CJK COMPATIBILITY IDEOGRAPH-2F8E3; QQC
+2F8EC ; [.FB84.0020.0002.236A3][.B6A3.0000.0000.236A3] # CJK COMPATIBILITY IDEOGRAPH-2F8EC; QQC
+2F8F0 ; [.FB84.0020.0002.238A7][.B8A7.0000.0000.238A7] # CJK COMPATIBILITY IDEOGRAPH-2F8F0; QQC
+2F8F7 ; [.FB84.0020.0002.23A8D][.BA8D.0000.0000.23A8D] # CJK COMPATIBILITY IDEOGRAPH-2F8F7; QQC
+2F8F9 ; [.FB84.0020.0002.23AFA][.BAFA.0000.0000.23AFA] # CJK COMPATIBILITY IDEOGRAPH-2F8F9; QQC
+2F8FB ; [.FB84.0020.0002.23CBC][.BCBC.0000.0000.23CBC] # CJK COMPATIBILITY IDEOGRAPH-2F8FB; QQC
+2F906 ; [.FB84.0020.0002.23D1E][.BD1E.0000.0000.23D1E] # CJK COMPATIBILITY IDEOGRAPH-2F906; QQC
+2F90D ; [.FB84.0020.0002.23ED1][.BED1.0000.0000.23ED1] # CJK COMPATIBILITY IDEOGRAPH-2F90D; QQC
+2F910 ; [.FB84.0020.0002.23F5E][.BF5E.0000.0000.23F5E] # CJK COMPATIBILITY IDEOGRAPH-2F910; QQC
+2F911 ; [.FB84.0020.0002.23F8E][.BF8E.0000.0000.23F8E] # CJK COMPATIBILITY IDEOGRAPH-2F911; QQC
+2F91D ; [.FB84.0020.0002.24263][.C263.0000.0000.24263] # CJK COMPATIBILITY IDEOGRAPH-2F91D; QQC
+2F91F ; [.FB84.0020.0002.243AB][.C3AB.0000.0000.243AB] # CJK COMPATIBILITY IDEOGRAPH-2F91F; QQC
+2F923 ; [.FB84.0020.0002.24608][.C608.0000.0000.24608] # CJK COMPATIBILITY IDEOGRAPH-2F923; QQC
+2F926 ; [.FB84.0020.0002.24735][.C735.0000.0000.24735] # CJK COMPATIBILITY IDEOGRAPH-2F926; QQC
+2F927 ; [.FB84.0020.0002.24814][.C814.0000.0000.24814] # CJK COMPATIBILITY IDEOGRAPH-2F927; QQC
+2F935 ; [.FB84.0020.0002.24C36][.CC36.0000.0000.24C36] # CJK COMPATIBILITY IDEOGRAPH-2F935; QQC
+2F937 ; [.FB84.0020.0002.24C92][.CC92.0000.0000.24C92] # CJK COMPATIBILITY IDEOGRAPH-2F937; QQC
+2F93B ; [.FB84.0020.0002.24FA1][.CFA1.0000.0000.24FA1] # CJK COMPATIBILITY IDEOGRAPH-2F93B; QQC
+2F93C ; [.FB84.0020.0002.24FB8][.CFB8.0000.0000.24FB8] # CJK COMPATIBILITY IDEOGRAPH-2F93C; QQC
+2F93D ; [.FB84.0020.0002.25044][.D044.0000.0000.25044] # CJK COMPATIBILITY IDEOGRAPH-2F93D; QQC
+2F942 ; [.FB84.0020.0002.250F2][.D0F2.0000.0000.250F2] # CJK COMPATIBILITY IDEOGRAPH-2F942; QQC
+2F941 ; [.FB84.0020.0002.250F3][.D0F3.0000.0000.250F3] # CJK COMPATIBILITY IDEOGRAPH-2F941; QQC
+2F943 ; [.FB84.0020.0002.25119][.D119.0000.0000.25119] # CJK COMPATIBILITY IDEOGRAPH-2F943; QQC
+2F944 ; [.FB84.0020.0002.25133][.D133.0000.0000.25133] # CJK COMPATIBILITY IDEOGRAPH-2F944; QQC
+FAD5 ; [.FB84.0020.0002.25249][.D249.0000.0000.25249] # CJK COMPATIBILITY IDEOGRAPH-FAD5; QQC
+2F94D ; [.FB84.0020.0002.2541D][.D41D.0000.0000.2541D] # CJK COMPATIBILITY IDEOGRAPH-2F94D; QQC
+2F952 ; [.FB84.0020.0002.25626][.D626.0000.0000.25626] # CJK COMPATIBILITY IDEOGRAPH-2F952; QQC
+2F954 ; [.FB84.0020.0002.2569A][.D69A.0000.0000.2569A] # CJK COMPATIBILITY IDEOGRAPH-2F954; QQC
+2F955 ; [.FB84.0020.0002.256C5][.D6C5.0000.0000.256C5] # CJK COMPATIBILITY IDEOGRAPH-2F955; QQC
+2F95C ; [.FB84.0020.0002.2597C][.D97C.0000.0000.2597C] # CJK COMPATIBILITY IDEOGRAPH-2F95C; QQC
+2F95D ; [.FB84.0020.0002.25AA7][.DAA7.0000.0000.25AA7] # CJK COMPATIBILITY IDEOGRAPH-2F95D; QQC
+2F95E ; [.FB84.0020.0002.25AA7][.DAA7.0000.0000.25AA7] # CJK COMPATIBILITY IDEOGRAPH-2F95E; QQC
+2F961 ; [.FB84.0020.0002.25BAB][.DBAB.0000.0000.25BAB] # CJK COMPATIBILITY IDEOGRAPH-2F961; QQC
+2F965 ; [.FB84.0020.0002.25C80][.DC80.0000.0000.25C80] # CJK COMPATIBILITY IDEOGRAPH-2F965; QQC
+FAD6 ; [.FB84.0020.0002.25CD0][.DCD0.0000.0000.25CD0] # CJK COMPATIBILITY IDEOGRAPH-FAD6; QQC
+2F96B ; [.FB84.0020.0002.25F86][.DF86.0000.0000.25F86] # CJK COMPATIBILITY IDEOGRAPH-2F96B; QQC
+2F898 ; [.FB84.0020.0002.261DA][.E1DA.0000.0000.261DA] # CJK COMPATIBILITY IDEOGRAPH-2F898; QQC
+2F972 ; [.FB84.0020.0002.26228][.E228.0000.0000.26228] # CJK COMPATIBILITY IDEOGRAPH-2F972; QQC
+2F973 ; [.FB84.0020.0002.26247][.E247.0000.0000.26247] # CJK COMPATIBILITY IDEOGRAPH-2F973; QQC
+2F975 ; [.FB84.0020.0002.262D9][.E2D9.0000.0000.262D9] # CJK COMPATIBILITY IDEOGRAPH-2F975; QQC
+2F977 ; [.FB84.0020.0002.2633E][.E33E.0000.0000.2633E] # CJK COMPATIBILITY IDEOGRAPH-2F977; QQC
+2F97B ; [.FB84.0020.0002.264DA][.E4DA.0000.0000.264DA] # CJK COMPATIBILITY IDEOGRAPH-2F97B; QQC
+2F97C ; [.FB84.0020.0002.26523][.E523.0000.0000.26523] # CJK COMPATIBILITY IDEOGRAPH-2F97C; QQC
+2F97E ; [.FB84.0020.0002.265A8][.E5A8.0000.0000.265A8] # CJK COMPATIBILITY IDEOGRAPH-2F97E; QQC
+2F987 ; [.FB84.0020.0002.267A7][.E7A7.0000.0000.267A7] # CJK COMPATIBILITY IDEOGRAPH-2F987; QQC
+2F988 ; [.FB84.0020.0002.267B5][.E7B5.0000.0000.267B5] # CJK COMPATIBILITY IDEOGRAPH-2F988; QQC
+2F997 ; [.FB84.0020.0002.26B3C][.EB3C.0000.0000.26B3C] # CJK COMPATIBILITY IDEOGRAPH-2F997; QQC
+2F9A4 ; [.FB84.0020.0002.26C36][.EC36.0000.0000.26C36] # CJK COMPATIBILITY IDEOGRAPH-2F9A4; QQC
+2F9A6 ; [.FB84.0020.0002.26CD5][.ECD5.0000.0000.26CD5] # CJK COMPATIBILITY IDEOGRAPH-2F9A6; QQC
+2F9A5 ; [.FB84.0020.0002.26D6B][.ED6B.0000.0000.26D6B] # CJK COMPATIBILITY IDEOGRAPH-2F9A5; QQC
+2F9AD ; [.FB84.0020.0002.26F2C][.EF2C.0000.0000.26F2C] # CJK COMPATIBILITY IDEOGRAPH-2F9AD; QQC
+2F9B0 ; [.FB84.0020.0002.26FB1][.EFB1.0000.0000.26FB1] # CJK COMPATIBILITY IDEOGRAPH-2F9B0; QQC
+2F9B1 ; [.FB84.0020.0002.270D2][.F0D2.0000.0000.270D2] # CJK COMPATIBILITY IDEOGRAPH-2F9B1; QQC
+2F9AB ; [.FB84.0020.0002.273CA][.F3CA.0000.0000.273CA] # CJK COMPATIBILITY IDEOGRAPH-2F9AB; QQC
+2F9C5 ; [.FB84.0020.0002.27667][.F667.0000.0000.27667] # CJK COMPATIBILITY IDEOGRAPH-2F9C5; QQC
+2F9CB ; [.FB84.0020.0002.278AE][.F8AE.0000.0000.278AE] # CJK COMPATIBILITY IDEOGRAPH-2F9CB; QQC
+2F9CC ; [.FB84.0020.0002.27966][.F966.0000.0000.27966] # CJK COMPATIBILITY IDEOGRAPH-2F9CC; QQC
+2F9D3 ; [.FB84.0020.0002.27CA8][.FCA8.0000.0000.27CA8] # CJK COMPATIBILITY IDEOGRAPH-2F9D3; QQC
+FAD7 ; [.FB84.0020.0002.27ED3][.FED3.0000.0000.27ED3] # CJK COMPATIBILITY IDEOGRAPH-FAD7; QQC
+2F9D8 ; [.FB84.0020.0002.27F2F][.FF2F.0000.0000.27F2F] # CJK COMPATIBILITY IDEOGRAPH-2F9D8; QQC
+2F9E0 ; [.FB85.0020.0002.285D2][.85D2.0000.0000.285D2] # CJK COMPATIBILITY IDEOGRAPH-2F9E0; QQC
+2F9E1 ; [.FB85.0020.0002.285ED][.85ED.0000.0000.285ED] # CJK COMPATIBILITY IDEOGRAPH-2F9E1; QQC
+2F9E5 ; [.FB85.0020.0002.2872E][.872E.0000.0000.2872E] # CJK COMPATIBILITY IDEOGRAPH-2F9E5; QQC
+2F9ED ; [.FB85.0020.0002.28BFA][.8BFA.0000.0000.28BFA] # CJK COMPATIBILITY IDEOGRAPH-2F9ED; QQC
+2F9F1 ; [.FB85.0020.0002.28D77][.8D77.0000.0000.28D77] # CJK COMPATIBILITY IDEOGRAPH-2F9F1; QQC
+2F9F6 ; [.FB85.0020.0002.29145][.9145.0000.0000.29145] # CJK COMPATIBILITY IDEOGRAPH-2F9F6; QQC
+2F81C ; [.FB85.0020.0002.291DF][.91DF.0000.0000.291DF] # CJK COMPATIBILITY IDEOGRAPH-2F81C; QQC
+2F9F7 ; [.FB85.0020.0002.2921A][.921A.0000.0000.2921A] # CJK COMPATIBILITY IDEOGRAPH-2F9F7; QQC
+2F9FB ; [.FB85.0020.0002.2940A][.940A.0000.0000.2940A] # CJK COMPATIBILITY IDEOGRAPH-2F9FB; QQC
+2F9FD ; [.FB85.0020.0002.29496][.9496.0000.0000.29496] # CJK COMPATIBILITY IDEOGRAPH-2F9FD; QQC
+2FA01 ; [.FB85.0020.0002.295B6][.95B6.0000.0000.295B6] # CJK COMPATIBILITY IDEOGRAPH-2FA01; QQC
+2FA09 ; [.FB85.0020.0002.29B30][.9B30.0000.0000.29B30] # CJK COMPATIBILITY IDEOGRAPH-2FA09; QQC
+2FA10 ; [.FB85.0020.0002.2A0CE][.A0CE.0000.0000.2A0CE] # CJK COMPATIBILITY IDEOGRAPH-2FA10; QQC
+2FA12 ; [.FB85.0020.0002.2A105][.A105.0000.0000.2A105] # CJK COMPATIBILITY IDEOGRAPH-2FA12; QQC
+2FA13 ; [.FB85.0020.0002.2A20E][.A20E.0000.0000.2A20E] # CJK COMPATIBILITY IDEOGRAPH-2FA13; QQC
+2FA14 ; [.FB85.0020.0002.2A291][.A291.0000.0000.2A291] # CJK COMPATIBILITY IDEOGRAPH-2FA14; QQC
+2F88F ; [.FB85.0020.0002.2A392][.A392.0000.0000.2A392] # CJK COMPATIBILITY IDEOGRAPH-2F88F; QQC
+2FA1D ; [.FB85.0020.0002.2A600][.A600.0000.0000.2A600] # CJK COMPATIBILITY IDEOGRAPH-2FA1D; QQC
diff --git a/Master/tlpkg/tlperl/lib/Unicode/Collate/keys.txt b/Master/tlpkg/tlperl/lib/Unicode/Collate/keys.txt
new file mode 100644
index 00000000000..aaa2d2a5a77
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Unicode/Collate/keys.txt
@@ -0,0 +1,864 @@
+#### This file is generated from allkeys-3.1.1.txt (unicode.org)
+#### by deleting many many entries.
+####
+#### This table is intended ONLY for doing a test
+#### of Unicode/Collate.pm, a Perl module.
+####
+#### The entries contained here ARE:
+#### 0000..007F # Basic Latin
+#### 0080..00FF # Latin-1 Supplement
+#### 0300..036F # Combining Diacritical Marks
+#### 1100..11FF # Hangul Jamo
+#### 2000..206F # General Punctuation
+#### 3040..309F # Hiragana
+#### 30A0..30FF # Katakana
+####
+#### To fetch the original file, access to this:
+#### http://www.unicode.org/reports/tr10/allkeys.txt
+####
+@version 3.1.1
+0000 ; [.0000.0000.0000.0000] # [0000] NULL (in 6429)
+0001 ; [.0000.0000.0000.0000] # [0001] START OF HEADING (in 6429)
+0002 ; [.0000.0000.0000.0000] # [0002] START OF TEXT (in 6429)
+0003 ; [.0000.0000.0000.0000] # [0003] END OF TEXT (in 6429)
+0004 ; [.0000.0000.0000.0000] # [0004] END OF TRANSMISSION (in 6429)
+0005 ; [.0000.0000.0000.0000] # [0005] ENQUIRY (in 6429)
+0006 ; [.0000.0000.0000.0000] # [0006] ACKNOWLEDGE (in 6429)
+0007 ; [.0000.0000.0000.0000] # [0007] BELL (in 6429)
+0008 ; [.0000.0000.0000.0000] # [0008] BACKSPACE (in 6429)
+000E ; [.0000.0000.0000.0000] # [000E] SHIFT OUT (in 6429)
+000F ; [.0000.0000.0000.0000] # [000F] SHIFT IN (in 6429)
+0010 ; [.0000.0000.0000.0000] # [0010] DATA LINK ESCAPE (in 6429)
+0011 ; [.0000.0000.0000.0000] # [0011] DEVICE CONTROL ONE (in 6429)
+0012 ; [.0000.0000.0000.0000] # [0012] DEVICE CONTROL TWO (in 6429)
+0013 ; [.0000.0000.0000.0000] # [0013] DEVICE CONTROL THREE (in 6429)
+0014 ; [.0000.0000.0000.0000] # [0014] DEVICE CONTROL FOUR (in 6429)
+0015 ; [.0000.0000.0000.0000] # [0015] NEGATIVE ACKNOWLEDGE (in 6429)
+0016 ; [.0000.0000.0000.0000] # [0016] SYNCHRONOUS IDLE (in 6429)
+0017 ; [.0000.0000.0000.0000] # [0017] END OF TRANSMISSION BLOCK (in 6429)
+0018 ; [.0000.0000.0000.0000] # [0018] CANCEL (in 6429)
+0019 ; [.0000.0000.0000.0000] # [0019] END OF MEDIUM (in 6429)
+001A ; [.0000.0000.0000.0000] # [001A] SUBSTITUTE (in 6429)
+001B ; [.0000.0000.0000.0000] # [001B] ESCAPE (in 6429)
+001C ; [.0000.0000.0000.0000] # [001C] FILE SEPARATOR (in 6429)
+001D ; [.0000.0000.0000.0000] # [001D] GROUP SEPARATOR (in 6429)
+001E ; [.0000.0000.0000.0000] # [001E] RECORD SEPARATOR (in 6429)
+001F ; [.0000.0000.0000.0000] # [001F] UNIT SEPARATOR (in 6429)
+007F ; [.0000.0000.0000.0000] # [007F] DELETE (in 6429)
+0080 ; [.0000.0000.0000.0000] # [0080] <control>
+0081 ; [.0000.0000.0000.0000] # [0081] <control>
+0082 ; [.0000.0000.0000.0000] # [0082] BREAK PERMITTED HERE (in 6429)
+0083 ; [.0000.0000.0000.0000] # [0083] NO BREAK HERE (in 6429)
+0084 ; [.0000.0000.0000.0000] # [0084] <control>
+0086 ; [.0000.0000.0000.0000] # [0086] START OF SELECTED AREA (in 6429)
+0087 ; [.0000.0000.0000.0000] # [0087] END OF SELECTED AREA (in 6429)
+0088 ; [.0000.0000.0000.0000] # [0088] CHARACTER TABULATION SET (in 6429)
+0089 ; [.0000.0000.0000.0000] # [0089] CHARACTER TABULATION WITH JUSTIFICATION (in 6429)
+008A ; [.0000.0000.0000.0000] # [008A] LINE TABULATION SET (in 6429)
+008B ; [.0000.0000.0000.0000] # [008B] PARTIAL LINE FORWARD (in 6429)
+008C ; [.0000.0000.0000.0000] # [008C] PARTIAL LINE BACKWARD (in 6429)
+008D ; [.0000.0000.0000.0000] # [008D] PARTIAL LINE FEED (in 6429)
+008E ; [.0000.0000.0000.0000] # [008E] SINGLE SHIFT TWO (in 6429)
+008F ; [.0000.0000.0000.0000] # [008F] SINGLE SHIFT THREE (in 6429)
+0090 ; [.0000.0000.0000.0000] # [0090] DEVICE CONTROL STRING (in 6429)
+0091 ; [.0000.0000.0000.0000] # [0091] PRIVATE USE ONE (in 6429)
+0092 ; [.0000.0000.0000.0000] # [0092] PRIVATE USE TWO (in 6429)
+0093 ; [.0000.0000.0000.0000] # [0093] SET TRANSMIT STATE (in 6429)
+0094 ; [.0000.0000.0000.0000] # [0094] CANCEL CHARACTER (in 6429)
+0095 ; [.0000.0000.0000.0000] # [0095] MESSAGE WAITING (in 6429)
+0096 ; [.0000.0000.0000.0000] # [0096] START OF GUARDED AREA (in 6429)
+0097 ; [.0000.0000.0000.0000] # [0097] END OF GUARDED AREA (in 6429)
+0098 ; [.0000.0000.0000.0000] # [0098] START OF STRING (in 6429)
+0099 ; [.0000.0000.0000.0000] # [0099] <control>
+009A ; [.0000.0000.0000.0000] # [009A] SINGLE CHARACTER INTRODUCER (in 6429)
+009B ; [.0000.0000.0000.0000] # [009B] CONTROL SEQUENCE INTRODUCER (in 6429)
+009C ; [.0000.0000.0000.0000] # [009C] STRING TERMINATOR (in 6429)
+009D ; [.0000.0000.0000.0000] # [009D] OPERATING SYSTEM COMMAND (in 6429)
+009E ; [.0000.0000.0000.0000] # [009E] PRIVACY MESSAGE (in 6429)
+009F ; [.0000.0000.0000.0000] # [009F] APPLICATION PROGRAM COMMAND (in 6429)
+200B ; [.0000.0000.0000.0000] # [200B] ZERO WIDTH SPACE
+200C ; [.0000.0000.0000.0000] # [200C] ZERO WIDTH NON-JOINER
+200D ; [.0000.0000.0000.0000] # [200D] ZERO WIDTH JOINER
+200E ; [.0000.0000.0000.0000] # [200E] LEFT-TO-RIGHT MARK
+200F ; [.0000.0000.0000.0000] # [200F] RIGHT-TO-LEFT MARK
+202A ; [.0000.0000.0000.0000] # [202A] LEFT-TO-RIGHT EMBEDDING
+202B ; [.0000.0000.0000.0000] # [202B] RIGHT-TO-LEFT EMBEDDING
+202C ; [.0000.0000.0000.0000] # [202C] POP DIRECTIONAL FORMATTING
+202D ; [.0000.0000.0000.0000] # [202D] LEFT-TO-RIGHT OVERRIDE
+202E ; [.0000.0000.0000.0000] # [202E] RIGHT-TO-LEFT OVERRIDE
+206A ; [.0000.0000.0000.0000] # [206A] INHIBIT SYMMETRIC SWAPPING
+206B ; [.0000.0000.0000.0000] # [206B] ACTIVATE SYMMETRIC SWAPPING
+206C ; [.0000.0000.0000.0000] # [206C] INHIBIT ARABIC FORM SHAPING
+206D ; [.0000.0000.0000.0000] # [206D] ACTIVATE ARABIC FORM SHAPING
+206E ; [.0000.0000.0000.0000] # [206E] NATIONAL DIGIT SHAPES
+206F ; [.0000.0000.0000.0000] # [206F] NOMINAL DIGIT SHAPES
+0009 ; [*0201.0020.0002.0009] # HORIZONTAL TABULATION (in 6429)
+000A ; [*0202.0020.0002.000A] # LINE FEED (in 6429)
+000B ; [*0203.0020.0002.000B] # VERTICAL TABULATION (in 6429)
+000C ; [*0204.0020.0002.000C] # FORM FEED (in 6429)
+000D ; [*0205.0020.0002.000D] # CARRIAGE RETURN (in 6429)
+0020 ; [*0209.0020.0002.0020] # SPACE
+0021 ; [*024B.0020.0002.0021] # EXCLAMATION MARK
+0022 ; [*0270.0020.0002.0022] # QUOTATION MARK
+0023 ; [*02A9.0020.0002.0023] # NUMBER SIGN
+0025 ; [*02AA.0020.0002.0025] # PERCENT SIGN
+0026 ; [*02A7.0020.0002.0026] # AMPERSAND
+0027 ; [*0269.0020.0002.0027] # APOSTROPHE
+0028 ; [*027A.0020.0002.0028] # LEFT PARENTHESIS
+0029 ; [*027B.0020.0002.0029] # RIGHT PARENTHESIS
+002A ; [*02A2.0020.0002.002A] # ASTERISK
+002B ; [*039F.0020.0002.002B] # PLUS SIGN
+002C ; [*022D.0020.0002.002C] # COMMA
+002D ; [*0221.0020.0002.002D] # HYPHEN-MINUS
+002E ; [*0255.0020.0002.002E] # FULL STOP
+002F ; [*02A4.0020.0002.002F] # SOLIDUS
+003A ; [*0237.0020.0002.003A] # COLON
+003B ; [*0235.0020.0002.003B] # SEMICOLON
+003C ; [*03A3.0020.0002.003C] # LESS-THAN SIGN
+003D ; [*03A4.0020.0002.003D] # EQUALS SIGN
+003E ; [*03A5.0020.0002.003E] # GREATER-THAN SIGN
+003F ; [*024E.0020.0002.003F] # QUESTION MARK
+0040 ; [*02A1.0020.0002.0040] # COMMERCIAL AT
+005B ; [*027C.0020.0002.005B] # LEFT SQUARE BRACKET
+005C ; [*02A6.0020.0002.005C] # REVERSE SOLIDUS
+005D ; [*027D.0020.0002.005D] # RIGHT SQUARE BRACKET
+005E ; [*020F.0020.0002.005E] # CIRCUMFLEX ACCENT
+005F ; [*021B.0020.0002.005F] # LOW LINE
+0060 ; [*020C.0020.0002.0060] # GRAVE ACCENT
+007B ; [*027E.0020.0002.007B] # LEFT CURLY BRACKET
+007C ; [*03A7.0020.0002.007C] # VERTICAL LINE
+007D ; [*027F.0020.0002.007D] # RIGHT CURLY BRACKET
+007E ; [*03AA.0020.0002.007E] # TILDE
+0085 ; [*0206.0020.0002.0085] # NEXT LINE (in 6429)
+00A0 ; [*0209.0020.001B.00A0] # NO-BREAK SPACE; QQK
+00A1 ; [*024C.0020.0002.00A1] # INVERTED EXCLAMATION MARK
+00A6 ; [*03A8.0020.0002.00A6] # BROKEN BAR
+00A7 ; [*029C.0020.0002.00A7] # SECTION SIGN
+00A8 ; [*0214.0020.0002.00A8] # DIAERESIS
+00A9 ; [*029F.0020.0002.00A9] # COPYRIGHT SIGN
+00AB ; [*0278.0020.0002.00AB] # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+00AC ; [*03A6.0020.0002.00AC] # NOT SIGN
+00AD ; [*0220.0020.0002.00AD] # SOFT HYPHEN
+00AE ; [*02A0.0020.0002.00AE] # REGISTERED SIGN
+00AF ; [*0210.0020.0002.00AF] # MACRON
+00B0 ; [*030A.0020.0002.00B0] # DEGREE SIGN
+00B1 ; [*03A0.0020.0002.00B1] # PLUS-MINUS SIGN
+00B4 ; [*020D.0020.0002.00B4] # ACUTE ACCENT
+00B6 ; [*029D.0020.0002.00B6] # PILCROW SIGN
+00B7 ; [*025F.0020.0002.00B7] # MIDDLE DOT
+00B8 ; [*0219.0020.0002.00B8] # CEDILLA
+00BB ; [*0279.0020.0002.00BB] # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+00BF ; [*024F.0020.0002.00BF] # INVERTED QUESTION MARK
+00D7 ; [*03A2.0020.0002.00D7] # MULTIPLICATION SIGN
+00F7 ; [*03A1.0020.0002.00F7] # DIVISION SIGN
+2000 ; [*0209.0020.0004.2000] # EN QUAD; QQK
+2001 ; [*0209.0020.0004.2001] # EM QUAD; QQK
+2002 ; [*0209.0020.0004.2002] # EN SPACE; QQK
+2003 ; [*0209.0020.0004.2003] # EM SPACE; QQK
+2004 ; [*0209.0020.0004.2004] # THREE-PER-EM SPACE; QQK
+2005 ; [*0209.0020.0004.2005] # FOUR-PER-EM SPACE; QQK
+2006 ; [*0209.0020.0004.2006] # SIX-PER-EM SPACE; QQK
+2007 ; [*0209.0020.001B.2007] # FIGURE SPACE; QQK
+2008 ; [*0209.0020.0004.2008] # PUNCTUATION SPACE; QQK
+2009 ; [*0209.0020.0004.2009] # THIN SPACE; QQK
+200A ; [*0209.0020.0004.200A] # HAIR SPACE; QQK
+2010 ; [*0225.0020.0002.2010] # HYPHEN
+2011 ; [*0225.0020.001B.2011] # NON-BREAKING HYPHEN; QQK
+2012 ; [*0226.0020.0002.2012] # FIGURE DASH
+2013 ; [*0227.0020.0002.2013] # EN DASH
+2014 ; [*0228.0020.0002.2014] # EM DASH
+2015 ; [*0229.0020.0002.2015] # HORIZONTAL BAR
+2016 ; [*03A9.0020.0002.2016] # DOUBLE VERTICAL LINE
+2017 ; [*021C.0020.0002.2017] # DOUBLE LOW LINE
+2018 ; [*026A.0020.0002.2018] # LEFT SINGLE QUOTATION MARK
+2019 ; [*026B.0020.0002.2019] # RIGHT SINGLE QUOTATION MARK
+201A ; [*026C.0020.0002.201A] # SINGLE LOW-9 QUOTATION MARK
+201B ; [*026D.0020.0002.201B] # SINGLE HIGH-REVERSED-9 QUOTATION MARK
+201C ; [*0271.0020.0002.201C] # LEFT DOUBLE QUOTATION MARK
+201D ; [*0272.0020.0002.201D] # RIGHT DOUBLE QUOTATION MARK
+201E ; [*0273.0020.0002.201E] # DOUBLE LOW-9 QUOTATION MARK
+201F ; [*0274.0020.0002.201F] # DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+2020 ; [*02AE.0020.0002.2020] # DAGGER
+2021 ; [*02AF.0020.0002.2021] # DOUBLE DAGGER
+2022 ; [*02B0.0020.0002.2022] # BULLET
+2023 ; [*02B1.0020.0002.2023] # TRIANGULAR BULLET
+2024 ; [*0255.0020.0004.2024] # ONE DOT LEADER; QQK
+2025 ; [*0255.0020.0004.2025][*0255.0020.0004.2025] # TWO DOT LEADER; QQKN
+2026 ; [*0255.0020.0004.2026][*0255.0020.0004.2026][*0255.0020.001F.2026] # HORIZONTAL ELLIPSIS; QQKN
+2027 ; [*02B2.0020.0002.2027] # HYPHENATION POINT
+2028 ; [*0207.0020.0002.2028] # LINE SEPARATOR
+2029 ; [*0208.0020.0002.2029] # PARAGRAPH SEPARATOR
+202F ; [*0209.0020.001B.202F] # NARROW NO-BREAK SPACE; QQK
+2030 ; [*02AC.0020.0002.2030] # PER MILLE SIGN
+2031 ; [*02AD.0020.0002.2031] # PER TEN THOUSAND SIGN
+2032 ; [*02B6.0020.0002.2032] # PRIME
+2033 ; [*02B6.0020.0004.2033][*02B6.0020.0004.2033] # DOUBLE PRIME; QQKN
+2034 ; [*02B6.0020.0004.2034][*02B6.0020.0004.2034][*02B6.0020.001F.2034] # TRIPLE PRIME; QQKN
+2035 ; [*02B7.0020.0002.2035] # REVERSED PRIME
+2036 ; [*02B7.0020.0004.2036][*02B7.0020.0004.2036] # REVERSED DOUBLE PRIME; QQKN
+2037 ; [*02B7.0020.0004.2037][*02B7.0020.0004.2037][*02B7.0020.001F.2037] # REVERSED TRIPLE PRIME; QQKN
+2038 ; [*02B9.0020.0002.2038] # CARET
+2039 ; [*026E.0020.0002.2039] # SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+203A ; [*026F.0020.0002.203A] # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+203B ; [*02BA.0020.0002.203B] # REFERENCE MARK
+203C ; [*024B.0020.0004.203C][*024B.0020.0004.203C] # DOUBLE EXCLAMATION MARK; QQKN
+203D ; [*0254.0020.0002.203D] # INTERROBANG
+203E ; [*0211.0020.0002.203E] # OVERLINE
+203F ; [*02BB.0020.0002.203F] # UNDERTIE
+2040 ; [*02BC.0020.0002.2040] # CHARACTER TIE
+2041 ; [*02BD.0020.0002.2041] # CARET INSERTION POINT
+2042 ; [*02BE.0020.0002.2042] # ASTERISM
+2043 ; [*02B3.0020.0002.2043] # HYPHEN BULLET
+2044 ; [*02A5.0020.0002.2044] # FRACTION SLASH
+2045 ; [*0286.0020.0002.2045] # LEFT SQUARE BRACKET WITH QUILL
+2046 ; [*0287.0020.0002.2046] # RIGHT SQUARE BRACKET WITH QUILL
+2048 ; [*024E.0020.0004.2048][*024B.0020.0004.2048] # QUESTION EXCLAMATION MARK; QQKN
+2049 ; [*024B.0020.0004.2049][*024E.0020.0004.2049] # EXCLAMATION QUESTION MARK; QQKN
+204A ; [*02A8.0020.0002.204A] # TIRONIAN SIGN ET
+204B ; [*029E.0020.0002.204B] # REVERSED PILCROW SIGN
+204C ; [*02B4.0020.0002.204C] # BLACK LEFTWARDS BULLET
+204D ; [*02B5.0020.0002.204D] # BLACK RIGHTWARDS BULLET
+309B ; [*021E.0020.0002.309B] # KATAKANA-HIRAGANA VOICED SOUND MARK
+309C ; [*021F.0020.0002.309C] # KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+30FB ; [*022C.0020.0002.30FB] # KATAKANA MIDDLE DOT
+0332 ; [.0000.0021.0002.0332] # COMBINING LOW LINE
+0313 ; [.0000.0022.0002.0313] # COMBINING COMMA ABOVE
+0343 ; [.0000.0022.0002.0343] # COMBINING GREEK KORONIS; QQC
+0314 ; [.0000.002A.0002.0314] # COMBINING REVERSED COMMA ABOVE
+0301 ; [.0000.0032.0002.0301] # COMBINING ACUTE ACCENT
+0341 ; [.0000.0032.0002.0341] # COMBINING ACUTE TONE MARK; QQC
+0300 ; [.0000.0035.0002.0300] # COMBINING GRAVE ACCENT
+0340 ; [.0000.0035.0002.0340] # COMBINING GRAVE TONE MARK; QQC
+0306 ; [.0000.0037.0002.0306] # COMBINING BREVE
+0302 ; [.0000.003C.0002.0302] # COMBINING CIRCUMFLEX ACCENT
+030C ; [.0000.0041.0002.030C] # COMBINING CARON
+030A ; [.0000.0043.0002.030A] # COMBINING RING ABOVE
+0342 ; [.0000.0045.0002.0342] # COMBINING GREEK PERISPOMENI
+0308 ; [.0000.0047.0002.0308] # COMBINING DIAERESIS
+0344 ; [.0000.0047.0002.0308][.0000.0032.0002.0301] # COMBINING GREEK DIALYTIKA TONOS; QQCM
+030B ; [.0000.004D.0002.030B] # COMBINING DOUBLE ACUTE ACCENT
+0303 ; [.0000.004E.0002.0303] # COMBINING TILDE
+0307 ; [.0000.0052.0002.0307] # COMBINING DOT ABOVE
+0338 ; [.0000.0054.0002.0338] # COMBINING LONG SOLIDUS OVERLAY
+0327 ; [.0000.0055.0002.0327] # COMBINING CEDILLA
+0328 ; [.0000.0058.0002.0328] # COMBINING OGONEK
+0304 ; [.0000.005A.0002.0304] # COMBINING MACRON
+0305 ; [.0000.005E.0002.0305] # COMBINING OVERLINE
+0309 ; [.0000.005F.0002.0309] # COMBINING HOOK ABOVE
+030D ; [.0000.0060.0002.030D] # COMBINING VERTICAL LINE ABOVE
+030E ; [.0000.0061.0002.030E] # COMBINING DOUBLE VERTICAL LINE ABOVE
+030F ; [.0000.0062.0002.030F] # COMBINING DOUBLE GRAVE ACCENT
+0310 ; [.0000.0063.0002.0310] # COMBINING CANDRABINDU
+0311 ; [.0000.0064.0002.0311] # COMBINING INVERTED BREVE
+0312 ; [.0000.0065.0002.0312] # COMBINING TURNED COMMA ABOVE
+0315 ; [.0000.0066.0002.0315] # COMBINING COMMA ABOVE RIGHT
+0316 ; [.0000.0067.0002.0316] # COMBINING GRAVE ACCENT BELOW
+0317 ; [.0000.0068.0002.0317] # COMBINING ACUTE ACCENT BELOW
+0318 ; [.0000.0069.0002.0318] # COMBINING LEFT TACK BELOW
+0319 ; [.0000.006A.0002.0319] # COMBINING RIGHT TACK BELOW
+031A ; [.0000.006B.0002.031A] # COMBINING LEFT ANGLE ABOVE
+031B ; [.0000.006C.0002.031B] # COMBINING HORN
+031C ; [.0000.0072.0002.031C] # COMBINING LEFT HALF RING BELOW
+031D ; [.0000.0073.0002.031D] # COMBINING UP TACK BELOW
+031E ; [.0000.0074.0002.031E] # COMBINING DOWN TACK BELOW
+031F ; [.0000.0075.0002.031F] # COMBINING PLUS SIGN BELOW
+0320 ; [.0000.0076.0002.0320] # COMBINING MINUS SIGN BELOW
+0321 ; [.0000.0077.0002.0321] # COMBINING PALATALIZED HOOK BELOW
+0322 ; [.0000.0078.0002.0322] # COMBINING RETROFLEX HOOK BELOW
+0323 ; [.0000.0079.0002.0323] # COMBINING DOT BELOW
+0324 ; [.0000.007E.0002.0324] # COMBINING DIAERESIS BELOW
+0325 ; [.0000.007F.0002.0325] # COMBINING RING BELOW
+0326 ; [.0000.0080.0002.0326] # COMBINING COMMA BELOW
+0329 ; [.0000.0081.0002.0329] # COMBINING VERTICAL LINE BELOW
+032A ; [.0000.0082.0002.032A] # COMBINING BRIDGE BELOW
+032B ; [.0000.0083.0002.032B] # COMBINING INVERTED DOUBLE ARCH BELOW
+032C ; [.0000.0084.0002.032C] # COMBINING CARON BELOW
+032D ; [.0000.0085.0002.032D] # COMBINING CIRCUMFLEX ACCENT BELOW
+032E ; [.0000.0086.0002.032E] # COMBINING BREVE BELOW
+032F ; [.0000.0087.0002.032F] # COMBINING INVERTED BREVE BELOW
+0330 ; [.0000.0088.0002.0330] # COMBINING TILDE BELOW
+0331 ; [.0000.0089.0002.0331] # COMBINING MACRON BELOW
+0333 ; [.0000.008A.0002.0333] # COMBINING DOUBLE LOW LINE
+0334 ; [.0000.008B.0002.0334] # COMBINING TILDE OVERLAY
+0335 ; [.0000.008C.0002.0335] # COMBINING SHORT STROKE OVERLAY
+0336 ; [.0000.008D.0002.0336] # COMBINING LONG STROKE OVERLAY
+0337 ; [.0000.008E.0002.0337] # COMBINING SHORT SOLIDUS OVERLAY
+0339 ; [.0000.008F.0002.0339] # COMBINING RIGHT HALF RING BELOW
+033A ; [.0000.0090.0002.033A] # COMBINING INVERTED BRIDGE BELOW
+033B ; [.0000.0091.0002.033B] # COMBINING SQUARE BELOW
+033C ; [.0000.0092.0002.033C] # COMBINING SEAGULL BELOW
+033D ; [.0000.0093.0002.033D] # COMBINING X ABOVE
+033E ; [.0000.0094.0002.033E] # COMBINING VERTICAL TILDE
+033F ; [.0000.0095.0002.033F] # COMBINING DOUBLE OVERLINE
+0345 ; [.0000.0096.0002.0345] # COMBINING GREEK YPOGEGRAMMENI
+0346 ; [.0000.0097.0002.0346] # COMBINING BRIDGE ABOVE
+0347 ; [.0000.0098.0002.0347] # COMBINING EQUALS SIGN BELOW
+0348 ; [.0000.0099.0002.0348] # COMBINING DOUBLE VERTICAL LINE BELOW
+0349 ; [.0000.009A.0002.0349] # COMBINING LEFT ANGLE BELOW
+034A ; [.0000.009B.0002.034A] # COMBINING NOT TILDE ABOVE
+034B ; [.0000.009C.0002.034B] # COMBINING HOMOTHETIC ABOVE
+034C ; [.0000.009D.0002.034C] # COMBINING ALMOST EQUAL TO ABOVE
+034D ; [.0000.009E.0002.034D] # COMBINING LEFT RIGHT ARROW BELOW
+034E ; [.0000.009F.0002.034E] # COMBINING UPWARDS ARROW BELOW
+0360 ; [.0000.00A0.0002.0360] # COMBINING DOUBLE TILDE
+0361 ; [.0000.00A1.0002.0361] # COMBINING DOUBLE INVERTED BREVE
+0362 ; [.0000.00A2.0002.0362] # COMBINING DOUBLE RIGHTWARDS ARROW BELOW
+3099 ; [.0000.013D.0002.3099] # COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
+309A ; [.0000.013E.0002.309A] # COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+309D ; [.09DB.0020.0002.309D] # HIRAGANA ITERATION MARK
+309E ; [.09DB.0020.0002.309D][.0000.013D.0002.3099] # HIRAGANA VOICED ITERATION MARK; QQCM
+30FC ; [.09DC.0020.0002.30FC] # KATAKANA-HIRAGANA PROLONGED SOUND MARK
+30FD ; [.09DD.0020.0002.30FD] # KATAKANA ITERATION MARK
+30FE ; [.09DD.0020.0002.30FD][.0000.013D.0002.3099] # KATAKANA VOICED ITERATION MARK; QQCM
+00A4 ; [.09DE.0020.0002.00A4] # CURRENCY SIGN
+00A2 ; [.09DF.0020.0002.00A2] # CENT SIGN
+0024 ; [.09E0.0020.0002.0024] # DOLLAR SIGN
+00A3 ; [.09E1.0020.0002.00A3] # POUND SIGN
+00A5 ; [.09E2.0020.0002.00A5] # YEN SIGN
+0030 ; [.0A0B.0020.0002.0030] # DIGIT ZERO
+0031 ; [.0A0C.0020.0002.0031] # DIGIT ONE
+00B9 ; [.0A0C.0020.0014.00B9] # SUPERSCRIPT ONE; QQK
+00BD ; [.0A0C.0020.001E.00BD][*02A5.0020.001E.00BD][.0A0D.0020.001F.00BD] # VULGAR FRACTION ONE HALF; QQKN
+00BC ; [.0A0C.0020.001E.00BC][*02A5.0020.001E.00BC][.0A0F.0020.001F.00BC] # VULGAR FRACTION ONE QUARTER; QQKN
+0032 ; [.0A0D.0020.0002.0032] # DIGIT TWO
+00B2 ; [.0A0D.0020.0014.00B2] # SUPERSCRIPT TWO; QQK
+0033 ; [.0A0E.0020.0002.0033] # DIGIT THREE
+00B3 ; [.0A0E.0020.0014.00B3] # SUPERSCRIPT THREE; QQK
+00BE ; [.0A0E.0020.001E.00BE][*02A5.0020.001E.00BE][.0A0F.0020.001F.00BE] # VULGAR FRACTION THREE QUARTERS; QQKN
+0034 ; [.0A0F.0020.0002.0034] # DIGIT FOUR
+0035 ; [.0A10.0020.0002.0035] # DIGIT FIVE
+0036 ; [.0A11.0020.0002.0036] # DIGIT SIX
+0037 ; [.0A12.0020.0002.0037] # DIGIT SEVEN
+0038 ; [.0A13.0020.0002.0038] # DIGIT EIGHT
+0039 ; [.0A14.0020.0002.0039] # DIGIT NINE
+0061 ; [.0A15.0020.0002.0061] # LATIN SMALL LETTER A
+0041 ; [.0A15.0020.0008.0041] # LATIN CAPITAL LETTER A
+00AA ; [.0A15.0020.0014.00AA] # FEMININE ORDINAL INDICATOR; QQK
+00E1 ; [.0A15.0020.0002.0061][.0000.0032.0002.0301] # LATIN SMALL LETTER A WITH ACUTE; QQCM
+00C1 ; [.0A15.0020.0008.0041][.0000.0032.0002.0301] # LATIN CAPITAL LETTER A WITH ACUTE; QQCM
+00E0 ; [.0A15.0020.0002.0061][.0000.0035.0002.0300] # LATIN SMALL LETTER A WITH GRAVE; QQCM
+00C0 ; [.0A15.0020.0008.0041][.0000.0035.0002.0300] # LATIN CAPITAL LETTER A WITH GRAVE; QQCM
+00E2 ; [.0A15.0020.0002.0061][.0000.003C.0002.0302] # LATIN SMALL LETTER A WITH CIRCUMFLEX; QQCM
+00C2 ; [.0A15.0020.0008.0041][.0000.003C.0002.0302] # LATIN CAPITAL LETTER A WITH CIRCUMFLEX; QQCM
+00E5 ; [.0A15.0020.0002.0061][.0000.0043.0002.030A] # LATIN SMALL LETTER A WITH RING ABOVE; QQCM
+00C5 ; [.0A15.0020.0008.0041][.0000.0043.0002.030A] # LATIN CAPITAL LETTER A WITH RING ABOVE; QQCM
+00E4 ; [.0A15.0020.0002.0061][.0000.0047.0002.0308] # LATIN SMALL LETTER A WITH DIAERESIS; QQCM
+00C4 ; [.0A15.0020.0008.0041][.0000.0047.0002.0308] # LATIN CAPITAL LETTER A WITH DIAERESIS; QQCM
+00E3 ; [.0A15.0020.0002.0061][.0000.004E.0002.0303] # LATIN SMALL LETTER A WITH TILDE; QQCM
+00C3 ; [.0A15.0020.0008.0041][.0000.004E.0002.0303] # LATIN CAPITAL LETTER A WITH TILDE; QQCM
+00E6 ; [.0A19.0020.0002.00E6] # LATIN SMALL LETTER AE
+00C6 ; [.0A19.0020.0008.00C6] # LATIN CAPITAL LETTER AE
+0062 ; [.0A29.0020.0002.0062] # LATIN SMALL LETTER B
+0042 ; [.0A29.0020.0008.0042] # LATIN CAPITAL LETTER B
+0063 ; [.0A3D.0020.0002.0063] # LATIN SMALL LETTER C
+0043 ; [.0A3D.0020.0008.0043] # LATIN CAPITAL LETTER C
+00E7 ; [.0A3D.0020.0002.0063][.0000.0055.0002.0327] # LATIN SMALL LETTER C WITH CEDILLA; QQCM
+00C7 ; [.0A3D.0020.0008.0043][.0000.0055.0002.0327] # LATIN CAPITAL LETTER C WITH CEDILLA; QQCM
+0064 ; [.0A49.0020.0002.0064] # LATIN SMALL LETTER D
+0044 ; [.0A49.0020.0008.0044] # LATIN CAPITAL LETTER D
+00F0 ; [.0A5D.0020.0002.00F0] # LATIN SMALL LETTER ETH
+00D0 ; [.0A5D.0020.0008.00D0] # LATIN CAPITAL LETTER ETH
+0065 ; [.0A65.0020.0002.0065] # LATIN SMALL LETTER E
+0045 ; [.0A65.0020.0008.0045] # LATIN CAPITAL LETTER E
+00E9 ; [.0A65.0020.0002.0065][.0000.0032.0002.0301] # LATIN SMALL LETTER E WITH ACUTE; QQCM
+00C9 ; [.0A65.0020.0008.0045][.0000.0032.0002.0301] # LATIN CAPITAL LETTER E WITH ACUTE; QQCM
+00E8 ; [.0A65.0020.0002.0065][.0000.0035.0002.0300] # LATIN SMALL LETTER E WITH GRAVE; QQCM
+00C8 ; [.0A65.0020.0008.0045][.0000.0035.0002.0300] # LATIN CAPITAL LETTER E WITH GRAVE; QQCM
+00EA ; [.0A65.0020.0002.0065][.0000.003C.0002.0302] # LATIN SMALL LETTER E WITH CIRCUMFLEX; QQCM
+00CA ; [.0A65.0020.0008.0045][.0000.003C.0002.0302] # LATIN CAPITAL LETTER E WITH CIRCUMFLEX; QQCM
+00EB ; [.0A65.0020.0002.0065][.0000.0047.0002.0308] # LATIN SMALL LETTER E WITH DIAERESIS; QQCM
+00CB ; [.0A65.0020.0008.0045][.0000.0047.0002.0308] # LATIN CAPITAL LETTER E WITH DIAERESIS; QQCM
+0066 ; [.0A91.0020.0002.0066] # LATIN SMALL LETTER F
+0046 ; [.0A91.0020.0008.0046] # LATIN CAPITAL LETTER F
+0067 ; [.0A99.0020.0002.0067] # LATIN SMALL LETTER G
+0047 ; [.0A99.0020.0008.0047] # LATIN CAPITAL LETTER G
+0068 ; [.0AB9.0020.0002.0068] # LATIN SMALL LETTER H
+0048 ; [.0AB9.0020.0008.0048] # LATIN CAPITAL LETTER H
+0069 ; [.0AD3.0020.0002.0069] # LATIN SMALL LETTER I
+0049 ; [.0AD3.0020.0008.0049] # LATIN CAPITAL LETTER I
+00ED ; [.0AD3.0020.0002.0069][.0000.0032.0002.0301] # LATIN SMALL LETTER I WITH ACUTE; QQCM
+00CD ; [.0AD3.0020.0008.0049][.0000.0032.0002.0301] # LATIN CAPITAL LETTER I WITH ACUTE; QQCM
+00EC ; [.0AD3.0020.0002.0069][.0000.0035.0002.0300] # LATIN SMALL LETTER I WITH GRAVE; QQCM
+00CC ; [.0AD3.0020.0008.0049][.0000.0035.0002.0300] # LATIN CAPITAL LETTER I WITH GRAVE; QQCM
+00EE ; [.0AD3.0020.0002.0069][.0000.003C.0002.0302] # LATIN SMALL LETTER I WITH CIRCUMFLEX; QQCM
+00CE ; [.0AD3.0020.0008.0049][.0000.003C.0002.0302] # LATIN CAPITAL LETTER I WITH CIRCUMFLEX; QQCM
+00EF ; [.0AD3.0020.0002.0069][.0000.0047.0002.0308] # LATIN SMALL LETTER I WITH DIAERESIS; QQCM
+00CF ; [.0AD3.0020.0008.0049][.0000.0047.0002.0308] # LATIN CAPITAL LETTER I WITH DIAERESIS; QQCM
+006A ; [.0AE7.0020.0002.006A] # LATIN SMALL LETTER J
+004A ; [.0AE7.0020.0008.004A] # LATIN CAPITAL LETTER J
+006B ; [.0AF7.0020.0002.006B] # LATIN SMALL LETTER K
+004B ; [.0AF7.0020.0008.004B] # LATIN CAPITAL LETTER K
+006C ; [.0B03.0020.0002.006C] # LATIN SMALL LETTER L
+004C ; [.0B03.0020.0008.004C] # LATIN CAPITAL LETTER L
+006D ; [.0B2B.0020.0002.006D] # LATIN SMALL LETTER M
+004D ; [.0B2B.0020.0008.004D] # LATIN CAPITAL LETTER M
+006E ; [.0B33.0020.0002.006E] # LATIN SMALL LETTER N
+004E ; [.0B33.0020.0008.004E] # LATIN CAPITAL LETTER N
+00F1 ; [.0B33.0020.0002.006E][.0000.004E.0002.0303] # LATIN SMALL LETTER N WITH TILDE; QQCM
+00D1 ; [.0B33.0020.0008.004E][.0000.004E.0002.0303] # LATIN CAPITAL LETTER N WITH TILDE; QQCM
+006F ; [.0B4B.0020.0002.006F] # LATIN SMALL LETTER O
+004F ; [.0B4B.0020.0008.004F] # LATIN CAPITAL LETTER O
+00BA ; [.0B4B.0020.0014.00BA] # MASCULINE ORDINAL INDICATOR; QQK
+00F3 ; [.0B4B.0020.0002.006F][.0000.0032.0002.0301] # LATIN SMALL LETTER O WITH ACUTE; QQCM
+00D3 ; [.0B4B.0020.0008.004F][.0000.0032.0002.0301] # LATIN CAPITAL LETTER O WITH ACUTE; QQCM
+00F2 ; [.0B4B.0020.0002.006F][.0000.0035.0002.0300] # LATIN SMALL LETTER O WITH GRAVE; QQCM
+00D2 ; [.0B4B.0020.0008.004F][.0000.0035.0002.0300] # LATIN CAPITAL LETTER O WITH GRAVE; QQCM
+00F4 ; [.0B4B.0020.0002.006F][.0000.003C.0002.0302] # LATIN SMALL LETTER O WITH CIRCUMFLEX; QQCM
+00D4 ; [.0B4B.0020.0008.004F][.0000.003C.0002.0302] # LATIN CAPITAL LETTER O WITH CIRCUMFLEX; QQCM
+00F6 ; [.0B4B.0020.0002.006F][.0000.0047.0002.0308] # LATIN SMALL LETTER O WITH DIAERESIS; QQCM
+00D6 ; [.0B4B.0020.0008.004F][.0000.0047.0002.0308] # LATIN CAPITAL LETTER O WITH DIAERESIS; QQCM
+00F5 ; [.0B4B.0020.0002.006F][.0000.004E.0002.0303] # LATIN SMALL LETTER O WITH TILDE; QQCM
+00D5 ; [.0B4B.0020.0008.004F][.0000.004E.0002.0303] # LATIN CAPITAL LETTER O WITH TILDE; QQCM
+00F8 ; [.0B53.0020.0002.00F8] # LATIN SMALL LETTER O WITH STROKE
+00D8 ; [.0B53.0020.0008.00D8] # LATIN CAPITAL LETTER O WITH STROKE
+0070 ; [.0B67.0020.0002.0070] # LATIN SMALL LETTER P
+0050 ; [.0B67.0020.0008.0050] # LATIN CAPITAL LETTER P
+0071 ; [.0B73.0020.0002.0071] # LATIN SMALL LETTER Q
+0051 ; [.0B73.0020.0008.0051] # LATIN CAPITAL LETTER Q
+0072 ; [.0B7F.0020.0002.0072] # LATIN SMALL LETTER R
+0052 ; [.0B7F.0020.0008.0052] # LATIN CAPITAL LETTER R
+0073 ; [.0BA7.0020.0002.0073] # LATIN SMALL LETTER S
+0053 ; [.0BA7.0020.0008.0053] # LATIN CAPITAL LETTER S
+00DF ; [.0BA7.0020.0004.00DF][.0000.0153.0004.00DF][.0BA7.0020.001F.00DF] # LATIN SMALL LETTER SHARP S; QQKN
+0074 ; [.0BBF.0020.0002.0074] # LATIN SMALL LETTER T
+0054 ; [.0BBF.0020.0008.0054] # LATIN CAPITAL LETTER T
+0075 ; [.0BD7.0020.0002.0075] # LATIN SMALL LETTER U
+0055 ; [.0BD7.0020.0008.0055] # LATIN CAPITAL LETTER U
+00FA ; [.0BD7.0020.0002.0075][.0000.0032.0002.0301] # LATIN SMALL LETTER U WITH ACUTE; QQCM
+00DA ; [.0BD7.0020.0008.0055][.0000.0032.0002.0301] # LATIN CAPITAL LETTER U WITH ACUTE; QQCM
+00F9 ; [.0BD7.0020.0002.0075][.0000.0035.0002.0300] # LATIN SMALL LETTER U WITH GRAVE; QQCM
+00D9 ; [.0BD7.0020.0008.0055][.0000.0035.0002.0300] # LATIN CAPITAL LETTER U WITH GRAVE; QQCM
+00FB ; [.0BD7.0020.0002.0075][.0000.003C.0002.0302] # LATIN SMALL LETTER U WITH CIRCUMFLEX; QQCM
+00DB ; [.0BD7.0020.0008.0055][.0000.003C.0002.0302] # LATIN CAPITAL LETTER U WITH CIRCUMFLEX; QQCM
+00FC ; [.0BD7.0020.0002.0075][.0000.0047.0002.0308] # LATIN SMALL LETTER U WITH DIAERESIS; QQCM
+00DC ; [.0BD7.0020.0008.0055][.0000.0047.0002.0308] # LATIN CAPITAL LETTER U WITH DIAERESIS; QQCM
+0076 ; [.0BEF.0020.0002.0076] # LATIN SMALL LETTER V
+0056 ; [.0BEF.0020.0008.0056] # LATIN CAPITAL LETTER V
+0077 ; [.0BFB.0020.0002.0077] # LATIN SMALL LETTER W
+0057 ; [.0BFB.0020.0008.0057] # LATIN CAPITAL LETTER W
+0078 ; [.0C03.0020.0002.0078] # LATIN SMALL LETTER X
+0058 ; [.0C03.0020.0008.0058] # LATIN CAPITAL LETTER X
+0079 ; [.0C07.0020.0002.0079] # LATIN SMALL LETTER Y
+0059 ; [.0C07.0020.0008.0059] # LATIN CAPITAL LETTER Y
+00FD ; [.0C07.0020.0002.0079][.0000.0032.0002.0301] # LATIN SMALL LETTER Y WITH ACUTE; QQCM
+00DD ; [.0C07.0020.0008.0059][.0000.0032.0002.0301] # LATIN CAPITAL LETTER Y WITH ACUTE; QQCM
+00FF ; [.0C07.0020.0002.0079][.0000.0047.0002.0308] # LATIN SMALL LETTER Y WITH DIAERESIS; QQCM
+007A ; [.0C13.0020.0002.007A] # LATIN SMALL LETTER Z
+005A ; [.0C13.0020.0008.005A] # LATIN CAPITAL LETTER Z
+00FE ; [.0C3B.0020.0002.00FE] # LATIN SMALL LETTER THORN
+00DE ; [.0C3B.0020.0008.00DE] # LATIN CAPITAL LETTER THORN
+00B5 ; [.0C9F.0020.0004.00B5] # MICRO SIGN; QQK
+1100 ; [.1831.0020.0002.1100] # HANGUL CHOSEONG KIYEOK
+1101 ; [.1832.0020.0002.1101] # HANGUL CHOSEONG SSANGKIYEOK
+1102 ; [.1833.0020.0002.1102] # HANGUL CHOSEONG NIEUN
+1103 ; [.1834.0020.0002.1103] # HANGUL CHOSEONG TIKEUT
+1104 ; [.1835.0020.0002.1104] # HANGUL CHOSEONG SSANGTIKEUT
+1105 ; [.1836.0020.0002.1105] # HANGUL CHOSEONG RIEUL
+1106 ; [.1837.0020.0002.1106] # HANGUL CHOSEONG MIEUM
+1107 ; [.1838.0020.0002.1107] # HANGUL CHOSEONG PIEUP
+1108 ; [.1839.0020.0002.1108] # HANGUL CHOSEONG SSANGPIEUP
+1109 ; [.183A.0020.0002.1109] # HANGUL CHOSEONG SIOS
+110A ; [.183B.0020.0002.110A] # HANGUL CHOSEONG SSANGSIOS
+110B ; [.183C.0020.0002.110B] # HANGUL CHOSEONG IEUNG
+110C ; [.183D.0020.0002.110C] # HANGUL CHOSEONG CIEUC
+110D ; [.183E.0020.0002.110D] # HANGUL CHOSEONG SSANGCIEUC
+110E ; [.183F.0020.0002.110E] # HANGUL CHOSEONG CHIEUCH
+110F ; [.1840.0020.0002.110F] # HANGUL CHOSEONG KHIEUKH
+1110 ; [.1841.0020.0002.1110] # HANGUL CHOSEONG THIEUTH
+1111 ; [.1842.0020.0002.1111] # HANGUL CHOSEONG PHIEUPH
+1112 ; [.1843.0020.0002.1112] # HANGUL CHOSEONG HIEUH
+1113 ; [.1844.0020.0002.1113] # HANGUL CHOSEONG NIEUN-KIYEOK
+1114 ; [.1845.0020.0002.1114] # HANGUL CHOSEONG SSANGNIEUN
+1115 ; [.1846.0020.0002.1115] # HANGUL CHOSEONG NIEUN-TIKEUT
+1116 ; [.1847.0020.0002.1116] # HANGUL CHOSEONG NIEUN-PIEUP
+1117 ; [.1848.0020.0002.1117] # HANGUL CHOSEONG TIKEUT-KIYEOK
+1118 ; [.1849.0020.0002.1118] # HANGUL CHOSEONG RIEUL-NIEUN
+1119 ; [.184A.0020.0002.1119] # HANGUL CHOSEONG SSANGRIEUL
+111A ; [.184B.0020.0002.111A] # HANGUL CHOSEONG RIEUL-HIEUH
+111B ; [.184C.0020.0002.111B] # HANGUL CHOSEONG KAPYEOUNRIEUL
+111C ; [.184D.0020.0002.111C] # HANGUL CHOSEONG MIEUM-PIEUP
+111D ; [.184E.0020.0002.111D] # HANGUL CHOSEONG KAPYEOUNMIEUM
+111E ; [.184F.0020.0002.111E] # HANGUL CHOSEONG PIEUP-KIYEOK
+111F ; [.1850.0020.0002.111F] # HANGUL CHOSEONG PIEUP-NIEUN
+1120 ; [.1851.0020.0002.1120] # HANGUL CHOSEONG PIEUP-TIKEUT
+1121 ; [.1852.0020.0002.1121] # HANGUL CHOSEONG PIEUP-SIOS
+1122 ; [.1853.0020.0002.1122] # HANGUL CHOSEONG PIEUP-SIOS-KIYEOK
+1123 ; [.1854.0020.0002.1123] # HANGUL CHOSEONG PIEUP-SIOS-TIKEUT
+1124 ; [.1855.0020.0002.1124] # HANGUL CHOSEONG PIEUP-SIOS-PIEUP
+1125 ; [.1856.0020.0002.1125] # HANGUL CHOSEONG PIEUP-SSANGSIOS
+1126 ; [.1857.0020.0002.1126] # HANGUL CHOSEONG PIEUP-SIOS-CIEUC
+1127 ; [.1858.0020.0002.1127] # HANGUL CHOSEONG PIEUP-CIEUC
+1128 ; [.1859.0020.0002.1128] # HANGUL CHOSEONG PIEUP-CHIEUCH
+1129 ; [.185A.0020.0002.1129] # HANGUL CHOSEONG PIEUP-THIEUTH
+112A ; [.185B.0020.0002.112A] # HANGUL CHOSEONG PIEUP-PHIEUPH
+112B ; [.185C.0020.0002.112B] # HANGUL CHOSEONG KAPYEOUNPIEUP
+112C ; [.185D.0020.0002.112C] # HANGUL CHOSEONG KAPYEOUNSSANGPIEUP
+112D ; [.185E.0020.0002.112D] # HANGUL CHOSEONG SIOS-KIYEOK
+112E ; [.185F.0020.0002.112E] # HANGUL CHOSEONG SIOS-NIEUN
+112F ; [.1860.0020.0002.112F] # HANGUL CHOSEONG SIOS-TIKEUT
+1130 ; [.1861.0020.0002.1130] # HANGUL CHOSEONG SIOS-RIEUL
+1131 ; [.1862.0020.0002.1131] # HANGUL CHOSEONG SIOS-MIEUM
+1132 ; [.1863.0020.0002.1132] # HANGUL CHOSEONG SIOS-PIEUP
+1133 ; [.1864.0020.0002.1133] # HANGUL CHOSEONG SIOS-PIEUP-KIYEOK
+1134 ; [.1865.0020.0002.1134] # HANGUL CHOSEONG SIOS-SSANGSIOS
+1135 ; [.1866.0020.0002.1135] # HANGUL CHOSEONG SIOS-IEUNG
+1136 ; [.1867.0020.0002.1136] # HANGUL CHOSEONG SIOS-CIEUC
+1137 ; [.1868.0020.0002.1137] # HANGUL CHOSEONG SIOS-CHIEUCH
+1138 ; [.1869.0020.0002.1138] # HANGUL CHOSEONG SIOS-KHIEUKH
+1139 ; [.186A.0020.0002.1139] # HANGUL CHOSEONG SIOS-THIEUTH
+113A ; [.186B.0020.0002.113A] # HANGUL CHOSEONG SIOS-PHIEUPH
+113B ; [.186C.0020.0002.113B] # HANGUL CHOSEONG SIOS-HIEUH
+113C ; [.186D.0020.0002.113C] # HANGUL CHOSEONG CHITUEUMSIOS
+113D ; [.186E.0020.0002.113D] # HANGUL CHOSEONG CHITUEUMSSANGSIOS
+113E ; [.186F.0020.0002.113E] # HANGUL CHOSEONG CEONGCHIEUMSIOS
+113F ; [.1870.0020.0002.113F] # HANGUL CHOSEONG CEONGCHIEUMSSANGSIOS
+1140 ; [.1871.0020.0002.1140] # HANGUL CHOSEONG PANSIOS
+1141 ; [.1872.0020.0002.1141] # HANGUL CHOSEONG IEUNG-KIYEOK
+1142 ; [.1873.0020.0002.1142] # HANGUL CHOSEONG IEUNG-TIKEUT
+1143 ; [.1874.0020.0002.1143] # HANGUL CHOSEONG IEUNG-MIEUM
+1144 ; [.1875.0020.0002.1144] # HANGUL CHOSEONG IEUNG-PIEUP
+1145 ; [.1876.0020.0002.1145] # HANGUL CHOSEONG IEUNG-SIOS
+1146 ; [.1877.0020.0002.1146] # HANGUL CHOSEONG IEUNG-PANSIOS
+1147 ; [.1878.0020.0002.1147] # HANGUL CHOSEONG SSANGIEUNG
+1148 ; [.1879.0020.0002.1148] # HANGUL CHOSEONG IEUNG-CIEUC
+1149 ; [.187A.0020.0002.1149] # HANGUL CHOSEONG IEUNG-CHIEUCH
+114A ; [.187B.0020.0002.114A] # HANGUL CHOSEONG IEUNG-THIEUTH
+114B ; [.187C.0020.0002.114B] # HANGUL CHOSEONG IEUNG-PHIEUPH
+114C ; [.187D.0020.0002.114C] # HANGUL CHOSEONG YESIEUNG
+114D ; [.187E.0020.0002.114D] # HANGUL CHOSEONG CIEUC-IEUNG
+114E ; [.187F.0020.0002.114E] # HANGUL CHOSEONG CHITUEUMCIEUC
+114F ; [.1880.0020.0002.114F] # HANGUL CHOSEONG CHITUEUMSSANGCIEUC
+1150 ; [.1881.0020.0002.1150] # HANGUL CHOSEONG CEONGCHIEUMCIEUC
+1151 ; [.1882.0020.0002.1151] # HANGUL CHOSEONG CEONGCHIEUMSSANGCIEUC
+1152 ; [.1883.0020.0002.1152] # HANGUL CHOSEONG CHIEUCH-KHIEUKH
+1153 ; [.1884.0020.0002.1153] # HANGUL CHOSEONG CHIEUCH-HIEUH
+1154 ; [.1885.0020.0002.1154] # HANGUL CHOSEONG CHITUEUMCHIEUCH
+1155 ; [.1886.0020.0002.1155] # HANGUL CHOSEONG CEONGCHIEUMCHIEUCH
+1156 ; [.1887.0020.0002.1156] # HANGUL CHOSEONG PHIEUPH-PIEUP
+1157 ; [.1888.0020.0002.1157] # HANGUL CHOSEONG KAPYEOUNPHIEUPH
+1158 ; [.1889.0020.0002.1158] # HANGUL CHOSEONG SSANGHIEUH
+1159 ; [.188A.0020.0002.1159] # HANGUL CHOSEONG YEORINHIEUH
+115F ; [.188B.0020.0002.115F] # HANGUL CHOSEONG FILLER
+1160 ; [.188C.0020.0002.1160] # HANGUL JUNGSEONG FILLER
+1161 ; [.188D.0020.0002.1161] # HANGUL JUNGSEONG A
+1162 ; [.188E.0020.0002.1162] # HANGUL JUNGSEONG AE
+1163 ; [.188F.0020.0002.1163] # HANGUL JUNGSEONG YA
+1164 ; [.1890.0020.0002.1164] # HANGUL JUNGSEONG YAE
+1165 ; [.1891.0020.0002.1165] # HANGUL JUNGSEONG EO
+1166 ; [.1892.0020.0002.1166] # HANGUL JUNGSEONG E
+1167 ; [.1893.0020.0002.1167] # HANGUL JUNGSEONG YEO
+1168 ; [.1894.0020.0002.1168] # HANGUL JUNGSEONG YE
+1169 ; [.1895.0020.0002.1169] # HANGUL JUNGSEONG O
+116A ; [.1896.0020.0002.116A] # HANGUL JUNGSEONG WA
+116B ; [.1897.0020.0002.116B] # HANGUL JUNGSEONG WAE
+116C ; [.1898.0020.0002.116C] # HANGUL JUNGSEONG OE
+116D ; [.1899.0020.0002.116D] # HANGUL JUNGSEONG YO
+116E ; [.189A.0020.0002.116E] # HANGUL JUNGSEONG U
+116F ; [.189B.0020.0002.116F] # HANGUL JUNGSEONG WEO
+1170 ; [.189C.0020.0002.1170] # HANGUL JUNGSEONG WE
+1171 ; [.189D.0020.0002.1171] # HANGUL JUNGSEONG WI
+1172 ; [.189E.0020.0002.1172] # HANGUL JUNGSEONG YU
+1173 ; [.189F.0020.0002.1173] # HANGUL JUNGSEONG EU
+1174 ; [.18A0.0020.0002.1174] # HANGUL JUNGSEONG YI
+1175 ; [.18A1.0020.0002.1175] # HANGUL JUNGSEONG I
+1176 ; [.18A2.0020.0002.1176] # HANGUL JUNGSEONG A-O
+1177 ; [.18A3.0020.0002.1177] # HANGUL JUNGSEONG A-U
+1178 ; [.18A4.0020.0002.1178] # HANGUL JUNGSEONG YA-O
+1179 ; [.18A5.0020.0002.1179] # HANGUL JUNGSEONG YA-YO
+117A ; [.18A6.0020.0002.117A] # HANGUL JUNGSEONG EO-O
+117B ; [.18A7.0020.0002.117B] # HANGUL JUNGSEONG EO-U
+117C ; [.18A8.0020.0002.117C] # HANGUL JUNGSEONG EO-EU
+117D ; [.18A9.0020.0002.117D] # HANGUL JUNGSEONG YEO-O
+117E ; [.18AA.0020.0002.117E] # HANGUL JUNGSEONG YEO-U
+117F ; [.18AB.0020.0002.117F] # HANGUL JUNGSEONG O-EO
+1180 ; [.18AC.0020.0002.1180] # HANGUL JUNGSEONG O-E
+1181 ; [.18AD.0020.0002.1181] # HANGUL JUNGSEONG O-YE
+1182 ; [.18AE.0020.0002.1182] # HANGUL JUNGSEONG O-O
+1183 ; [.18AF.0020.0002.1183] # HANGUL JUNGSEONG O-U
+1184 ; [.18B0.0020.0002.1184] # HANGUL JUNGSEONG YO-YA
+1185 ; [.18B1.0020.0002.1185] # HANGUL JUNGSEONG YO-YAE
+1186 ; [.18B2.0020.0002.1186] # HANGUL JUNGSEONG YO-YEO
+1187 ; [.18B3.0020.0002.1187] # HANGUL JUNGSEONG YO-O
+1188 ; [.18B4.0020.0002.1188] # HANGUL JUNGSEONG YO-I
+1189 ; [.18B5.0020.0002.1189] # HANGUL JUNGSEONG U-A
+118A ; [.18B6.0020.0002.118A] # HANGUL JUNGSEONG U-AE
+118B ; [.18B7.0020.0002.118B] # HANGUL JUNGSEONG U-EO-EU
+118C ; [.18B8.0020.0002.118C] # HANGUL JUNGSEONG U-YE
+118D ; [.18B9.0020.0002.118D] # HANGUL JUNGSEONG U-U
+118E ; [.18BA.0020.0002.118E] # HANGUL JUNGSEONG YU-A
+118F ; [.18BB.0020.0002.118F] # HANGUL JUNGSEONG YU-EO
+1190 ; [.18BC.0020.0002.1190] # HANGUL JUNGSEONG YU-E
+1191 ; [.18BD.0020.0002.1191] # HANGUL JUNGSEONG YU-YEO
+1192 ; [.18BE.0020.0002.1192] # HANGUL JUNGSEONG YU-YE
+1193 ; [.18BF.0020.0002.1193] # HANGUL JUNGSEONG YU-U
+1194 ; [.18C0.0020.0002.1194] # HANGUL JUNGSEONG YU-I
+1195 ; [.18C1.0020.0002.1195] # HANGUL JUNGSEONG EU-U
+1196 ; [.18C2.0020.0002.1196] # HANGUL JUNGSEONG EU-EU
+1197 ; [.18C3.0020.0002.1197] # HANGUL JUNGSEONG YI-U
+1198 ; [.18C4.0020.0002.1198] # HANGUL JUNGSEONG I-A
+1199 ; [.18C5.0020.0002.1199] # HANGUL JUNGSEONG I-YA
+119A ; [.18C6.0020.0002.119A] # HANGUL JUNGSEONG I-O
+119B ; [.18C7.0020.0002.119B] # HANGUL JUNGSEONG I-U
+119C ; [.18C8.0020.0002.119C] # HANGUL JUNGSEONG I-EU
+119D ; [.18C9.0020.0002.119D] # HANGUL JUNGSEONG I-ARAEA
+119E ; [.18CA.0020.0002.119E] # HANGUL JUNGSEONG ARAEA
+119F ; [.18CB.0020.0002.119F] # HANGUL JUNGSEONG ARAEA-EO
+11A0 ; [.18CC.0020.0002.11A0] # HANGUL JUNGSEONG ARAEA-U
+11A1 ; [.18CD.0020.0002.11A1] # HANGUL JUNGSEONG ARAEA-I
+11A2 ; [.18CE.0020.0002.11A2] # HANGUL JUNGSEONG SSANGARAEA
+11A8 ; [.18CF.0020.0002.11A8] # HANGUL JONGSEONG KIYEOK
+11A9 ; [.18D0.0020.0002.11A9] # HANGUL JONGSEONG SSANGKIYEOK
+11AA ; [.18D1.0020.0002.11AA] # HANGUL JONGSEONG KIYEOK-SIOS
+11AB ; [.18D2.0020.0002.11AB] # HANGUL JONGSEONG NIEUN
+11AC ; [.18D3.0020.0002.11AC] # HANGUL JONGSEONG NIEUN-CIEUC
+11AD ; [.18D4.0020.0002.11AD] # HANGUL JONGSEONG NIEUN-HIEUH
+11AE ; [.18D5.0020.0002.11AE] # HANGUL JONGSEONG TIKEUT
+11AF ; [.18D6.0020.0002.11AF] # HANGUL JONGSEONG RIEUL
+11B0 ; [.18D7.0020.0002.11B0] # HANGUL JONGSEONG RIEUL-KIYEOK
+11B1 ; [.18D8.0020.0002.11B1] # HANGUL JONGSEONG RIEUL-MIEUM
+11B2 ; [.18D9.0020.0002.11B2] # HANGUL JONGSEONG RIEUL-PIEUP
+11B3 ; [.18DA.0020.0002.11B3] # HANGUL JONGSEONG RIEUL-SIOS
+11B4 ; [.18DB.0020.0002.11B4] # HANGUL JONGSEONG RIEUL-THIEUTH
+11B5 ; [.18DC.0020.0002.11B5] # HANGUL JONGSEONG RIEUL-PHIEUPH
+11B6 ; [.18DD.0020.0002.11B6] # HANGUL JONGSEONG RIEUL-HIEUH
+11B7 ; [.18DE.0020.0002.11B7] # HANGUL JONGSEONG MIEUM
+11B8 ; [.18DF.0020.0002.11B8] # HANGUL JONGSEONG PIEUP
+11B9 ; [.18E0.0020.0002.11B9] # HANGUL JONGSEONG PIEUP-SIOS
+11BA ; [.18E1.0020.0002.11BA] # HANGUL JONGSEONG SIOS
+11BB ; [.18E2.0020.0002.11BB] # HANGUL JONGSEONG SSANGSIOS
+11BC ; [.18E3.0020.0002.11BC] # HANGUL JONGSEONG IEUNG
+11BD ; [.18E4.0020.0002.11BD] # HANGUL JONGSEONG CIEUC
+11BE ; [.18E5.0020.0002.11BE] # HANGUL JONGSEONG CHIEUCH
+11BF ; [.18E6.0020.0002.11BF] # HANGUL JONGSEONG KHIEUKH
+11C0 ; [.18E7.0020.0002.11C0] # HANGUL JONGSEONG THIEUTH
+11C1 ; [.18E8.0020.0002.11C1] # HANGUL JONGSEONG PHIEUPH
+11C2 ; [.18E9.0020.0002.11C2] # HANGUL JONGSEONG HIEUH
+11C3 ; [.18EA.0020.0002.11C3] # HANGUL JONGSEONG KIYEOK-RIEUL
+11C4 ; [.18EB.0020.0002.11C4] # HANGUL JONGSEONG KIYEOK-SIOS-KIYEOK
+11C5 ; [.18EC.0020.0002.11C5] # HANGUL JONGSEONG NIEUN-KIYEOK
+11C6 ; [.18ED.0020.0002.11C6] # HANGUL JONGSEONG NIEUN-TIKEUT
+11C7 ; [.18EE.0020.0002.11C7] # HANGUL JONGSEONG NIEUN-SIOS
+11C8 ; [.18EF.0020.0002.11C8] # HANGUL JONGSEONG NIEUN-PANSIOS
+11C9 ; [.18F0.0020.0002.11C9] # HANGUL JONGSEONG NIEUN-THIEUTH
+11CA ; [.18F1.0020.0002.11CA] # HANGUL JONGSEONG TIKEUT-KIYEOK
+11CB ; [.18F2.0020.0002.11CB] # HANGUL JONGSEONG TIKEUT-RIEUL
+11CC ; [.18F3.0020.0002.11CC] # HANGUL JONGSEONG RIEUL-KIYEOK-SIOS
+11CD ; [.18F4.0020.0002.11CD] # HANGUL JONGSEONG RIEUL-NIEUN
+11CE ; [.18F5.0020.0002.11CE] # HANGUL JONGSEONG RIEUL-TIKEUT
+11CF ; [.18F6.0020.0002.11CF] # HANGUL JONGSEONG RIEUL-TIKEUT-HIEUH
+11D0 ; [.18F7.0020.0002.11D0] # HANGUL JONGSEONG SSANGRIEUL
+11D1 ; [.18F8.0020.0002.11D1] # HANGUL JONGSEONG RIEUL-MIEUM-KIYEOK
+11D2 ; [.18F9.0020.0002.11D2] # HANGUL JONGSEONG RIEUL-MIEUM-SIOS
+11D3 ; [.18FA.0020.0002.11D3] # HANGUL JONGSEONG RIEUL-PIEUP-SIOS
+11D4 ; [.18FB.0020.0002.11D4] # HANGUL JONGSEONG RIEUL-PIEUP-HIEUH
+11D5 ; [.18FC.0020.0002.11D5] # HANGUL JONGSEONG RIEUL-KAPYEOUNPIEUP
+11D6 ; [.18FD.0020.0002.11D6] # HANGUL JONGSEONG RIEUL-SSANGSIOS
+11D7 ; [.18FE.0020.0002.11D7] # HANGUL JONGSEONG RIEUL-PANSIOS
+11D8 ; [.18FF.0020.0002.11D8] # HANGUL JONGSEONG RIEUL-KHIEUKH
+11D9 ; [.1900.0020.0002.11D9] # HANGUL JONGSEONG RIEUL-YEORINHIEUH
+11DA ; [.1901.0020.0002.11DA] # HANGUL JONGSEONG MIEUM-KIYEOK
+11DB ; [.1902.0020.0002.11DB] # HANGUL JONGSEONG MIEUM-RIEUL
+11DC ; [.1903.0020.0002.11DC] # HANGUL JONGSEONG MIEUM-PIEUP
+11DD ; [.1904.0020.0002.11DD] # HANGUL JONGSEONG MIEUM-SIOS
+11DE ; [.1905.0020.0002.11DE] # HANGUL JONGSEONG MIEUM-SSANGSIOS
+11DF ; [.1906.0020.0002.11DF] # HANGUL JONGSEONG MIEUM-PANSIOS
+11E0 ; [.1907.0020.0002.11E0] # HANGUL JONGSEONG MIEUM-CHIEUCH
+11E1 ; [.1908.0020.0002.11E1] # HANGUL JONGSEONG MIEUM-HIEUH
+11E2 ; [.1909.0020.0002.11E2] # HANGUL JONGSEONG KAPYEOUNMIEUM
+11E3 ; [.190A.0020.0002.11E3] # HANGUL JONGSEONG PIEUP-RIEUL
+11E4 ; [.190B.0020.0002.11E4] # HANGUL JONGSEONG PIEUP-PHIEUPH
+11E5 ; [.190C.0020.0002.11E5] # HANGUL JONGSEONG PIEUP-HIEUH
+11E6 ; [.190D.0020.0002.11E6] # HANGUL JONGSEONG KAPYEOUNPIEUP
+11E7 ; [.190E.0020.0002.11E7] # HANGUL JONGSEONG SIOS-KIYEOK
+11E8 ; [.190F.0020.0002.11E8] # HANGUL JONGSEONG SIOS-TIKEUT
+11E9 ; [.1910.0020.0002.11E9] # HANGUL JONGSEONG SIOS-RIEUL
+11EA ; [.1911.0020.0002.11EA] # HANGUL JONGSEONG SIOS-PIEUP
+11EB ; [.1912.0020.0002.11EB] # HANGUL JONGSEONG PANSIOS
+11EC ; [.1913.0020.0002.11EC] # HANGUL JONGSEONG IEUNG-KIYEOK
+11ED ; [.1914.0020.0002.11ED] # HANGUL JONGSEONG IEUNG-SSANGKIYEOK
+11EE ; [.1915.0020.0002.11EE] # HANGUL JONGSEONG SSANGIEUNG
+11EF ; [.1916.0020.0002.11EF] # HANGUL JONGSEONG IEUNG-KHIEUKH
+11F0 ; [.1917.0020.0002.11F0] # HANGUL JONGSEONG YESIEUNG
+11F1 ; [.1918.0020.0002.11F1] # HANGUL JONGSEONG YESIEUNG-SIOS
+11F2 ; [.1919.0020.0002.11F2] # HANGUL JONGSEONG YESIEUNG-PANSIOS
+11F3 ; [.191A.0020.0002.11F3] # HANGUL JONGSEONG PHIEUPH-PIEUP
+11F4 ; [.191B.0020.0002.11F4] # HANGUL JONGSEONG KAPYEOUNPHIEUPH
+11F5 ; [.191C.0020.0002.11F5] # HANGUL JONGSEONG HIEUH-NIEUN
+11F6 ; [.191D.0020.0002.11F6] # HANGUL JONGSEONG HIEUH-RIEUL
+11F7 ; [.191E.0020.0002.11F7] # HANGUL JONGSEONG HIEUH-MIEUM
+11F8 ; [.191F.0020.0002.11F8] # HANGUL JONGSEONG HIEUH-PIEUP
+11F9 ; [.1920.0020.0002.11F9] # HANGUL JONGSEONG YEORINHIEUH
+3041 ; [.1921.0020.000D.3041] # HIRAGANA LETTER SMALL A
+3042 ; [.1921.0020.000E.3042] # HIRAGANA LETTER A
+30A1 ; [.1921.0020.000F.30A1] # KATAKANA LETTER SMALL A
+30A2 ; [.1921.0020.0011.30A2] # KATAKANA LETTER A
+3043 ; [.1922.0020.000D.3043] # HIRAGANA LETTER SMALL I
+3044 ; [.1922.0020.000E.3044] # HIRAGANA LETTER I
+30A3 ; [.1922.0020.000F.30A3] # KATAKANA LETTER SMALL I
+30A4 ; [.1922.0020.0011.30A4] # KATAKANA LETTER I
+3045 ; [.1923.0020.000D.3045] # HIRAGANA LETTER SMALL U
+3046 ; [.1923.0020.000E.3046] # HIRAGANA LETTER U
+30A5 ; [.1923.0020.000F.30A5] # KATAKANA LETTER SMALL U
+30A6 ; [.1923.0020.0011.30A6] # KATAKANA LETTER U
+3094 ; [.1923.0020.000E.3046][.0000.013D.0002.3099] # HIRAGANA LETTER VU; QQCM
+30F4 ; [.1923.0020.0011.30A6][.0000.013D.0002.3099] # KATAKANA LETTER VU; QQCM
+3047 ; [.1924.0020.000D.3047] # HIRAGANA LETTER SMALL E
+3048 ; [.1924.0020.000E.3048] # HIRAGANA LETTER E
+30A7 ; [.1924.0020.000F.30A7] # KATAKANA LETTER SMALL E
+30A8 ; [.1924.0020.0011.30A8] # KATAKANA LETTER E
+3049 ; [.1925.0020.000D.3049] # HIRAGANA LETTER SMALL O
+304A ; [.1925.0020.000E.304A] # HIRAGANA LETTER O
+30A9 ; [.1925.0020.000F.30A9] # KATAKANA LETTER SMALL O
+30AA ; [.1925.0020.0011.30AA] # KATAKANA LETTER O
+304B ; [.1926.0020.000E.304B] # HIRAGANA LETTER KA
+30F5 ; [.1926.0020.000F.30F5] # KATAKANA LETTER SMALL KA
+30AB ; [.1926.0020.0011.30AB] # KATAKANA LETTER KA
+304C ; [.1926.0020.000E.304B][.0000.013D.0002.3099] # HIRAGANA LETTER GA; QQCM
+30AC ; [.1926.0020.0011.30AB][.0000.013D.0002.3099] # KATAKANA LETTER GA; QQCM
+304D ; [.1927.0020.000E.304D] # HIRAGANA LETTER KI
+30AD ; [.1927.0020.0011.30AD] # KATAKANA LETTER KI
+304E ; [.1927.0020.000E.304D][.0000.013D.0002.3099] # HIRAGANA LETTER GI; QQCM
+30AE ; [.1927.0020.0011.30AD][.0000.013D.0002.3099] # KATAKANA LETTER GI; QQCM
+304F ; [.1928.0020.000E.304F] # HIRAGANA LETTER KU
+30AF ; [.1928.0020.0011.30AF] # KATAKANA LETTER KU
+3050 ; [.1928.0020.000E.304F][.0000.013D.0002.3099] # HIRAGANA LETTER GU; QQCM
+30B0 ; [.1928.0020.0011.30AF][.0000.013D.0002.3099] # KATAKANA LETTER GU; QQCM
+3051 ; [.1929.0020.000E.3051] # HIRAGANA LETTER KE
+30F6 ; [.1929.0020.000F.30F6] # KATAKANA LETTER SMALL KE
+30B1 ; [.1929.0020.0011.30B1] # KATAKANA LETTER KE
+3052 ; [.1929.0020.000E.3051][.0000.013D.0002.3099] # HIRAGANA LETTER GE; QQCM
+30B2 ; [.1929.0020.0011.30B1][.0000.013D.0002.3099] # KATAKANA LETTER GE; QQCM
+3053 ; [.192A.0020.000E.3053] # HIRAGANA LETTER KO
+30B3 ; [.192A.0020.0011.30B3] # KATAKANA LETTER KO
+3054 ; [.192A.0020.000E.3053][.0000.013D.0002.3099] # HIRAGANA LETTER GO; QQCM
+30B4 ; [.192A.0020.0011.30B3][.0000.013D.0002.3099] # KATAKANA LETTER GO; QQCM
+3055 ; [.192B.0020.000E.3055] # HIRAGANA LETTER SA
+30B5 ; [.192B.0020.0011.30B5] # KATAKANA LETTER SA
+3056 ; [.192B.0020.000E.3055][.0000.013D.0002.3099] # HIRAGANA LETTER ZA; QQCM
+30B6 ; [.192B.0020.0011.30B5][.0000.013D.0002.3099] # KATAKANA LETTER ZA; QQCM
+3057 ; [.192C.0020.000E.3057] # HIRAGANA LETTER SI
+30B7 ; [.192C.0020.0011.30B7] # KATAKANA LETTER SI
+3058 ; [.192C.0020.000E.3057][.0000.013D.0002.3099] # HIRAGANA LETTER ZI; QQCM
+30B8 ; [.192C.0020.0011.30B7][.0000.013D.0002.3099] # KATAKANA LETTER ZI; QQCM
+3059 ; [.192D.0020.000E.3059] # HIRAGANA LETTER SU
+30B9 ; [.192D.0020.0011.30B9] # KATAKANA LETTER SU
+305A ; [.192D.0020.000E.3059][.0000.013D.0002.3099] # HIRAGANA LETTER ZU; QQCM
+30BA ; [.192D.0020.0011.30B9][.0000.013D.0002.3099] # KATAKANA LETTER ZU; QQCM
+305B ; [.192E.0020.000E.305B] # HIRAGANA LETTER SE
+30BB ; [.192E.0020.0011.30BB] # KATAKANA LETTER SE
+305C ; [.192E.0020.000E.305B][.0000.013D.0002.3099] # HIRAGANA LETTER ZE; QQCM
+30BC ; [.192E.0020.0011.30BB][.0000.013D.0002.3099] # KATAKANA LETTER ZE; QQCM
+305D ; [.192F.0020.000E.305D] # HIRAGANA LETTER SO
+30BD ; [.192F.0020.0011.30BD] # KATAKANA LETTER SO
+305E ; [.192F.0020.000E.305D][.0000.013D.0002.3099] # HIRAGANA LETTER ZO; QQCM
+30BE ; [.192F.0020.0011.30BD][.0000.013D.0002.3099] # KATAKANA LETTER ZO; QQCM
+305F ; [.1930.0020.000E.305F] # HIRAGANA LETTER TA
+30BF ; [.1930.0020.0011.30BF] # KATAKANA LETTER TA
+3060 ; [.1930.0020.000E.305F][.0000.013D.0002.3099] # HIRAGANA LETTER DA; QQCM
+30C0 ; [.1930.0020.0011.30BF][.0000.013D.0002.3099] # KATAKANA LETTER DA; QQCM
+3061 ; [.1931.0020.000E.3061] # HIRAGANA LETTER TI
+30C1 ; [.1931.0020.0011.30C1] # KATAKANA LETTER TI
+3062 ; [.1931.0020.000E.3061][.0000.013D.0002.3099] # HIRAGANA LETTER DI; QQCM
+30C2 ; [.1931.0020.0011.30C1][.0000.013D.0002.3099] # KATAKANA LETTER DI; QQCM
+3063 ; [.1932.0020.000D.3063] # HIRAGANA LETTER SMALL TU
+3064 ; [.1932.0020.000E.3064] # HIRAGANA LETTER TU
+30C3 ; [.1932.0020.000F.30C3] # KATAKANA LETTER SMALL TU
+30C4 ; [.1932.0020.0011.30C4] # KATAKANA LETTER TU
+3065 ; [.1932.0020.000E.3064][.0000.013D.0002.3099] # HIRAGANA LETTER DU; QQCM
+30C5 ; [.1932.0020.0011.30C4][.0000.013D.0002.3099] # KATAKANA LETTER DU; QQCM
+3066 ; [.1933.0020.000E.3066] # HIRAGANA LETTER TE
+30C6 ; [.1933.0020.0011.30C6] # KATAKANA LETTER TE
+3067 ; [.1933.0020.000E.3066][.0000.013D.0002.3099] # HIRAGANA LETTER DE; QQCM
+30C7 ; [.1933.0020.0011.30C6][.0000.013D.0002.3099] # KATAKANA LETTER DE; QQCM
+3068 ; [.1934.0020.000E.3068] # HIRAGANA LETTER TO
+30C8 ; [.1934.0020.0011.30C8] # KATAKANA LETTER TO
+3069 ; [.1934.0020.000E.3068][.0000.013D.0002.3099] # HIRAGANA LETTER DO; QQCM
+30C9 ; [.1934.0020.0011.30C8][.0000.013D.0002.3099] # KATAKANA LETTER DO; QQCM
+306A ; [.1935.0020.000E.306A] # HIRAGANA LETTER NA
+30CA ; [.1935.0020.0011.30CA] # KATAKANA LETTER NA
+306B ; [.1936.0020.000E.306B] # HIRAGANA LETTER NI
+30CB ; [.1936.0020.0011.30CB] # KATAKANA LETTER NI
+306C ; [.1937.0020.000E.306C] # HIRAGANA LETTER NU
+30CC ; [.1937.0020.0011.30CC] # KATAKANA LETTER NU
+306D ; [.1938.0020.000E.306D] # HIRAGANA LETTER NE
+30CD ; [.1938.0020.0011.30CD] # KATAKANA LETTER NE
+306E ; [.1939.0020.000E.306E] # HIRAGANA LETTER NO
+30CE ; [.1939.0020.0011.30CE] # KATAKANA LETTER NO
+306F ; [.193A.0020.000E.306F] # HIRAGANA LETTER HA
+30CF ; [.193A.0020.0011.30CF] # KATAKANA LETTER HA
+3070 ; [.193A.0020.000E.306F][.0000.013D.0002.3099] # HIRAGANA LETTER BA; QQCM
+30D0 ; [.193A.0020.0011.30CF][.0000.013D.0002.3099] # KATAKANA LETTER BA; QQCM
+3071 ; [.193A.0020.000E.306F][.0000.013E.0002.309A] # HIRAGANA LETTER PA; QQCM
+30D1 ; [.193A.0020.0011.30CF][.0000.013E.0002.309A] # KATAKANA LETTER PA; QQCM
+3072 ; [.193B.0020.000E.3072] # HIRAGANA LETTER HI
+30D2 ; [.193B.0020.0011.30D2] # KATAKANA LETTER HI
+3073 ; [.193B.0020.000E.3072][.0000.013D.0002.3099] # HIRAGANA LETTER BI; QQCM
+30D3 ; [.193B.0020.0011.30D2][.0000.013D.0002.3099] # KATAKANA LETTER BI; QQCM
+3074 ; [.193B.0020.000E.3072][.0000.013E.0002.309A] # HIRAGANA LETTER PI; QQCM
+30D4 ; [.193B.0020.0011.30D2][.0000.013E.0002.309A] # KATAKANA LETTER PI; QQCM
+3075 ; [.193C.0020.000E.3075] # HIRAGANA LETTER HU
+30D5 ; [.193C.0020.0011.30D5] # KATAKANA LETTER HU
+3076 ; [.193C.0020.000E.3075][.0000.013D.0002.3099] # HIRAGANA LETTER BU; QQCM
+30D6 ; [.193C.0020.0011.30D5][.0000.013D.0002.3099] # KATAKANA LETTER BU; QQCM
+3077 ; [.193C.0020.000E.3075][.0000.013E.0002.309A] # HIRAGANA LETTER PU; QQCM
+30D7 ; [.193C.0020.0011.30D5][.0000.013E.0002.309A] # KATAKANA LETTER PU; QQCM
+3078 ; [.193D.0020.000E.3078] # HIRAGANA LETTER HE
+30D8 ; [.193D.0020.0011.30D8] # KATAKANA LETTER HE
+3079 ; [.193D.0020.000E.3078][.0000.013D.0002.3099] # HIRAGANA LETTER BE; QQCM
+30D9 ; [.193D.0020.0011.30D8][.0000.013D.0002.3099] # KATAKANA LETTER BE; QQCM
+307A ; [.193D.0020.000E.3078][.0000.013E.0002.309A] # HIRAGANA LETTER PE; QQCM
+30DA ; [.193D.0020.0011.30D8][.0000.013E.0002.309A] # KATAKANA LETTER PE; QQCM
+307B ; [.193E.0020.000E.307B] # HIRAGANA LETTER HO
+30DB ; [.193E.0020.0011.30DB] # KATAKANA LETTER HO
+307C ; [.193E.0020.000E.307B][.0000.013D.0002.3099] # HIRAGANA LETTER BO; QQCM
+30DC ; [.193E.0020.0011.30DB][.0000.013D.0002.3099] # KATAKANA LETTER BO; QQCM
+307D ; [.193E.0020.000E.307B][.0000.013E.0002.309A] # HIRAGANA LETTER PO; QQCM
+30DD ; [.193E.0020.0011.30DB][.0000.013E.0002.309A] # KATAKANA LETTER PO; QQCM
+307E ; [.193F.0020.000E.307E] # HIRAGANA LETTER MA
+30DE ; [.193F.0020.0011.30DE] # KATAKANA LETTER MA
+307F ; [.1940.0020.000E.307F] # HIRAGANA LETTER MI
+30DF ; [.1940.0020.0011.30DF] # KATAKANA LETTER MI
+3080 ; [.1941.0020.000E.3080] # HIRAGANA LETTER MU
+30E0 ; [.1941.0020.0011.30E0] # KATAKANA LETTER MU
+3081 ; [.1942.0020.000E.3081] # HIRAGANA LETTER ME
+30E1 ; [.1942.0020.0011.30E1] # KATAKANA LETTER ME
+3082 ; [.1943.0020.000E.3082] # HIRAGANA LETTER MO
+30E2 ; [.1943.0020.0011.30E2] # KATAKANA LETTER MO
+3083 ; [.1944.0020.000D.3083] # HIRAGANA LETTER SMALL YA
+3084 ; [.1944.0020.000E.3084] # HIRAGANA LETTER YA
+30E3 ; [.1944.0020.000F.30E3] # KATAKANA LETTER SMALL YA
+30E4 ; [.1944.0020.0011.30E4] # KATAKANA LETTER YA
+3085 ; [.1945.0020.000D.3085] # HIRAGANA LETTER SMALL YU
+3086 ; [.1945.0020.000E.3086] # HIRAGANA LETTER YU
+30E5 ; [.1945.0020.000F.30E5] # KATAKANA LETTER SMALL YU
+30E6 ; [.1945.0020.0011.30E6] # KATAKANA LETTER YU
+3087 ; [.1946.0020.000D.3087] # HIRAGANA LETTER SMALL YO
+3088 ; [.1946.0020.000E.3088] # HIRAGANA LETTER YO
+30E7 ; [.1946.0020.000F.30E7] # KATAKANA LETTER SMALL YO
+30E8 ; [.1946.0020.0011.30E8] # KATAKANA LETTER YO
+3089 ; [.1947.0020.000E.3089] # HIRAGANA LETTER RA
+30E9 ; [.1947.0020.0011.30E9] # KATAKANA LETTER RA
+308A ; [.1948.0020.000E.308A] # HIRAGANA LETTER RI
+30EA ; [.1948.0020.0011.30EA] # KATAKANA LETTER RI
+308B ; [.1949.0020.000E.308B] # HIRAGANA LETTER RU
+30EB ; [.1949.0020.0011.30EB] # KATAKANA LETTER RU
+308C ; [.194A.0020.000E.308C] # HIRAGANA LETTER RE
+30EC ; [.194A.0020.0011.30EC] # KATAKANA LETTER RE
+308D ; [.194B.0020.000E.308D] # HIRAGANA LETTER RO
+30ED ; [.194B.0020.0011.30ED] # KATAKANA LETTER RO
+308E ; [.194C.0020.000D.308E] # HIRAGANA LETTER SMALL WA
+308F ; [.194C.0020.000E.308F] # HIRAGANA LETTER WA
+30EE ; [.194C.0020.000F.30EE] # KATAKANA LETTER SMALL WA
+30EF ; [.194C.0020.0011.30EF] # KATAKANA LETTER WA
+30F7 ; [.194C.0020.0011.30EF][.0000.013D.0002.3099] # KATAKANA LETTER VA; QQCM
+3090 ; [.194D.0020.000E.3090] # HIRAGANA LETTER WI
+30F0 ; [.194D.0020.0011.30F0] # KATAKANA LETTER WI
+30F8 ; [.194D.0020.0011.30F0][.0000.013D.0002.3099] # KATAKANA LETTER VI; QQCM
+3091 ; [.194E.0020.000E.3091] # HIRAGANA LETTER WE
+30F1 ; [.194E.0020.0011.30F1] # KATAKANA LETTER WE
+30F9 ; [.194E.0020.0011.30F1][.0000.013D.0002.3099] # KATAKANA LETTER VE; QQCM
+3092 ; [.194F.0020.000E.3092] # HIRAGANA LETTER WO
+30F2 ; [.194F.0020.0011.30F2] # KATAKANA LETTER WO
+30FA ; [.194F.0020.0011.30F2][.0000.013D.0002.3099] # KATAKANA LETTER VO; QQCM
+3093 ; [.1950.0020.000E.3093] # HIRAGANA LETTER N
+30F3 ; [.1950.0020.0011.30F3] # KATAKANA LETTER N
diff --git a/Master/tlpkg/tlperl/lib/Unicode/Normalize.pm b/Master/tlpkg/tlperl/lib/Unicode/Normalize.pm
new file mode 100644
index 00000000000..ad5ff82a836
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Unicode/Normalize.pm
@@ -0,0 +1,520 @@
+package Unicode::Normalize;
+
+BEGIN {
+ unless ("A" eq pack('U', 0x41)) {
+ die "Unicode::Normalize cannot stringify a Unicode code point\n";
+ }
+}
+
+use 5.006;
+use strict;
+use warnings;
+use Carp;
+
+no warnings 'utf8';
+
+our $VERSION = '1.03';
+our $PACKAGE = __PACKAGE__;
+
+require Exporter;
+require DynaLoader;
+
+our @ISA = qw(Exporter DynaLoader);
+our @EXPORT = qw( NFC NFD NFKC NFKD );
+our @EXPORT_OK = qw(
+ normalize decompose reorder compose
+ checkNFD checkNFKD checkNFC checkNFKC check
+ getCanon getCompat getComposite getCombinClass
+ isExclusion isSingleton isNonStDecomp isComp2nd isComp_Ex
+ isNFD_NO isNFC_NO isNFC_MAYBE isNFKD_NO isNFKC_NO isNFKC_MAYBE
+ FCD checkFCD FCC checkFCC composeContiguous
+ splitOnLastStarter
+);
+our %EXPORT_TAGS = (
+ all => [ @EXPORT, @EXPORT_OK ],
+ normalize => [ @EXPORT, qw/normalize decompose reorder compose/ ],
+ check => [ qw/checkNFD checkNFKD checkNFC checkNFKC check/ ],
+ fast => [ qw/FCD checkFCD FCC checkFCC composeContiguous/ ],
+);
+
+######
+
+bootstrap Unicode::Normalize $VERSION;
+
+######
+
+##
+## utilites for tests
+##
+
+sub pack_U {
+ return pack('U*', @_);
+}
+
+sub unpack_U {
+ return unpack('U*', shift(@_).pack('U*'));
+}
+
+
+##
+## normalization forms
+##
+
+sub FCD ($) {
+ my $str = shift;
+ return checkFCD($str) ? $str : NFD($str);
+}
+
+our %formNorm = (
+ NFC => \&NFC, C => \&NFC,
+ NFD => \&NFD, D => \&NFD,
+ NFKC => \&NFKC, KC => \&NFKC,
+ NFKD => \&NFKD, KD => \&NFKD,
+ FCD => \&FCD, FCC => \&FCC,
+);
+
+sub normalize($$)
+{
+ my $form = shift;
+ my $str = shift;
+ if (exists $formNorm{$form}) {
+ return $formNorm{$form}->($str);
+ }
+ croak($PACKAGE."::normalize: invalid form name: $form");
+}
+
+
+##
+## quick check
+##
+
+our %formCheck = (
+ NFC => \&checkNFC, C => \&checkNFC,
+ NFD => \&checkNFD, D => \&checkNFD,
+ NFKC => \&checkNFKC, KC => \&checkNFKC,
+ NFKD => \&checkNFKD, KD => \&checkNFKD,
+ FCD => \&checkFCD, FCC => \&checkFCC,
+);
+
+sub check($$)
+{
+ my $form = shift;
+ my $str = shift;
+ if (exists $formCheck{$form}) {
+ return $formCheck{$form}->($str);
+ }
+ croak($PACKAGE."::check: invalid form name: $form");
+}
+
+1;
+__END__
+
+=head1 NAME
+
+Unicode::Normalize - Unicode Normalization Forms
+
+=head1 SYNOPSIS
+
+(1) using function names exported by default:
+
+ use Unicode::Normalize;
+
+ $NFD_string = NFD($string); # Normalization Form D
+ $NFC_string = NFC($string); # Normalization Form C
+ $NFKD_string = NFKD($string); # Normalization Form KD
+ $NFKC_string = NFKC($string); # Normalization Form KC
+
+(2) using function names exported on request:
+
+ use Unicode::Normalize 'normalize';
+
+ $NFD_string = normalize('D', $string); # Normalization Form D
+ $NFC_string = normalize('C', $string); # Normalization Form C
+ $NFKD_string = normalize('KD', $string); # Normalization Form KD
+ $NFKC_string = normalize('KC', $string); # Normalization Form KC
+
+=head1 DESCRIPTION
+
+Parameters:
+
+C<$string> is used as a string under character semantics (see F<perlunicode>).
+
+C<$code_point> should be an unsigned integer representing a Unicode code point.
+
+Note: Between XSUB and pure Perl, there is an incompatibility
+about the interpretation of C<$code_point> as a decimal number.
+XSUB converts C<$code_point> to an unsigned integer, but pure Perl does not.
+Do not use a floating point nor a negative sign in C<$code_point>.
+
+=head2 Normalization Forms
+
+=over 4
+
+=item C<$NFD_string = NFD($string)>
+
+It returns the Normalization Form D (formed by canonical decomposition).
+
+=item C<$NFC_string = NFC($string)>
+
+It returns the Normalization Form C (formed by canonical decomposition
+followed by canonical composition).
+
+=item C<$NFKD_string = NFKD($string)>
+
+It returns the Normalization Form KD (formed by compatibility decomposition).
+
+=item C<$NFKC_string = NFKC($string)>
+
+It returns the Normalization Form KC (formed by compatibility decomposition
+followed by B<canonical> composition).
+
+=item C<$FCD_string = FCD($string)>
+
+If the given string is in FCD ("Fast C or D" form; cf. UTN #5),
+it returns the string without modification; otherwise it returns an FCD string.
+
+Note: FCD is not always unique, then plural forms may be equivalent
+each other. C<FCD()> will return one of these equivalent forms.
+
+=item C<$FCC_string = FCC($string)>
+
+It returns the FCC form ("Fast C Contiguous"; cf. UTN #5).
+
+Note: FCC is unique, as well as four normalization forms (NF*).
+
+=item C<$normalized_string = normalize($form_name, $string)>
+
+It returns the normalization form of C<$form_name>.
+
+As C<$form_name>, one of the following names must be given.
+
+ 'C' or 'NFC' for Normalization Form C (UAX #15)
+ 'D' or 'NFD' for Normalization Form D (UAX #15)
+ 'KC' or 'NFKC' for Normalization Form KC (UAX #15)
+ 'KD' or 'NFKD' for Normalization Form KD (UAX #15)
+
+ 'FCD' for "Fast C or D" Form (UTN #5)
+ 'FCC' for "Fast C Contiguous" (UTN #5)
+
+=back
+
+=head2 Decomposition and Composition
+
+=over 4
+
+=item C<$decomposed_string = decompose($string [, $useCompatMapping])>
+
+It returns the concatenation of the decomposition of each character
+in the string.
+
+If the second parameter (a boolean) is omitted or false,
+the decomposition is canonical decomposition;
+if the second parameter (a boolean) is true,
+the decomposition is compatibility decomposition.
+
+The string returned is not always in NFD/NFKD. Reordering may be required.
+
+ $NFD_string = reorder(decompose($string)); # eq. to NFD()
+ $NFKD_string = reorder(decompose($string, TRUE)); # eq. to NFKD()
+
+=item C<$reordered_string = reorder($string)>
+
+It returns the result of reordering the combining characters
+according to Canonical Ordering Behavior.
+
+For example, when you have a list of NFD/NFKD strings,
+you can get the concatenated NFD/NFKD string from them, by saying
+
+ $concat_NFD = reorder(join '', @NFD_strings);
+ $concat_NFKD = reorder(join '', @NFKD_strings);
+
+=item C<$composed_string = compose($string)>
+
+It returns the result of canonical composition
+without applying any decomposition.
+
+For example, when you have a NFD/NFKD string,
+you can get its NFC/NFKC string, by saying
+
+ $NFC_string = compose($NFD_string);
+ $NFKC_string = compose($NFKD_string);
+
+=back
+
+=head2 Quick Check
+
+(see Annex 8, UAX #15; and F<DerivedNormalizationProps.txt>)
+
+The following functions check whether the string is in that normalization form.
+
+The result returned will be one of the following:
+
+ YES The string is in that normalization form.
+ NO The string is not in that normalization form.
+ MAYBE Dubious. Maybe yes, maybe no.
+
+=over 4
+
+=item C<$result = checkNFD($string)>
+
+It returns true (C<1>) if C<YES>; false (C<empty string>) if C<NO>.
+
+=item C<$result = checkNFC($string)>
+
+It returns true (C<1>) if C<YES>; false (C<empty string>) if C<NO>;
+C<undef> if C<MAYBE>.
+
+=item C<$result = checkNFKD($string)>
+
+It returns true (C<1>) if C<YES>; false (C<empty string>) if C<NO>.
+
+=item C<$result = checkNFKC($string)>
+
+It returns true (C<1>) if C<YES>; false (C<empty string>) if C<NO>;
+C<undef> if C<MAYBE>.
+
+=item C<$result = checkFCD($string)>
+
+It returns true (C<1>) if C<YES>; false (C<empty string>) if C<NO>.
+
+=item C<$result = checkFCC($string)>
+
+It returns true (C<1>) if C<YES>; false (C<empty string>) if C<NO>;
+C<undef> if C<MAYBE>.
+
+Note: If a string is not in FCD, it must not be in FCC.
+So C<checkFCC($not_FCD_string)> should return C<NO>.
+
+=item C<$result = check($form_name, $string)>
+
+It returns true (C<1>) if C<YES>; false (C<empty string>) if C<NO>;
+C<undef> if C<MAYBE>.
+
+As C<$form_name>, one of the following names must be given.
+
+ 'C' or 'NFC' for Normalization Form C (UAX #15)
+ 'D' or 'NFD' for Normalization Form D (UAX #15)
+ 'KC' or 'NFKC' for Normalization Form KC (UAX #15)
+ 'KD' or 'NFKD' for Normalization Form KD (UAX #15)
+
+ 'FCD' for "Fast C or D" Form (UTN #5)
+ 'FCC' for "Fast C Contiguous" (UTN #5)
+
+=back
+
+B<Note>
+
+In the cases of NFD, NFKD, and FCD, the answer must be
+either C<YES> or C<NO>. The answer C<MAYBE> may be returned
+in the cases of NFC, NFKC, and FCC.
+
+A C<MAYBE> string should contain at least one combining character
+or the like. For example, C<COMBINING ACUTE ACCENT> has
+the MAYBE_NFC/MAYBE_NFKC property.
+
+Both C<checkNFC("A\N{COMBINING ACUTE ACCENT}")>
+and C<checkNFC("B\N{COMBINING ACUTE ACCENT}")> will return C<MAYBE>.
+C<"A\N{COMBINING ACUTE ACCENT}"> is not in NFC
+(its NFC is C<"\N{LATIN CAPITAL LETTER A WITH ACUTE}">),
+while C<"B\N{COMBINING ACUTE ACCENT}"> is in NFC.
+
+If you want to check exactly, compare the string with its NFC/NFKC/FCC.
+
+ if ($string eq NFC($string)) {
+ # $string is exactly normalized in NFC;
+ } else {
+ # $string is not normalized in NFC;
+ }
+
+ if ($string eq NFKC($string)) {
+ # $string is exactly normalized in NFKC;
+ } else {
+ # $string is not normalized in NFKC;
+ }
+
+=head2 Character Data
+
+These functions are interface of character data used internally.
+If you want only to get Unicode normalization forms, you don't need
+call them yourself.
+
+=over 4
+
+=item C<$canonical_decomposition = getCanon($code_point)>
+
+If the character is canonically decomposable (including Hangul Syllables),
+it returns the (full) canonical decomposition as a string.
+Otherwise it returns C<undef>.
+
+B<Note:> According to the Unicode standard, the canonical decomposition
+of the character that is not canonically decomposable is same as
+the character itself.
+
+=item C<$compatibility_decomposition = getCompat($code_point)>
+
+If the character is compatibility decomposable (including Hangul Syllables),
+it returns the (full) compatibility decomposition as a string.
+Otherwise it returns C<undef>.
+
+B<Note:> According to the Unicode standard, the compatibility decomposition
+of the character that is not compatibility decomposable is same as
+the character itself.
+
+=item C<$code_point_composite = getComposite($code_point_here, $code_point_next)>
+
+If two characters here and next (as code points) are composable
+(including Hangul Jamo/Syllables and Composition Exclusions),
+it returns the code point of the composite.
+
+If they are not composable, it returns C<undef>.
+
+=item C<$combining_class = getCombinClass($code_point)>
+
+It returns the combining class (as an integer) of the character.
+
+=item C<$may_be_composed_with_prev_char = isComp2nd($code_point)>
+
+It returns a boolean whether the character of the specified codepoint
+may be composed with the previous one in a certain composition
+(including Hangul Compositions, but excluding
+Composition Exclusions and Non-Starter Decompositions).
+
+=item C<$is_exclusion = isExclusion($code_point)>
+
+It returns a boolean whether the code point is a composition exclusion.
+
+=item C<$is_singleton = isSingleton($code_point)>
+
+It returns a boolean whether the code point is a singleton
+
+=item C<$is_non_starter_decomposition = isNonStDecomp($code_point)>
+
+It returns a boolean whether the code point has Non-Starter Decomposition.
+
+=item C<$is_Full_Composition_Exclusion = isComp_Ex($code_point)>
+
+It returns a boolean of the derived property Comp_Ex
+(Full_Composition_Exclusion). This property is generated from
+Composition Exclusions + Singletons + Non-Starter Decompositions.
+
+=item C<$NFD_is_NO = isNFD_NO($code_point)>
+
+It returns a boolean of the derived property NFD_NO
+(NFD_Quick_Check=No).
+
+=item C<$NFC_is_NO = isNFC_NO($code_point)>
+
+It returns a boolean of the derived property NFC_NO
+(NFC_Quick_Check=No).
+
+=item C<$NFC_is_MAYBE = isNFC_MAYBE($code_point)>
+
+It returns a boolean of the derived property NFC_MAYBE
+(NFC_Quick_Check=Maybe).
+
+=item C<$NFKD_is_NO = isNFKD_NO($code_point)>
+
+It returns a boolean of the derived property NFKD_NO
+(NFKD_Quick_Check=No).
+
+=item C<$NFKC_is_NO = isNFKC_NO($code_point)>
+
+It returns a boolean of the derived property NFKC_NO
+(NFKC_Quick_Check=No).
+
+=item C<$NFKC_is_MAYBE = isNFKC_MAYBE($code_point)>
+
+It returns a boolean of the derived property NFKC_MAYBE
+(NFKC_Quick_Check=Maybe).
+
+=back
+
+=head1 EXPORT
+
+C<NFC>, C<NFD>, C<NFKC>, C<NFKD>: by default.
+
+C<normalize> and other some functions: on request.
+
+=head1 CAVEATS
+
+=over 4
+
+=item Perl's version vs. Unicode version
+
+Since this module refers to perl core's Unicode database in the directory
+F</lib/unicore> (or formerly F</lib/unicode>), the Unicode version of
+normalization implemented by this module depends on your perl's version.
+
+ perl's version implemented Unicode version
+ 5.6.1 3.0.1
+ 5.7.2 3.1.0
+ 5.7.3 3.1.1 (normalization is same as 3.1.0)
+ 5.8.0 3.2.0
+ 5.8.1-5.8.3 4.0.0
+ 5.8.4-5.8.6 4.0.1 (normalization is same as 4.0.0)
+ 5.8.7-5.8.8 4.1.0
+ 5.10.0 5.0.0
+ 5.8.9 5.1.0
+
+=item Correction of decomposition mapping
+
+In older Unicode versions, a small number of characters (all of which are
+CJK compatibility ideographs as far as they have been found) may have
+an erroneous decomposition mapping (see F<NormalizationCorrections.txt>).
+Anyhow, this module will neither refer to F<NormalizationCorrections.txt>
+nor provide any specific version of normalization. Therefore this module
+running on an older perl with an older Unicode database may use
+the erroneous decomposition mapping blindly conforming to the Unicode database.
+
+=item Revised definition of canonical composition
+
+In Unicode 4.1.0, the definition D2 of canonical composition (which
+affects NFC and NFKC) has been changed (see Public Review Issue #29
+and recent UAX #15). This module has used the newer definition
+since the version 0.07 (Oct 31, 2001).
+This module will not support the normalization according to the older
+definition, even if the Unicode version implemented by perl is
+lower than 4.1.0.
+
+=back
+
+=head1 AUTHOR
+
+SADAHIRO Tomoyuki <SADAHIRO@cpan.org>
+
+Copyright(C) 2001-2007, SADAHIRO Tomoyuki. Japan. All rights reserved.
+
+This module is free software; you can redistribute it
+and/or modify it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+=over 4
+
+=item http://www.unicode.org/reports/tr15/
+
+Unicode Normalization Forms - UAX #15
+
+=item http://www.unicode.org/Public/UNIDATA/CompositionExclusions.txt
+
+Composition Exclusion Table
+
+=item http://www.unicode.org/Public/UNIDATA/DerivedNormalizationProps.txt
+
+Derived Normalization Properties
+
+=item http://www.unicode.org/Public/UNIDATA/NormalizationCorrections.txt
+
+Normalization Corrections
+
+=item http://www.unicode.org/review/pr-29.html
+
+Public Review Issue #29: Normalization Issue
+
+=item http://www.unicode.org/notes/tn5/
+
+Canonical Equivalence in Applications - UTN #5
+
+=back
+
+=cut
diff --git a/Master/tlpkg/tlperl/lib/Unicode/UCD.pm b/Master/tlpkg/tlperl/lib/Unicode/UCD.pm
new file mode 100644
index 00000000000..c6ee8e05fe2
--- /dev/null
+++ b/Master/tlpkg/tlperl/lib/Unicode/UCD.pm
@@ -0,0 +1,1230 @@
+package Unicode::UCD;
+
+use strict;
+use warnings;
+
+our $VERSION = '0.27';
+
+use Storable qw(dclone);
+
+require Exporter;
+
+our @ISA = qw(Exporter);
+
+our @EXPORT_OK = qw(charinfo
+ charblock charscript
+ charblocks charscripts
+ charinrange
+ general_categories bidi_types
+ compexcl
+ casefold casespec
+ namedseq);
+
+use Carp;
+
+=head1 NAME
+
+Unicode::UCD - Unicode character database
+
+=head1 SYNOPSIS
+
+ use Unicode::UCD 'charinfo';
+ my $charinfo = charinfo($codepoint);
+
+ use Unicode::UCD 'casefold';
+ my $casefold = casefold(0xFB00);
+
+ use Unicode::UCD 'casespec';
+ my $casespec = casespec(0xFB00);
+
+ use Unicode::UCD 'charblock';
+ my $charblock = charblock($codepoint);
+
+ use Unicode::UCD 'charscript';
+ my $charscript = charscript($codepoint);
+
+ use Unicode::UCD 'charblocks';
+ my $charblocks = charblocks();
+
+ use Unicode::UCD 'charscripts';
+ my $charscripts = charscripts();
+
+ use Unicode::UCD qw(charscript charinrange);
+ my $range = charscript($script);
+ print "looks like $script\n" if charinrange($range, $codepoint);
+
+ use Unicode::UCD qw(general_categories bidi_types);
+ my $categories = general_categories();
+ my $types = bidi_types();
+
+ use Unicode::UCD 'compexcl';
+ my $compexcl = compexcl($codepoint);
+
+ use Unicode::UCD 'namedseq';
+ my $namedseq = namedseq($named_sequence_name);
+
+ my $unicode_version = Unicode::UCD::UnicodeVersion();
+
+=head1 DESCRIPTION
+
+The Unicode::UCD module offers a series of functions that
+provide a simple interface to the Unicode
+Character Database.
+
+=head2 code point argument
+
+Some of the functions are called with a I<code point argument>, which is either
+a decimal or a hexadecimal scalar designating a Unicode code point, or C<U+>
+followed by hexadecimals designating a Unicode code point. In other words, if
+you want a code point to be interpreted as a hexadecimal number, you must
+prefix it with either C<0x> or C<U+>, because a string like e.g. C<123> will be
+interpreted as a decimal code point. Also note that Unicode is B<not> limited
+to 16 bits (the number of Unicode code points is open-ended, in theory
+unlimited): you may have more than 4 hexdigits.
+=cut
+
+my $UNICODEFH;
+my $BLOCKSFH;
+my $SCRIPTSFH;
+my $VERSIONFH;
+my $COMPEXCLFH;
+my $CASEFOLDFH;
+my $CASESPECFH;
+my $NAMEDSEQFH;
+
+sub openunicode {
+ my ($rfh, @path) = @_;
+ my $f;
+ unless (defined $$rfh) {
+ for my $d (@INC) {
+ use File::Spec;
+ $f = File::Spec->catfile($d, "unicore", @path);
+ last if open($$rfh, $f);
+ undef $f;
+ }
+ croak __PACKAGE__, ": failed to find ",
+ File::Spec->catfile(@path), " in @INC"
+ unless defined $f;
+ }
+ return $f;
+}
+
+=head2 B<charinfo()>
+
+ use Unicode::UCD 'charinfo';
+
+ my $charinfo = charinfo(0x41);
+
+This returns information about the input L</code point argument>
+as a reference to a hash of fields as defined by the Unicode
+standard. If the L</code point argument> is not assigned in the standard
+(i.e., has the general category C<Cn> meaning C<Unassigned>)
+or is a non-character (meaning it is guaranteed to never be assigned in
+the standard),
+B<undef> is returned.
+
+Fields that aren't applicable to the particular code point argument exist in the
+returned hash, and are empty.
+
+The keys in the hash with the meanings of their values are:
+
+=over
+
+=item B<code>
+
+the input L</code point argument> expressed in hexadecimal, with leading zeros
+added if necessary to make it contain at least four hexdigits
+
+=item B<name>
+
+name of I<code>, all IN UPPER CASE.
+Some control-type code points do not have names.
+This field will be empty for C<Surrogate> and C<Private Use> code points,
+and for the others without a name,
+it will contain a description enclosed in angle brackets, like
+C<E<lt>controlE<gt>>.
+
+
+=item B<category>
+
+The short name of the general category of I<code>.
+This will match one of the keys in the hash returned by L</general_categories()>.
+
+=item B<combining>
+
+the combining class number for I<code> used in the Canonical Ordering Algorithm.
+For Unicode 5.1, this is described in Section 3.11 C<Canonical Ordering Behavior>
+available at
+L<http://www.unicode.org/versions/Unicode5.1.0/>
+
+=item B<bidi>
+
+bidirectional type of I<code>.
+This will match one of the keys in the hash returned by L</bidi_types()>.
+
+=item B<decomposition>
+
+is empty if I<code> has no decomposition; or is one or more codes
+(separated by spaces) that taken in order represent a decomposition for
+I<code>. Each has at least four hexdigits.
+The codes may be preceded by a word enclosed in angle brackets then a space,
+like C<E<lt>compatE<gt> >, giving the type of decomposition
+
+=item B<decimal>
+
+if I<code> is a decimal digit this is its integer numeric value
+
+=item B<digit>
+
+if I<code> represents a whole number, this is its integer numeric value
+
+=item B<numeric>
+
+if I<code> represents a whole or rational number, this is its numeric value.
+Rational values are expressed as a string like C<1/4>.
+
+=item B<mirrored>
+
+C<Y> or C<N> designating if I<code> is mirrored in bidirectional text
+
+=item B<unicode10>
+
+name of I<code> in the Unicode 1.0 standard if one
+existed for this code point and is different from the current name
+
+=item B<comment>
+
+ISO 10646 comment field.
+It appears in parentheses in the ISO 10646 names list,
+or contains an asterisk to indicate there is
+a note for this code point in Annex P of that standard.
+
+=item B<upper>
+
+is empty if there is no single code point uppercase mapping for I<code>;
+otherwise it is that mapping expressed as at least four hexdigits.
+(L</casespec()> should be used in addition to B<charinfo()>
+for case mappings when the calling program can cope with multiple code point
+mappings.)
+
+=item B<lower>
+
+is empty if there is no single code point lowercase mapping for I<code>;
+otherwise it is that mapping expressed as at least four hexdigits.
+(L</casespec()> should be used in addition to B<charinfo()>
+for case mappings when the calling program can cope with multiple code point
+mappings.)
+
+=item B<title>
+
+is empty if there is no single code point titlecase mapping for I<code>;
+otherwise it is that mapping expressed as at least four hexdigits.
+(L</casespec()> should be used in addition to B<charinfo()>
+for case mappings when the calling program can cope with multiple code point
+mappings.)
+
+=item B<block>
+
+block I<code> belongs to (used in \p{In...}).
+See L</Blocks versus Scripts>.
+
+
+=item B<script>
+
+script I<code> belongs to.
+See L</Blocks versus Scripts>.
+
+=back
+
+Note that you cannot do (de)composition and casing based solely on the
+I<decomposition>, I<combining>, I<lower>, I<upper>, and I<title> fields;
+you will need also the L</compexcl()>, and L</casespec()> functions.
+
+=cut
+
+# NB: This function is duplicated in charnames.pm
+sub _getcode {
+ my $arg = shift;
+
+ if ($arg =~ /^[1-9]\d*$/) {
+ return $arg;
+ } elsif ($arg =~ /^(?:[Uu]\+|0[xX])?([[:xdigit:]]+)$/) {
+ return hex($1);
+ }
+
+ return;
+}
+
+# Lingua::KO::Hangul::Util not part of the standard distribution
+# but it will be used if available.
+
+eval { require Lingua::KO::Hangul::Util };
+my $hasHangulUtil = ! $@;
+if ($hasHangulUtil) {
+ Lingua::KO::Hangul::Util->import();
+}
+
+sub hangul_decomp { # internal: called from charinfo
+ if ($hasHangulUtil) {
+ my @tmp = decomposeHangul(shift);
+ return sprintf("%04X %04X", @tmp) if @tmp == 2;
+ return sprintf("%04X %04X %04X", @tmp) if @tmp == 3;
+ }
+ return;
+}
+
+sub hangul_charname { # internal: called from charinfo
+ return sprintf("HANGUL SYLLABLE-%04X", shift);
+}
+
+sub han_charname { # internal: called from charinfo
+ return sprintf("CJK UNIFIED IDEOGRAPH-%04X", shift);
+}
+
+# Overwritten by data in file
+my %first_last = (
+ 'CJK Ideograph Extension A' => [ 0x3400, 0x4DB5 ],
+ 'CJK Ideograph' => [ 0x4E00, 0x9FA5 ],
+ 'CJK Ideograph Extension B' => [ 0x20000, 0x2A6D6 ],
+);
+
+get_charinfo_ranges();
+
+sub get_charinfo_ranges {
+ my @blocks = keys %first_last;
+
+ my $fh;
+ openunicode( \$fh, 'UnicodeData.txt' );
+ if( defined $fh ){
+ while( my $line = <$fh> ){
+ next unless $line =~ /(?:First|Last)/;
+ if( grep{ $line =~ /[^;]+;<$_\s*,\s*(?:First|Last)>/ }@blocks ){
+ my ($number,$block,$type);
+ ($number,$block) = split /;/, $line;
+ $block =~ s/<|>//g;
+ ($block,$type) = split /, /, $block;
+ my $index = $type eq 'First' ? 0 : 1;
+ $first_last{ $block }->[$index] = hex $number;
+ }
+ }
+ }
+}
+
+my @CharinfoRanges = (
+# block name
+# [ first, last, coderef to name, coderef to decompose ],
+# CJK Ideographs Extension A
+ [ @{ $first_last{'CJK Ideograph Extension A'} }, \&han_charname, undef ],
+# CJK Ideographs
+ [ @{ $first_last{'CJK Ideograph'} }, \&han_charname, undef ],
+# Hangul Syllables
+ [ 0xAC00, 0xD7A3, $hasHangulUtil ? \&getHangulName : \&hangul_charname, \&hangul_decomp ],
+# Non-Private Use High Surrogates
+ [ 0xD800, 0xDB7F, undef, undef ],
+# Private Use High Surrogates
+ [ 0xDB80, 0xDBFF, undef, undef ],
+# Low Surrogates
+ [ 0xDC00, 0xDFFF, undef, undef ],
+# The Private Use Area
+ [ 0xE000, 0xF8FF, undef, undef ],
+# CJK Ideographs Extension B
+ [ @{ $first_last{'CJK Ideograph Extension B'} }, \&han_charname, undef ],
+# Plane 15 Private Use Area
+ [ 0xF0000, 0xFFFFD, undef, undef ],
+# Plane 16 Private Use Area
+ [ 0x100000, 0x10FFFD, undef, undef ],
+);
+
+sub charinfo {
+ my $arg = shift;
+ my $code = _getcode($arg);
+ croak __PACKAGE__, "::charinfo: unknown code '$arg'"
+ unless defined $code;
+ my $hexk = sprintf("%06X", $code);
+ my($rcode,$rname,$rdec);
+ foreach my $range (@CharinfoRanges){
+ if ($range->[0] <= $code && $code <= $range->[1]) {
+ $rcode = $hexk;
+ $rcode =~ s/^0+//;
+ $rcode = sprintf("%04X", hex($rcode));
+ $rname = $range->[2] ? $range->[2]->($code) : '';
+ $rdec = $range->[3] ? $range->[3]->($code) : '';
+ $hexk = sprintf("%06X", $range->[0]); # replace by the first
+ last;
+ }
+ }
+ openunicode(\$UNICODEFH, "UnicodeData.txt");
+ if (defined $UNICODEFH) {
+ use Search::Dict 1.02;
+ if (look($UNICODEFH, "$hexk;", { xfrm => sub { $_[0] =~ /^([^;]+);(.+)/; sprintf "%06X;$2", hex($1) } } ) >= 0) {
+ my $line = <$UNICODEFH>;
+ return unless defined $line;
+ chomp $line;
+ my %prop;
+ @prop{qw(
+ code name category
+ combining bidi decomposition
+ decimal digit numeric
+ mirrored unicode10 comment
+ upper lower title
+ )} = split(/;/, $line, -1);
+ $hexk =~ s/^0+//;
+ $hexk = sprintf("%04X", hex($hexk));
+ if ($prop{code} eq $hexk) {
+ $prop{block} = charblock($code);
+ $prop{script} = charscript($code);
+ if(defined $rname){
+ $prop{code} = $rcode;
+ $prop{name} = $rname;
+ $prop{decomposition} = $rdec;
+ }
+ return \%prop;
+ }
+ }
+ }
+ return;
+}
+
+sub _search { # Binary search in a [[lo,hi,prop],[...],...] table.
+ my ($table, $lo, $hi, $code) = @_;
+
+ return if $lo > $hi;
+
+ my $mid = int(($lo+$hi) / 2);
+
+ if ($table->[$mid]->[0] < $code) {
+ if ($table->[$mid]->[1] >= $code) {
+ return $table->[$mid]->[2];
+ } else {
+ _search($table, $mid + 1, $hi, $code);
+ }
+ } elsif ($table->[$mid]->[0] > $code) {
+ _search($table, $lo, $mid - 1, $code);
+ } else {
+ return $table->[$mid]->[2];
+ }
+}
+
+sub charinrange {
+ my ($range, $arg) = @_;
+ my $code = _getcode($arg);
+ croak __PACKAGE__, "::charinrange: unknown code '$arg'"
+ unless defined $code;
+ _search($range, 0, $#$range, $code);
+}
+
+=head2 B<charblock()>
+
+ use Unicode::UCD 'charblock';
+
+ my $charblock = charblock(0x41);
+ my $charblock = charblock(1234);
+ my $charblock = charblock(0x263a);
+ my $charblock = charblock("U+263a");
+
+ my $range = charblock('Armenian');
+
+With a L</code point argument> charblock() returns the I<block> the code point
+belongs to, e.g. C<Basic Latin>.
+If the code point is unassigned, this returns the block it would belong to if
+it were assigned (which it may in future versions of the Unicode Standard).
+
+See also L</Blocks versus Scripts>.
+
+If supplied with an argument that can't be a code point, charblock() tries
+to do the opposite and interpret the argument as a code point block. The
+return value is a I<range>: an anonymous list of lists that contain
+I<start-of-range>, I<end-of-range> code point pairs. You can test whether
+a code point is in a range using the L</charinrange()> function. If the
+argument is not a known code point block, B<undef> is returned.
+
+=cut
+
+my @BLOCKS;
+my %BLOCKS;
+
+sub _charblocks {
+ unless (@BLOCKS) {
+ if (openunicode(\$BLOCKSFH, "Blocks.txt")) {
+ local $_;
+ while (<$BLOCKSFH>) {
+ if (/^([0-9A-F]+)\.\.([0-9A-F]+);\s+(.+)/) {
+ my ($lo, $hi) = (hex($1), hex($2));
+ my $subrange = [ $lo, $hi, $3 ];
+ push @BLOCKS, $subrange;
+ push @{$BLOCKS{$3}}, $subrange;
+ }
+ }
+ close($BLOCKSFH);
+ }
+ }
+}
+
+sub charblock {
+ my $arg = shift;
+
+ _charblocks() unless @BLOCKS;
+
+ my $code = _getcode($arg);
+
+ if (defined $code) {
+ _search(\@BLOCKS, 0, $#BLOCKS, $code);
+ } else {
+ if (exists $BLOCKS{$arg}) {
+ return dclone $BLOCKS{$arg};
+ } else {
+ return;
+ }
+ }
+}
+
+=head2 B<charscript()>
+
+ use Unicode::UCD 'charscript';
+
+ my $charscript = charscript(0x41);
+ my $charscript = charscript(1234);
+ my $charscript = charscript("U+263a");
+
+ my $range = charscript('Thai');
+
+With a L</code point argument> charscript() returns the I<script> the
+code point belongs to, e.g. C<Latin>, C<Greek>, C<Han>.
+If the code point is unassigned, it returns B<undef>
+
+If supplied with an argument that can't be a code point, charscript() tries
+to do the opposite and interpret the argument as a code point script. The
+return value is a I<range>: an anonymous list of lists that contain
+I<start-of-range>, I<end-of-range> code point pairs. You can test whether a
+code point is in a range using the L</charinrange()> function. If the
+argument is not a known code point script, B<undef> is returned.
+
+See also L</Blocks versus Scripts>.
+
+=cut
+
+my @SCRIPTS;
+my %SCRIPTS;
+
+sub _charscripts {
+ unless (@SCRIPTS) {
+ if (openunicode(\$SCRIPTSFH, "Scripts.txt")) {
+ local $_;
+ while (<$SCRIPTSFH>) {
+ if (/^([0-9A-F]+)(?:\.\.([0-9A-F]+))?\s+;\s+(\w+)/) {
+ my ($lo, $hi) = (hex($1), $2 ? hex($2) : hex($1));
+ my $script = lc($3);
+ $script =~ s/\b(\w)/uc($1)/ge;
+ my $subrange = [ $lo, $hi, $script ];
+ push @SCRIPTS, $subrange;
+ push @{$SCRIPTS{$script}}, $subrange;
+ }
+ }
+ close($SCRIPTSFH);
+ @SCRIPTS = sort { $a->[0] <=> $b->[0] } @SCRIPTS;
+ }
+ }
+}
+
+sub charscript {
+ my $arg = shift;
+
+ _charscripts() unless @SCRIPTS;
+
+ my $code = _getcode($arg);
+
+ if (defined $code) {
+ _search(\@SCRIPTS, 0, $#SCRIPTS, $code);
+ } else {
+ if (exists $SCRIPTS{$arg}) {
+ return dclone $SCRIPTS{$arg};
+ } else {
+ return;
+ }
+ }
+}
+
+=head2 B<charblocks()>
+
+ use Unicode::UCD 'charblocks';
+
+ my $charblocks = charblocks();
+
+charblocks() returns a reference to a hash with the known block names
+as the keys, and the code point ranges (see L</charblock()>) as the values.
+
+See also L</Blocks versus Scripts>.
+
+=cut
+
+sub charblocks {
+ _charblocks() unless %BLOCKS;
+ return dclone \%BLOCKS;
+}
+
+=head2 B<charscripts()>
+
+ use Unicode::UCD 'charscripts';
+
+ my $charscripts = charscripts();
+
+charscripts() returns a reference to a hash with the known script
+names as the keys, and the code point ranges (see L</charscript()>) as
+the values.
+
+See also L</Blocks versus Scripts>.
+
+=cut
+
+sub charscripts {
+ _charscripts() unless %SCRIPTS;
+ return dclone \%SCRIPTS;
+}
+
+=head2 B<charinrange()>
+
+In addition to using the C<\p{In...}> and C<\P{In...}> constructs, you
+can also test whether a code point is in the I<range> as returned by
+L</charblock()> and L</charscript()> or as the values of the hash returned
+by L</charblocks()> and L</charscripts()> by using charinrange():
+
+ use Unicode::UCD qw(charscript charinrange);
+
+ $range = charscript('Hiragana');
+ print "looks like hiragana\n" if charinrange($range, $codepoint);
+
+=cut
+
+my %GENERAL_CATEGORIES =
+ (
+ 'L' => 'Letter',
+ 'LC' => 'CasedLetter',
+ 'Lu' => 'UppercaseLetter',
+ 'Ll' => 'LowercaseLetter',
+ 'Lt' => 'TitlecaseLetter',
+ 'Lm' => 'ModifierLetter',
+ 'Lo' => 'OtherLetter',
+ 'M' => 'Mark',
+ 'Mn' => 'NonspacingMark',
+ 'Mc' => 'SpacingMark',
+ 'Me' => 'EnclosingMark',
+ 'N' => 'Number',
+ 'Nd' => 'DecimalNumber',
+ 'Nl' => 'LetterNumber',
+ 'No' => 'OtherNumber',
+ 'P' => 'Punctuation',
+ 'Pc' => 'ConnectorPunctuation',
+ 'Pd' => 'DashPunctuation',
+ 'Ps' => 'OpenPunctuation',
+ 'Pe' => 'ClosePunctuation',
+ 'Pi' => 'InitialPunctuation',
+ 'Pf' => 'FinalPunctuation',
+ 'Po' => 'OtherPunctuation',
+ 'S' => 'Symbol',
+ 'Sm' => 'MathSymbol',
+ 'Sc' => 'CurrencySymbol',
+ 'Sk' => 'ModifierSymbol',
+ 'So' => 'OtherSymbol',
+ 'Z' => 'Separator',
+ 'Zs' => 'SpaceSeparator',
+ 'Zl' => 'LineSeparator',
+ 'Zp' => 'ParagraphSeparator',
+ 'C' => 'Other',
+ 'Cc' => 'Control',
+ 'Cf' => 'Format',
+ 'Cs' => 'Surrogate',
+ 'Co' => 'PrivateUse',
+ 'Cn' => 'Unassigned',
+ );
+
+sub general_categories {
+ return dclone \%GENERAL_CATEGORIES;
+}
+
+=head2 B<general_categories()>
+
+ use Unicode::UCD 'general_categories';
+
+ my $categories = general_categories();
+
+This returns a reference to a hash which has short
+general category names (such as C<Lu>, C<Nd>, C<Zs>, C<S>) as keys and long
+names (such as C<UppercaseLetter>, C<DecimalNumber>, C<SpaceSeparator>,
+C<Symbol>) as values. The hash is reversible in case you need to go
+from the long names to the short names. The general category is the
+one returned from
+L</charinfo()> under the C<category> key.
+
+=cut
+
+my %BIDI_TYPES =
+ (
+ 'L' => 'Left-to-Right',
+ 'LRE' => 'Left-to-Right Embedding',
+ 'LRO' => 'Left-to-Right Override',
+ 'R' => 'Right-to-Left',
+ 'AL' => 'Right-to-Left Arabic',
+ 'RLE' => 'Right-to-Left Embedding',
+ 'RLO' => 'Right-to-Left Override',
+ 'PDF' => 'Pop Directional Format',
+ 'EN' => 'European Number',
+ 'ES' => 'European Number Separator',
+ 'ET' => 'European Number Terminator',
+ 'AN' => 'Arabic Number',
+ 'CS' => 'Common Number Separator',
+ 'NSM' => 'Non-Spacing Mark',
+ 'BN' => 'Boundary Neutral',
+ 'B' => 'Paragraph Separator',
+ 'S' => 'Segment Separator',
+ 'WS' => 'Whitespace',
+ 'ON' => 'Other Neutrals',
+ );
+
+=head2 B<bidi_types()>
+
+ use Unicode::UCD 'bidi_types';
+
+ my $categories = bidi_types();
+
+This returns a reference to a hash which has the short
+bidi (bidirectional) type names (such as C<L>, C<R>) as keys and long
+names (such as C<Left-to-Right>, C<Right-to-Left>) as values. The
+hash is reversible in case you need to go from the long names to the
+short names. The bidi type is the one returned from
+L</charinfo()>
+under the C<bidi> key. For the exact meaning of the various bidi classes
+the Unicode TR9 is recommended reading:
+L<http://www.unicode.org/reports/tr9/>
+(as of Unicode 5.0.0)
+
+=cut
+
+sub bidi_types {
+ return dclone \%BIDI_TYPES;
+}
+
+=head2 B<compexcl()>
+
+ use Unicode::UCD 'compexcl';
+
+ my $compexcl = compexcl(0x09dc);
+
+This returns B<true> if the
+L</code point argument> should not be produced by composition normalization,
+B<AND> if that fact is not otherwise determinable from the Unicode data base.
+It currently does not return B<true> if the code point has a decomposition
+consisting of another single code point, nor if its decomposition starts
+with a code point whose combining class is non-zero. Code points that meet
+either of these conditions should also not be produced by composition
+normalization.
+
+It returns B<false> otherwise.
+
+=cut
+
+my %COMPEXCL;
+
+sub _compexcl {
+ unless (%COMPEXCL) {
+ if (openunicode(\$COMPEXCLFH, "CompositionExclusions.txt")) {
+ local $_;
+ while (<$COMPEXCLFH>) {
+ if (/^([0-9A-F]+)\s+\#\s+/) {
+ my $code = hex($1);
+ $COMPEXCL{$code} = undef;
+ }
+ }
+ close($COMPEXCLFH);
+ }
+ }
+}
+
+sub compexcl {
+ my $arg = shift;
+ my $code = _getcode($arg);
+ croak __PACKAGE__, "::compexcl: unknown code '$arg'"
+ unless defined $code;
+
+ _compexcl() unless %COMPEXCL;
+
+ return exists $COMPEXCL{$code};
+}
+
+=head2 B<casefold()>
+
+ use Unicode::UCD 'casefold';
+
+ my $casefold = casefold(0xDF);
+ if (defined $casefold) {
+ my @full_fold_hex = split / /, $casefold->{'full'};
+ my $full_fold_string =
+ join "", map {chr(hex($_))} @full_fold_hex;
+ my @turkic_fold_hex =
+ split / /, ($casefold->{'turkic'} ne "")
+ ? $casefold->{'turkic'}
+ : $casefold->{'full'};
+ my $turkic_fold_string =
+ join "", map {chr(hex($_))} @turkic_fold_hex;
+ }
+ if (defined $casefold && $casefold->{'simple'} ne "") {
+ my $simple_fold_hex = $casefold->{'simple'};
+ my $simple_fold_string = chr(hex($simple_fold_hex));
+ }
+
+This returns the (almost) locale-independent case folding of the
+character specified by the L</code point argument>.
+
+If there is no case folding for that code point, B<undef> is returned.
+
+If there is a case folding for that code point, a reference to a hash
+with the following fields is returned:
+
+=over
+
+=item B<code>
+
+the input L</code point argument> expressed in hexadecimal, with leading zeros
+added if necessary to make it contain at least four hexdigits
+
+=item B<full>
+
+one or more codes (separated by spaces) that taken in order give the
+code points for the case folding for I<code>.
+Each has at least four hexdigits.
+
+=item B<simple>
+
+is empty, or is exactly one code with at least four hexdigits which can be used
+as an alternative case folding when the calling program cannot cope with the
+fold being a sequence of multiple code points. If I<full> is just one code
+point, then I<simple> equals I<full>. If there is no single code point folding
+defined for I<code>, then I<simple> is the empty string. Otherwise, it is an
+inferior, but still better-than-nothing alternative folding to I<full>.
+
+=item B<mapping>
+
+is the same as I<simple> if I<simple> is not empty, and it is the same as I<full>
+otherwise. It can be considered to be the simplest possible folding for
+I<code>. It is defined primarily for backwards compatibility.
+
+=item B<status>
+
+is C<C> (for C<common>) if the best possible fold is a single code point
+(I<simple> equals I<full> equals I<mapping>). It is C<S> if there are distinct
+folds, I<simple> and I<full> (I<mapping> equals I<simple>). And it is C<F> if
+there only a I<full> fold (I<mapping> equals I<full>; I<simple> is empty). Note
+that this
+describes the contents of I<mapping>. It is defined primarily for backwards
+compatibility.
+
+On versions 3.1 and earlier of Unicode, I<status> can also be
+C<I> which is the same as C<C> but is a special case for dotted uppercase I and
+dotless lowercase i:
+
+=over
+
+=item B<*>
+
+If you use this C<I> mapping, the result is case-insensitive,
+but dotless and dotted I's are not distinguished
+
+=item B<*>
+
+If you exclude this C<I> mapping, the result is not fully case-insensitive, but
+dotless and dotted I's are distinguished
+
+=back
+
+=item B<turkic>
+
+contains any special folding for Turkic languages. For versions of Unicode
+starting with 3.2, this field is empty unless I<code> has a different folding
+in Turkic languages, in which case it is one or more codes (separated by
+spaces) that taken in order give the code points for the case folding for
+I<code> in those languages.
+Each code has at least four hexdigits.
+Note that this folding does not maintain canonical equivalence without
+additional processing.
+
+For versions of Unicode 3.1 and earlier, this field is empty unless there is a
+special folding for Turkic languages, in which case I<status> is C<I>, and
+I<mapping>, I<full>, I<simple>, and I<turkic> are all equal.
+
+=back
+
+Programs that want complete generality and the best folding results should use
+the folding contained in the I<full> field. But note that the fold for some
+code points will be a sequence of multiple code points.
+
+Programs that can't cope with the fold mapping being multiple code points can
+use the folding contained in the I<simple> field, with the loss of some
+generality. In Unicode 5.1, about 7% of the defined foldings have no single
+code point folding.
+
+The I<mapping> and I<status> fields are provided for backwards compatibility for
+existing programs. They contain the same values as in previous versions of
+this function.
+
+Locale is not completely independent. The I<turkic> field contains results to
+use when the locale is a Turkic language.
+
+For more information about case mappings see
+L<http://www.unicode.org/unicode/reports/tr21>
+
+=cut
+
+my %CASEFOLD;
+
+sub _casefold {
+ unless (%CASEFOLD) {
+ if (openunicode(\$CASEFOLDFH, "CaseFolding.txt")) {
+ local $_;
+ while (<$CASEFOLDFH>) {
+ if (/^([0-9A-F]+); ([CFIST]); ([0-9A-F]+(?: [0-9A-F]+)*);/) {
+ my $code = hex($1);
+ $CASEFOLD{$code}{'code'} = $1;
+ $CASEFOLD{$code}{'turkic'} = "" unless
+ defined $CASEFOLD{$code}{'turkic'};
+ if ($2 eq 'C' || $2 eq 'I') { # 'I' is only on 3.1 and
+ # earlier Unicodes
+ # Both entries there (I
+ # only checked 3.1) are
+ # the same as C, and
+ # there are no other
+ # entries for those
+ # codepoints, so treat
+ # as if C, but override
+ # the turkic one for
+ # 'I'.
+ $CASEFOLD{$code}{'status'} = $2;
+ $CASEFOLD{$code}{'full'} = $CASEFOLD{$code}{'simple'} =
+ $CASEFOLD{$code}{'mapping'} = $3;
+ $CASEFOLD{$code}{'turkic'} = $3 if $2 eq 'I';
+ } elsif ($2 eq 'F') {
+ $CASEFOLD{$code}{'full'} = $3;
+ unless (defined $CASEFOLD{$code}{'simple'}) {
+ $CASEFOLD{$code}{'simple'} = "";
+ $CASEFOLD{$code}{'mapping'} = $3;
+ $CASEFOLD{$code}{'status'} = $2;
+ }
+ } elsif ($2 eq 'S') {
+
+
+ # There can't be a simple without a full, and simple
+ # overrides all but full
+
+ $CASEFOLD{$code}{'simple'} = $3;
+ $CASEFOLD{$code}{'mapping'} = $3;
+ $CASEFOLD{$code}{'status'} = $2;
+ } elsif ($2 eq 'T') {
+ $CASEFOLD{$code}{'turkic'} = $3;
+ } # else can't happen because only [CIFST] are possible
+ }
+ }
+ close($CASEFOLDFH);
+ }
+ }
+}
+
+sub casefold {
+ my $arg = shift;
+ my $code = _getcode($arg);
+ croak __PACKAGE__, "::casefold: unknown code '$arg'"
+ unless defined $code;
+
+ _casefold() unless %CASEFOLD;
+
+ return $CASEFOLD{$code};
+}
+
+=head2 B<casespec()>
+
+ use Unicode::UCD 'casespec';
+
+ my $casespec = casespec(0xFB00);
+
+This returns the potentially locale-dependent case mappings of the L</code point
+argument>. The mappings may be longer than a single code point (which the basic
+Unicode case mappings as returned by L</charinfo()> never are).
+
+If there are no case mappings for the L</code point argument>, or if all three
+possible mappings (I<lower>, I<title> and I<upper>) result in single code
+points and are locale independent and unconditional, B<undef> is returned
+(which means that the case mappings, if any, for the code point are those
+returned by L</charinfo()>).
+
+Otherwise, a reference to a hash giving the mappings (or a reference to a hash
+of such hashes, explained below) is returned with the following keys and their
+meanings:
+
+The keys in the bottom layer hash with the meanings of their values are:
+
+=over
+
+=item B<code>
+
+the input L</code point argument> expressed in hexadecimal, with leading zeros
+added if necessary to make it contain at least four hexdigits
+
+=item B<lower>
+
+one or more codes (separated by spaces) that taken in order give the
+code points for the lower case of I<code>.
+Each has at least four hexdigits.
+
+=item B<title>
+
+one or more codes (separated by spaces) that taken in order give the
+code points for the title case of I<code>.
+Each has at least four hexdigits.
+
+=item B<lower>
+
+one or more codes (separated by spaces) that taken in order give the
+code points for the upper case of I<code>.
+Each has at least four hexdigits.
+
+=item B<condition>
+
+the conditions for the mappings to be valid.
+If B<undef>, the mappings are always valid.
+When defined, this field is a list of conditions,
+all of which must be true for the mappings to be valid.
+The list consists of one or more
+I<locales> (see below)
+and/or I<contexts> (explained in the next paragraph),
+separated by spaces.
+(Other than as used to separate elements, spaces are to be ignored.)
+Case distinctions in the condition list are not significant.
+Conditions preceded by "NON_" represent the negation of the condition.
+
+A I<context> is one of those defined in the Unicode standard.
+For Unicode 5.1, they are defined in Section 3.13 C<Default Case Operations>
+available at
+L<http://www.unicode.org/versions/Unicode5.1.0/>.
+These are for context-sensitive casing.
+
+=back
+
+The hash described above is returned for locale-independent casing, where
+at least one of the mappings has length longer than one. If B<undef> is
+returned, the code point may have mappings, but if so, all are length one,
+and are returned by L</charinfo()>.
+Note that when this function does return a value, it will be for the complete
+set of mappings for a code point, even those whose length is one.
+
+If there are additional casing rules that apply only in certain locales,
+an additional key for each will be defined in the returned hash. Each such key
+will be its locale name, defined as a 2-letter ISO 3166 country code, possibly
+followed by a "_" and a 2-letter ISO language code (possibly followed by a "_"
+and a variant code). You can find the lists of all possible locales, see
+L<Locale::Country> and L<Locale::Language>.
+(In Unicode 5.1, the only locales returned by this function
+are C<lt>, C<tr>, and C<az>.)
+
+Each locale key is a reference to a hash that has the form above, and gives
+the casing rules for that particular locale, which take precedence over the
+locale-independent ones when in that locale.
+
+If the only casing for a code point is locale-dependent, then the returned
+hash will not have any of the base keys, like C<code>, C<upper>, etc., but
+will contain only locale keys.
+
+For more information about case mappings see
+L<http://www.unicode.org/unicode/reports/tr21/>
+
+=cut
+
+my %CASESPEC;
+
+sub _casespec {
+ unless (%CASESPEC) {
+ if (openunicode(\$CASESPECFH, "SpecialCasing.txt")) {
+ local $_;
+ while (<$CASESPECFH>) {
+ if (/^([0-9A-F]+); ([0-9A-F]+(?: [0-9A-F]+)*)?; ([0-9A-F]+(?: [0-9A-F]+)*)?; ([0-9A-F]+(?: [0-9A-F]+)*)?; (\w+(?: \w+)*)?/) {
+ my ($hexcode, $lower, $title, $upper, $condition) =
+ ($1, $2, $3, $4, $5);
+ my $code = hex($hexcode);
+ if (exists $CASESPEC{$code}) {
+ if (exists $CASESPEC{$code}->{code}) {
+ my ($oldlower,
+ $oldtitle,
+ $oldupper,
+ $oldcondition) =
+ @{$CASESPEC{$code}}{qw(lower
+ title
+ upper
+ condition)};
+ if (defined $oldcondition) {
+ my ($oldlocale) =
+ ($oldcondition =~ /^([a-z][a-z](?:_\S+)?)/);
+ delete $CASESPEC{$code};
+ $CASESPEC{$code}->{$oldlocale} =
+ { code => $hexcode,
+ lower => $oldlower,
+ title => $oldtitle,
+ upper => $oldupper,
+ condition => $oldcondition };
+ }
+ }
+ my ($locale) =
+ ($condition =~ /^([a-z][a-z](?:_\S+)?)/);
+ $CASESPEC{$code}->{$locale} =
+ { code => $hexcode,
+ lower => $lower,
+ title => $title,
+ upper => $upper,
+ condition => $condition };
+ } else {
+ $CASESPEC{$code} =
+ { code => $hexcode,
+ lower => $lower,
+ title => $title,
+ upper => $upper,
+ condition => $condition };
+ }
+ }
+ }
+ close($CASESPECFH);
+ }
+ }
+}
+
+sub casespec {
+ my $arg = shift;
+ my $code = _getcode($arg);
+ croak __PACKAGE__, "::casespec: unknown code '$arg'"
+ unless defined $code;
+
+ _casespec() unless %CASESPEC;
+
+ return ref $CASESPEC{$code} ? dclone $CASESPEC{$code} : $CASESPEC{$code};
+}
+
+=head2 B<namedseq()>
+
+ use Unicode::UCD 'namedseq';
+
+ my $namedseq = namedseq("KATAKANA LETTER AINU P");
+ my @namedseq = namedseq("KATAKANA LETTER AINU P");
+ my %namedseq = namedseq();
+
+If used with a single argument in a scalar context, returns the string
+consisting of the code points of the named sequence, or B<undef> if no
+named sequence by that name exists. If used with a single argument in
+a list context, it returns the list of the ordinals of the code points. If used
+with no
+arguments in a list context, returns a hash with the names of the
+named sequences as the keys and the named sequences as strings as
+the values. Otherwise, it returns B<undef> or an empty list depending
+on the context.
+
+This function only operates on officially approved (not provisional) named
+sequences.
+
+=cut
+
+my %NAMEDSEQ;
+
+sub _namedseq {
+ unless (%NAMEDSEQ) {
+ if (openunicode(\$NAMEDSEQFH, "NamedSequences.txt")) {
+ local $_;
+ while (<$NAMEDSEQFH>) {
+ if (/^(.+)\s*;\s*([0-9A-F]+(?: [0-9A-F]+)*)$/) {
+ my ($n, $s) = ($1, $2);
+ my @s = map { chr(hex($_)) } split(' ', $s);
+ $NAMEDSEQ{$n} = join("", @s);
+ }
+ }
+ close($NAMEDSEQFH);
+ }
+ }
+}
+
+sub namedseq {
+ _namedseq() unless %NAMEDSEQ;
+ my $wantarray = wantarray();
+ if (defined $wantarray) {
+ if ($wantarray) {
+ if (@_ == 0) {
+ return %NAMEDSEQ;
+ } elsif (@_ == 1) {
+ my $s = $NAMEDSEQ{ $_[0] };
+ return defined $s ? map { ord($_) } split('', $s) : ();
+ }
+ } elsif (@_ == 1) {
+ return $NAMEDSEQ{ $_[0] };
+ }
+ }
+ return;
+}
+
+=head2 Unicode::UCD::UnicodeVersion
+
+This returns the version of the Unicode Character Database, in other words, the
+version of the Unicode standard the database implements. The version is a
+string of numbers delimited by dots (C<'.'>).
+
+=cut
+
+my $UNICODEVERSION;
+
+sub UnicodeVersion {
+ unless (defined $UNICODEVERSION) {
+ openunicode(\$VERSIONFH, "version");
+ chomp($UNICODEVERSION = <$VERSIONFH>);
+ close($VERSIONFH);
+ croak __PACKAGE__, "::VERSION: strange version '$UNICODEVERSION'"
+ unless $UNICODEVERSION =~ /^\d+(?:\.\d+)+$/;
+ }
+ return $UNICODEVERSION;
+}
+
+=head2 B<Blocks versus Scripts>
+
+The difference between a block and a script is that scripts are closer
+to the linguistic notion of a set of code points required to present
+languages, while block is more of an artifact of the Unicode code point
+numbering and separation into blocks of (mostly) 256 code points.
+
+For example the Latin B<script> is spread over several B<blocks>, such
+as C<Basic Latin>, C<Latin 1 Supplement>, C<Latin Extended-A>, and
+C<Latin Extended-B>. On the other hand, the Latin script does not
+contain all the characters of the C<Basic Latin> block (also known as
+ASCII): it includes only the letters, and not, for example, the digits
+or the punctuation.
+
+For blocks see L<http://www.unicode.org/Public/UNIDATA/Blocks.txt>
+
+For scripts see UTR #24: L<http://www.unicode.org/unicode/reports/tr24/>
+
+=head2 B<Matching Scripts and Blocks>
+
+Scripts are matched with the regular-expression construct
+C<\p{...}> (e.g. C<\p{Tibetan}> matches characters of the Tibetan script),
+while C<\p{In...}> is used for blocks (e.g. C<\p{InTibetan}> matches
+any of the 256 code points in the Tibetan block).
+
+
+=head2 Implementation Note
+
+The first use of charinfo() opens a read-only filehandle to the Unicode
+Character Database (the database is included in the Perl distribution).
+The filehandle is then kept open for further queries. In other words,
+if you are wondering where one of your filehandles went, that's where.
+
+=head1 BUGS
+
+Does not yet support EBCDIC platforms.
+
+L</compexcl()> should give a complete list of excluded code points.
+
+=head1 AUTHOR
+
+Jarkko Hietaniemi
+
+=cut
+
+1;