#!./perl

use strict;
use warnings;
use utf8;

# This tests that the ANYOF nodes generated by bracketed character classes are
# as expected.  The representation of these is not guaranteed, and this test
# may need to be updated if it changes.  But it is here to make sure that no
# unexpected changes occur.  These could come from faulty generation of the
# node, or faulty display of them (or both).  Because these causes come from
# very different parts of the regex compiler, it is unlikely that a commit
# would change both of them, so this test will adequately serve to test both.

BEGIN {
    chdir 't' if -d 't';
    require './test.pl';
    set_up_inc('../lib','.','../ext/re');
    require Config; import Config;
    skip_all('no re module') unless defined &DynaLoader::boot_DynaLoader;
}

# An array is used instead of a hash, so that the tests are carried out in the
# order given by this file.  Even-numbered indices are the regexes to compile.
# The next higher element is the expected compilation result.
#
# It is painful to port some of these to EBCDIC, as not only do the code point
# numbers change (for those < 256), but the order changes, as the compiled
# version is sorted by native code point order.  On EBCDIC, \r comes before
# \n, and 'k' before "K', for example.  So, the tests where there are
# differences are skipped on EBCDIC.  They are all at the beginning of the
# array, and a special marker entry is used to delmit the boundary between
# skipped and not skipped.
#
# NOTE:  If the pattern contains (?8) it will be upgraded to UTF-8 after
#        stripping that

use Unicode::UCD;
my $highest_cp = $Unicode::UCD::MAX_CP;
my $highest_cp_string = sprintf "%X", $highest_cp;
$highest_cp_string = "$highest_cp_string";

my $infinity = $highest_cp_string;
$infinity =~ s/^7/F/;  # Make infinity larger than the largest legal one, and
                       # at the time of this writing, we really internally
                       # allow UV_MAX to be infinity.

sub  get_compiled ($) {
    # Convert platform-independent values to what is suitable for the
    # platform

    my $pattern = shift;

    $pattern =~ s/{INFTY}/\\x{$infinity}/g;
    $pattern =~ s/{HIGHEST_CP}/\\x{$highest_cp_string}/g;
    my $use_utf8 = ($pattern =~ s/\Q(?8)//);

    $pattern = "my \$a = '$pattern';";
    $pattern .= "utf8::upgrade(\$a);" if $use_utf8;
    $pattern .= "qr/\$a/";
    my $actual_pattern = "use re qw(Debug COMPILE); $pattern";

    my $result = fresh_perl($actual_pattern);
    if ($? != 0) {  # Re-run so as to display STDERR.
        fail($pattern, "Until this is fixed, the planned number of tests will be wrong");
        fresh_perl($actual_pattern, { stderr => 0, verbose => 1 });
        return;
    }

    # The Debug output will come back as a bunch of lines.  We are
    # interested only in the line after /Final program/
    my @lines = split /\n/, $result;
    while (defined ($_ = shift @lines)) {
        last if /Final program/;
    }

    $_ = shift @lines;

    s/ \s* \( \d+ \) \s* //x;   # Get rid of the node branch
    s/ ^ \s* \d+ : \s* //x;     # ... And the node number

    # Use platform-independent values
    s/$infinity/INFTY/ig;
    s/$highest_cp_string/HIGHEST_CP/ig;

    return $_;
}

# Note: EXACTish lowercases the hex; ANYOF uppercases, without braces

my @tests = (
    '[\xe0\xc0]' => 'EXACTFU <\\x{e0}>',
    '[\xe1\xc1]' => 'EXACTFU <\\x{e1}>',
    '[\xe2\xc2]' => 'EXACTFU <\\x{e2}>',
    '[\xe3\xc3]' => 'EXACTFU <\\x{e3}>',
    '[\xe4\xc4]' => 'EXACTFU <\\x{e4}>',
    '[\xc5\xe5]' => 'ANYOF[\\xC5\\xE5]',
    '[\xe6\xc6]' => 'EXACTFU <\\x{e6}>',
    '[\xe7\xc7]' => 'EXACTFU <\\x{e7}>',
    '[\xe8\xc8]' => 'EXACTFU <\\x{e8}>',
    '[\xe9\xc9]' => 'EXACTFU <\\x{e9}>',
    '[\xea\xca]' => 'EXACTFU <\\x{ea}>',
    '[\xeb\xcb]' => 'EXACTFU <\\x{eb}>',
    '[\xec\xcc]' => 'EXACTFU <\\x{ec}>',
    '[\xee\xce]' => 'EXACTFU <\\x{ee}>',
    '[\xef\xcf]' => 'EXACTFU <\\x{ef}>',
    '[\xf0\xd0]' => 'EXACTFU <\\x{f0}>',
    '[\xf1\xd1]' => 'EXACTFU <\\x{f1}>',
    '[\xf2\xd2]' => 'EXACTFU <\\x{f2}>',
    '[\xf3\xd3]' => 'EXACTFU <\\x{f3}>',
    '[\xf4\xd4]' => 'EXACTFU <\\x{f4}>',
    '[\xf5\xd5]' => 'EXACTFU <\\x{f5}>',
    '[\xf6\xd6]' => 'EXACTFU <\\x{f6}>',
    '[\xf8\xd8]' => 'EXACTFU <\\x{f8}>',
    '[\xf9\xd9]' => 'EXACTFU <\\x{f9}>',
    '[\xfa\xda]' => 'EXACTFU <\\x{fa}>',
    '[\xfb\xdb]' => 'EXACTFU <\\x{fb}>',
    '[\xfc\xdc]' => 'EXACTFU <\\x{fc}>',
    '[\xfd\xdd]' => 'EXACTFU <\\x{fd}>',
    '[\xfe\xde]' => 'EXACTFU <\\x{fe}>',

    '[[{]' => 'ANYOFM[\[\{]',
    '[^\S ]' => 'ANYOFD[\t\n\x0B\f\r{utf8}\x85\xA0][1680 2000-200A 2028-2029 202F 205F 3000]',
    '[^\n\r]' => 'ANYOF[^\n\r][0100-INFTY]',
    '[^\/\|,\$\%%\@\ \%"\<\>\:\#\&\*\{\}\[\]\(\)]' => 'ANYOF[^ "#$%&()*,/:<>@\[\]\{|\}][0100-INFTY]',
    '[[:ascii:]]' => 'ANYOFM[\x00-\x7F]',
    '[[:^ascii:]]' => 'NANYOFM[\x00-\x7F]',
    '[[:^ascii:]\x{2C2}]' => 'NANYOFM[\x00-\x7F]',
    '(?u)[[:ascii:]]' => 'ANYOFM[\x00-\x7F]',
    '(?u)[[:^ascii:]]' => 'NANYOFM[\x00-\x7F]',
    '(?a)[[:ascii:]]' => 'ANYOFM[\x00-\x7F]',
    '(?a)[[:^ascii:]]' => 'NANYOFM[\x00-\x7F]',
    '(?a)[[:^ascii:]\x{2C2}]' => 'NANYOFM[\x00-\x7F]',
    '[[:cntrl:]]' => 'POSIXD[:cntrl:]',
    '[^[:^print:][:^ascii:]]' => 'POSIXA[:print:]',
    '[[:blank:]]' => 'POSIXD[:blank:]',
    '[ [:blank:]]' => 'POSIXD[:blank:]',
    '[_[:blank:]]' => 'ANYOFD[\t _{utf8}\xA0][1680 2000-200A 202F 205F 3000]',
    '[_[:^blank:]]' => 'NPOSIXD[:blank:]',
    '[\xA0[:^blank:]]' => 'ANYOF[^\t ][0100-167F 1681-1FFF 200B-202E 2030-205E 2060-2FFF 3001-INFTY]',
    '(?d:[_[:^blank:]])' => 'NPOSIXD[:blank:]',
    '[\x{07}-\x{0B}]' => 'ANYOFR[\a\b\t\n\x0B]',
    '(?l)[\x{2029}]' => 'EXACTL <\x{2029}>',
    '(?l)(?[\x{2029}])' => 'ANYOFL{utf8-locale-reqd}[2029]', # regex sets requires utf8 locale for /l
    '(?il)[\x{212A}]' => 'EXACTFL <\\x{212a}>',
    '(?il)(?[\x{212A}])' => 'ANYOFL{utf8-locale-reqd}[Kk][212A]',

    '(?i)b[s]\xe0' => 'ANYOFM[Bb]',    # The s goes into a 2nd node

    '[aA]' => 'ANYOFM[Aa]',
    '[bB]' => 'ANYOFM[Bb]',
    '[kK]' => 'ANYOFM[Kk]',

    'ebcdic_ok_below_this_marker',

    '(?i:[^:])' => 'NANYOFM[:]',

    '[^\n]' => 'REG_ANY',

    '[[:alpha:]]' => 'POSIXD[:alpha:]',
    '[[:^alpha:]]' => 'NPOSIXD[:alpha:]',
    '[[:^alpha:]\x{2C2}]' => 'NPOSIXU[:alpha:]',
    '(?l)[[:alpha:]]' => 'POSIXL[:alpha:]',
    '(?l)[[:^alpha:]]' => 'NPOSIXL[:alpha:]',
    '(?l)[[:^alpha:]\x{2C2}]' => 'NPOSIXL[:alpha:]',
    '(?u)[[:alpha:]]' => 'POSIXU[:alpha:]',
    '(?u)[[:^alpha:]]' => 'NPOSIXU[:alpha:]',
    '(?a)[[:alpha:]]' => 'POSIXA[:alpha:]',
    '(?a)[[:^alpha:]]' => 'NPOSIXA[:alpha:]',
    '(?a)[[:^alpha:]\x{2C2}]' => 'NPOSIXA[:alpha:]',
    '[[:alpha:][:^alpha:]]' => 'SANY',
    '[^[:alpha:][:^alpha:]]' => 'OPFAIL',
    '(?l)[[:alpha:][:^alpha:]]' => 'SANY',
    '(?l)[^[:alpha:][:^alpha:]]' => 'OPFAIL',
    '(?u)[[:alpha:][:^alpha:]]' => 'SANY',
    '(?u)[^[:alpha:][:^alpha:]]' => 'OPFAIL',
    '(?a)[[:alpha:][:^alpha:]]' => 'SANY',
    '(?a)[^[:alpha:][:^alpha:]]' => 'OPFAIL',
    '[[:alnum:]]' => 'POSIXD[:alnum:]',
    '[[:^alnum:]]' => 'NPOSIXD[:alnum:]',
    '[[:^alnum:]\x{2C2}]' => 'NPOSIXU[:alnum:]',
    '(?l)[[:alnum:]]' => 'POSIXL[:alnum:]',
    '(?l)[[:^alnum:]]' => 'NPOSIXL[:alnum:]',
    '(?l)[[:^alnum:]\x{2C2}]' => 'NPOSIXL[:alnum:]',
    '(?u)[[:alnum:]]' => 'POSIXU[:alnum:]',
    '(?u)[[:^alnum:]]' => 'NPOSIXU[:alnum:]',
    '(?a)[[:alnum:]]' => 'POSIXA[:alnum:]',
    '(?a)[[:^alnum:]]' => 'NPOSIXA[:alnum:]',
    '(?a)[[:^alnum:]\x{2C2}]' => 'NPOSIXA[:alnum:]',
    '[[:alnum:][:^alnum:]]' => 'SANY',
    '[^[:alnum:][:^alnum:]]' => 'OPFAIL',
    '(?l)[[:alnum:][:^alnum:]]' => 'SANY',
    '(?l)[^[:alnum:][:^alnum:]]' => 'OPFAIL',
    '(?u)[[:alnum:][:^alnum:]]' => 'SANY',
    '(?u)[^[:alnum:][:^alnum:]]' => 'OPFAIL',
    '(?a)[[:alnum:][:^alnum:]]' => 'SANY',
    '(?a)[^[:alnum:][:^alnum:]]' => 'OPFAIL',
    '(?l)[[:ascii:]]' => 'POSIXL[:ascii:]',
    '(?l)[[:^ascii:]]' => 'NPOSIXL[:ascii:]',
    '(?l)[[:^ascii:]\x{2C2}]' => 'NPOSIXL[:ascii:]',
    '[[:ascii:][:^ascii:]]' => 'SANY',
    '[^[:ascii:][:^ascii:]]' => 'OPFAIL',
    '(?l)[[:ascii:][:^ascii:]]' => 'SANY',
    '(?l)[^[:ascii:][:^ascii:]]' => 'OPFAIL',
    '(?u)[[:ascii:][:^ascii:]]' => 'SANY',
    '(?u)[^[:ascii:][:^ascii:]]' => 'OPFAIL',
    '(?a)[[:ascii:][:^ascii:]]' => 'SANY',
    '(?a)[^[:ascii:][:^ascii:]]' => 'OPFAIL',
    '[[:^blank:]]' => 'NPOSIXD[:blank:]',
    '[[:^blank:]\x{2C2}]' => 'NPOSIXU[:blank:]',
    '(?l)[[:blank:]]' => 'POSIXL[:blank:]',
    '(?l)[[:^blank:]]' => 'NPOSIXL[:blank:]',
    '(?l)[[:^blank:]\x{2C2}]' => 'NPOSIXL[:blank:]',
    '(?u)[[:blank:]]' => 'POSIXU[:blank:]',
    '(?u)[[:^blank:]]' => 'NPOSIXU[:blank:]',
    '(?a)[[:blank:]]' => 'POSIXA[:blank:]',
    '(?a)[[:^blank:]]' => 'NPOSIXA[:blank:]',
    '(?a)[[:^blank:]\x{2C2}]' => 'NPOSIXA[:blank:]',
    '[[:blank:]]' => 'POSIXD[:blank:]',
    '[[:blank:][:^blank:]]' => 'SANY',
    '[^[:blank:][:^blank:]]' => 'OPFAIL',
    '(?l)[[:blank:][:^blank:]]' => 'SANY',
    '(?l)[^[:blank:][:^blank:]]' => 'OPFAIL',
    '(?u)[[:blank:][:^blank:]]' => 'SANY',
    '(?u)[^[:blank:][:^blank:]]' => 'OPFAIL',
    '(?a)[[:blank:][:^blank:]]' => 'SANY',
    '(?a)[^[:blank:][:^blank:]]' => 'OPFAIL',
    '[[:^cntrl:]]' => 'NPOSIXD[:cntrl:]',
    '[[:^cntrl:]\x{2C2}]' => 'NPOSIXU[:cntrl:]',
    '(?l)[[:cntrl:]]' => 'POSIXL[:cntrl:]',
    '(?l)[[:^cntrl:]]' => 'NPOSIXL[:cntrl:]',
    '(?l)[[:^cntrl:]\x{2C2}]' => 'NPOSIXL[:cntrl:]',
    '(?u)[[:cntrl:]]' => 'POSIXU[:cntrl:]',
    '(?u)[[:^cntrl:]]' => 'NPOSIXU[:cntrl:]',
    '(?a)[[:cntrl:]]' => 'POSIXA[:cntrl:]',
    '(?a)[[:^cntrl:]]' => 'NPOSIXA[:cntrl:]',
    '(?a)[[:^cntrl:]\x{2C2}]' => 'NPOSIXA[:cntrl:]',
    '[[:cntrl:][:^cntrl:]]' => 'SANY',
    '[^[:cntrl:][:^cntrl:]]' => 'OPFAIL',
    '(?l)[[:cntrl:][:^cntrl:]]' => 'SANY',
    '(?l)[^[:cntrl:][:^cntrl:]]' => 'OPFAIL',
    '(?u)[[:cntrl:][:^cntrl:]]' => 'SANY',
    '(?u)[^[:cntrl:][:^cntrl:]]' => 'OPFAIL',
    '(?a)[[:cntrl:][:^cntrl:]]' => 'SANY',
    '(?a)[^[:cntrl:][:^cntrl:]]' => 'OPFAIL',
    '[[:digit:]]' => 'POSIXU[\d]',
    '[[:^digit:]]' => 'NPOSIXU[\d]',
    '[[:^digit:]\x{2C2}]' => 'NPOSIXU[\d]',
    '(?l)[[:digit:]]' => 'POSIXL[\d]',
    '(?l)[[:^digit:]]' => 'NPOSIXL[\d]',
    '(?l)[[:^digit:]\x{2C2}]' => 'NPOSIXL[\d]',
    '(?u)[[:digit:]]' => 'POSIXU[\d]',
    '(?u)[[:^digit:]]' => 'NPOSIXU[\d]',
    '(?a)[[:digit:]]' => 'POSIXA[\d]',
    '(?a)[[:^digit:]]' => 'NPOSIXA[\d]',
    '(?a)[[:^digit:]\x{2C2}]' => 'NPOSIXA[\d]',
    '[[:digit:][:^digit:]]' => 'SANY',
    '[^[:digit:][:^digit:]]' => 'OPFAIL',
    '(?l)[[:digit:][:^digit:]]' => 'SANY',
    '(?l)[^[:digit:][:^digit:]]' => 'OPFAIL',
    '(?u)[[:digit:][:^digit:]]' => 'SANY',
    '(?u)[^[:digit:][:^digit:]]' => 'OPFAIL',
    '(?a)[[:digit:][:^digit:]]' => 'SANY',
    '(?a)[^[:digit:][:^digit:]]' => 'OPFAIL',
    '[[:graph:]]' => 'POSIXD[:graph:]',
    '[[:^graph:]]' => 'NPOSIXD[:graph:]',
    '[[:^graph:]\x{FFFF}]' => 'NPOSIXU[:graph:]',
    '(?l)[[:graph:]]' => 'POSIXL[:graph:]',
    '(?l)[[:^graph:]]' => 'NPOSIXL[:graph:]',
    '(?l)[[:^graph:]\x{FFFF}]' => 'NPOSIXL[:graph:]',
    '(?u)[[:graph:]]' => 'POSIXU[:graph:]',
    '(?u)[[:^graph:]]' => 'NPOSIXU[:graph:]',
    '(?a)[[:graph:]]' => 'POSIXA[:graph:]',
    '(?a)[[:^graph:]]' => 'NPOSIXA[:graph:]',
    '(?a)[[:^graph:]\x{FFFF}]' => 'NPOSIXA[:graph:]',
    '[[:graph:][:^graph:]]' => 'SANY',
    '[^[:graph:][:^graph:]]' => 'OPFAIL',
    '(?l)[[:graph:][:^graph:]]' => 'SANY',
    '(?l)[^[:graph:][:^graph:]]' => 'OPFAIL',
    '(?u)[[:graph:][:^graph:]]' => 'SANY',
    '(?u)[^[:graph:][:^graph:]]' => 'OPFAIL',
    '(?a)[[:graph:][:^graph:]]' => 'SANY',
    '(?a)[^[:graph:][:^graph:]]' => 'OPFAIL',
    '[[:lower:]]' => 'POSIXD[:lower:]',
    '[[:^lower:]]' => 'NPOSIXD[:lower:]',
    '[[:^lower:]\x{2C2}]' => 'NPOSIXU[:lower:]',
    '(?l)[[:lower:]]' => 'POSIXL[:lower:]',
    '(?l)[[:^lower:]]' => 'NPOSIXL[:lower:]',
    '(?l)[[:^lower:]\x{2C2}]' => 'NPOSIXL[:lower:]',
    '(?u)[[:lower:]]' => 'POSIXU[:lower:]',
    '(?u)[[:^lower:]]' => 'NPOSIXU[:lower:]',
    '(?a)[[:lower:]]' => 'POSIXA[:lower:]',
    '(?a)[[:^lower:]]' => 'NPOSIXA[:lower:]',
    '(?a)[[:^lower:]\x{2C2}]' => 'NPOSIXA[:lower:]',
    '[[:lower:][:^lower:]]' => 'SANY',
    '[^[:lower:][:^lower:]]' => 'OPFAIL',
    '(?l)[[:lower:][:^lower:]]' => 'SANY',
    '(?l)[^[:lower:][:^lower:]]' => 'OPFAIL',
    '(?u)[[:lower:][:^lower:]]' => 'SANY',
    '(?u)[^[:lower:][:^lower:]]' => 'OPFAIL',
    '(?a)[[:lower:][:^lower:]]' => 'SANY',
    '(?a)[^[:lower:][:^lower:]]' => 'OPFAIL',
    '[[:print:]]' => 'POSIXD[:print:]',
    '[[:^print:]]' => 'NPOSIXD[:print:]',
    '[[:^print:]\x{FFFF}]' => 'NPOSIXU[:print:]',
    '(?l)[[:print:]]' => 'POSIXL[:print:]',
    '(?l)[[:^print:]]' => 'NPOSIXL[:print:]',
    '(?l)[[:^print:]\x{FFFF}]' => 'NPOSIXL[:print:]',
    '(?u)[[:print:]]' => 'POSIXU[:print:]',
    '(?u)[[:^print:]]' => 'NPOSIXU[:print:]',
    '(?a)[[:print:]]' => 'POSIXA[:print:]',
    '(?a)[[:^print:]]' => 'NPOSIXA[:print:]',
    '(?a)[[:^print:]\x{FFFF}]' => 'NPOSIXA[:print:]',
    '[[:print:][:^print:]]' => 'SANY',
    '[^[:print:][:^print:]]' => 'OPFAIL',
    '(?l)[[:print:][:^print:]]' => 'SANY',
    '(?l)[^[:print:][:^print:]]' => 'OPFAIL',
    '(?u)[[:print:][:^print:]]' => 'SANY',
    '(?u)[^[:print:][:^print:]]' => 'OPFAIL',
    '(?a)[[:print:][:^print:]]' => 'SANY',
    '(?a)[^[:print:][:^print:]]' => 'OPFAIL',
    '[[:punct:]]' => 'POSIXD[:punct:]',
    '[[:^punct:]]' => 'NPOSIXD[:punct:]',
    '[[:^punct:]\x{2C2}]' => 'NPOSIXU[:punct:]',
    '(?l)[[:punct:]]' => 'POSIXL[:punct:]',
    '(?l)[[:^punct:]]' => 'NPOSIXL[:punct:]',
    '(?l)[[:^punct:]\x{2C2}]' => 'NPOSIXL[:punct:]',
    '(?u)[[:punct:]]' => 'POSIXU[:punct:]',
    '(?u)[[:^punct:]]' => 'NPOSIXU[:punct:]',
    '(?a)[[:punct:]]' => 'POSIXA[:punct:]',
    '(?a)[[:^punct:]]' => 'NPOSIXA[:punct:]',
    '(?a)[[:^punct:]\x{2C2}]' => 'NPOSIXA[:punct:]',
    '[[:punct:][:^punct:]]' => 'SANY',
    '[^[:punct:][:^punct:]]' => 'OPFAIL',
    '(?l)[[:punct:][:^punct:]]' => 'SANY',
    '(?l)[^[:punct:][:^punct:]]' => 'OPFAIL',
    '(?u)[[:punct:][:^punct:]]' => 'SANY',
    '(?u)[^[:punct:][:^punct:]]' => 'OPFAIL',
    '(?a)[[:punct:][:^punct:]]' => 'SANY',
    '(?a)[^[:punct:][:^punct:]]' => 'OPFAIL',
    '[[:space:]]' => 'POSIXD[\s]',
    '[[:^space:]]' => 'NPOSIXD[\s]',
    '[[:^space:]\x{2C2}]' => 'NPOSIXU[\s]',
    '(?l)[[:space:]]' => 'POSIXL[\s]',
    '(?l)[[:^space:]]' => 'NPOSIXL[\s]',
    '(?l)[[:^space:]\x{2C2}]' => 'NPOSIXL[\s]',
    '(?u)[[:space:]]' => 'POSIXU[\s]',
    '(?u)[[:^space:]]' => 'NPOSIXU[\s]',
    '(?a)[[:space:]]' => 'POSIXA[\s]',
    '(?a)[[:^space:]]' => 'NPOSIXA[\s]',
    '(?a)[[:^space:]\x{2C2}]' => 'NPOSIXA[\s]',
    '[[:space:][:^space:]]' => 'SANY',
    '[^[:space:][:^space:]]' => 'OPFAIL',
    '(?l)[[:space:][:^space:]]' => 'SANY',
    '(?l)[^[:space:][:^space:]]' => 'OPFAIL',
    '(?u)[[:space:][:^space:]]' => 'SANY',
    '(?u)[^[:space:][:^space:]]' => 'OPFAIL',
    '(?a)[[:space:][:^space:]]' => 'SANY',
    '(?a)[^[:space:][:^space:]]' => 'OPFAIL',
    '[[:upper:]]' => 'POSIXD[:upper:]',
    '[[:^upper:]]' => 'NPOSIXD[:upper:]',
    '[[:^upper:]\x{2C2}]' => 'NPOSIXU[:upper:]',
    '(?l)[[:upper:]]' => 'POSIXL[:upper:]',
    '(?l)[[:^upper:]]' => 'NPOSIXL[:upper:]',
    '(?l)[[:^upper:]\x{2C2}]' => 'NPOSIXL[:upper:]',
    '(?u)[[:upper:]]' => 'POSIXU[:upper:]',
    '(?u)[[:^upper:]]' => 'NPOSIXU[:upper:]',
    '(?a)[[:upper:]]' => 'POSIXA[:upper:]',
    '(?a)[[:^upper:]]' => 'NPOSIXA[:upper:]',
    '(?a)[[:^upper:]\x{2C2}]' => 'NPOSIXA[:upper:]',
    '[[:upper:][:^upper:]]' => 'SANY',
    '[^[:upper:][:^upper:]]' => 'OPFAIL',
    '(?l)[[:upper:][:^upper:]]' => 'SANY',
    '(?l)[^[:upper:][:^upper:]]' => 'OPFAIL',
    '(?u)[[:upper:][:^upper:]]' => 'SANY',
    '(?u)[^[:upper:][:^upper:]]' => 'OPFAIL',
    '(?a)[[:upper:][:^upper:]]' => 'SANY',
    '(?a)[^[:upper:][:^upper:]]' => 'OPFAIL',
    '[\v]' => 'POSIXU[\v]',
    '[^\v]' => 'NPOSIXU[\v]',
    '[\V\x{2C2}]' => 'NPOSIXU[\v]',
    '(?l)[\v]' => 'POSIXU[\v]',
    '(?l)[^\v]' => 'NPOSIXU[\v]',
    '(?l)[\V\x{2C2}]' => 'NPOSIXU[\v]',
    '(?u)[\v]' => 'POSIXU[\v]',
    '(?u)[^\v]' => 'NPOSIXU[\v]',
    '(?a)[\v]' => 'POSIXU[\v]',
    '(?a)[^\v]' => 'NPOSIXU[\v]',
    '(?a)[\V\x{2C2}]' => 'NPOSIXU[\v]',
    '[\v\V]' => 'SANY',
    '[^\v\V]' => 'OPFAIL',
    '(?l)[\v\V]' => 'SANY',
    '(?l)[^\v\V]' => 'OPFAIL',
    '(?u)[\v\V]' => 'SANY',
    '(?u)[^\v\V]' => 'OPFAIL',
    '(?a)[\v\V]' => 'SANY',
    '(?a)[^\v\V]' => 'OPFAIL',
    '[[:word:]]' => 'POSIXD[\w]',
    '[[:^word:]]' => 'NPOSIXD[\w]',
    '[[:^word:]\x{2C2}]' => 'NPOSIXU[\w]',
    '(?l)[[:word:]]' => 'POSIXL[\w]',
    '(?l)[[:^word:]]' => 'NPOSIXL[\w]',
    '(?l)[[:^word:]\x{2C2}]' => 'NPOSIXL[\w]',
    '(?u)[[:word:]]' => 'POSIXU[\w]',
    '(?u)[[:^word:]]' => 'NPOSIXU[\w]',
    '(?a)[[:word:]]' => 'POSIXA[\w]',
    '(?a)[[:^word:]]' => 'NPOSIXA[\w]',
    '(?a)[[:^word:]\x{2C2}]' => 'NPOSIXA[\w]',
    '[[:word:][:^word:]]' => 'SANY',
    '[^[:word:][:^word:]]' => 'OPFAIL',
    '(?l)[[:word:][:^word:]]' => 'SANY',
    '(?l)[^[:word:][:^word:]]' => 'OPFAIL',
    '(?u)[[:word:][:^word:]]' => 'SANY',
    '(?u)[^[:word:][:^word:]]' => 'OPFAIL',
    '(?a)[[:word:][:^word:]]' => 'SANY',
    '(?a)[^[:word:][:^word:]]' => 'OPFAIL',
    '[[:xdigit:]]' => 'POSIXU[:xdigit:]',
    '[[:^xdigit:]]' => 'NPOSIXU[:xdigit:]',
    '[[:^xdigit:]\x{2C2}]' => 'NPOSIXU[:xdigit:]',
    '(?l)[[:xdigit:]]' => 'POSIXL[:xdigit:]',
    '(?l)[[:^xdigit:]]' => 'NPOSIXL[:xdigit:]',
    '(?l)[[:^xdigit:]\x{2C2}]' => 'NPOSIXL[:xdigit:]',
    '(?u)[[:xdigit:]]' => 'POSIXU[:xdigit:]',
    '(?u)[[:^xdigit:]]' => 'NPOSIXU[:xdigit:]',
    '(?a)[[:xdigit:]]' => 'POSIXA[:xdigit:]',
    '(?a)[[:^xdigit:]]' => 'NPOSIXA[:xdigit:]',
    '(?a)[[:^xdigit:]\x{2C2}]' => 'NPOSIXA[:xdigit:]',
    '[[:xdigit:][:^xdigit:]]' => 'SANY',
    '[^[:xdigit:][:^xdigit:]]' => 'OPFAIL',
    '(?l)[[:xdigit:][:^xdigit:]]' => 'SANY',
    '(?l)[^[:xdigit:][:^xdigit:]]' => 'OPFAIL',
    '(?u)[[:xdigit:][:^xdigit:]]' => 'SANY',
    '(?u)[^[:xdigit:][:^xdigit:]]' => 'OPFAIL',
    '(?a)[[:xdigit:][:^xdigit:]]' => 'SANY',
    '(?a)[^[:xdigit:][:^xdigit:]]' => 'OPFAIL',
    '(?i)[[:lower:]]' => 'POSIXD[:cased:]',
    '(?i)[[:^lower:]]' => 'NPOSIXD[:cased:]',
    '(?i)[[:^lower:]\x{2C2}]' => 'NPOSIXU[:cased:]',
    '(?i)(?l)[[:lower:]]' => 'POSIXL[:cased:]',
    '(?i)(?l)[[:^lower:]]' => 'NPOSIXL[:cased:]',
    '(?i)(?l)[[:^lower:]\x{2C2}]' => 'NPOSIXL[:cased:]',
    '(?i)(?u)[[:lower:]]' => 'POSIXU[:cased:]',
    '(?i)(?u)[[:^lower:]]' => 'NPOSIXU[:cased:]',
    '(?i)(?a)[[:lower:]]' => 'POSIXA[:alpha:]',
    '(?i)(?a)[[:^lower:]]' => 'NPOSIXA[:alpha:]',
    '(?i)(?a)[[:^lower:]\x{2C2}]' => 'NPOSIXA[:alpha:]',
    '(?i)[[:upper:]]' => 'POSIXD[:cased:]',
    '(?i)[[:^upper:]]' => 'NPOSIXD[:cased:]',
    '(?i)[[:^upper:]\x{2C2}]' => 'NPOSIXU[:cased:]',
    '(?i)(?l)[[:upper:]]' => 'POSIXL[:cased:]',
    '(?i)(?l)[[:^upper:]]' => 'NPOSIXL[:cased:]',
    '(?i)(?l)[[:^upper:]\x{2C2}]' => 'NPOSIXL[:cased:]',
    '(?i)(?u)[[:upper:]]' => 'POSIXU[:cased:]',
    '(?i)(?u)[[:^upper:]]' => 'NPOSIXU[:cased:]',
    '(?i)(?a)[[:upper:]]' => 'POSIXA[:alpha:]',
    '(?i)(?a)[[:^upper:]]' => 'NPOSIXA[:alpha:]',
    '(?i)(?a)[[:^upper:]\x{2C2}]' => 'NPOSIXA[:alpha:]',
    '(?i)[\d\w]' => 'POSIXD[\w]',
    '(?i)[\D\w]' => 'SANY',
    #'(?i)(?l)[\d\w]' => varies depending on Unicode release
    '(?i)(?l)[\D\w]' => 'ANYOFPOSIXL{i}[\\w\\D][0100-INFTY]',
    '(?i)(?u)[\d\w]' => 'POSIXU[\w]',
    '(?i)(?u)[\D\w]' => 'SANY',
    '(?i)(?a)[\d\w]' => 'POSIXA[\w]',
    '(?i)(?a)[\D\w]' => 'SANY',
    '(?l:[\x{212A}])' => 'EXACTL <\x{212a}>',
    '(?l:[\s\x{212A}])' => 'ANYOFPOSIXL[\s][1680 2000-200A 2028-2029 202F 205F 212A 3000]',
    '(?l:[^\S\x{202F}])' => 'ANYOFPOSIXL[^\\S][1680 2000-200A 2028-2029 205F 3000]',
    '(?li:[a-z])' => (($::IS_ASCII)
                     ? 'ANYOFL{i}[a-z{utf8 locale}\x{017F}\x{212A}]'
                     : 'ANYOFL{i}[a-ij-rs-z{utf8 locale}\x{017F}\x{212A}]'),
    '\p{All}' => 'SANY',
    '\P{All}' => 'OPFAIL',
    '[\p{Any}]' => 'ANYOF[\x00-\xFF][0100-10FFFF]',

    '[\p{IsMyRuntimeProperty}]' => 'ANYOF[+main::IsMyRuntimeProperty]',
    '[^\p{IsMyRuntimeProperty}]' => 'ANYOF[^{+main::IsMyRuntimeProperty}]',
    '[a\p{IsMyRuntimeProperty}]' => 'ANYOF[a][+main::IsMyRuntimeProperty]',
    '[^a\p{IsMyRuntimeProperty}]' => 'ANYOF[^a{+main::IsMyRuntimeProperty}]',
    '[^a\x{100}\p{IsMyRuntimeProperty}]' => 'ANYOF[^a{+main::IsMyRuntimeProperty}0100]',
    '[^\p{All}\p{IsMyRuntimeProperty}]' => 'OPFAIL',
    '[\p{All}\p{IsMyRuntimeProperty}]' => 'SANY',

    '[\x{00}-{HIGHEST_CP}]' => 'ANYOF[\x00-\xFF][0100-HIGHEST_CP]',
    '[\x{00}-{INFTY}]' => 'SANY',
    '[\x{101}-{INFTY}]' => 'ANYOFH[0101-INFTY]',
    '[\x{101}-{HIGHEST_CP}]' => 'ANYOFH[0101-HIGHEST_CP]',
    '[\x{102}\x{104}]' => 'ANYOFHb[0102 0104]',
    '[\x{102}-\x{104}{HIGHEST_CP}]' => 'ANYOFH[0102-0104 HIGHEST_CP]',
    '[\x{102}-\x{104}\x{101}]' => 'ANYOFRb[0101-0104]',
    '[\x{102}-\x{104}\x{101}-{INFTY}]' => 'ANYOFH[0101-INFTY]',
    '[\x{102}-\x{104}\x{101}-{HIGHEST_CP}]' => 'ANYOFH[0101-HIGHEST_CP]',
    '[\x{102}-\x{104}\x{102}]' => 'ANYOFRb[0102-0104]',
    '[\x{102}-\x{104}\x{102}-{INFTY}]' => 'ANYOFH[0102-INFTY]',
    '[\x{102}-\x{104}\x{102}-{HIGHEST_CP}]' => 'ANYOFH[0102-HIGHEST_CP]',
    '[\x{102}-\x{104}\x{103}]' => 'ANYOFRb[0102-0104]',
    '[\x{102}-\x{104}\x{103}-{INFTY}]' => 'ANYOFH[0102-INFTY]',
    '[\x{102}-\x{104}\x{103}-{HIGHEST_CP}]' => 'ANYOFH[0102-HIGHEST_CP]',
    '[\x{102}-\x{104}\x{104}]' => 'ANYOFRb[0102-0104]',
    '[\x{102}-\x{104}\x{104}-{INFTY}]' => 'ANYOFH[0102-INFTY]',
    '[\x{102}-\x{104}\x{104}-{HIGHEST_CP}]' => 'ANYOFH[0102-HIGHEST_CP]',
    '[\x{102}-\x{104}\x{105}]' => 'ANYOFRb[0102-0105]',
    '[\x{102}-\x{104}\x{105}-{INFTY}]' => 'ANYOFH[0102-INFTY]',
    '[\x{102}-\x{104}\x{105}-{HIGHEST_CP}]' => 'ANYOFH[0102-HIGHEST_CP]',
    '[\x{102}-\x{104}\x{106}]' => 'ANYOFHb[0102-0104 0106]',
    '[\x{102}-\x{104}\x{106}-{INFTY}]' => 'ANYOFH[0102-0104 0106-INFTY]',
    '[\x{102}-\x{104}\x{106}-{HIGHEST_CP}]' => 'ANYOFH[0102-0104 0106-HIGHEST_CP]',
    '[\x{102}-\x{104}\x{108}-\x{10A}{HIGHEST_CP}]' => 'ANYOFH[0102-0104 0108-010A HIGHEST_CP]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{101}]' => 'ANYOFHb[0101-0104 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{101}-{INFTY}]' => 'ANYOFH[0101-INFTY]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{101}-{HIGHEST_CP}]' => 'ANYOFH[0101-HIGHEST_CP]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{102}]' => 'ANYOFHb[0101-0104 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{103}]' => 'ANYOFHb[0101-0104 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{104}]' => 'ANYOFHb[0101-0104 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{105}]' => 'ANYOFHb[0101-0105 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{106}]' => 'ANYOFHb[0101-0106 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{107}]' => 'ANYOFRb[0101-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{108}]' => 'ANYOFRb[0101-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{109}]' => 'ANYOFRb[0101-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{10A}]' => 'ANYOFRb[0101-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{10B}]' => 'ANYOFRb[0101-010B]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{102}]' => 'ANYOFHb[0102-0104 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{102}-{INFTY}]' => 'ANYOFH[0102-INFTY]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{102}-{HIGHEST_CP}]' => 'ANYOFH[0102-HIGHEST_CP]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{102}]' => 'ANYOFHb[0102-0104 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{103}]' => 'ANYOFHb[0102-0104 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{104}]' => 'ANYOFHb[0102-0104 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{105}]' => 'ANYOFHb[0102-0105 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{106}]' => 'ANYOFHb[0102-0106 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{107}]' => 'ANYOFRb[0102-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{108}]' => 'ANYOFRb[0102-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{109}]' => 'ANYOFRb[0102-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{10A}]' => 'ANYOFRb[0102-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{10B}]' => 'ANYOFRb[0102-010B]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{10C}]' => 'ANYOFRb[0102-010C]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{103}]' => 'ANYOFHb[0102-0104 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{103}-{INFTY}]' => 'ANYOFH[0102-INFTY]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{103}-{HIGHEST_CP}]' => 'ANYOFH[0102-HIGHEST_CP]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{103}-\x{104}]' => 'ANYOFHb[0102-0104 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{103}-\x{105}]' => 'ANYOFHb[0102-0105 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{103}-\x{106}]' => 'ANYOFHb[0102-0106 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{103}-\x{107}]' => 'ANYOFRb[0102-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{103}-\x{108}]' => 'ANYOFRb[0102-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{103}-\x{109}]' => 'ANYOFRb[0102-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{103}-\x{10A}]' => 'ANYOFRb[0102-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{103}-\x{10B}]' => 'ANYOFRb[0102-010B]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{103}-\x{10C}]' => 'ANYOFRb[0102-010C]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{104}]' => 'ANYOFHb[0102-0104 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{104}-{INFTY}]' => 'ANYOFH[0102-INFTY]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{104}-{HIGHEST_CP}]' => 'ANYOFH[0102-HIGHEST_CP]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{104}-\x{105}]' => 'ANYOFHb[0102-0105 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{104}-\x{106}]' => 'ANYOFHb[0102-0106 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{104}-\x{107}]' => 'ANYOFRb[0102-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{104}-\x{108}]' => 'ANYOFRb[0102-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{104}-\x{109}]' => 'ANYOFRb[0102-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{104}-\x{10A}]' => 'ANYOFRb[0102-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{104}-\x{10B}]' => 'ANYOFRb[0102-010B]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{104}-\x{10C}]' => 'ANYOFRb[0102-010C]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{105}]' => 'ANYOFHb[0102-0105 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{105}-{INFTY}]' => 'ANYOFH[0102-INFTY]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{105}-{HIGHEST_CP}]' => 'ANYOFH[0102-HIGHEST_CP]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{105}-\x{106}]' => 'ANYOFHb[0102-0106 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{105}-\x{107}]' => 'ANYOFRb[0102-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{105}-\x{108}]' => 'ANYOFRb[0102-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{105}-\x{109}]' => 'ANYOFRb[0102-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{105}-\x{10A}]' => 'ANYOFRb[0102-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{105}-\x{10B}]' => 'ANYOFRb[0102-010B]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{105}-\x{10C}]' => 'ANYOFRb[0102-010C]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{106}]' => 'ANYOFHb[0102-0104 0106 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{106}-{INFTY}]' => 'ANYOFH[0102-0104 0106-INFTY]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{106}-{HIGHEST_CP}]' => 'ANYOFH[0102-0104 0106-HIGHEST_CP]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{106}-\x{107}]' => 'ANYOFHb[0102-0104 0106-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{106}-\x{108}]' => 'ANYOFHb[0102-0104 0106-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{106}-\x{109}]' => 'ANYOFHb[0102-0104 0106-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{106}-\x{10A}]' => 'ANYOFHb[0102-0104 0106-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{106}-\x{10B}]' => 'ANYOFHb[0102-0104 0106-010B]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{106}-\x{10C}]' => 'ANYOFHb[0102-0104 0106-010C]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{107}]' => 'ANYOFHb[0102-0104 0107-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{108}]' => 'ANYOFHb[0102-0104 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{109}]' => 'ANYOFHb[0102-0104 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{10A}]' => 'ANYOFHb[0102-0104 0108-010A]',
    '[\x{102}-\x{104}\x{108}-\x{10A}\x{10B}]' => 'ANYOFHb[0102-0104 0108-010B]',
    '[\x{103}\x{102}]' => 'EXACTFU_REQ8 <\x{103}>',
    '[\x{104}\x{102}]' => 'ANYOFHb[0102 0104]',
    '[\x{104}\x{102}\x{103}]' => 'ANYOFRb[0102-0104]',
    '[\x{106}-{INFTY}\x{104}]' => 'ANYOFH[0104 0106-INFTY]',
    '[\x{106}-{INFTY}\x{104}-{INFTY}]' => 'ANYOFH[0104-INFTY]',
    '[\x{106}-{INFTY}\x{104}-{HIGHEST_CP}]' => 'ANYOFH[0104-INFTY]',
    '[\x{106}-{INFTY}\x{104}-\x{105}]' => 'ANYOFH[0104-INFTY]',
    '[\x{106}-{INFTY}\x{104}-\x{106}]' => 'ANYOFH[0104-INFTY]',
    '[\x{106}-{INFTY}\x{104}-\x{107}]' => 'ANYOFH[0104-INFTY]',
    '[\x{106}-{INFTY}\x{105}]' => 'ANYOFH[0105-INFTY]',
    '[\x{106}-{INFTY}\x{105}-{INFTY}]' => 'ANYOFH[0105-INFTY]',
    '[\x{106}-{INFTY}\x{105}-{HIGHEST_CP}]' => 'ANYOFH[0105-INFTY]',
    '[\x{106}-{INFTY}\x{105}-\x{106}]' => 'ANYOFH[0105-INFTY]',
    '[\x{106}-{INFTY}\x{105}-\x{107}]' => 'ANYOFH[0105-INFTY]',
    '[\x{106}-{INFTY}\x{106}]' => 'ANYOFH[0106-INFTY]',
    '[\x{106}-{INFTY}\x{106}-{INFTY}]' => 'ANYOFH[0106-INFTY]',
    '[\x{106}-{INFTY}\x{106}-{HIGHEST_CP}]' => 'ANYOFH[0106-INFTY]',
    '[\x{106}-{INFTY}\x{106}-\x{107}]' => 'ANYOFH[0106-INFTY]',
    '[\x{106}-{INFTY}\x{107}]' => 'ANYOFH[0106-INFTY]',
    '[\x{106}-{INFTY}\x{107}-{INFTY}]' => 'ANYOFH[0106-INFTY]',
    '[\x{106}-{INFTY}\x{107}-{HIGHEST_CP}]' => 'ANYOFH[0106-INFTY]',
    '[\x{106}-{INFTY}\x{107}-\x{107}]' => 'ANYOFH[0106-INFTY]',
    '[\x{10C}-{INFTY}{HIGHEST_CP}]' => 'ANYOFH[010C-INFTY]',
    '[\x{10C}-{INFTY}\x{00}-{HIGHEST_CP}]' => 'SANY',
    '[\x{10C}-{INFTY}\x{00}-{INFTY}]' => 'SANY',
    '[\x{10C}-{INFTY}\x{101}-{INFTY}]' => 'ANYOFH[0101-INFTY]',
    '[\x{10C}-{INFTY}\x{101}-{HIGHEST_CP}]' => 'ANYOFH[0101-INFTY]',
    '[\x{10C}-{INFTY}\x{102}\x{104}]' => 'ANYOFH[0102 0104 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}{HIGHEST_CP}]' => 'ANYOFH[0102-0104 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{100}]' => 'ANYOFH[0100 0102-0104 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{101}]' => 'ANYOFH[0101-0104 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{101}-{INFTY}]' => 'ANYOFH[0101-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{101}-{HIGHEST_CP}]' => 'ANYOFH[0101-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{102}]' => 'ANYOFH[0102-0104 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{102}-{INFTY}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{102}-{HIGHEST_CP}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{103}]' => 'ANYOFH[0102-0104 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{103}-{INFTY}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{103}-{HIGHEST_CP}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{104}]' => 'ANYOFH[0102-0104 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{104}-{INFTY}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{104}-{HIGHEST_CP}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{105}]' => 'ANYOFH[0102-0105 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{105}-{INFTY}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{105}-{HIGHEST_CP}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{106}]' => 'ANYOFH[0102-0104 0106 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{106}-{INFTY}]' => 'ANYOFH[0102-0104 0106-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{106}-{HIGHEST_CP}]' => 'ANYOFH[0102-0104 0106-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}{HIGHEST_CP}]' => 'ANYOFH[0102-0104 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{101}]' => 'ANYOFH[0101-0104 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{101}-{INFTY}]' => 'ANYOFH[0101-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{101}-{HIGHEST_CP}]' => 'ANYOFH[0101-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{102}]' => 'ANYOFH[0101-0104 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{103}]' => 'ANYOFH[0101-0104 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{104}]' => 'ANYOFH[0101-0104 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{105}]' => 'ANYOFH[0101-0105 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{106}]' => 'ANYOFH[0101-0106 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{107}]' => 'ANYOFH[0101-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{108}]' => 'ANYOFH[0101-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{109}]' => 'ANYOFH[0101-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{10A}]' => 'ANYOFH[0101-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{101}-\x{10B}]' => 'ANYOFH[0101-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{102}]' => 'ANYOFH[0102-0104 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{102}-{INFTY}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{102}-{HIGHEST_CP}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{102}]' => 'ANYOFH[0102-0104 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{103}]' => 'ANYOFH[0102-0104 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{104}]' => 'ANYOFH[0102-0104 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{105}]' => 'ANYOFH[0102-0105 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{106}]' => 'ANYOFH[0102-0106 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{107}]' => 'ANYOFH[0102-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{108}]' => 'ANYOFH[0102-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{109}]' => 'ANYOFH[0102-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{10A}]' => 'ANYOFH[0102-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{10B}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{102}-\x{10C}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{103}]' => 'ANYOFH[0102-0104 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{103}-{INFTY}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{103}-{HIGHEST_CP}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{103}-\x{104}]' => 'ANYOFH[0102-0104 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{103}-\x{105}]' => 'ANYOFH[0102-0105 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{103}-\x{106}]' => 'ANYOFH[0102-0106 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{103}-\x{107}]' => 'ANYOFH[0102-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{103}-\x{108}]' => 'ANYOFH[0102-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{103}-\x{109}]' => 'ANYOFH[0102-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{103}-\x{10A}]' => 'ANYOFH[0102-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{103}-\x{10B}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{103}-\x{10C}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{104}]' => 'ANYOFH[0102-0104 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{104}-{INFTY}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{104}-{HIGHEST_CP}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{104}-\x{105}]' => 'ANYOFH[0102-0105 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{104}-\x{106}]' => 'ANYOFH[0102-0106 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{104}-\x{107}]' => 'ANYOFH[0102-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{104}-\x{108}]' => 'ANYOFH[0102-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{104}-\x{109}]' => 'ANYOFH[0102-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{104}-\x{10A}]' => 'ANYOFH[0102-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{104}-\x{10B}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{104}-\x{10C}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{105}]' => 'ANYOFH[0102-0105 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{105}-{INFTY}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{105}-{HIGHEST_CP}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{105}-\x{106}]' => 'ANYOFH[0102-0106 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{105}-\x{107}]' => 'ANYOFH[0102-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{105}-\x{108}]' => 'ANYOFH[0102-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{105}-\x{109}]' => 'ANYOFH[0102-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{105}-\x{10A}]' => 'ANYOFH[0102-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{105}-\x{10B}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{105}-\x{10C}]' => 'ANYOFH[0102-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{106}]' => 'ANYOFH[0102-0104 0106 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{106}-{INFTY}]' => 'ANYOFH[0102-0104 0106-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{106}-{HIGHEST_CP}]' => 'ANYOFH[0102-0104 0106-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{106}-\x{107}]' => 'ANYOFH[0102-0104 0106-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{106}-\x{108}]' => 'ANYOFH[0102-0104 0106-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{106}-\x{109}]' => 'ANYOFH[0102-0104 0106-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{106}-\x{10A}]' => 'ANYOFH[0102-0104 0106-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{106}-\x{10B}]' => 'ANYOFH[0102-0104 0106-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{106}-\x{10C}]' => 'ANYOFH[0102-0104 0106-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{107}]' => 'ANYOFH[0102-0104 0107-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{108}]' => 'ANYOFH[0102-0104 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{109}]' => 'ANYOFH[0102-0104 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{10A}]' => 'ANYOFH[0102-0104 0108-010A 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{102}-\x{104}\x{108}-\x{10A}\x{10B}]' => 'ANYOFH[0102-0104 0108-INFTY]',
    '[\x{10C}-{INFTY}\x{103}\x{102}]' => 'ANYOFH[0102-0103 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{104}\x{102}]' => 'ANYOFH[0102 0104 010C-INFTY]',
    '[\x{10C}-{INFTY}\x{104}\x{102}\x{103}]' => 'ANYOFH[0102-0104 010C-INFTY]',
    '[{HIGHEST_CP}]' => 'EXACT_REQ8 <\x{HIGHEST_CP}>',

    '(?8)(?i)[\x{410}]' => 'EXACTFU_REQ8 <\x{430}>',
    '(?8)(?i)[\x{399}]' => 'EXACTFU_REQ8 <\x{3b9}>',
    '(?8)(?i)[\x{345}\x{399}\x{3B9}\x{1FBE}]' => 'EXACTFU_REQ8 <\x{3b9}>',
    '(?i)[\x{2b9}]' => 'EXACT_REQ8 <\x{2b9}>',           # Doesn't participate in a fold
    '(?8)(?i)[\x{2b9}]' => 'EXACT_REQ8 <\x{2b9}>',
    '(?i)[\x{2bc}]' => 'EXACTFU_REQ8 <\x{2bc}>', # Part of a multi-char fold, ASCII component
    '(?i)[\x{390}]' => 'EXACTFU_REQ8 <\x{3b9}\x{308}\x{301}>', # Part of a multi-char fold, no ASCII component

    '(?i)[\x{1E9E}]' => 'EXACTFU <ss>',
    '(?iaa)[\x{1E9E}]' => 'EXACTFAA <\x{17f}\x{17f}>',
    '(?i)[\x{FB00}]' => 'EXACTFU <ff>',
    '(?iaa)[\x{FB00}]' => 'EXACT_REQ8 <\x{fb00}>',
    '(?i)[\x{FB00}]' => 'EXACTFU <ff>',
    '(?i)[\x{FB01}]' => 'EXACTFU <fi>',
    '(?i)[\x{FB02}]' => 'EXACTFU <fl>',
    '(?i)[\x{FB03}]' => 'EXACTFU <ffi>',
    '(?i)[\x{FB04}]' => 'EXACTFU <ffl>',
    '(?i)[\x{FB05}]' => 'EXACTFU <st>',
    '(?i)[\x{FB06}]' => 'EXACTFU <st>',

    '[a][b]' => 'EXACT <ab>',
    '[a]\x{100}' => 'EXACT_REQ8 <a\x{100}>',
    '(?8)[\x{100}]a' => 'EXACT_REQ8 <\x{100}a>',
    '(?i)[b][c]' => 'EXACTFU <bc>',
    '(?i)[b]\x{100}' => 'EXACTFU_REQ8 <b\x{101}>',
    '(?8)(?i)[\x{100}]b' => 'EXACTFU_REQ8 <\x{101}b>',
    '(?i)b[s]' => 'EXACTFU <bs>',
    '(?i)b[s]c' => 'EXACTFU <bsc>',
    '(?i)bs[s]c' => 'EXACTF <bss>',  # The c goes into a 2nd node
    '(?iu)bs[s]c' => 'EXACTFUP <bssc>',
    '(?i)b[s]sc' => 'EXACTF <bssc>',
    '(?iu)b[s]sc' => 'EXACTFUP <bssc>',
    '(?i)[b]st' => 'EXACTFU <bst>',
    '(?i)[b]st[s]' => 'EXACTFU <bsts>',
    '(?i)[b]st[s]st' => 'EXACTF <bstsst>',
    '(?iu)[b]st[s]st' => 'EXACTFUP <bstsst>',
    '(?i)[s][s]' => 'EXACTF <ss>',
    '(?iu)[s][s]' => 'EXACTFUP <ss>',
);

my @single_chars_to_test =
(
    "\x00",     # Always potentially problematic
    "\x01",     # Unnamed control
    "\b",       # Named control
    "\n",       # Potentially special
    "\r",       # Potentially special
    "\cK",      # Potentially special
    "0",        # Digit
    ":",        # Not in any fold
    "A",        # ASCII capital, participates in multi-char fold
    "a",        # ASCII small, participates in multi-char fold
    "B",        # ASCII capital, participates only in case-pair fold
    "b",        # ASCII small, participates only in case-pair fold
    "K",        # ASCII capital, folded to from above Latin1
    "k",        # ASCII small, folded to from above Latin1
    "\c?",      # Potentially special
    "\x80",     # Latin1 control
    "\xB5",     # Micro sign, folds to above Latin1
    "\xC0",     # Latin1 capital, participates only in case-pair fold
    "\xE0",     # Latin1 small, participates only in case-pair fold
    "\xC5",     # Latin1 capital, folded to from above Latin1
    "\xE5",     # Latin1 small, folded to from above Latin1
    "\xDF",     # Small sharp S. folds to 'ss'
    "\xF7",     # Doesn't participate in any fold
    "\xFF",     # Folded to by above Latin1
    "\x{100}",  # First few above Latin1 characters
    "\x{101}",
    "\x{102}",
    "\x{103}",
    "\x{104}",
    "\x{105}",
    "\x{106}",
    "\x{107}",
    "\x{108}",
    "\x{2029}",
);

my @single_tests;
for my $char (@single_chars_to_test) {
    my $cp = ord $char;
    my $hex = sprintf "%02x", $cp;
    my $oct = sprintf "%o", $cp;
    my $cp_string;

    my $cased;
    my $folded_hex;

    {
        use feature 'unicode_strings';
        $cased = uc $char ne $char || lc $char ne $char;
        $folded_hex = ($cased)
                      ? sprintf("%02x", ord lc $char)
                      : $hex;
        #print STDERR "$hex, $folded_hex\n";
    }

    for my $fold ("", "i") {
        #next unless $fold;
        for my $charset ("", "u", "l", "aa") {
            #next if $charset eq "aa" && ! $fold;

            my $modifiers = $fold . $charset;
            $modifiers = "(?$modifiers)" if $modifiers;

            for my $upgrade ("", "(?8)") {
                push @single_tests, "$upgrade$modifiers\[\\x{$hex}\]";
                if ($cp < 256 || $upgrade) {
                    push @single_tests, get_compiled("$upgrade$modifiers\\x{$hex}");
                }
                else {
                    use feature 'fc';

                    my %list = ( sprintf("%X", $cp) => 1 );
                    if ($fold) {
                        for my $op (qw(fc lc uc)) {
                            my $result = eval "$op(\"$char\")";
                            $list{sprintf "%X", ord $result} = 1;
                        }
                    }

                    my $mod_cp = $cp;
                    my $op;

                    if (! $fold || scalar keys %list == 1) {
                        $op = ($charset eq 'l')
                                ? 'EXACTL'
                                : ($cp < 256)
                                ? 'EXACT'
                                : 'EXACT_REQ8';
                    }
                    else {
                        $op = ($charset eq 'aa')
                        ? 'EXACTFAA'
                        : ($charset eq 'l')
                            ? (($cp < 256)
                            ? 'EXACTFL'
                            : 'EXACTFLU8')
                            : ($cp < 256)
                            ? 'EXACTFU'
                            : 'EXACTFU_REQ8';
                        $mod_cp = ord fc $char;
                    }

                    push @single_tests, sprintf "$op <\\x{%X}>", $mod_cp;
                }
            }
        }
    }
}

unshift @tests, @single_tests;

plan(scalar (@tests - 1) / 2);  # -1 because of the marker.

my $skip_ebcdic = $::IS_EBCDIC;
while (defined (my $test = shift @tests)) {

    if ($test eq 'ebcdic_ok_below_this_marker') {
        $skip_ebcdic = 0;
        next;
    }

    my $expected = shift @tests;

    SKIP: {
        skip("test not ported to EBCDIC", 1) if $skip_ebcdic;

        my $display_expected = $expected
                                        =~ s/ HIGHEST_CP /$highest_cp_string/xgr;
        my $test_name = "Verify compilation of $test displays as"
                      . " $expected";

        my $result = get_compiled($test);
        if ($expected =~ / ^ ANYOF[HR] /x) {
            like($result, qr/ ^ \Q$expected\E (?:\Q (First UTF-8 byte=\x\E
                              [[:xdigit:]]{2} )? /x, $test_name);
        }
        else {
            is($result, $expected, $test_name);
        }
    }
}
