source: trunk/third/perl/lib/utf8_heavy.pl @ 14545

Revision 14545, 5.4 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r14544, which included commits to RCS files with non-trunk default branches.
Line 
1package utf8;
2
3my $DEBUG = 0;
4my $seq = "AAA0000";
5
6sub DESTROY {}
7
8sub croak { require Carp; Carp::croak(@_) }
9
10sub SWASHNEW {
11    my ($class, $type, $list, $minbits, $none) = @_;
12    local $^D = 0 if $^D;
13    print STDERR "SWASHNEW @_\n" if $DEBUG;
14    my $extras;
15    my $bits;
16 
17    if ($type and ref ${"${class}::{$type}"} eq $class) {
18        warn qq/Found \${"${class}::{$type}"}\n/ if $DEBUG;
19        return ${"${class}::{$type}"};  # Already there...
20    }
21
22    $type ||= $seq++;
23
24    my $caller;
25    my $i = 0;
26    while (($caller = caller($i)) eq __PACKAGE__) { $i++ }
27    my $encoding = $enc{$caller} || "unicode";
28    (my $file = $type) =~ s!::!/!g;
29    $file =~ s#^(I[sn]|To)([A-Z].*)#$1/$2#;
30    $list ||= eval { $caller->$type(); }
31        || do "$file.pl"
32        || do "$encoding/$file.pl"
33        || do "$encoding/Is/${type}.pl"
34        || croak("Can't find $encoding character property definition via $caller->$type or $file.pl");
35
36    $| = 1;
37
38    if ($list) {
39        my @tmp = split(/^/m, $list);
40        my %seen;
41        no warnings;
42        $extras = join '', grep /^[^0-9a-fA-F]/, @tmp;
43        $list = join '',
44            sort { hex $a <=> hex $b }
45            grep {/^([0-9a-fA-F]+)/ and not $seen{$1}++} @tmp; # XXX doesn't do ranges right
46    }
47
48    if ($none) {
49        my $hextra = sprintf "%04x", $none + 1;
50        $list =~ s/\tXXXX$/\t$hextra/mg;
51    }
52
53    if ($minbits < 32) {
54        my $top = 0;
55        while ($list =~ /^([0-9a-fA-F]+)(?:\t([0-9a-fA-F]+)?)(?:\t([0-9a-fA-F]+))?/mg) {
56            my $min = hex $1;
57            my $max = hex(defined $2 ? $2 : $1);
58            my $val = hex(defined $3 ? $3 : "");
59            $val += $max - $min if defined $3;
60            $top = $val if $val > $top;
61        }
62        $bits =
63            $top > 0xffff ? 32 :
64            $top > 0xff ? 16 :
65            $top > 1 ? 8 : 1
66    }
67    $bits = $minbits if $bits < $minbits;
68
69    my @extras;
70    for my $x ($extras) {
71        pos $x = 0;
72        while ($x =~ /^([^0-9a-fA-F\n])(.*)/mg) {
73            my $char = $1;
74            my $name = $2;
75            # print STDERR "$1 => $2\n" if $DEBUG;
76            if ($char =~ /[-+!]/) {
77                my ($c,$t) = split(/::/, $name, 2);     # bogus use of ::, really
78                my $subobj = $c->SWASHNEW($t, "", 0, 0, 0);
79                push @extras, $name => $subobj;
80                $bits = $subobj->{BITS} if $bits < $subobj->{BITS};
81            }
82        }
83    }
84
85    print STDERR "CLASS = $class, TYPE => $type, BITS => $bits, NONE => $none\nEXTRAS =>\n$extras\nLIST =>\n$list\n" if $DEBUG;
86
87    ${"${class}::{$type}"} = bless {
88        TYPE => $type,
89        BITS => $bits,
90        EXTRAS => $extras,
91        LIST => $list,
92        NONE => $none,
93        @extras,
94    } => $class;
95}
96
97# NOTE: utf8.c:swash_init() assumes entries are never modified once generated.
98
99sub SWASHGET {
100    my ($self, $start, $len) = @_;
101    local $^D = 0 if $^D;
102    my $type = $self->{TYPE};
103    my $bits = $self->{BITS};
104    my $none = $self->{NONE};
105    print STDERR "SWASHGET @_ [$type/$bits/$none]\n" if $DEBUG;
106    my $end = $start + $len;
107    my $swatch = "";
108    my $key;
109    vec($swatch, $len - 1, $bits) = 0;  # Extend to correct length.
110    if ($none) {
111        for $key (0 .. $len - 1) { vec($swatch, $key, $bits) = $none }
112    }
113
114    for ($self->{LIST}) {
115        pos $_ = 0;
116        if ($bits > 1) {
117          LINE:
118            while (/^([0-9a-fA-F]+)(?:\t([0-9a-fA-F]+)?)(?:\t([0-9a-fA-F]+))?/mg) {
119                my $min = hex $1;
120                my $max = (defined $2 ? hex $2 : $min);
121                my $val = hex $3;
122                next if $max < $start;
123#               print "$min $max $val\n";
124                if ($none) {
125                    if ($min < $start) {
126                        $val += $start - $min if $val < $none;
127                        $min = $start;
128                    }
129                    for ($key = $min; $key <= $max; $key++) {
130                        last LINE if $key >= $end;
131#                       print STDERR "$key => $val\n" if $DEBUG;
132                        vec($swatch, $key - $start, $bits) = $val;
133                        ++$val if $val < $none;
134                    }
135                }
136                else {
137                    if ($min < $start) {
138                        $val += $start - $min;
139                        $min = $start;
140                    }
141                    for ($key = $min; $key <= $max; $key++, $val++) {
142                        last LINE if $key >= $end;
143#                       print STDERR "$key => $val\n" if $DEBUG;
144                        vec($swatch, $key - $start, $bits) = $val;
145                    }
146                }
147            }
148        }
149        else {
150          LINE:
151            while (/^([0-9a-fA-F]+)(?:\t([0-9a-fA-F]+))?/mg) {
152                my $min = hex $1;
153                my $max = (defined $2 ? hex $2 : $min);
154                next if $max < $start;
155                if ($min < $start) {
156                    $min = $start;
157                }
158                for ($key = $min; $key <= $max; $key++) {
159                    last LINE if $key >= $end;
160#                   print STDERR "$key => 1\n" if $DEBUG;
161                    vec($swatch, $key - $start, 1) = 1;
162                }
163            }
164        }
165    }
166    for my $x ($self->{EXTRAS}) {
167        pos $x = 0;
168        while ($x =~ /^([-+!])(.*)/mg) {
169            my $char = $1;
170            my $name = $2;
171            print STDERR "INDIRECT $1 $2\n" if $DEBUG;
172            my $otherbits = $self->{$name}->{BITS};
173            croak("SWASHGET size mismatch") if $bits < $otherbits;
174            my $other = $self->{$name}->SWASHGET($start, $len);
175            if ($char eq '+') {
176                if ($bits == 1 and $otherbits == 1) {
177                    $swatch |= $other;
178                }
179                else {
180                    for ($key = 0; $key < $len; $key++) {
181                        vec($swatch, $key, $bits) = vec($other, $key, $otherbits);
182                    }
183                }
184            }
185            elsif ($char eq '!') {
186                if ($bits == 1 and $otherbits == 1) {
187                    $swatch |= ~$other;
188                }
189                else {
190                    for ($key = 0; $key < $len; $key++) {
191                        if (!vec($other, $key, $otherbits)) {
192                            vec($swatch, $key, $bits) = 1;
193                        }
194                    }
195                }
196            }
197            elsif ($char eq '-') {
198                if ($bits == 1 and $otherbits == 1) {
199                    $swatch &= ~$other;
200                }
201                else {
202                    for ($key = 0; $key < $len; $key++) {
203                        if (vec($other, $key, $otherbits)) {
204                            vec($swatch, $key, $bits) = 0;
205                        }
206                    }
207                }
208            }
209        }
210    }
211    if ($DEBUG) {
212        print STDERR "CELLS ";
213        for ($key = 0; $key < $len; $key++) {
214            print STDERR vec($swatch, $key, $bits), " ";
215        }
216        print STDERR "\n";
217    }
218    $swatch;
219}
220
2211;
Note: See TracBrowser for help on using the repository browser.