summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/charnames.pm258
-rw-r--r--lib/charnames.t117
-rw-r--r--t/lib/charnames/alias2
3 files changed, 284 insertions, 93 deletions
diff --git a/lib/charnames.pm b/lib/charnames.pm
index 93747fd317..b2de8c5590 100644
--- a/lib/charnames.pm
+++ b/lib/charnames.pm
@@ -2,7 +2,7 @@ package charnames;
use strict;
use warnings;
use File::Spec;
-our $VERSION = '1.11';
+our $VERSION = '1.12';
use bytes (); # for $bytes::hint_bits
@@ -399,8 +399,36 @@ my %deprecated_aliases = (
'REVERSE INDEX' => 0x8D, # REVERSE LINE FEED
);
+
my $txt; # The table of official character names
+my %full_names_cache; # Holds already-looked-up names, so don't have to
+# re-look them up again. The previous versions of charnames had scoping
+# bugs. For example if we use script A in one scope and find and cache
+# what Z resolves to, we can't use that cache in a different scope that
+# uses script B instead of A, as Z might be an entirely different letter
+# there; or there might be different aliases in effect in different
+# scopes, or :short may be in effect or not effect in different scopes,
+# or various combinations thereof. This was solved in this version
+# mostly by moving things to %^H. But some things couldn't be moved
+# there. One of them was the cache of runtime looked-up names, in part
+# because %^H is read-only at runtime. I (khw) don't know why the cache
+# was run-time only in the previous versions: perhaps oversight; perhaps
+# that compile time looking doesn't happen in a loop so didn't think it
+# was worthwhile; perhaps not wanting to make the cache too large. But
+# I decided to make it compile time as well; this could easily be
+# changed.
+# Anyway, this hash is not scoped, and is added to at runtime. It
+# doesn't have scoping problems because the data in it is restricted to
+# official names, which are always invariant, and we only set it and
+# look at it at during :full lookups, so is unaffected by any other
+# scoped options. I put this in to maintain parity with the older
+# version. If desired, a %short_names cache could also be made, as well
+# as one for each script, say in %script_names_cache, with each key
+# being a hash for a script named in a 'use charnames' statement. I
+# decided not to do that for now, just because it's added complication,
+# and because I'm just trying to maintain parity, not extend it.
+
# Designed so that test decimal first, and then hex. Leading zeros
# imply non-decimal, as do non-[0-9]
my $decimal_qr = qr/^[1-9]\d*$/;
@@ -423,21 +451,25 @@ sub alias (@) # Set up a single alias
my $alias = ref $_[0] ? $_[0] : { @_ };
foreach my $name (keys %$alias) {
my $value = $alias->{$name};
+ next unless defined $value; # Omit if screwed up.
+
+ # Is slightly slower to just after this statement see if it is
+ # decimal, since we already know it is after having converted from
+ # hex, but makes the code easier to maintain, and is called
+ # infrequently, only at compile-time
+ if ($value !~ $decimal_qr && $value =~ $hex_qr) {
+ $value = CORE::hex $1;
+ }
if ($value =~ $decimal_qr) {
- $user_numeric_aliases{$name} = $value;
+ $^H{charnames_ord_aliases}{$name} = $value;
# Use a canonical form.
- $inverse_user_aliases{sprintf("%04X", $value)} = $name;
- }
- elsif ($value =~ $hex_qr) {
- my $decimal = CORE::hex $1;
- $user_numeric_aliases{$name} = $decimal;
-
- # Must convert to decimal and back to guarantee canonical form
- $inverse_user_aliases{sprintf("%04X", $decimal)} = $name;
+ $^H{charnames_inverse_ords}{sprintf("%04X", $value)} = $name;
}
else {
- $user_name_aliases{$name} = $value;
+ # XXX validate syntax when deprecation cycle complete. ie. start
+ # with an alpha only, etc.
+ $^H{charnames_name_aliases}{$name} = $value;
}
}
} # alias
@@ -471,23 +503,39 @@ sub alias_file ($) # Reads a file containing alias definitions
} # alias_file
-sub lookup_name {
- my $name = shift;
- my $runtime = shift; # compile vs run time
+sub lookup_name ($;$) {
# Finds the ordinal of a character name, first in the aliases, then in
# the large table. If not found, returns undef if runtime; if
# compile, complains and returns the Unicode replacement character.
+ my $runtime = (@_ > 1); # compile vs run time
+
+ my $name = shift;
+ my $hints_ref = shift;
+
my $ord;
+ if ($runtime) {
+ # At runtime, but currently not at compile time, $^H gets
+ # stringified, so un-stringify back to the original data structures.
+ # These get thrown away by perl before the next invocation
+ # Also fill in the hash with the non-stringified data.
+
+ %{$^H{charnames_name_aliases}} = split ',', $hints_ref->{charnames_stringified_names};
+ %{$^H{charnames_ord_aliases}} = split ',', $hints_ref->{charnames_stringified_ords};
+ @{$^H{charnames_scripts}} = split ',', $hints_ref->{charnames_stringified_scripts};
+ $^H{charnames_full} = $hints_ref->{charnames_full};
+ $^H{charnames_short} = $hints_ref->{charnames_short};
+ }
+
# User alias should be checked first or else can't override ours, and if we
# add any, could conflict with theirs.
- if (exists $user_numeric_aliases{$name}) {
- $ord = $user_numeric_aliases{$name};
+ if (exists $^H{charnames_ord_aliases}{$name}) {
+ $ord = $^H{charnames_ord_aliases}{$name};
}
- elsif (exists $user_name_aliases{$name}) {
- $name = $user_name_aliases{$name};
+ elsif (exists $^H{charnames_name_aliases}{$name}) {
+ $name = $^H{charnames_name_aliases}{$name};
}
elsif (exists $system_aliases{$name}) {
$ord = $system_aliases{$name};
@@ -501,75 +549,93 @@ sub lookup_name {
my @off;
if (! defined $ord) {
- ## Suck in the code/name list as a big string.
- ## Lines look like:
- ## "0052\t\tLATIN CAPITAL LETTER R\n"
- $txt = do "unicore/Name.pl" unless $txt;
- ## @off will hold the index into the code/name string of the start and
- ## end of the name as we find it.
- ## If :full, look for the name exactly; runtime implies full
- if (($runtime || $^H{charnames_full}) && $txt =~ /\t\t\Q$name\E$/m) {
- @off = ($-[0] + 2, $+[0]); # The 2 is for the 2 tabs
+ if ($^H{charnames_full} && exists $full_names_cache{$name}) {
+ $ord = $full_names_cache{$name};
}
+ else {
- ## If we didn't get above, and :short allowed, look for the short name.
- ## The short name is like "greek:Sigma"
- unless (@off) {
- if (($runtime || $^H{charnames_short}) && $name =~ /^(.+?):(.+)/s) {
- my ($script, $cname) = ($1, $2);
- my $case = $cname =~ /[[:upper:]]/ ? "CAPITAL" : "SMALL";
- if ($txt =~ m/\t\t\U$script\E (?:$case )?LETTER \U\Q$cname\E$/m) {
- @off = ($-[0] + 2, $+[0]);
- }
+ ## Suck in the code/name list as a big string.
+ ## Lines look like:
+ ## "0052\t\tLATIN CAPITAL LETTER R\n"
+ $txt = do "unicore/Name.pl" unless $txt;
+
+ ## @off will hold the index into the code/name string of the start and
+ ## end of the name as we find it.
+
+ ## If :full, look for the name exactly; runtime implies full
+ my $found_full = 0; # Tells us if can cache the result
+ if ($^H{charnames_full}) {
+ if ($txt =~ /\t\t\Q$name\E$/m) {
+ @off = ($-[0] + 2, $+[0]); # The 2 is for the 2 tabs
+ $found_full = 1;
+ }
}
- }
- ## If we still don't have it, check for the name among the loaded
- ## scripts.
- if (! $runtime && not @off) {
- my $case = $name =~ /[[:upper:]]/ ? "CAPITAL" : "SMALL";
- for my $script (@{$^H{charnames_scripts}}) {
- if ($txt =~ m/\t\t$script (?:$case )?LETTER \U\Q$name\E$/m) {
- @off = ($-[0] + 2, $+[0]);
- last;
- }
+ # If we didn't get it above keep looking
+ if (! $found_full) {
+
+ # If :short is allowed, look for the short name, which is like
+ # "greek:Sigma"
+ if (($^H{charnames_short}) && $name =~ /^(.+?):(.+)/s) {
+ my ($script, $cname) = ($1, $2);
+ my $case = $cname =~ /[[:upper:]]/ ? "CAPITAL" : "SMALL";
+ if ($txt =~ m/\t\t\U$script\E (?:$case )?LETTER \U\Q$cname\E$/m) {
+ @off = ($-[0] + 2, $+[0]);
+ }
+ }
+
+ ## If we still don't have it, check for the name among the loaded
+ ## scripts.
+ unless (@off) {
+ my $case = $name =~ /[[:upper:]]/ ? "CAPITAL" : "SMALL";
+ for my $script (@{$^H{charnames_scripts}}) {
+ if ($txt =~ m/\t\t$script (?:$case )?LETTER \U\Q$name\E$/m) {
+ @off = ($-[0] + 2, $+[0]);
+ last;
+ }
+ }
+
+ ## If we don't have it by now, give up.
+ unless (@off) {
+ return if $runtime;
+ carp "Unknown charname '$name'";
+ return 0xFFFD;
+ }
+ }
}
- }
- ## If we don't have it by now, give up.
- unless (@off) {
- return if $runtime;
- carp "Unknown charname '$name'";
- return 0xFFFD;
+ ##
+ ## Now know where in the string the name starts.
+ ## The code, in hex, is before that.
+ ##
+ ## The code can be 4-6 characters long, so we've got to sort of
+ ## go look for it, just after the newline that comes before $off[0].
+ ##
+ ## This would be much easier if unicore/Name.pl had info in
+ ## a name/code order, instead of code/name order.
+ ##
+ ## The +1 after the rindex() is to skip past the newline we're finding,
+ ## or, if the rindex() fails, to put us to an offset of zero.
+ ##
+ my $hexstart = rindex($txt, "\n", $off[0]) + 1;
+
+ ## we know where it starts, so turn into number -
+ ## the ordinal for the char.
+ $ord = CORE::hex substr($txt, $hexstart, $off[0] - 2 - $hexstart);
+
+ # Cache the input so as to not have to search the large table
+ # again, but only if it came from the one search that we cache.
+ $full_names_cache{$name} = $ord if $found_full;
}
-
- ##
- ## Now know where in the string the name starts.
- ## The code, in hex, is before that.
- ##
- ## The code can be 4-6 characters long, so we've got to sort of
- ## go look for it, just after the newline that comes before $off[0].
- ##
- ## This would be much easier if unicore/Name.pl had info in
- ## a name/code order, instead of code/name order.
- ##
- ## The +1 after the rindex() is to skip past the newline we're finding,
- ## or, if the rindex() fails, to put us to an offset of zero.
- ##
- my $hexstart = rindex($txt, "\n", $off[0]) + 1;
-
- ## we know where it starts, so turn into number -
- ## the ordinal for the char.
- $ord = CORE::hex substr($txt, $hexstart, $off[0] - 2 - $hexstart);
}
return $ord if $runtime || $ord <= 255 || ! ($^H & $bytes::hint_bits);
# Here is compile time, "use bytes" is in effect, and the character
# won't fit in a byte
- # Get the official name if have one
+ # Use the official name if have one
$name = substr($txt, $off[0], $off[1] - $off[0]) if @off;
croak not_legal_use_bytes_msg($name, $ord);
} # lookup_name
@@ -580,8 +646,8 @@ sub charnames {
# For \N{...}. Looks up the character name and returns its ordinal if
# found, undef otherwise. If not in 'use bytes', forces into utf8
- my $ord = lookup_name($name, 0); # 0 means compile-time
- return unless defined $ord;
+ my $ord = lookup_name($name);
+ return if ! defined $ord;
return chr $ord if $^H & $bytes::hint_bits;
no warnings 'utf8'; # allow even illegal characters
@@ -596,6 +662,9 @@ sub import
carp("`use charnames' needs explicit imports list");
}
$^H{charnames} = \&charnames ;
+ $^H{charnames_ord_aliases} = {};
+ $^H{charnames_name_aliases} = {};
+ $^H{charnames_inverse_ords} = {};
##
## fill %h keys with our @_ args.
@@ -647,9 +716,19 @@ sub import
}
}
}
+
+ # %^H gets stringified, so serialize it ourselves so can extract the
+ # real data back later.
+ $^H{charnames_stringified_ords} = join ",", %{$^H{charnames_ord_aliases}};
+ $^H{charnames_stringified_names} = join ",", %{$^H{charnames_name_aliases}};
+ $^H{charnames_stringified_inverse_ords} = join ",", %{$^H{charnames_inverse_ords}};
+ $^H{charnames_stringified_scripts} = join ",", @{$^H{charnames_scripts}};
} # import
-my %viacode; # Cache of already-found codes
+# Cache of already looked-up values. This is set to only contain
+# official values, and user aliases can't override them, so scoping is
+# not an issue.
+my %viacode;
sub viacode {
@@ -692,26 +771,26 @@ sub viacode {
# The name starts with the next character and goes up to the
# next new-line. Using capturing parentheses above instead of
- # @$+ more than doubles the execution time in Perl 5.13
+ # @+ more than doubles the execution time in Perl 5.13
$viacode{$hex} = substr($txt, $+[0], index($txt, "\n", $+[0]) - $+[0]);
- return $viacode{$hex};
+ return $viacode{$hex};
}
}
# See if there is a user name for it, before giving up completely.
- if (! exists $inverse_user_aliases{$hex}) {
+ # First get the scoped aliases.
+ my %code_point_aliases = split ',',
+ (caller(0))[10]->{charnames_stringified_inverse_ords};
+ if (! exists $code_point_aliases{$hex}) {
if (CORE::hex($hex) > 0x10FFFF) {
carp "Unicode characters only allocated up to U+10FFFF (you asked for U+$hex)";
}
return;
}
- $viacode{$hex} = $inverse_user_aliases{$hex};
- return $inverse_user_aliases{$hex};
+ return $code_point_aliases{$hex};
} # viacode
-my %vianame; # Cache of already-found names
-
sub vianame
{
if (@_ != 1) {
@@ -734,11 +813,7 @@ sub vianame
return;
}
- if (! exists $vianame{$arg}) {
- $vianame{$arg} = lookup_name($arg, 1); # 1 means run-time
- }
-
- return $vianame{$arg};
+ return lookup_name($arg, (caller(0))[10]);
} # vianame
@@ -1041,12 +1116,13 @@ For example,
prints "2722".
C<vianame> takes the identical inputs that C<\N{...}> does under the
-L<C<:full> and C<:short>|/DESCRIPTION> options to the C<charnames>
-pragma, including any L<custom aliases|/CUSTOM ALIASES> you may have
-defined.
+L<C<:full> option|/DESCRIPTION> to C<charnames>. In addition, any other
+options for the controlling C<"use charnames"> in the same scope apply,
+like any L<script list, C<:short> option|/DESCRIPTION>, or L<custom
+aliases|/CUSTOM ALIASES> you may have defined.
There are just a few differences. The main one is that under
-most circumstances, (see L</BUGS> for the other ones), vianame returns
+most (see L</BUGS> for the others) circumstances, vianame returns
an ord, whereas C<\\N{...}> is seamlessly placed as a chr into the
string in which it appears. This leads to a second difference.
Since an ord is returned, it can be that of any character, even one
diff --git a/lib/charnames.t b/lib/charnames.t
index 1269c5202e..93fa3e9608 100644
--- a/lib/charnames.t
+++ b/lib/charnames.t
@@ -14,7 +14,7 @@ BEGIN {
$SIG{__WARN__} = sub { push @WARN, @_ };
}
-our $local_tests = 440;
+our $local_tests = 514;
# ---- For the alias extensions
require "../t/lib/common.pl";
@@ -652,3 +652,118 @@ is("\N{U+1D0C5}", "\N{BYZANTINE MUSICAL SYMBOL FTHORA SKLIRON CHROMA VASIS}");
$res .= '-3' if ":" =~ /\N{COLON}/i;
is($res, "foo-foo-1--2-3");
}
+
+{
+ # Test scoping. Outer block sets up some things; inner blocks
+ # override them, and then see if get restored.
+
+ use charnames ":full",
+ ":alias" => {
+ mychar1 => "LATIN SMALL LETTER E",
+ mychar2 => "LATIN CAPITAL LETTER A",
+ myprivate1 => 0xE8000, # Private use area
+ myprivate2 => 0x100000, # Private use area
+ },
+ ":short",
+ qw( katakana ),
+ ;
+
+ my $hiragana_be = "\N{HIRAGANA LETTER BE}";
+
+ is("\N{mychar1}", "e", "Outer block: verify that \\N{mychar1} works");
+ is(charnames::vianame("mychar1"), ord("e"), "Outer block: verify that vianame(mychar1) works");
+ is("\N{mychar2}", "A", "Outer block: verify that \\N{mychar2} works");
+ is(charnames::vianame("mychar2"), ord("A"), "Outer block: verify that vianame(mychar2) works");
+ is("\N{myprivate1}", "\x{E8000}", "Outer block: verify that \\N{myprivate1} works");
+ cmp_ok(charnames::vianame("myprivate1"), "==", 0xE8000, "Outer block: verify that vianame(myprivate1) works");
+ is(charnames::viacode(0xE8000), "myprivate1", "Outer block: verify that myprivate1 viacode works");
+ is("\N{myprivate2}", "\x{100000}", "Outer block: verify that \\N{myprivate2} works");
+ cmp_ok(charnames::vianame("myprivate2"), "==", 0x100000, "Outer block: verify that vianame(myprivate2) works");
+ is(charnames::viacode(0x100000), "myprivate2", "Outer block: verify that myprivate2 viacode works");
+ is("\N{BE}", "\N{KATAKANA LETTER BE}", "Outer block: verify that \\N uses the correct script ");
+ cmp_ok(charnames::vianame("BE"), "==", ord("\N{KATAKANA LETTER BE}"), "Outer block: verify that vianame uses the correct script");
+ is("\N{Hiragana:BE}", $hiragana_be, "Outer block: verify that :short works with \\N");
+ cmp_ok(charnames::vianame("Hiragana:BE"), "==", ord($hiragana_be), "Outer block: verify that :short works with vianame");
+
+ {
+ use charnames ":full",
+ ":alias" => {
+ mychar1 => "LATIN SMALL LETTER F",
+ myprivate1 => 0xE8001, # Private use area
+ },
+
+ # BE is in both hiragana and katakana; see if
+ # different default script delivers different
+ # letter.
+ qw( hiragana ),
+ ;
+ is("\N{mychar1}", "f", "Inner block: verify that \\N{mychar1} is redefined");
+ is(charnames::vianame("mychar1"), ord("f"), "Inner block: verify that vianame(mychar1) is redefined");
+ is("\N{mychar2}", "\x{FFFD}", "Inner block: verify that \\N{mychar2} outer definition didn't leak");
+ ok( ! defined charnames::vianame("mychar2"), "Inner block: verify that vianame(mychar2) outer definition didn't leak");
+ is("\N{myprivate1}", "\x{E8001}", "Inner block: verify that \\N{myprivate1} is redefined ");
+ cmp_ok(charnames::vianame("myprivate1"), "==", 0xE8001, "Inner block: verify that vianame(myprivate1) is redefined");
+ is(charnames::viacode(0xE8001), "myprivate1", "Inner block: verify that myprivate1 viacode is redefined");
+ ok(! defined charnames::viacode(0xE8000), "Inner block: verify that outer myprivate1 viacode didn't leak");
+ is("\N{myprivate2}", "\x{FFFD}", "Inner block: verify that \\N{myprivate2} outer definition didn't leak");
+ ok(! defined charnames::vianame("myprivate2"), "Inner block: verify that vianame(myprivate2) outer definition didn't leak");
+ ok(! defined charnames::viacode(0x100000), "Inner block: verify that myprivate2 viacode outer definition didn't leak");
+ is("\N{BE}", $hiragana_be, "Inner block: verify that \\N uses the correct script");
+ cmp_ok(charnames::vianame("BE"), "==", ord($hiragana_be), "Inner block: verify that vianame uses the correct script");
+ is("\N{Hiragana:BE}", "\x{FFFD}", "Inner block without :short: \\N with short doesn't work");
+ ok(! defined charnames::vianame("Hiragana:BE"), "Inner block without :short: verify that vianame with short doesn't work");
+
+ { # An inner block where only :short definitions are valid.
+ use charnames ":short";
+ is("\N{mychar1}", "\x{FFFD}", "Inner inner block: verify that mychar1 outer definition didn't leak with \\N");
+ ok( ! defined charnames::vianame("mychar1"), "Inner inner block: verify that mychar1 outer definition didn't leak with vianame");
+ is("\N{mychar2}", "\x{FFFD}", "Inner inner block: verify that mychar2 outer definition didn't leak with \\N");
+ ok( ! defined charnames::vianame("mychar2"), "Inner inner block: verify that mychar2 outer definition didn't leak with vianame");
+ is("\N{myprivate1}", "\x{FFFD}", "Inner inner block: verify that myprivate1 outer definition didn't leak with \\N");
+ ok(! defined charnames::vianame("myprivate1"), "Inner inner block: verify that myprivate1 outer definition didn't leak with vianame");
+ is("\N{myprivate2}", "\x{FFFD}", "Inner inner block: verify that myprivate2 outer definition didn't leak with \\N");
+ ok(! defined charnames::vianame("myprivate2"), "Inner inner block: verify that myprivate2 outer definition didn't leak with vianame");
+ ok(! defined charnames::viacode(0xE8000), "Inner inner block: verify that mychar1 outer outer definition didn't leak with viacode");
+ ok(! defined charnames::viacode(0xE8001), "Inner inner block: verify that mychar1 outer definition didn't leak with viacode");
+ ok(! defined charnames::viacode(0x100000), "Inner inner block: verify that mychar2 outer definition didn't leak with viacode");
+ is("\N{BE}", "\x{FFFD}", "Inner inner block without script: verify that outer :script didn't leak with \\N");
+ ok(! defined charnames::vianame("BE"), "Inner inner block without script: verify that outer :script didn't leak with vianames");
+ is("\N{HIRAGANA LETTER BE}", "\x{FFFD}", "Inner inner block without :full: verify that outer :full didn't leak with \\N");
+ is("\N{Hiragana:BE}", $hiragana_be, "Inner inner block with :short: verify that \\N works with :short");
+ cmp_ok(charnames::vianame("Hiragana:BE"), "==", ord($hiragana_be), "Inner inner block with :short: verify that vianame works with :short");
+ }
+
+ # Back to previous block. All previous tests should work again.
+ is("\N{mychar1}", "f", "Inner block: verify that \\N{mychar1} is redefined");
+ is(charnames::vianame("mychar1"), ord("f"), "Inner block: verify that vianame(mychar1) is redefined");
+ is("\N{mychar2}", "\x{FFFD}", "Inner block: verify that \\N{mychar2} outer definition didn't leak");
+ ok( ! defined charnames::vianame("mychar2"), "Inner block: verify that vianame(mychar2) outer definition didn't leak");
+ is("\N{myprivate1}", "\x{E8001}", "Inner block: verify that \\N{myprivate1} is redefined ");
+ cmp_ok(charnames::vianame("myprivate1"), "==", 0xE8001, "Inner block: verify that vianame(myprivate1) is redefined");
+ is(charnames::viacode(0xE8001), "myprivate1", "Inner block: verify that myprivate1 viacode is redefined");
+ ok(! defined charnames::viacode(0xE8000), "Inner block: verify that outer myprivate1 viacode didn't leak");
+ is("\N{myprivate2}", "\x{FFFD}", "Inner block: verify that \\N{myprivate2} outer definition didn't leak");
+ ok(! defined charnames::vianame("myprivate2"), "Inner block: verify that vianame(myprivate2) outer definition didn't leak");
+ ok(! defined charnames::viacode(0x100000), "Inner block: verify that myprivate2 viacode outer definition didn't leak");
+ is("\N{BE}", $hiragana_be, "Inner block: verify that \\N uses the correct script");
+ cmp_ok(charnames::vianame("BE"), "==", ord($hiragana_be), "Inner block: verify that vianame uses the correct script");
+ is("\N{Hiragana:BE}", "\x{FFFD}", "Inner block without :short: \\N with short doesn't work");
+ ok(! defined charnames::vianame("Hiragana:BE"), "Inner block without :short: verify that vianame with short doesn't work");
+ }
+
+ # Back to previous block. All tests from that block should work again.
+ is("\N{mychar1}", "e", "Outer block: verify that \\N{mychar1} works");
+ is(charnames::vianame("mychar1"), ord("e"), "Outer block: verify that vianame(mychar1) works");
+ is("\N{mychar2}", "A", "Outer block: verify that \\N{mychar2} works");
+ is(charnames::vianame("mychar2"), ord("A"), "Outer block: verify that vianame(mychar2) works");
+ is("\N{myprivate1}", "\x{E8000}", "Outer block: verify that \\N{myprivate1} works");
+ cmp_ok(charnames::vianame("myprivate1"), "==", 0xE8000, "Outer block: verify that vianame(myprivate1) works");
+ is(charnames::viacode(0xE8000), "myprivate1", "Outer block: verify that myprivate1 viacode works");
+ is("\N{myprivate2}", "\x{100000}", "Outer block: verify that \\N{myprivate2} works");
+ cmp_ok(charnames::vianame("myprivate2"), "==", 0x100000, "Outer block: verify that vianame(myprivate2) works");
+ is(charnames::viacode(0x100000), "myprivate2", "Outer block: verify that myprivate2 viacode works");
+ is("\N{BE}", "\N{KATAKANA LETTER BE}", "Outer block: verify that \\N uses the correct script ");
+ cmp_ok(charnames::vianame("BE"), "==", ord("\N{KATAKANA LETTER BE}"), "Outer block: verify that vianame uses the correct script");
+ is("\N{Hiragana:BE}", $hiragana_be, "Outer block: verify that :short works with \\N");
+ cmp_ok(charnames::vianame("Hiragana:BE"), "==", ord($hiragana_be), "Outer block: verify that :short works with vianame");
+}
diff --git a/t/lib/charnames/alias b/t/lib/charnames/alias
index 76a139fef2..a0fd20c5ba 100644
--- a/t/lib/charnames/alias
+++ b/t/lib/charnames/alias
@@ -83,7 +83,7 @@ use charnames ":short", ":alias" => { e_ACUTE => "LATIN:e WITH ACUTE", "a_ACUTE"
"Here: \N{e_ACUTE}\N{a_ACUTE}!\n";
EXPECT
OPTIONS regex
-Use of uninitialized value
+Unknown charname 'a_ACUTE' at
########
# alias with hashref two aliases
use charnames ":short", ":alias" => {