xref: /openbsd-src/gnu/usr.bin/perl/lib/B/Deparse-core.t (revision 3d61058aa5c692477b6d18acfbbdb653a9930ff9)
16fb12b70Safresh1#!./perl
26fb12b70Safresh1
36fb12b70Safresh1# Test the core keywords.
46fb12b70Safresh1#
56fb12b70Safresh1# Initially this test file just checked that CORE::foo got correctly
66fb12b70Safresh1# deparsed as CORE::foo, hence the name. It's since been expanded
7b8851fccSafresh1# to fully test both CORE:: versus none, plus that any arguments
86fb12b70Safresh1# are correctly deparsed. It also cross-checks against regen/keywords.pl
96fb12b70Safresh1# to make sure we've tested all keywords, and with the correct strength.
106fb12b70Safresh1#
116fb12b70Safresh1# A keyword can be either weak or strong. Strong keywords can never be
126fb12b70Safresh1# overridden, while weak ones can. So deparsing of weak keywords depends
136fb12b70Safresh1# on whether a sub of that name has been created:
146fb12b70Safresh1#
156fb12b70Safresh1# for both:         keyword(..) deparsed as keyword(..)
166fb12b70Safresh1# for weak:   CORE::keyword(..) deparsed as CORE::keyword(..)
176fb12b70Safresh1# for strong: CORE::keyword(..) deparsed as keyword(..)
186fb12b70Safresh1#
196fb12b70Safresh1# Three permutations of lex/nonlex args are checked for:
206fb12b70Safresh1#
216fb12b70Safresh1#   foo($a,$b,$c,...)
226fb12b70Safresh1#   foo(my $a,$b,$c,...)
236fb12b70Safresh1#   my ($a,$b,$c,...); foo($a,$b,$c,...)
246fb12b70Safresh1#
256fb12b70Safresh1# Note that tests for prefixing feature.pm-enabled keywords with CORE:: when
266fb12b70Safresh1# feature.pm is not enabled are in deparse.t, as they fit that format better.
276fb12b70Safresh1
286fb12b70Safresh1
296fb12b70Safresh1BEGIN {
306fb12b70Safresh1    require Config;
316fb12b70Safresh1    if (($Config::Config{extensions} !~ /\bB\b/) ){
326fb12b70Safresh1        print "1..0 # Skip -- Perl configured without B module\n";
336fb12b70Safresh1        exit 0;
346fb12b70Safresh1    }
356fb12b70Safresh1}
366fb12b70Safresh1
37*3d61058aSafresh1use warnings;
386fb12b70Safresh1use strict;
396fb12b70Safresh1use Test::More;
406fb12b70Safresh1
416fb12b70Safresh1use feature (sprintf(":%vd", $^V)); # to avoid relying on the feature
426fb12b70Safresh1                                    # logic to add CORE::
436fb12b70Safresh1use B::Deparse;
44eac174f2Safresh1my $deparse = B::Deparse->new();
456fb12b70Safresh1
466fb12b70Safresh1my %SEEN;
47eac174f2Safresh1my %SEEN_STRENGTH;
486fb12b70Safresh1
49eac174f2Safresh1# For a given keyword, create a sub of that name,
50eac174f2Safresh1# then deparse 3 different assignment expressions
51eac174f2Safresh1# using that keyword.  See if the $expr we get back
52eac174f2Safresh1# matches $expected_expr.
536fb12b70Safresh1
546fb12b70Safresh1sub testit {
55b8851fccSafresh1    my ($keyword, $expr, $expected_expr, $lexsub) = @_;
566fb12b70Safresh1
576fb12b70Safresh1    $expected_expr //= $expr;
586fb12b70Safresh1    $SEEN{$keyword} = 1;
596fb12b70Safresh1
606fb12b70Safresh1    # lex=0:   () = foo($a,$b,$c)
616fb12b70Safresh1    # lex=1:   my ($a,$b); () = foo($a,$b,$c)
626fb12b70Safresh1    # lex=2:   () = foo(my $a,$b,$c)
636fb12b70Safresh1    for my $lex (0, 1, 2) {
64eac174f2Safresh1        next if ($lex and $keyword =~ /local|our|state|my/);
656fb12b70Safresh1        my $vars = $lex == 1 ? 'my($a, $b, $c, $d, $e);' . "\n    " : "";
666fb12b70Safresh1
676fb12b70Safresh1        if ($lex == 2) {
686fb12b70Safresh1            my $repl = 'my $a';
69b8851fccSafresh1            if ($expr =~ 'CORE::do') {
70b8851fccSafresh1                # do foo() is a syntax error, so B::Deparse emits
71b8851fccSafresh1                # do (foo()), but does not distinguish between foo and my,
72b8851fccSafresh1                # because it is too complicated.
73b8851fccSafresh1                $repl = '(my $a)';
746fb12b70Safresh1            }
756fb12b70Safresh1            s/\$a/$repl/ for $expr, $expected_expr;
766fb12b70Safresh1        }
776fb12b70Safresh1
786fb12b70Safresh1        my $desc = "$keyword: lex=$lex $expr => $expected_expr";
79b8851fccSafresh1        $desc .= " (lex sub)" if $lexsub;
806fb12b70Safresh1
819f11ffb7Safresh1        my $code;
826fb12b70Safresh1        my $code_ref;
83b8851fccSafresh1        if ($lexsub) {
84b8851fccSafresh1            package lexsubtest;
85eac174f2Safresh1            no warnings 'experimental::lexical_subs';
86b8851fccSafresh1            use feature 'lexical_subs';
87*3d61058aSafresh1            $code = "no warnings 'syntax'; no strict 'vars'; sub { state sub $keyword; ${vars}() = $expr }";
8856d68f1eSafresh1            $code = "use feature 'isa';\n$code" if $keyword eq "isa";
89eac174f2Safresh1            $code = "use feature 'switch';\n$code" if $keyword eq "break";
90eac174f2Safresh1            $code_ref = eval $code or die "$@ in $expr";
91b8851fccSafresh1        }
92b8851fccSafresh1        else {
936fb12b70Safresh1            package test;
946fb12b70Safresh1            use subs ();
956fb12b70Safresh1            import subs $keyword;
96*3d61058aSafresh1            $code = "no warnings 'syntax'; no strict 'vars'; sub { ${vars}() = $expr }";
9756d68f1eSafresh1            $code = "use feature 'isa';\n$code" if $keyword eq "isa";
98eac174f2Safresh1            $code = "use feature 'switch';\n$code" if $keyword eq "break";
99eac174f2Safresh1            $code_ref = eval $code or die "$@ in $expr";
1006fb12b70Safresh1        }
1016fb12b70Safresh1
1026fb12b70Safresh1        my $got_text = $deparse->coderef2text($code_ref);
1036fb12b70Safresh1
104b8851fccSafresh1        unless ($got_text =~ /
105b8851fccSafresh1    package (?:lexsub)?test;
1069f11ffb7Safresh1(?:    BEGIN \{\$\{\^WARNING_BITS\} = "[^"]+"\}
1079f11ffb7Safresh1)?    use strict 'refs', 'subs';
1086fb12b70Safresh1    use feature [^\n]+
1099f11ffb7Safresh1(?:    (?:CORE::)?state sub \w+;
1109f11ffb7Safresh1)?    \Q$vars\E\(\) = (.*)
1119f11ffb7Safresh1\}/s) {
1126fb12b70Safresh1            ::fail($desc);
1136fb12b70Safresh1            ::diag("couldn't extract line from boilerplate\n");
1146fb12b70Safresh1            ::diag($got_text);
1156fb12b70Safresh1            return;
1166fb12b70Safresh1        }
1176fb12b70Safresh1
1186fb12b70Safresh1        my $got_expr = $1;
1199f11ffb7Safresh1        is $got_expr, $expected_expr, $desc
1209f11ffb7Safresh1            or ::diag("ORIGINAL CODE:\n$code");;
1216fb12b70Safresh1    }
1226fb12b70Safresh1}
1236fb12b70Safresh1
1246fb12b70Safresh1
1256fb12b70Safresh1# Deparse can't distinguish 'and' from '&&' etc
1266fb12b70Safresh1my %infix_map = qw(and && or ||);
1276fb12b70Safresh1
128eac174f2Safresh1# Test a keyword that is a binary infix operator, like 'cmp'.
1296fb12b70Safresh1# $parens - "$a op $b" is deparsed as "($a op $b)"
1306fb12b70Safresh1# $strong - keyword is strong
1316fb12b70Safresh1
1326fb12b70Safresh1sub do_infix_keyword {
1336fb12b70Safresh1    my ($keyword, $parens, $strong) = @_;
134eac174f2Safresh1    $SEEN_STRENGTH{$keyword} = $strong;
1356fb12b70Safresh1    my $nkey = $infix_map{$keyword} // $keyword;
1366fb12b70Safresh1    my $exp = "\$a $nkey \$b";
1376fb12b70Safresh1    $exp = "($exp)" if $parens;
1386fb12b70Safresh1    $exp .= ";";
1396fb12b70Safresh1    # with infix notation, a keyword is always interpreted as core,
1406fb12b70Safresh1    # so no need for Deparse to disambiguate with CORE::
1416fb12b70Safresh1    testit $keyword, "(\$a CORE::$keyword \$b)", $exp;
1426fb12b70Safresh1    testit $keyword, "(\$a $keyword \$b)", $exp;
143b8851fccSafresh1    testit $keyword, "(\$a CORE::$keyword \$b)", $exp, 1;
144b8851fccSafresh1    testit $keyword, "(\$a $keyword \$b)", $exp, 1;
1456fb12b70Safresh1    if (!$strong) {
146b8851fccSafresh1        # B::Deparse fully qualifies any sub whose name is a keyword,
147b8851fccSafresh1        # imported or not, since the importedness may not be reproduced by
148b8851fccSafresh1        # the deparsed code.  x is special.
149b8851fccSafresh1        my $pre = "test::" x ($keyword ne 'x');
150b8851fccSafresh1        testit $keyword, "$keyword(\$a, \$b)", "$pre$keyword(\$a, \$b);";
1516fb12b70Safresh1    }
152b8851fccSafresh1    testit $keyword, "$keyword(\$a, \$b)", "$keyword(\$a, \$b);", 1;
1536fb12b70Safresh1}
1546fb12b70Safresh1
155eac174f2Safresh1# Test a keyword that is a standard op/function, like 'index(...)'.
156eac174f2Safresh1# $narg   - how many args to test it with
1576fb12b70Safresh1# $parens - "foo $a, $b" is deparsed as "foo($a, $b)"
1586fb12b70Safresh1# $dollar - an extra '$_' arg will appear in the deparsed output
1596fb12b70Safresh1# $strong - keyword is strong
1606fb12b70Safresh1
1616fb12b70Safresh1
1626fb12b70Safresh1sub do_std_keyword {
1636fb12b70Safresh1    my ($keyword, $narg, $parens, $dollar, $strong) = @_;
1646fb12b70Safresh1
165eac174f2Safresh1    $SEEN_STRENGTH{$keyword} = $strong;
1666fb12b70Safresh1
1676fb12b70Safresh1    for my $core (0,1) { # if true, add CORE:: to keyword being deparsed
168b8851fccSafresh1        for my $lexsub (0,1) { # if true, define lex sub
1696fb12b70Safresh1            my @code;
1706fb12b70Safresh1            for my $do_exp(0, 1) { # first create expr, then expected-expr
1716fb12b70Safresh1                my @args = map "\$$_", (undef,"a".."z")[1..$narg];
172b8851fccSafresh1                push @args, '$_'
173b8851fccSafresh1                    if $dollar && $do_exp && ($strong && !$lexsub or $core);
1746fb12b70Safresh1                my $args = join(', ', @args);
175b8851fccSafresh1                # XXX $lex_parens is temporary, until lex subs are
176b8851fccSafresh1                #     deparsed properly.
177b8851fccSafresh1                my $lex_parens =
178b8851fccSafresh1                    !$core && $do_exp && $lexsub && $keyword ne 'map';
179b8851fccSafresh1                $args = ((!$core && !$strong) || $parens || $lex_parens)
1806fb12b70Safresh1                    ? "($args)"
181eac174f2Safresh1                    :  @args
182eac174f2Safresh1                        ? " $args"
183eac174f2Safresh1                        : "";
184eac174f2Safresh1                push @code, (
185eac174f2Safresh1                    ($core && !($do_exp && $strong))
186b8851fccSafresh1                    ? "CORE::"
187b8851fccSafresh1                    : $lexsub && $do_exp
188b8851fccSafresh1                        ? "CORE::" x $core
189eac174f2Safresh1                        : $do_exp && !$core && !$strong
190eac174f2Safresh1                            ? "test::"
191eac174f2Safresh1                            : ""
192eac174f2Safresh1                ) . "$keyword$args;";
1936fb12b70Safresh1            }
194b8851fccSafresh1            # code[0]: to run; code[1]: expected
195b8851fccSafresh1            testit $keyword, @code, $lexsub;
196b8851fccSafresh1        }
1976fb12b70Safresh1    }
1986fb12b70Safresh1}
1996fb12b70Safresh1
2006fb12b70Safresh1
2016fb12b70Safresh1while (<DATA>) {
2026fb12b70Safresh1    chomp;
2036fb12b70Safresh1    s/#.*//;
2046fb12b70Safresh1    next unless /\S/;
2056fb12b70Safresh1
2066fb12b70Safresh1    my @fields = split;
2076fb12b70Safresh1    die "not 3 fields" unless @fields == 3;
2086fb12b70Safresh1    my ($keyword, $args, $flags) = @fields;
2096fb12b70Safresh1
2106fb12b70Safresh1    $args = '012' if $args eq '@';
2116fb12b70Safresh1
2126fb12b70Safresh1    my $parens  = $flags =~ s/p//;
2136fb12b70Safresh1    my $invert1 = $flags =~ s/1//;
2146fb12b70Safresh1    my $dollar  = $flags =~ s/\$//;
2156fb12b70Safresh1    my $strong  = $flags =~ s/\+//;
2166fb12b70Safresh1    die "unrecognised flag(s): '$flags'" unless $flags =~ /^-?$/;
2176fb12b70Safresh1
2186fb12b70Safresh1    if ($args eq 'B') { # binary infix
2196fb12b70Safresh1        die "$keyword: binary (B) op can't have '\$' flag\\n" if $dollar;
2206fb12b70Safresh1        die "$keyword: binary (B) op can't have '1' flag\\n" if $invert1;
2216fb12b70Safresh1        do_infix_keyword($keyword, $parens, $strong);
2226fb12b70Safresh1    }
2236fb12b70Safresh1    else {
2246fb12b70Safresh1        my @narg = split //, $args;
2256fb12b70Safresh1        for my $n (0..$#narg) {
2266fb12b70Safresh1            my $narg = $narg[$n];
2276fb12b70Safresh1            my $p = $parens;
2286fb12b70Safresh1            $p = !$p if ($n == 0 && $invert1);
2296fb12b70Safresh1            do_std_keyword($keyword, $narg, $p, (!$n && $dollar), $strong);
2306fb12b70Safresh1        }
2316fb12b70Safresh1    }
2326fb12b70Safresh1}
2336fb12b70Safresh1
2346fb12b70Safresh1
2356fb12b70Safresh1# Special cases
2366fb12b70Safresh1
2376fb12b70Safresh1testit dbmopen  => 'CORE::dbmopen(%foo, $bar, $baz);';
2386fb12b70Safresh1testit dbmclose => 'CORE::dbmclose %foo;';
2396fb12b70Safresh1
2406fb12b70Safresh1testit delete   => 'CORE::delete $h{\'foo\'};', 'delete $h{\'foo\'};';
241b8851fccSafresh1testit delete   => 'CORE::delete $h{\'foo\'};', undef, 1;
242b8851fccSafresh1testit delete   => 'CORE::delete @h{\'foo\'};', undef, 1;
243b8851fccSafresh1testit delete   => 'CORE::delete $h[0];', undef, 1;
244b8851fccSafresh1testit delete   => 'CORE::delete @h[0];', undef, 1;
2456fb12b70Safresh1testit delete   => 'delete $h{\'foo\'};',       'delete $h{\'foo\'};';
2466fb12b70Safresh1
2476fb12b70Safresh1# do is listed as strong, but only do { block } is strong;
2486fb12b70Safresh1# do $file is weak,  so test it separately here
2496fb12b70Safresh1testit do       => 'CORE::do $a;';
250b8851fccSafresh1testit do       => 'do $a;',                    'test::do($a);';
2516fb12b70Safresh1testit do       => 'CORE::do { 1 }',
2526fb12b70Safresh1		   "do {\n        1\n    };";
253b8851fccSafresh1testit do       => 'CORE::do { 1 }',
254b8851fccSafresh1		   "CORE::do {\n        1\n    };", 1;
2556fb12b70Safresh1testit do       => 'do { 1 };',
2566fb12b70Safresh1		   "do {\n        1\n    };";
2576fb12b70Safresh1
2586fb12b70Safresh1testit each     => 'CORE::each %bar;';
259b8851fccSafresh1testit each     => 'CORE::each @foo;';
2606fb12b70Safresh1
2616fb12b70Safresh1testit eof      => 'CORE::eof();';
2626fb12b70Safresh1
2636fb12b70Safresh1testit exists   => 'CORE::exists $h{\'foo\'};', 'exists $h{\'foo\'};';
264b8851fccSafresh1testit exists   => 'CORE::exists $h{\'foo\'};', undef, 1;
265b8851fccSafresh1testit exists   => 'CORE::exists &foo;', undef, 1;
266b8851fccSafresh1testit exists   => 'CORE::exists $h[0];', undef, 1;
2676fb12b70Safresh1testit exists   => 'exists $h{\'foo\'};',       'exists $h{\'foo\'};';
2686fb12b70Safresh1
2696fb12b70Safresh1testit exec     => 'CORE::exec($foo $bar);';
2706fb12b70Safresh1
2716fb12b70Safresh1testit glob     => 'glob;',                       'glob($_);';
2726fb12b70Safresh1testit glob     => 'CORE::glob;',                 'CORE::glob($_);';
2736fb12b70Safresh1testit glob     => 'glob $a;',                    'glob($a);';
2746fb12b70Safresh1testit glob     => 'CORE::glob $a;',              'CORE::glob($a);';
2756fb12b70Safresh1
2766fb12b70Safresh1testit grep     => 'CORE::grep { $a } $b, $c',    'grep({$a;} $b, $c);';
2776fb12b70Safresh1
2786fb12b70Safresh1testit keys     => 'CORE::keys %bar;';
279b8851fccSafresh1testit keys     => 'CORE::keys @bar;';
2806fb12b70Safresh1
2816fb12b70Safresh1testit map      => 'CORE::map { $a } $b, $c',    'map({$a;} $b, $c);';
2826fb12b70Safresh1
2836fb12b70Safresh1testit not      => '3 unless CORE::not $a && $b;';
2846fb12b70Safresh1
285b8851fccSafresh1testit pop      => 'CORE::pop @foo;';
286b8851fccSafresh1
287b8851fccSafresh1testit push     => 'CORE::push @foo;',           'CORE::push(@foo);';
288b8851fccSafresh1testit push     => 'CORE::push @foo, 1;',        'CORE::push(@foo, 1);';
289b8851fccSafresh1testit push     => 'CORE::push @foo, 1, 2;',     'CORE::push(@foo, 1, 2);';
290b8851fccSafresh1
2916fb12b70Safresh1testit readline => 'CORE::readline $a . $b;';
2926fb12b70Safresh1
2936fb12b70Safresh1testit readpipe => 'CORE::readpipe $a + $b;';
2946fb12b70Safresh1
2956fb12b70Safresh1testit reverse  => 'CORE::reverse sort(@foo);';
2966fb12b70Safresh1
297b8851fccSafresh1testit shift    => 'CORE::shift @foo;';
298b8851fccSafresh1
299b8851fccSafresh1testit splice   => q{CORE::splice @foo;},                 q{CORE::splice(@foo);};
300b8851fccSafresh1testit splice   => q{CORE::splice @foo, 0;},              q{CORE::splice(@foo, 0);};
301b8851fccSafresh1testit splice   => q{CORE::splice @foo, 0, 1;},           q{CORE::splice(@foo, 0, 1);};
302b8851fccSafresh1testit splice   => q{CORE::splice @foo, 0, 1, 'a';},      q{CORE::splice(@foo, 0, 1, 'a');};
303b8851fccSafresh1testit splice   => q{CORE::splice @foo, 0, 1, 'a', 'b';}, q{CORE::splice(@foo, 0, 1, 'a', 'b');};
304b8851fccSafresh1
3056fb12b70Safresh1# note that the test does '() = split...' which is why the
3066fb12b70Safresh1# limit is optimised to 1
3076fb12b70Safresh1testit split    => 'split;',                     q{split(' ', $_, 1);};
3086fb12b70Safresh1testit split    => 'CORE::split;',               q{split(' ', $_, 1);};
3096fb12b70Safresh1testit split    => 'split $a;',                  q{split(/$a/u, $_, 1);};
3106fb12b70Safresh1testit split    => 'CORE::split $a;',            q{split(/$a/u, $_, 1);};
3116fb12b70Safresh1testit split    => 'split $a, $b;',              q{split(/$a/u, $b, 1);};
3126fb12b70Safresh1testit split    => 'CORE::split $a, $b;',        q{split(/$a/u, $b, 1);};
3136fb12b70Safresh1testit split    => 'split $a, $b, $c;',          q{split(/$a/u, $b, $c);};
3146fb12b70Safresh1testit split    => 'CORE::split $a, $b, $c;',    q{split(/$a/u, $b, $c);};
3156fb12b70Safresh1
3166fb12b70Safresh1testit sub      => 'CORE::sub { $a, $b }',
3176fb12b70Safresh1			"sub {\n        \$a, \$b;\n    }\n    ;";
3186fb12b70Safresh1
3196fb12b70Safresh1testit system   => 'CORE::system($foo $bar);';
3206fb12b70Safresh1
321b8851fccSafresh1testit unshift  => 'CORE::unshift @foo;',        'CORE::unshift(@foo);';
322b8851fccSafresh1testit unshift  => 'CORE::unshift @foo, 1;',     'CORE::unshift(@foo, 1);';
323b8851fccSafresh1testit unshift  => 'CORE::unshift @foo, 1, 2;',  'CORE::unshift(@foo, 1, 2);';
324b8851fccSafresh1
3256fb12b70Safresh1testit values   => 'CORE::values %bar;';
326b8851fccSafresh1testit values   => 'CORE::values @foo;';
3276fb12b70Safresh1
3286fb12b70Safresh1
3296fb12b70Safresh1# XXX These are deparsed wrapped in parens.
3306fb12b70Safresh1# whether they should be, I don't know!
3316fb12b70Safresh1
3326fb12b70Safresh1testit dump     => '(CORE::dump);';
3336fb12b70Safresh1testit dump     => '(CORE::dump FOO);';
3346fb12b70Safresh1testit goto     => '(CORE::goto);',     '(goto);';
3356fb12b70Safresh1testit goto     => '(CORE::goto FOO);', '(goto FOO);';
3366fb12b70Safresh1testit last     => '(CORE::last);',     '(last);';
3376fb12b70Safresh1testit last     => '(CORE::last FOO);', '(last FOO);';
3386fb12b70Safresh1testit next     => '(CORE::next);',     '(next);';
3396fb12b70Safresh1testit next     => '(CORE::next FOO);', '(next FOO);';
3406fb12b70Safresh1testit redo     => '(CORE::redo);',     '(redo);';
3416fb12b70Safresh1testit redo     => '(CORE::redo FOO);', '(redo FOO);';
3426fb12b70Safresh1testit redo     => '(CORE::redo);',     '(redo);';
3436fb12b70Safresh1testit redo     => '(CORE::redo FOO);', '(redo FOO);';
3446fb12b70Safresh1testit return   => '(return);',         '(return);';
3456fb12b70Safresh1testit return   => '(CORE::return);',   '(return);';
3466fb12b70Safresh1
3476fb12b70Safresh1# these are the keywords I couldn't think how to test within this framework
3486fb12b70Safresh1
3496fb12b70Safresh1my %not_tested = map { $_ => 1} qw(
3506fb12b70Safresh1    __DATA__
3516fb12b70Safresh1    __END__
3526fb12b70Safresh1    __FILE__
3536fb12b70Safresh1    __LINE__
3546fb12b70Safresh1    __PACKAGE__
355*3d61058aSafresh1    __CLASS__
356e0680481Safresh1    ADJUST
3576fb12b70Safresh1    AUTOLOAD
3586fb12b70Safresh1    BEGIN
3596fb12b70Safresh1    CHECK
3606fb12b70Safresh1    CORE
3616fb12b70Safresh1    DESTROY
3626fb12b70Safresh1    END
3636fb12b70Safresh1    INIT
3646fb12b70Safresh1    UNITCHECK
365eac174f2Safresh1    catch
366e0680481Safresh1    class
3676fb12b70Safresh1    default
368eac174f2Safresh1    defer
3696fb12b70Safresh1    else
3706fb12b70Safresh1    elsif
371e0680481Safresh1    field
372eac174f2Safresh1    finally
3736fb12b70Safresh1    for
3746fb12b70Safresh1    foreach
3756fb12b70Safresh1    format
3766fb12b70Safresh1    given
3776fb12b70Safresh1    if
3786fb12b70Safresh1    m
379e0680481Safresh1    method
3806fb12b70Safresh1    no
3816fb12b70Safresh1    package
3826fb12b70Safresh1    q
3836fb12b70Safresh1    qq
3846fb12b70Safresh1    qr
3856fb12b70Safresh1    qw
3866fb12b70Safresh1    qx
3876fb12b70Safresh1    require
3886fb12b70Safresh1    s
3896fb12b70Safresh1    tr
390eac174f2Safresh1    try
3916fb12b70Safresh1    unless
3926fb12b70Safresh1    until
3936fb12b70Safresh1    use
3946fb12b70Safresh1    when
3956fb12b70Safresh1    while
3966fb12b70Safresh1    y
3976fb12b70Safresh1);
3986fb12b70Safresh1
3996fb12b70Safresh1# Sanity check against keyword data:
4006fb12b70Safresh1# make sure we haven't missed any keywords,
4016fb12b70Safresh1# and that we got the strength right.
4026fb12b70Safresh1
4036fb12b70Safresh1SKIP:
4046fb12b70Safresh1{
4056fb12b70Safresh1    skip "sanity checks when not PERL_CORE", 1 unless defined $ENV{PERL_CORE};
4066fb12b70Safresh1    my $count = 0;
4076fb12b70Safresh1    my $file = '../regen/keywords.pl';
4086fb12b70Safresh1    my $pass = 1;
4096fb12b70Safresh1    if (open my $fh, '<', $file) {
4106fb12b70Safresh1	while (<$fh>) {
4116fb12b70Safresh1	    last if /^__END__$/;
4126fb12b70Safresh1	}
4136fb12b70Safresh1	while (<$fh>) {
4146fb12b70Safresh1	    next unless /^([+\-])(\w+)$/;
4156fb12b70Safresh1	    my ($strength, $key) = ($1, $2);
4166fb12b70Safresh1	    $strength = ($strength eq '+') ? 1 : 0;
4176fb12b70Safresh1	    $count++;
4186fb12b70Safresh1	    if (!$SEEN{$key} && !$not_tested{$key}) {
4196fb12b70Safresh1		diag("keyword '$key' seen in $file, but not tested here!!");
4206fb12b70Safresh1		$pass = 0;
4216fb12b70Safresh1	    }
422eac174f2Safresh1	    if (exists $SEEN_STRENGTH{$key} and $SEEN_STRENGTH{$key} != $strength) {
4236fb12b70Safresh1		diag("keyword '$key' strengh as seen in $file doen't match here!!");
4246fb12b70Safresh1		$pass = 0;
4256fb12b70Safresh1	    }
4266fb12b70Safresh1	}
4276fb12b70Safresh1    }
4286fb12b70Safresh1    else {
4296fb12b70Safresh1	diag("Can't open $file: $!");
4306fb12b70Safresh1	$pass = 0;
4316fb12b70Safresh1    }
4326fb12b70Safresh1    # insanity check
4336fb12b70Safresh1    if ($count < 200) {
4346fb12b70Safresh1	diag("Saw $count keywords: less than 200!");
4356fb12b70Safresh1	$pass = 0;
4366fb12b70Safresh1    }
4376fb12b70Safresh1    ok($pass, "sanity checks");
4386fb12b70Safresh1}
4396fb12b70Safresh1
440eac174f2Safresh1done_testing();
4416fb12b70Safresh1
4426fb12b70Safresh1__DATA__
4436fb12b70Safresh1#
4446fb12b70Safresh1# format:
4456fb12b70Safresh1#   keyword args flags
4466fb12b70Safresh1#
4476fb12b70Safresh1# args consists of:
4486fb12b70Safresh1#  * one of more digits indictating which lengths of args the function accepts,
4496fb12b70Safresh1#  * or 'B' to indiate a binary infix operator,
4506fb12b70Safresh1#  * or '@' to indicate a list function.
4516fb12b70Safresh1#
4526fb12b70Safresh1# Flags consists of the following (or '-' if no flags):
4536fb12b70Safresh1#    + : strong keyword: can't be overrriden
4546fb12b70Safresh1#    p : the args are parenthesised on deparsing;
4556fb12b70Safresh1#    1 : parenthesising of 1st arg length is inverted
4566fb12b70Safresh1#        so '234 p1' means: foo a1,a2;  foo(a1,a2,a3); foo(a1,a2,a3,a4)
4576fb12b70Safresh1#    $ : on the first argument length, there is an implicit extra
4586fb12b70Safresh1#        '$_' arg which will appear on deparsing;
4596fb12b70Safresh1#        e.g. 12p$  will be tested as: foo(a1);     foo(a1,a2);
4606fb12b70Safresh1#                     and deparsed as: foo(a1, $_); foo(a1,a2);
4616fb12b70Safresh1#
4626fb12b70Safresh1# XXX Note that we really should get this data from regen/keywords.pl
4636fb12b70Safresh1# and regen/opcodes (augmented if necessary), rather than duplicating it
4646fb12b70Safresh1# here.
4656fb12b70Safresh1
4666fb12b70Safresh1__SUB__          0     -
4676fb12b70Safresh1abs              01    $
4686fb12b70Safresh1accept           2     p
4696fb12b70Safresh1alarm            01    $
4706fb12b70Safresh1and              B     -
4716fb12b70Safresh1atan2            2     p
4726fb12b70Safresh1bind             2     p
4736fb12b70Safresh1binmode          12    p
4746fb12b70Safresh1bless            1     p
4756fb12b70Safresh1break            0     -
4766fb12b70Safresh1caller           0     -
4776fb12b70Safresh1chdir            01    -
4786fb12b70Safresh1chmod            @     p1
4796fb12b70Safresh1chomp            @     $
4806fb12b70Safresh1chop             @     $
4816fb12b70Safresh1chown            @     p1
4826fb12b70Safresh1chr              01    $
4836fb12b70Safresh1chroot           01    $
4846fb12b70Safresh1close            01    -
4856fb12b70Safresh1closedir         1     -
4866fb12b70Safresh1cmp              B     -
4876fb12b70Safresh1connect          2     p
4886fb12b70Safresh1continue         0     -
4896fb12b70Safresh1cos              01    $
4906fb12b70Safresh1crypt            2     p
4916fb12b70Safresh1# dbmopen  handled specially
4926fb12b70Safresh1# dbmclose handled specially
4936fb12b70Safresh1defined          01    $+
4946fb12b70Safresh1# delete handled specially
4956fb12b70Safresh1die              @     p1
4966fb12b70Safresh1# do handled specially
4976fb12b70Safresh1# dump handled specially
498b8851fccSafresh1# each handled specially
4996fb12b70Safresh1endgrent         0     -
5006fb12b70Safresh1endhostent       0     -
5016fb12b70Safresh1endnetent        0     -
5026fb12b70Safresh1endprotoent      0     -
5036fb12b70Safresh1endpwent         0     -
5046fb12b70Safresh1endservent       0     -
5056fb12b70Safresh1eof              01    - # also tested specially
5066fb12b70Safresh1eq               B     -
5076fb12b70Safresh1eval             01    $+
5086fb12b70Safresh1evalbytes        01    $
5096fb12b70Safresh1exec             @     p1 # also tested specially
5106fb12b70Safresh1# exists handled specially
5116fb12b70Safresh1exit             01    -
5126fb12b70Safresh1exp              01    $
5136fb12b70Safresh1fc               01    $
5146fb12b70Safresh1fcntl            3     p
5156fb12b70Safresh1fileno           1     -
5166fb12b70Safresh1flock            2     p
5176fb12b70Safresh1fork             0     -
5186fb12b70Safresh1formline         2     p
5196fb12b70Safresh1ge               B     -
5206fb12b70Safresh1getc             01    -
5216fb12b70Safresh1getgrent         0     -
5226fb12b70Safresh1getgrgid         1     -
5236fb12b70Safresh1getgrnam         1     -
5246fb12b70Safresh1gethostbyaddr    2     p
5256fb12b70Safresh1gethostbyname    1     -
5266fb12b70Safresh1gethostent       0     -
5276fb12b70Safresh1getlogin         0     -
5286fb12b70Safresh1getnetbyaddr     2     p
5296fb12b70Safresh1getnetbyname     1     -
5306fb12b70Safresh1getnetent        0     -
5316fb12b70Safresh1getpeername      1     -
5326fb12b70Safresh1getpgrp          1     -
5336fb12b70Safresh1getppid          0     -
5346fb12b70Safresh1getpriority      2     p
5356fb12b70Safresh1getprotobyname   1     -
5366fb12b70Safresh1getprotobynumber 1     p
5376fb12b70Safresh1getprotoent      0     -
5386fb12b70Safresh1getpwent         0     -
5396fb12b70Safresh1getpwnam         1     -
5406fb12b70Safresh1getpwuid         1     -
5416fb12b70Safresh1getservbyname    2     p
5426fb12b70Safresh1getservbyport    2     p
5436fb12b70Safresh1getservent       0     -
5446fb12b70Safresh1getsockname      1     -
5456fb12b70Safresh1getsockopt       3     p
5466fb12b70Safresh1# given handled specially
5476fb12b70Safresh1grep             123   p+ # also tested specially
5486fb12b70Safresh1# glob handled specially
5496fb12b70Safresh1# goto handled specially
5506fb12b70Safresh1gmtime           01    -
5516fb12b70Safresh1gt               B     -
5526fb12b70Safresh1hex              01    $
5536fb12b70Safresh1index            23    p
5546fb12b70Safresh1int              01    $
5556fb12b70Safresh1ioctl            3     p
55656d68f1eSafresh1isa              B     -
557b8851fccSafresh1join             13    p
558b8851fccSafresh1# keys handled specially
5596fb12b70Safresh1kill             123   p
5606fb12b70Safresh1# last handled specially
5616fb12b70Safresh1lc               01    $
5626fb12b70Safresh1lcfirst          01    $
5636fb12b70Safresh1le               B     -
5646fb12b70Safresh1length           01    $
5656fb12b70Safresh1link             2     p
5666fb12b70Safresh1listen           2     p
5676fb12b70Safresh1local            1     p+
5686fb12b70Safresh1localtime        01    -
5696fb12b70Safresh1lock             1     -
5706fb12b70Safresh1log              01    $
5716fb12b70Safresh1lstat            01    $
5726fb12b70Safresh1lt               B     -
5736fb12b70Safresh1map              123   p+ # also tested specially
5746fb12b70Safresh1mkdir            @     p$
5756fb12b70Safresh1msgctl           3     p
5766fb12b70Safresh1msgget           2     p
5776fb12b70Safresh1msgrcv           5     p
5786fb12b70Safresh1msgsnd           3     p
5796fb12b70Safresh1my               123   p+ # skip with 0 args, as my() => ()
5806fb12b70Safresh1ne               B     -
5816fb12b70Safresh1# next handled specially
5826fb12b70Safresh1# not handled specially
5836fb12b70Safresh1oct              01    $
5846fb12b70Safresh1open             12345 p
5856fb12b70Safresh1opendir          2     p
5866fb12b70Safresh1or               B     -
5876fb12b70Safresh1ord              01    $
5886fb12b70Safresh1our              123   p+ # skip with 0 args, as our() => ()
5896fb12b70Safresh1pack             123   p
5906fb12b70Safresh1pipe             2     p
591b8851fccSafresh1pop              0     1 # also tested specially
5926fb12b70Safresh1pos              01    $+
5936fb12b70Safresh1print            @     p$+
5946fb12b70Safresh1printf           @     p$+
5956fb12b70Safresh1prototype        1     +
596b8851fccSafresh1# push handled specially
5976fb12b70Safresh1quotemeta        01    $
5986fb12b70Safresh1rand             01    -
5996fb12b70Safresh1read             34    p
6006fb12b70Safresh1readdir          1     -
6016fb12b70Safresh1# readline handled specially
6026fb12b70Safresh1readlink         01    $
6036fb12b70Safresh1# readpipe handled specially
6046fb12b70Safresh1recv             4     p
6056fb12b70Safresh1# redo handled specially
6066fb12b70Safresh1ref              01    $
6076fb12b70Safresh1rename           2     p
6086fb12b70Safresh1# XXX This code prints 'Undefined subroutine &main::require called':
6096fb12b70Safresh1#   use subs (); import subs 'require';
6106fb12b70Safresh1#   eval q[no strict 'vars'; sub { () = require; }]; print $@;
6116fb12b70Safresh1# so disable for now
6126fb12b70Safresh1#require          01    $+
6136fb12b70Safresh1reset            01    -
6146fb12b70Safresh1# return handled specially
6156fb12b70Safresh1reverse          @     p1 # also tested specially
6166fb12b70Safresh1rewinddir        1     -
6176fb12b70Safresh1rindex           23    p
6186fb12b70Safresh1rmdir            01    $
6196fb12b70Safresh1say              @     p$+
6206fb12b70Safresh1scalar           1     +
6216fb12b70Safresh1seek             3     p
6226fb12b70Safresh1seekdir          2     p
6236fb12b70Safresh1select           014   p1
6246fb12b70Safresh1semctl           4     p
6256fb12b70Safresh1semget           3     p
6266fb12b70Safresh1semop            2     p
6276fb12b70Safresh1send             34    p
6286fb12b70Safresh1setgrent         0     -
6296fb12b70Safresh1sethostent       1     -
6306fb12b70Safresh1setnetent        1     -
6316fb12b70Safresh1setpgrp          2     p
6326fb12b70Safresh1setpriority      3     p
6336fb12b70Safresh1setprotoent      1     -
6346fb12b70Safresh1setpwent         0     -
6356fb12b70Safresh1setservent       1     -
6366fb12b70Safresh1setsockopt       4     p
637b8851fccSafresh1shift            0     1 # also tested specially
6386fb12b70Safresh1shmctl           3     p
6396fb12b70Safresh1shmget           3     p
6406fb12b70Safresh1shmread          4     p
6416fb12b70Safresh1shmwrite         4     p
6426fb12b70Safresh1shutdown         2     p
6436fb12b70Safresh1sin              01    $
6446fb12b70Safresh1sleep            01    -
6456fb12b70Safresh1socket           4     p
6466fb12b70Safresh1socketpair       5     p
647eac174f2Safresh1sort             12    p+
6486fb12b70Safresh1# split handled specially
649b8851fccSafresh1# splice handled specially
6506fb12b70Safresh1sprintf          123   p
6516fb12b70Safresh1sqrt             01    $
6526fb12b70Safresh1srand            01    -
6536fb12b70Safresh1stat             01    $
6549f11ffb7Safresh1state            123   p1+ # skip with 0 args, as state() => ()
6556fb12b70Safresh1study            01    $+
6566fb12b70Safresh1# sub handled specially
6576fb12b70Safresh1substr           234   p
6586fb12b70Safresh1symlink          2     p
6596fb12b70Safresh1syscall          2     p
6606fb12b70Safresh1sysopen          34    p
6616fb12b70Safresh1sysread          34    p
6626fb12b70Safresh1sysseek          3     p
6636fb12b70Safresh1system           @     p1 # also tested specially
6646fb12b70Safresh1syswrite         234   p
6656fb12b70Safresh1tell             01    -
6666fb12b70Safresh1telldir          1     -
6676fb12b70Safresh1tie              234   p
6686fb12b70Safresh1tied             1     -
6696fb12b70Safresh1time             0     -
6706fb12b70Safresh1times            0     -
6716fb12b70Safresh1truncate         2     p
6726fb12b70Safresh1uc               01    $
6736fb12b70Safresh1ucfirst          01    $
6746fb12b70Safresh1umask            01    -
6756fb12b70Safresh1undef            01    +
6766fb12b70Safresh1unlink           @     p$
6776fb12b70Safresh1unpack           12    p$
678b8851fccSafresh1# unshift handled specially
6796fb12b70Safresh1untie            1     -
6806fb12b70Safresh1utime            @     p1
681b8851fccSafresh1# values handled specially
6826fb12b70Safresh1vec              3     p
6836fb12b70Safresh1wait             0     -
6846fb12b70Safresh1waitpid          2     p
6856fb12b70Safresh1wantarray        0     -
6866fb12b70Safresh1warn             @     p1
6876fb12b70Safresh1write            01    -
6886fb12b70Safresh1x                B     -
6896fb12b70Safresh1xor              B     p
690