#!./perl
BEGIN {
chdir
't'
if
-d
't'
;
require
'./test.pl'
;
skip_all_without_unicode_tables();
}
use
5.016;
use
open
qw( :utf8 :std )
;
no
warnings
qw(misc reserved)
;
plan (
tests
=> 66880);
{
no
strict;
local
$@;
eval
"\${\x{30cd}single:\x{30cd}colon} = 'label, not var'"
;
is ${
"\x{30cd}colon"
},
'label, not var'
,
'${\x{30cd}single:\x{30cd}colon} should be block-label'
;
local
$@;
no
utf8;
evalbytes
'${single:colon} = "block/label, not var"'
;
is($::colon,
'block/label, not var'
,
'...same with ${single:colon}'
);
}
{
local
$@;
eval
q<use strict; ${flark::fleem}>
;
is($@,
''
,
q<${package::var} works>
);
no
warnings
qw(syntax deprecated)
;
local
$@;
eval
q<use strict; ${fleem'flark}>
;
is($@,
''
,
q<...as does ${package'var}>
);
}
{
local
$@;
eval
'${☭asd} = 1'
;
like($@,
qr/\QUnrecognized character/
,
q(the first character in ${...} isn't special)
)
}
for
my
$v
(
qw( ^V ; < > ( )
{^GLOBAL_PHASE} ^W _ 1 4 0 ] ! @ / \ = )) {
SKIP: {
local
$@;
evalbytes
"\$$v;"
;
is $@,
''
,
"No syntax error for \$$v"
;
local
$@;
eval
"use utf8; \$$v;"
;
is $@,
''
,
"No syntax error for \$$v under 'use utf8'"
;
}
}
for
( 0x0 .. 0xff ) {
my
@warnings
;
local
$SIG
{__WARN__} =
sub
{
push
@warnings
,
@_
};
my
$ord
= utf8::unicode_to_native(
$_
);
my
$chr
=
chr
$ord
;
my
$syntax_error
= 0;
my
$deprecated
= 0;
my
$name
;
my
$tests
= 0;
my
$max_tests
= 6;
if
(
$chr
=~ /[[:graph:]]/a) {
$name
=
"'$chr'"
;
$syntax_error
= 1
if
$chr
eq
'{'
;
}
elsif
(
$chr
=~ /[[:space:]]/a) {
$name
=
sprintf
"\\x%02x, an ASCII space character"
,
$ord
;
$syntax_error
= 1;
}
elsif
(
$chr
=~ /[[:cntrl:]]/a) {
$name
=
sprintf
"\\x%02x, an ASCII control"
,
$ord
;
$syntax_error
= 1;
}
elsif
(
$chr
=~ /\pC/) {
if
(
$chr
eq
"\N{SHY}"
) {
$name
=
sprintf
"\\x%02x, SHY"
,
$ord
;
}
else
{
$name
=
sprintf
"\\x%02x, a C1 control"
,
$ord
;
}
$syntax_error
= 1;
$deprecated
= !
$syntax_error
;
}
elsif
(
$chr
=~ /\p{XIDStart}/) {
$name
=
sprintf
"\\x%02x, a non-ASCII XIDS character"
,
$ord
;
}
elsif
(
$chr
=~ /\p{XPosixSpace}/) {
$name
=
sprintf
"\\x%02x, a non-ASCII space character"
,
$ord
;
$syntax_error
= 1;
$deprecated
= !
$syntax_error
;
}
else
{
$name
=
sprintf
"\\x%02x, a non-ASCII, non-XIDS graphic character"
,
$ord
;
}
no
warnings
'closure'
;
my
$esc
=
sprintf
(
"%X"
,
$ord
);
utf8::downgrade(
$chr
);
if
(
$chr
!~ /\p{XIDS}/u) {
if
(
$syntax_error
) {
evalbytes
"\$$chr"
;
like($@,
qr/ syntax\ error | Unrecognized\ character /
x,
"$name as a length-1 variable generates a syntax error"
);
$tests
++;
utf8::upgrade(
$chr
);
eval
"no strict; \$$chr = 4;"
,
like($@,
qr/ syntax\ error | Unrecognized\ character /
x,
" ... and the same under 'use utf8'"
);
$tests
++;
}
elsif
(
$chr
=~ /[[:punct:][:digit:]]/a) {
next
if
(
$chr
eq
'#'
or
$chr
eq
'*'
); # RT 133583
local
$@;
evalbytes
"\$$chr;"
;
is $@,
''
,
"$name as a length-1 variable doesn't generate a syntax error"
;
$tests
++;
utf8::upgrade(
$chr
);
evalbytes
"no strict; use utf8; \$$chr;"
,
is $@,
''
,
" ... and the same under 'use utf8'"
;
$tests
++;
}
else
{
is evalbytes
"no strict; \$$chr = 10"
,
10,
"$name is legal as a length-1 variable"
;
$tests
++;
if
(
$chr
=~ /[[:ascii:]]/) {
utf8::upgrade(
$chr
);
is evalbytes
"no strict; use utf8; \$$chr = 1"
,
1,
" ... and is legal under 'use utf8'"
;
$tests
++;
}
else
{
utf8::upgrade(
$chr
);
local
$@;
eval
"no strict; use utf8; \$$chr = 1"
;
like $@,
qr/\QUnrecognized character \x{\E\L$esc/
,
" ... but is illegal as a length-1 variable under 'use utf8'"
;
$tests
++;
}
}
}
else
{
{
no
utf8;
local
$@;
evalbytes
"no strict; \$$chr = 1"
;
is($@,
''
,
"$name under 'no utf8', 'no strict', is a valid length-1 variable"
);
$tests
++;
if
(
$chr
!~ /[[:ascii:]]/) {
local
$@;
evalbytes
"use strict; \$$chr = 1"
;
is($@,
''
,
" ... and under 'no utf8' does not have to be required under strict, even though it matches XIDS"
);
$tests
++;
local
$@;
evalbytes
"\$a$chr = 1"
;
like($@,
qr/Unrecognized character /
,
" ... but under 'no utf8', it's not allowed in length-2+ variables"
);
$tests
++;
}
}
{
my
$utf8
=
$chr
;
utf8::upgrade(
$utf8
);
local
$@;
eval
"no strict; \$$utf8 = 1"
;
is($@,
''
,
" ... and under 'use utf8', 'no strict', is a valid length-1 variable"
);
$tests
++;
local
$@;
eval
"use strict; \$$utf8 = 1"
;
if
(
$chr
=~ /[ab]/) {
is($@,
''
,
" ... and under 'use utf8', 'use strict',"
.
" is a valid length-1 variable (\$a and \$b are special)"
);
$tests
++;
}
else
{
like($@,
qr/Global symbol "\$$utf8" requires explicit package name/
,
" ... and under utf8 has to be required under strict"
);
$tests
++;
}
}
}
if
(!
$deprecated
) {
if
(
$chr
=~ /[
for
(
my
$i
=
@warnings
- 1;
$i
>= 0;
$i
--) {
splice
@warnings
,
$i
, 1
if
$warnings
[
$i
] =~ /is
no
longer supported/;
}
}
my
$message
=
" ... and doesn't generate any warnings"
;
$message
=
" TODO $message"
if
$ord
== 0
||
$chr
=~ /\s/a;
if
(! ok(
@warnings
== 0,
$message
)) {
note
join
"\n"
,
@warnings
;
}
$tests
++;
}
elsif
(!
@warnings
) {
fail(
" ... and generates deprecation warnings (since is deprecated)"
);
$tests
++;
}
else
{
ok((
scalar
@warnings
==
grep
{
$_
=~ /deprecated/ }
@warnings
),
" ... and generates deprecation warnings (only)"
);
$tests
++;
}
SKIP: {
die
"Wrong max count for tests"
if
$tests
>
$max_tests
;
skip(
"untaken tests"
,
$max_tests
-
$tests
)
if
$max_tests
>
$tests
;
}
}
{
my
$ret
=
eval
"my \$c\x{327} = 100; \$c\x{327}"
;
is($@,
''
,
"ASCII character + combining character works as a variable name"
);
is(
$ret
, 100,
" ... and returns the correct value"
);
}
for
my
$chr
(
"\N{EM DASH}"
,
"\x{F8FF}"
,
"\N{POUND SIGN}"
,
"\N{SOFT HYPHEN}"
,
"\N{THIN SPACE}"
,
"\x{11_1111}"
,
"\x{DC00}"
,
"\N{COMBINING DIAERESIS}"
,
"\N{COMBINING ENCLOSING CIRCLE BACKSLASH}"
,
)
{
no
warnings
'non_unicode'
;
my
$esc
=
sprintf
(
"%x"
,
ord
$chr
);
local
$@;
eval
"\$$chr = 1; \$$chr"
;
like($@,
qr/\QUnrecognized character \x{$esc};/
,
"\\x{$esc} is illegal for a length-one identifier"
);
}
for
my
$i
(0x100..0xffff) {
my
$chr
=
chr
(
$i
);
my
$esc
=
sprintf
(
"%x"
,
$i
);
local
$@;
eval
"my \$$chr = q<test>; \$$chr;"
;
if
(
$chr
=~ /^\p{_Perl_IDStart}$/ ) {
is($@,
''
,
sprintf
(
"\\x{%04x} is XIDS, works as a length-1 variable"
,
$i
));
}
else
{
like($@,
qr/\QUnrecognized character \x{$esc};/
,
"\\x{$esc} isn't XIDS, illegal as a length-1 variable"
,
)
}
}
{
no
strict;
local
$@;
eval
<<'EOP';
q{$} =~ /(.)/;
is($$1, $$, q{$$1 parses as ${$1}});
$doof = "test";
$test = "Got here";
$::{+$$} = *doof;
is( $$$$1, $test, q{$$$$1 parses as ${${${$1}}}} );
EOP
is($@,
''
,
q{$$1 parses correctly}
);
for
my
$chr
(
q{@}
,
"\N{U+FF10}"
,
"\N{U+0300}"
) {
my
$esc
=
sprintf
(
"\\x{%x}"
,
ord
$chr
);
local
$@;
eval
<<" EOP";
\$$chr = q{\$};
\$\$$chr;
EOP
like($@,
qr/syntax error|Unrecognized character/
,
qq{\$\$$esc is a syntax error}
);
}
}
{
local
$@;
my
$var
= 10;
eval
' ${ var }'
;
is(
$@,
''
,
'${ var } works under strict'
);
{
no
strict;
for
my
$var
(
'$'
,
"^GLOBAL_PHASE"
,
"^V"
) {
eval
"\${ $var}"
;
is($@,
''
,
"\${ $var} works"
);
eval
"\${$var }"
;
is($@,
''
,
"\${$var } works"
);
eval
"\${ $var }"
;
is($@,
''
,
"\${ $var } works"
);
}
my
$var
=
"\7LOBAL_PHASE"
;
eval
"\${ $var}"
;
like($@,
qr/Unrecognized character \\x07/
,
"\${ $var} generates 'Unrecognized character' error"
);
eval
"\${$var }"
;
like($@,
qr/Unrecognized character \\x07/
,
"\${$var } generates 'Unrecognized character' error"
);
eval
"\${ $var }"
;
like($@,
qr/Unrecognized character \\x07/
,
"\${ $var } generates 'Unrecognized character' error"
);
}
}
{
is(
""
.
eval
"*{\nOIN}"
,
"*main::OIN"
,
"Newlines at the start of an identifier should be skipped over"
);
SKIP: {
skip(
'Is $^U on EBCDIC 1047, BC; nothing works on 0037'
, 1)
if
$::IS_EBCDIC;
is(
""
.
eval
"*{^JOIN}"
,
"*main::\nOIN"
,
" ... but \$^J is still legal"
);
}
my
$ret
=
eval
"\${\cT\n}"
;
like($@,
qr/\QUnrecognized character/
,
'${\n\cT\n} gives an error message'
);
}
{
sub
foo (&) { [1] }
my
%foo
= (
a
=>2);
my
$ret
= @{ foo {
"a"
} };
is(
$ret
,
$foo
{a},
'@{ foo { "a" } } is parsed as @foo{a}'
);
$ret
= @{
foo {
"a"
}
};
is(
$ret
,
$foo
{a},
'@{\nfoo { "a" } } is still parsed as @foo{a}'
);
}