mktables: Suppress complement tables
authorKarl Williamson <public@khwilliamson.com>
Fri, 1 Jul 2011 16:25:28 +0000 (10:25 -0600)
committerKarl Williamson <public@khwilliamson.com>
Sun, 3 Jul 2011 20:05:49 +0000 (14:05 -0600)
Consider the property \p{AHex}.  This is really \p{AHex=Y}, and there
is a corresponding \p{AHex=N} that is just the complement.  Prior to
this patch, 2 tables were generated for AHex.  Now, just one is, and the
N table is set-up in Heavy.pl to be the complement of the Y table.  This
saves quite a few tables and corresponding disk space.

Note that not all complements need be binary tables.

lib/unicore/mktables

index 95eff41..02623d1 100644 (file)
@@ -6465,6 +6465,11 @@ sub trace { return main::trace(@_); }
     # points.
     main::set_access('matches_all', \%matches_all, 'r');
 
+    my %complement;
+    # Points to the complement that this table is expressed in terms of; 0 if
+    # none.
+    main::set_access('complement', \%complement, 'r', 's' );
+
     sub new {
         my $class = shift;
 
@@ -6513,6 +6518,7 @@ sub trace { return main::trace(@_); }
         $matches_all{$addr} = $matches_all;
         $leader{$addr} = $self;
         $parent{$addr} = $self;
+        $complement{$addr} = 0;
 
         if (defined $format && $format ne $EMPTY_FORMAT) {
             Carp::my_carp_bug("'Format' must be '$EMPTY_FORMAT' in a match table instead of '$format'.  Using '$EMPTY_FORMAT'");
@@ -11193,6 +11199,19 @@ sub finish_Unicode() {
                 $default_table = $property->add_match_table($default_map);
             }
 
+            # And, if the property is binary, the default table will just
+            # be the complement of the other table.
+            if ($property_type == $BINARY) {
+                my $non_default_table;
+
+                # Find the non-default table.
+                for my $table ($property->tables) {
+                    next if $table == $default_table;
+                    $non_default_table = $table;
+                }
+                $default_table->set_complement($non_default_table);
+            }
+
             # This fills in any missing values with the default.  It's
             # tempting to save some time and memory in running this program
             # by skipping this step for binary tables where the default
@@ -12278,6 +12297,21 @@ sub register_file_for_name($$$) {
     # table, so skip if isn't the leader.
     return if $table->leader != $table;
 
+    # If this is a complement of another file, use that other file instead,
+    # with a ! prepended to it.
+    my $complement;
+    if (($complement = $table->complement) != 0) {
+        my @directories = $complement->file_path;
+
+        # This assumes that the 0th element is something like 'lib',
+        # the 1th element the property name (in its own directory), like
+        # 'AHex', and the 2th element the file like 'Y' which will have a .pl
+        # appended to it later.
+        $directories[1] =~ s/^/!/;
+        $file = pop @directories;
+        $directory_ref =\@directories;
+    }
+
     # Join all the file path components together, using slashes.
     my $full_filename = join('/', @$directory_ref, $file);
 
@@ -12345,7 +12379,7 @@ sub register_file_for_name($$$) {
             }
 
             # Keep a list of the deprecated properties and their filenames
-            if ($deprecated) {
+            if ($deprecated && $complement == 0) {
                 $utf8::why_deprecated{$sub_filename} = $deprecated;
             }
 
@@ -13511,6 +13545,14 @@ sub write_all_tables() {
                                 return 1 if ! defined $ext_a;
                                 my $ext_b = $b->external_name;
                                 return -1 if ! defined $ext_b;
+
+                                # But return the non-complement table before
+                                # the complement one, as the latter is defined
+                                # in terms of the former, and needs to have
+                                # the information for the former available.
+                                return 1 if $a->complement != 0;
+                                return -1 if $b->complement != 0;
+
                                 my $cmp = length $ext_a <=> length $ext_b;
 
                                 # Return result if lengths not equal
@@ -13803,7 +13845,8 @@ sub write_all_tables() {
 
         # Only need to write one file when shared by more than one
         # property
-        next if ! $is_property && $table->leader != $table;
+        next if ! $is_property
+                && ($table->leader != $table || $table->complement != 0);
 
         # Construct a nice comment to add to the file
         $table->set_final_comment;