xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/t/op/goto.t (revision 0:68f95e015346)
1*0Sstevel@tonic-gate#!./perl
2*0Sstevel@tonic-gate
3*0Sstevel@tonic-gate# "This IS structured code.  It's just randomly structured."
4*0Sstevel@tonic-gate
5*0Sstevel@tonic-gateBEGIN {
6*0Sstevel@tonic-gate    chdir 't' if -d 't';
7*0Sstevel@tonic-gate    @INC = qw(. ../lib);
8*0Sstevel@tonic-gate}
9*0Sstevel@tonic-gate
10*0Sstevel@tonic-gateprint "1..32\n";
11*0Sstevel@tonic-gate
12*0Sstevel@tonic-gaterequire "test.pl";
13*0Sstevel@tonic-gate
14*0Sstevel@tonic-gatewhile ($?) {
15*0Sstevel@tonic-gate    $foo = 1;
16*0Sstevel@tonic-gate  label1:
17*0Sstevel@tonic-gate    $foo = 2;
18*0Sstevel@tonic-gate    goto label2;
19*0Sstevel@tonic-gate} continue {
20*0Sstevel@tonic-gate    $foo = 0;
21*0Sstevel@tonic-gate    goto label4;
22*0Sstevel@tonic-gate  label3:
23*0Sstevel@tonic-gate    $foo = 4;
24*0Sstevel@tonic-gate    goto label4;
25*0Sstevel@tonic-gate}
26*0Sstevel@tonic-gategoto label1;
27*0Sstevel@tonic-gate
28*0Sstevel@tonic-gate$foo = 3;
29*0Sstevel@tonic-gate
30*0Sstevel@tonic-gatelabel2:
31*0Sstevel@tonic-gateprint "#1\t:$foo: == 2\n";
32*0Sstevel@tonic-gateif ($foo == 2) {print "ok 1\n";} else {print "not ok 1\n";}
33*0Sstevel@tonic-gategoto label3;
34*0Sstevel@tonic-gate
35*0Sstevel@tonic-gatelabel4:
36*0Sstevel@tonic-gateprint "#2\t:$foo: == 4\n";
37*0Sstevel@tonic-gateif ($foo == 4) {print "ok 2\n";} else {print "not ok 2\n";}
38*0Sstevel@tonic-gate
39*0Sstevel@tonic-gate$PERL = ($^O eq 'MSWin32') ? '.\perl' : ($^O eq 'MacOS') ? $^X : ($^O eq 'NetWare') ? 'perl' : './perl';
40*0Sstevel@tonic-gate$CMD = qq[$PERL -e "goto foo;" 2>&1 ];
41*0Sstevel@tonic-gate$x = `$CMD`;
42*0Sstevel@tonic-gate
43*0Sstevel@tonic-gateif ($x =~ /label/) {print "ok 3\n";} else {print "not ok 3\n";}
44*0Sstevel@tonic-gate
45*0Sstevel@tonic-gatesub foo {
46*0Sstevel@tonic-gate    goto bar;
47*0Sstevel@tonic-gate    print "not ok 4\n";
48*0Sstevel@tonic-gate    return;
49*0Sstevel@tonic-gatebar:
50*0Sstevel@tonic-gate    print "ok 4\n";
51*0Sstevel@tonic-gate}
52*0Sstevel@tonic-gate
53*0Sstevel@tonic-gate&foo;
54*0Sstevel@tonic-gate
55*0Sstevel@tonic-gatesub bar {
56*0Sstevel@tonic-gate    $x = 'bypass';
57*0Sstevel@tonic-gate    eval "goto $x";
58*0Sstevel@tonic-gate}
59*0Sstevel@tonic-gate
60*0Sstevel@tonic-gate&bar;
61*0Sstevel@tonic-gateexit;
62*0Sstevel@tonic-gate
63*0Sstevel@tonic-gateFINALE:
64*0Sstevel@tonic-gateprint "ok 13\n";
65*0Sstevel@tonic-gate
66*0Sstevel@tonic-gate# does goto LABEL handle block contexts correctly?
67*0Sstevel@tonic-gate
68*0Sstevel@tonic-gatemy $cond = 1;
69*0Sstevel@tonic-gatefor (1) {
70*0Sstevel@tonic-gate    if ($cond == 1) {
71*0Sstevel@tonic-gate	$cond = 0;
72*0Sstevel@tonic-gate	goto OTHER;
73*0Sstevel@tonic-gate    }
74*0Sstevel@tonic-gate    elsif ($cond == 0) {
75*0Sstevel@tonic-gate      OTHER:
76*0Sstevel@tonic-gate	$cond = 2;
77*0Sstevel@tonic-gate	print "ok 14\n";
78*0Sstevel@tonic-gate	goto THIRD;
79*0Sstevel@tonic-gate    }
80*0Sstevel@tonic-gate    else {
81*0Sstevel@tonic-gate      THIRD:
82*0Sstevel@tonic-gate	print "ok 15\n";
83*0Sstevel@tonic-gate    }
84*0Sstevel@tonic-gate}
85*0Sstevel@tonic-gateprint "ok 16\n";
86*0Sstevel@tonic-gate
87*0Sstevel@tonic-gate# Does goto work correctly within a for(;;) loop?
88*0Sstevel@tonic-gate#  (BUG ID 20010309.004)
89*0Sstevel@tonic-gate
90*0Sstevel@tonic-gatefor(my $i=0;!$i++;) {
91*0Sstevel@tonic-gate  my $x=1;
92*0Sstevel@tonic-gate  goto label;
93*0Sstevel@tonic-gate  label: print (defined $x?"ok ": "not ok ", "17\n")
94*0Sstevel@tonic-gate}
95*0Sstevel@tonic-gate
96*0Sstevel@tonic-gate# Does goto work correctly going *to* a for(;;) loop?
97*0Sstevel@tonic-gate#  (make sure it doesn't skip the initializer)
98*0Sstevel@tonic-gate
99*0Sstevel@tonic-gatemy ($z, $y) = (0);
100*0Sstevel@tonic-gateFORL1: for($y="ok 18\n"; $z;) {print $y; goto TEST19}
101*0Sstevel@tonic-gate($y,$z) = ("not ok 18\n", 1);
102*0Sstevel@tonic-gategoto FORL1;
103*0Sstevel@tonic-gate
104*0Sstevel@tonic-gate# Even from within the loop?
105*0Sstevel@tonic-gate
106*0Sstevel@tonic-gateTEST19: $z = 0;
107*0Sstevel@tonic-gateFORL2: for($y="ok 19\n"; 1;) {
108*0Sstevel@tonic-gate  if ($z) {
109*0Sstevel@tonic-gate    print $y;
110*0Sstevel@tonic-gate    last;
111*0Sstevel@tonic-gate  }
112*0Sstevel@tonic-gate  ($y, $z) = ("not ok 19\n", 1);
113*0Sstevel@tonic-gate  goto FORL2;
114*0Sstevel@tonic-gate}
115*0Sstevel@tonic-gate
116*0Sstevel@tonic-gate# Does goto work correctly within a try block?
117*0Sstevel@tonic-gate#  (BUG ID 20000313.004)
118*0Sstevel@tonic-gate
119*0Sstevel@tonic-gatemy $ok = 0;
120*0Sstevel@tonic-gateeval {
121*0Sstevel@tonic-gate  my $variable = 1;
122*0Sstevel@tonic-gate  goto LABEL20;
123*0Sstevel@tonic-gate  LABEL20: $ok = 1 if $variable;
124*0Sstevel@tonic-gate};
125*0Sstevel@tonic-gateprint ($ok&&!$@ ? "ok 20\n" : "not ok 20\n");
126*0Sstevel@tonic-gate
127*0Sstevel@tonic-gate# And within an eval-string?
128*0Sstevel@tonic-gate
129*0Sstevel@tonic-gate
130*0Sstevel@tonic-gate$ok = 0;
131*0Sstevel@tonic-gateeval q{
132*0Sstevel@tonic-gate  my $variable = 1;
133*0Sstevel@tonic-gate  goto LABEL21;
134*0Sstevel@tonic-gate  LABEL21: $ok = 1 if $variable;
135*0Sstevel@tonic-gate};
136*0Sstevel@tonic-gateprint ($ok&&!$@ ? "ok 21\n" : "not ok 21\n");
137*0Sstevel@tonic-gate
138*0Sstevel@tonic-gate
139*0Sstevel@tonic-gate# Test that goto works in nested eval-string
140*0Sstevel@tonic-gate$ok = 0;
141*0Sstevel@tonic-gate{eval q{
142*0Sstevel@tonic-gate  eval q{
143*0Sstevel@tonic-gate    goto LABEL22;
144*0Sstevel@tonic-gate  };
145*0Sstevel@tonic-gate  $ok = 0;
146*0Sstevel@tonic-gate  last;
147*0Sstevel@tonic-gate
148*0Sstevel@tonic-gate  LABEL22: $ok = 1;
149*0Sstevel@tonic-gate};
150*0Sstevel@tonic-gate$ok = 0 if $@;
151*0Sstevel@tonic-gate}
152*0Sstevel@tonic-gateprint ($ok ? "ok 22\n" : "not ok 22\n");
153*0Sstevel@tonic-gate
154*0Sstevel@tonic-gate{
155*0Sstevel@tonic-gate    my $false = 0;
156*0Sstevel@tonic-gate
157*0Sstevel@tonic-gate    $ok = 0;
158*0Sstevel@tonic-gate    { goto A; A: $ok = 1 } continue { }
159*0Sstevel@tonic-gate    print "not " unless $ok;
160*0Sstevel@tonic-gate    print "ok 23 - #20357 goto inside /{ } continue { }/ loop\n";
161*0Sstevel@tonic-gate
162*0Sstevel@tonic-gate    $ok = 0;
163*0Sstevel@tonic-gate    { do { goto A; A: $ok = 1 } while $false }
164*0Sstevel@tonic-gate    print "not " unless $ok;
165*0Sstevel@tonic-gate    print "ok 24 - #20154 goto inside /do { } while ()/ loop\n";
166*0Sstevel@tonic-gate
167*0Sstevel@tonic-gate    $ok = 0;
168*0Sstevel@tonic-gate    foreach(1) { goto A; A: $ok = 1 } continue { };
169*0Sstevel@tonic-gate    print "not " unless $ok;
170*0Sstevel@tonic-gate    print "ok 25 - goto inside /foreach () { } continue { }/ loop\n";
171*0Sstevel@tonic-gate
172*0Sstevel@tonic-gate    $ok = 0;
173*0Sstevel@tonic-gate    sub a {
174*0Sstevel@tonic-gate	A: { if ($false) { redo A; B: $ok = 1; redo A; } }
175*0Sstevel@tonic-gate	goto B unless $r++
176*0Sstevel@tonic-gate    }
177*0Sstevel@tonic-gate    a();
178*0Sstevel@tonic-gate    print "not " unless $ok;
179*0Sstevel@tonic-gate    print "ok 26 - #19061 loop label wiped away by goto\n";
180*0Sstevel@tonic-gate
181*0Sstevel@tonic-gate    $ok = 0;
182*0Sstevel@tonic-gate    for ($p=1;$p && goto A;$p=0) { A: $ok = 1 }
183*0Sstevel@tonic-gate    print "not " unless $ok;
184*0Sstevel@tonic-gate    print "ok 27 - weird case of goto and for(;;) loop\n";
185*0Sstevel@tonic-gate}
186*0Sstevel@tonic-gate
187*0Sstevel@tonic-gate# bug #9990 - don't prematurely free the CV we're &going to.
188*0Sstevel@tonic-gate
189*0Sstevel@tonic-gatesub f1 {
190*0Sstevel@tonic-gate    my $x;
191*0Sstevel@tonic-gate    goto sub { $x; print "ok 28 - don't prematurely free CV\n" }
192*0Sstevel@tonic-gate}
193*0Sstevel@tonic-gatef1();
194*0Sstevel@tonic-gate
195*0Sstevel@tonic-gate# bug #22181 - this used to coredump or make $x undefined, due to
196*0Sstevel@tonic-gate# erroneous popping of the inner BLOCK context
197*0Sstevel@tonic-gate
198*0Sstevel@tonic-gatefor ($i=0; $i<2; $i++) {
199*0Sstevel@tonic-gate    my $x = 1;
200*0Sstevel@tonic-gate    goto LABEL29;
201*0Sstevel@tonic-gate    LABEL29:
202*0Sstevel@tonic-gate    print "not " if !defined $x || $x != 1;
203*0Sstevel@tonic-gate}
204*0Sstevel@tonic-gateprint "ok 29 - goto in for(;;) with continuation\n";
205*0Sstevel@tonic-gate
206*0Sstevel@tonic-gate# bug #22299 - goto in require doesn't find label
207*0Sstevel@tonic-gate
208*0Sstevel@tonic-gateopen my $f, ">goto01.pm" or die;
209*0Sstevel@tonic-gateprint $f <<'EOT';
210*0Sstevel@tonic-gatepackage goto01;
211*0Sstevel@tonic-gategoto YYY;
212*0Sstevel@tonic-gatedie;
213*0Sstevel@tonic-gateYYY: print "OK\n";
214*0Sstevel@tonic-gate1;
215*0Sstevel@tonic-gateEOT
216*0Sstevel@tonic-gateclose $f;
217*0Sstevel@tonic-gate
218*0Sstevel@tonic-gatecurr_test(30);
219*0Sstevel@tonic-gatemy $r = runperl(prog => 'use goto01; print qq[DONE\n]');
220*0Sstevel@tonic-gateis($r, "OK\nDONE\n", "goto within use-d file");
221*0Sstevel@tonic-gateunlink "goto01.pm";
222*0Sstevel@tonic-gate
223*0Sstevel@tonic-gate# test for [perl #24108]
224*0Sstevel@tonic-gatesub i_return_a_label {
225*0Sstevel@tonic-gate    print "ok 31 - i_return_a_label called\n";
226*0Sstevel@tonic-gate    return "returned_label";
227*0Sstevel@tonic-gate}
228*0Sstevel@tonic-gateeval { goto +i_return_a_label; };
229*0Sstevel@tonic-gateprint "not ";
230*0Sstevel@tonic-gatereturned_label : print "ok 32 - done to returned_label\n";
231*0Sstevel@tonic-gate
232*0Sstevel@tonic-gateexit;
233*0Sstevel@tonic-gate
234*0Sstevel@tonic-gatebypass:
235*0Sstevel@tonic-gateprint "ok 5\n";
236*0Sstevel@tonic-gate
237*0Sstevel@tonic-gate# Test autoloading mechanism.
238*0Sstevel@tonic-gate
239*0Sstevel@tonic-gatesub two {
240*0Sstevel@tonic-gate    ($pack, $file, $line) = caller;	# Should indicate original call stats.
241*0Sstevel@tonic-gate    print "@_ $pack $file $line" eq "1 2 3 main $FILE $LINE"
242*0Sstevel@tonic-gate	? "ok 7\n"
243*0Sstevel@tonic-gate	: "not ok 7\n";
244*0Sstevel@tonic-gate}
245*0Sstevel@tonic-gate
246*0Sstevel@tonic-gatesub one {
247*0Sstevel@tonic-gate    eval <<'END';
248*0Sstevel@tonic-gate    sub one { print "ok 6\n"; goto &two; print "not ok 6\n"; }
249*0Sstevel@tonic-gateEND
250*0Sstevel@tonic-gate    goto &one;
251*0Sstevel@tonic-gate}
252*0Sstevel@tonic-gate
253*0Sstevel@tonic-gate$FILE = __FILE__;
254*0Sstevel@tonic-gate$LINE = __LINE__ + 1;
255*0Sstevel@tonic-gate&one(1,2,3);
256*0Sstevel@tonic-gate
257*0Sstevel@tonic-gate$wherever = NOWHERE;
258*0Sstevel@tonic-gateeval { goto $wherever };
259*0Sstevel@tonic-gateprint $@ =~ /Can't find label NOWHERE/ ? "ok 8\n" : "not ok 8\n";
260*0Sstevel@tonic-gate
261*0Sstevel@tonic-gate# see if a modified @_ propagates
262*0Sstevel@tonic-gate{
263*0Sstevel@tonic-gate  package Foo;
264*0Sstevel@tonic-gate  sub DESTROY	{ my $s = shift; print "ok $s->[0]\n"; }
265*0Sstevel@tonic-gate  sub show	{ print "# @_\nnot ok $_[0][0]\n" if @_ != 5; }
266*0Sstevel@tonic-gate  sub start	{ push @_, 1, "foo", {}; goto &show; }
267*0Sstevel@tonic-gate  for (9..11)	{ start(bless([$_]), 'bar'); }
268*0Sstevel@tonic-gate}
269*0Sstevel@tonic-gate
270*0Sstevel@tonic-gatesub auto {
271*0Sstevel@tonic-gate    goto &loadit;
272*0Sstevel@tonic-gate}
273*0Sstevel@tonic-gate
274*0Sstevel@tonic-gatesub AUTOLOAD { print @_ }
275*0Sstevel@tonic-gate
276*0Sstevel@tonic-gateauto("ok 12\n");
277*0Sstevel@tonic-gate
278*0Sstevel@tonic-gate$wherever = FINALE;
279*0Sstevel@tonic-gategoto $wherever;
280