GIF89a; EcchiShell v1.0
//proc/self/root/usr/share/perl5/

2 && DEBUG; # Can have maximum of one slash if (@parts > 2) { pop @recursed if @recursed; return $type; } foreach my $part (@parts) { print __LINE__, ": part=$part\n" if DEBUG; $part =~ s/^\+\s*//; # Remove leading plus $part =~ s/^-\s*/-/; # Remove blanks after unary # minus # Remove underscores between digits. $part =~ s/( ?<= [0-9] ) _ (?= [0-9] ) //xg; # No leading zeros (but don't make a single '0' # into a null string) $part =~ s/ ^ ( -? ) 0+ /$1/x; $part .= '0' if $part eq '-' || $part eq ""; # No trailing zeros after a decimal point $part =~ s/ ( \. .*? ) 0+ $ /$1/x; # Begin with a 0 if a leading decimal point $part =~ s/ ^ ( -? ) \. /${1}0./x; # Ensure not a trailing decimal point: turn into an # integer $part =~ s/ \. $ //x; print STDERR __LINE__, ": part=$part\n" if DEBUG; #return $type if $part eq ""; # Result better look like a number. (This test is # needed because, for example could have a plus in # the middle.) if ($part !~ / ^ -? [0-9]+ ( \. [0-9]+)? $ /x) { pop @recursed if @recursed; return $type; } } # If a rational... if (@parts == 2) { # If denominator is negative, get rid of it, and ... if ($parts[1] =~ s/^-//) { # If numerator is also negative, convert the # whole thing to positive, or move the minus to # the numerator if ($parts[0] !~ s/^-//) { $parts[0] = '-' . $parts[0]; } } $table = join '/', @parts; } elsif ($property ne 'nv' || $parts[0] !~ /\./) { # Here is not numeric value, or doesn't have a # decimal point. No further manipulation is # necessary. (Note the hard-coded property name. # This could fail if other properties eventually # had fractions as well; perhaps the cjk ones # could evolve to do that. This hard-coding could # be fixed by mktables generating a list of # properties that could have fractions.) $table = $parts[0]; } else { # Here is a floating point numeric_value. Try to # convert to rational. First see if is in the list # of known ones. if (exists $utf8::nv_floating_to_rational{$parts[0]}) { $table = $utf8::nv_floating_to_rational{$parts[0]}; } else { # Here not in the list. See if is close # enough to something in the list. First # determine what 'close enough' means. It has # to be as tight as what mktables says is the # maximum slop, and as tight as how many # digits we were passed. That is, if the user # said .667, .6667, .66667, etc. we match as # many digits as they passed until get to # where it doesn't matter any more due to the # machine's precision. If they said .6666668, # we fail. (my $fraction = $parts[0]) =~ s/^.*\.//; my $epsilon = 10 ** - (length($fraction)); if ($epsilon > $utf8::max_floating_slop) { $epsilon = $utf8::max_floating_slop; } # But it can't be tighter than the minimum # precision for this machine. If haven't # already calculated that minimum, do so now. if (! defined $min_floating_slop) { # Keep going down an order of magnitude # until find that adding this quantity to # 1 remains 1; but put an upper limit on # this so in case this algorithm doesn't # work properly on some platform, that we # won't loop forever. my $count = 0; $min_floating_slop = 1; while (1+ $min_floating_slop != 1 && $count++ < 50) { my $next = $min_floating_slop / 10; last if $next == 0; # If underflows, # use previous one $min_floating_slop = $next; print STDERR __LINE__, ": min_float_slop=$min_floating_slop\n" if DEBUG; } # Back off a couple orders of magnitude, # just to be safe. $min_floating_slop *= 100; } if ($epsilon < $min_floating_slop) { $epsilon = $min_floating_slop; } print STDERR __LINE__, ": fraction=.$fraction; epsilon=$epsilon\n" if DEBUG; undef $table; # And for each possible rational in the table, # see if it is within epsilon of the input. foreach my $official (keys %utf8::nv_floating_to_rational) { print STDERR __LINE__, ": epsilon=$epsilon, official=$official, diff=", abs($parts[0] - $official), "\n" if DEBUG; if (abs($parts[0] - $official) < $epsilon) { $table = $utf8::nv_floating_to_rational{$official}; last; } } # Quit if didn't find one. if (! defined $table) { pop @recursed if @recursed; return $type; } } } print STDERR __LINE__, ": $property=$table\n" if DEBUG; } } # Combine lhs (if any) and rhs to get something that matches # the syntax of the lookups. $property_and_table = "$prefix$table"; print STDERR __LINE__, ": $property_and_table\n" if DEBUG; # First try stricter matching. $file = $utf8::stricter_to_file_of{$property_and_table}; # If didn't find it, try again with looser matching by editing # out the applicable characters on the rhs and looking up # again. if (! defined $file) { $table = _loose_name($table); $property_and_table = "$prefix$table"; print STDERR __LINE__, ": $property_and_table\n" if DEBUG; $file = $utf8::loose_to_file_of{$property_and_table}; } # Add the constant and go fetch it in. if (defined $file) { # A beginning ! means to invert. The 0+ makes sure is # numeric $invert_it = 0 + $file =~ s/^!//; if ($utf8::why_deprecated{$file}) { warnings::warnif('deprecated', "Use of '$type' in \\p{} or \\P{} is deprecated because: $utf8::why_deprecated{$file};"); } if ($caseless && exists $utf8::caseless_equivalent{$property_and_table}) { $file = $utf8::caseless_equivalent{$property_and_table}; } $file= "$unicore_dir/lib/$file.pl"; last GETFILE; } print STDERR __LINE__, ": didn't find $property_and_table\n" if DEBUG; ## ## Last attempt -- see if it's a standard "To" name ## (e.g. "ToLower") ToTitle is used by ucfirst(). ## The user-level way to access ToDigit() and ToFold() ## is to use Unicode::UCD. ## # Only check if caller wants non-binary my $retried = 0; if ($minbits != 1 && $property_and_table =~ s/^to//) {{ # Look input up in list of properties for which we have # mapping files. if (defined ($file = $utf8::loose_property_to_file_of{$property_and_table})) { $type = $utf8::file_to_swash_name{$file}; print STDERR __LINE__, ": type set to $type\n" if DEBUG; $file = "$unicore_dir/$file.pl"; last GETFILE; } # If that fails see if there is a corresponding binary # property file elsif (defined ($file = $utf8::loose_to_file_of{$property_and_table})) { # Here, there is no map file for the property we are # trying to get the map of, but this is a binary # property, and there is a file for it that can easily # be translated to a mapping. # In the case of properties that are forced to binary, # they are a combination. We return the actual # mapping instead of the binary. If the input is # something like 'Tocjkkiicore', it will be found in # %loose_property_to_file_of above as => 'To/kIICore'. # But the form like ToIskiicore won't be. To fix # this, it was easiest to do it here. These # properties are the complements of the default # property, so there is an entry in %loose_to_file_of # that is 'iskiicore' => '!kIICore/N', If we find such # an entry, strip off things and try again, which # should find the entry in %loose_property_to_file_of. # Actual binary properties that are of this form, such # as this entry: 'ishrkt' => '!Perl/Any' will also be # retried, but won't be in %loose_property_to_file_of, # and instead the next time through, it will find # 'hrkt' => '!Perl/Any' and proceed. redo if ! $retried && $file =~ /^!/ && $property_and_table =~ s/^is//; # This is a binary property. Setting this here causes # it to be stored as such in the cache, so if someone # comes along later looking for just a binary, they # get it. $minbits = 1; # The 0+ makes sure is numeric $invert_it = 0 + $file =~ s/^!//; $file = "$unicore_dir/lib/$file.pl"; last GETFILE; } } } ## ## If we reach this line, it's because we couldn't figure ## out what to do with $type. Ouch. ## pop @recursed if @recursed; return $type; } # end of GETFILE block if (defined $file) { print STDERR __LINE__, ": found it (file='$file')\n" if DEBUG; ## ## If we reach here, it was due to a 'last GETFILE' above ## (exception: user-defined properties and mappings), so we ## have a filename, so now we load it if we haven't already. ## If we have, return the cached results. The cache key is the ## class and file to load, and whether the results need to be ## inverted. ## my $found = $Cache{$class, $file, $invert_it}; if ($found and ref($found) eq $class) { print STDERR __LINE__, ": Returning cached swash for '$class,$file,$invert_it' for \\p{$type}\n" if DEBUG; pop @recursed if @recursed; return $found; } local $@; local $!; $list = do $file; die $@ if $@; $list_is_from_mktables = 1; } } # End of $type is non-null # Here, either $type was null, or we found the requested property and # read it into $list my $extras = ""; my $bits = $minbits; # mktables lists don't have extras, like '&utf8::prop', so don't need # to separate them; also lists are already sorted, so don't need to do # that. if ($list && ! $list_is_from_mktables) { my $taint = substr($list,0,0); # maintain taint # Separate the extras from the code point list, and make sure # user-defined properties and tr/// are well-behaved for # downstream code. if ($user_defined || $none) { my @tmp = split(/^/m, $list); my %seen; no warnings; # The extras are anything that doesn't begin with a hex digit. $extras = join '', $taint, grep /^[^0-9a-fA-F]/, @tmp; # Remove the extras, and sort the remaining entries by the # numeric value of their beginning hex digits, removing any # duplicates. $list = join '', $taint, map { $_->[1] } sort { $a->[0] <=> $b->[0] } map { /^([0-9a-fA-F]+)/; [ CORE::hex($1), $_ ] } grep { /^([0-9a-fA-F]+)/ and not $seen{$1}++ } @tmp; # XXX doesn't do ranges right } else { # mktables has gone to some trouble to make non-user defined # properties well-behaved, so we can skip the effort we do for # user-defined ones. Any extras are at the very beginning of # the string. # This regex splits out the first lines of $list into $1 and # strips them off from $list, until we get one that begins # with a hex number, alone on the line, or followed by a tab. # Either portion may be empty. $list =~ s/ \A ( .*? ) (?: \z | (?= ^ [0-9a-fA-F]+ (?: \t | $) ) ) //msx; $extras = "$taint$1"; } } if ($none) { my $hextra = sprintf "%04x", $none + 1; $list =~ s/\tXXXX$/\t$hextra/mg; } if ($minbits != 1 && $minbits < 32) { # not binary property my $top = 0; while ($list =~ /^([0-9a-fA-F]+)(?:[\t]([0-9a-fA-F]+)?)(?:[ \t]([0-9a-fA-F]+))?/mg) { my $min = CORE::hex $1; my $max = defined $2 ? CORE::hex $2 : $min; my $val = defined $3 ? CORE::hex $3 : 0; $val += $max - $min if defined $3; $top = $val if $val > $top; } my $topbits = $top > 0xffff ? 32 : $top > 0xff ? 16 : 8; $bits = $topbits if $bits < $topbits; } my @extras; if ($extras) { for my $x ($extras) { my $taint = substr($x,0,0); # maintain taint pos $x = 0; while ($x =~ /^([^0-9a-fA-F\n])(.*)/mg) { my $char = "$1$taint"; my $name = "$2$taint"; print STDERR __LINE__, ": char [$char] => name [$name]\n" if DEBUG; if ($char =~ /[-+!&]/) { my ($c,$t) = split(/::/, $name, 2); # bogus use of ::, really my $subobj; if ($c eq 'utf8') { $subobj = utf8->SWASHNEW($t, "", $minbits, 0); } elsif (exists &$name) { $subobj = utf8->SWASHNEW($name, "", $minbits, 0); } elsif ($c =~ /^([0-9a-fA-F]+)/) { $subobj = utf8->SWASHNEW("", $c, $minbits, 0); } print STDERR __LINE__, ": returned from getting sub object for $name\n" if DEBUG; if (! ref $subobj) { pop @recursed if @recursed && $type; return $subobj; } push @extras, $name => $subobj; $bits = $subobj->{BITS} if $bits < $subobj->{BITS}; $user_defined = $subobj->{USER_DEFINED} if $subobj->{USER_DEFINED}; } } } } if (DEBUG) { print STDERR __LINE__, ": CLASS = $class, TYPE => $type, BITS => $bits, NONE => $none, INVERT_IT => $invert_it, USER_DEFINED => $user_defined"; print STDERR "\nLIST =>\n$list" if defined $list; print STDERR "\nEXTRAS =>\n$extras" if defined $extras; print STDERR "\n"; } my $SWASH = bless { TYPE => $type, BITS => $bits, EXTRAS => $extras, LIST => $list, NONE => $none, USER_DEFINED => $user_defined, @extras, } => $class; if ($file) { $Cache{$class, $file, $invert_it} = $SWASH; if ($type && exists $utf8::SwashInfo{$type} && exists $utf8::SwashInfo{$type}{'specials_name'}) { my $specials_name = $utf8::SwashInfo{$type}{'specials_name'}; no strict "refs"; print STDERR "\nspecials_name => $specials_name\n" if DEBUG; $SWASH->{'SPECIALS'} = \%$specials_name; } $SWASH->{'INVERT_IT'} = $invert_it; } pop @recursed if @recursed && $type; return $SWASH; } } # Now SWASHGET is recasted into a C function S_swatch_get (see utf8.c). 1;