This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Patch [perl #111400] [:upper:] broken for above Latin1
[perl5.git] / regen / mk_invlists.pl
index 5b69708..64e3d43 100644 (file)
@@ -71,12 +71,101 @@ sub output_invlist ($$) {
 output_invlist("Latin1", [ 0, 256 ]);
 output_invlist("AboveLatin1", [ 256 ]);
 
+# We construct lists for all the POSIX and backslash sequence character
+# classes in two forms:
+#   1) ones which match only in the ASCII range
+#   2) ones which match either in the Latin1 range, or the entire Unicode range
+#
+# These get compiled in, and hence affect the memory footprint of every Perl
+# program, even those not using Unicode.  To minimize the size, currently
+# the Latin1 version is generated for the beyond ASCII range except for those
+# lists that are quite small for the entire range, such as for \s, which is 22
+# UVs long plus 4 UVs (currently) for the header.
+#
+# To save even more memory, the ASCII versions could be derived from the
+# larger ones at runtime, saving some memory (minus the expense of the machine
+# instructions to do so), but these are all small anyway, so their total is
+# about 100 UVs.
+#
+# In the list of properties below that get generated, the L1 prefix is a fake
+# property that means just the Latin1 range of the full property (whose name
+# has an X prefix instead of L1).
+
 for my $prop (qw(
                 ASCII
+                L1Cased
+               VertSpace
+                PerlSpace
+                    XPerlSpace
+                PosixAlnum
+                    L1PosixAlnum
+                PosixAlpha
+                    L1PosixAlpha
+                PosixBlank
+                    XPosixBlank
+                PosixCntrl
+                    XPosixCntrl
+                PosixDigit
+                PosixGraph
+                    L1PosixGraph
+                PosixLower
+                    L1PosixLower
+                PosixPrint
+                    L1PosixPrint
+                PosixPunct
+                    L1PosixPunct
+                PosixSpace
+                    XPosixSpace
+                PosixUpper
+                    L1PosixUpper
+                PosixWord
+                    L1PosixWord
+                PosixXDigit
+                    XPosixXDigit
     )
 ) {
 
-    my @invlist = prop_invlist($prop);
+    # For the Latin1 properties, we change to use the eXtended version of the
+    # base property, then go through the result and get rid of everything not
+    # in Latin1 (above 255).  Actually, we retain the element for the range
+    # that crosses the 255/256 boundary if it is one that matches the
+    # property.  For example, in the Word property, there is a range of code
+    # points that start at U+00F8 and goes through U+02C1.  Instead of
+    # artifically cutting that off at 256 because 256 is the first code point
+    # above Latin1, we let the range go to its natural ending.  That gives us
+    # extra information with no added space taken.  But if the range that
+    # crosses the boundary is one that doesn't match the property, we don't
+    # start a new range above 255, as that could be construed as going to
+    # infinity.  For example, the Upper property doesn't include the character
+    # at 255, but does include the one at 256.  We don't include the 256 one.
+    my $lookup_prop = $prop;
+    $lookup_prop =~ s/^L1Posix/XPosix/ or $lookup_prop =~ s/^L1//;
+    my @invlist = prop_invlist($lookup_prop);
+
+    if ($lookup_prop ne $prop) {
+        for my $i (0 .. @invlist - 1 - 1) {
+            if ($invlist[$i] > 255) {
+
+                # In an inversion list, even-numbered elements give the code
+                # points that begin ranges that match the property;
+                # odd-numbered give ones that begin ranges that don't match.
+                # If $i is odd, we are at the first code point above 255 that
+                # doesn't match, which means the range it is ending does
+                # match, and crosses the 255/256 boundary.  We want to include
+                # this ending point, so increment $i, so the splice below
+                # includes it.  Conversely, if $i is even, it is the first
+                # code point above 255 that matches, which means there was no
+                # matching range that crossed the boundary, and we don't want
+                # to include this code point, so splice before it.
+                $i++ if $i % 2 != 0;
+
+                # Remove everything past this.
+                splice @invlist, $i;
+                last;
+            }
+        }
+    }
+
     output_invlist($prop, \@invlist);
 }