xref: /openbsd/gnu/usr.bin/perl/t/op/write.t (revision 4cfece93)
1#!./perl
2
3BEGIN {
4    chdir 't' if -d 't';
5    require './test.pl';
6    set_up_inc('../lib');
7}
8
9$| = 0; # test.pl now sets it on, which causes problems here.
10
11use strict;	# Amazed that this hackery can be made strict ...
12use Tie::Scalar;
13
14# read in a file
15sub cat {
16    my $file = shift;
17    local $/;
18    open my $fh, $file or die "can't open '$file': $!";
19    my $data = <$fh>;
20    close $fh;
21    $data;
22}
23
24# read in a utf-8 file
25#
26sub cat_utf8 {
27    my $file = shift;
28    local $/;
29    open my $fh, '<', $file or die "can't open '$file': $!";
30    binmode $fh, ':utf8';
31    my $data = <$fh> // die "Can't read from '$file': $!";
32    close $fh or die "error closing '$file': $!";
33    $data;
34}
35
36# write a format to a utf8 file, then read it back in and compare
37
38sub is_format_utf8 {
39    my ($glob, $want, $desc) = @_;
40    local $::Level = $::Level + 1;
41    my $file = 'Op_write.tmp';
42    open $glob, '>:utf8', $file or die "Can't create '$file': $!";
43    write $glob;
44    close $glob or die "Could not close '$file': $!";
45    is(cat_utf8($file), $want, $desc);
46}
47
48sub like_format_utf8 {
49    my ($glob, $want, $desc) = @_;
50    local $::Level = $::Level + 1;
51    my $file = 'Op_write.tmp';
52    open $glob, '>:utf8', $file or die "Can't create '$file': $!";
53    write $glob;
54    close $glob or die "Could not close '$file': $!";
55    like(cat_utf8($file), $want, $desc);
56}
57
58
59
60#-- testing numeric fields in all variants (WL)
61
62sub swrite {
63    my $format = shift;
64    local $^A = ""; # don't litter, use a local bin
65    formline( $format, @_ );
66    return $^A;
67}
68
69my @NumTests = (
70    # [ format, value1, expected1, value2, expected2, .... ]
71    [ '@###',           0,   '   0',         1, '   1',     9999.6, '####',
72		9999.4999,   '9999',    -999.6, '####',     1e+100, '####' ],
73
74    [ '@0##',           0,   '0000',         1, '0001',     9999.6, '####',
75		-999.4999,   '-999',    -999.6, '####',     1e+100, '####' ],
76
77    [ '^###',           0,   '   0',     undef, '    ' ],
78
79    [ '^0##',           0,   '0000',     undef, '    ' ],
80
81    [ '@###.',          0,  '   0.',         1, '   1.',    9999.6, '#####',
82                9999.4999,  '9999.',    -999.6, '#####' ],
83
84    [ '@##.##',         0, '  0.00',         1, '  1.00',  999.996, '######',
85                999.99499, '999.99',      -100, '######' ],
86
87    [ '@0#.##',         0, '000.00',         1, '001.00',       10, '010.00',
88                  -0.0001, qr/^[\-0]00\.00$/ ],
89
90);
91
92
93my $num_tests = 0;
94for my $tref ( @NumTests ){
95    $num_tests += (@$tref - 1)/2;
96}
97#---------------------------------------------------------
98
99# number of tests in section 1
100my $bas_tests = 21;
101
102# number of tests in section 3
103my $bug_tests = 66 + 3 * 3 * 5 * 2 * 3 + 2 + 66 + 6 + 2 + 3 + 96 + 11 + 14;
104
105# number of tests in section 4
106my $hmb_tests = 37;
107
108my $tests = $bas_tests + $num_tests + $bug_tests + $hmb_tests;
109
110plan $tests;
111
112############
113## Section 1
114############
115
116our ($fox, $multiline, $foo, $good);
117
118format OUT =
119the quick brown @<<
120$fox
121jumped
122@*
123$multiline
124^<<<<<<<<<
125$foo
126^<<<<<<<<<
127$foo
128^<<<<<<...
129$foo
130now @<<the@>>>> for all@|||||men to come @<<<<
131{
132    'i' . 's', "time\n", $good, 'to'
133}
134.
135
136open(OUT, '>Op_write.tmp') || die "Can't create Op_write.tmp";
137END { unlink_all 'Op_write.tmp' }
138
139$fox = 'foxiness';
140$good = 'good';
141$multiline = "forescore\nand\nseven years\n";
142$foo = 'when in the course of human events it becomes necessary';
143write(OUT);
144close OUT or die "Could not close: $!";
145
146my $right =
147"the quick brown fox
148jumped
149forescore
150and
151seven years
152when in
153the course
154of huma...
155now is the time for all good men to come to\n";
156
157is cat('Op_write.tmp'), $right and unlink_all 'Op_write.tmp';
158
159$fox = 'wolfishness';
160my $fox = 'foxiness';		# Test a lexical variable.
161
162format OUT2 =
163the quick brown @<<
164$fox
165jumped
166@*
167$multiline
168^<<<<<<<<< ~~
169$foo
170now @<<the@>>>> for all@|||||men to come @<<<<
171'i' . 's', "time\n", $good, 'to'
172.
173
174open OUT2, '>Op_write.tmp' or die "Can't create Op_write.tmp";
175
176$good = 'good';
177$multiline = "forescore\nand\nseven years\n";
178$foo = 'when in the course of human events it becomes necessary';
179write(OUT2);
180close OUT2 or die "Could not close: $!";
181
182$right =
183"the quick brown fox
184jumped
185forescore
186and
187seven years
188when in
189the course
190of human
191events it
192becomes
193necessary
194now is the time for all good men to come to\n";
195
196is cat('Op_write.tmp'), $right and unlink_all 'Op_write.tmp';
197
198eval <<'EOFORMAT';
199format OUT2 =
200the brown quick @<<
201$fox
202jumped
203@*
204$multiline
205and
206^<<<<<<<<< ~~
207$foo
208now @<<the@>>>> for all@|||||men to come @<<<<
209'i' . 's', "time\n", $good, 'to'
210.
211EOFORMAT
212
213open(OUT2, '>Op_write.tmp') || die "Can't create Op_write.tmp";
214
215$fox = 'foxiness';
216$good = 'good';
217$multiline = "forescore\nand\nseven years\n";
218$foo = 'when in the course of human events it becomes necessary';
219write(OUT2);
220close OUT2 or die "Could not close: $!";
221
222$right =
223"the brown quick fox
224jumped
225forescore
226and
227seven years
228and
229when in
230the course
231of human
232events it
233becomes
234necessary
235now is the time for all good men to come to\n";
236
237is cat('Op_write.tmp'), $right and unlink_all 'Op_write.tmp';
238
239# formline tests
240
241$right = <<EOT;
242@ a
243@> ab
244@>> abc
245@>>>  abc
246@>>>>   abc
247@>>>>>    abc
248@>>>>>>     abc
249@>>>>>>>      abc
250@>>>>>>>>       abc
251@>>>>>>>>>        abc
252@>>>>>>>>>>         abc
253EOT
254
255my $was1 = my $was2 = '';
256our $format2;
257for (0..10) {
258  # lexical picture
259  $^A = '';
260  my $format1 = '@' . '>' x $_;
261  formline $format1, 'abc';
262  $was1 .= "$format1 $^A\n";
263  # global
264  $^A = '';
265  local $format2 = '@' . '>' x $_;
266  formline $format2, 'abc';
267  $was2 .= "$format2 $^A\n";
268}
269is $was1, $right;
270is $was2, $right;
271
272$^A = '';
273
274# more test
275
276format OUT3 =
277^<<<<<<...
278$foo
279.
280
281open(OUT3, '>Op_write.tmp') || die "Can't create Op_write.tmp";
282
283$foo = 'fit          ';
284write(OUT3);
285close OUT3 or die "Could not close: $!";
286
287$right =
288"fit\n";
289
290is cat('Op_write.tmp'), $right and unlink_all 'Op_write.tmp';
291
292
293# test lexicals and globals
294{
295    my $test = curr_test();
296    my $this = "ok";
297    our $that = $test;
298    format LEX =
299@<<@|
300$this,$that
301.
302    open(LEX, ">&STDOUT") or die;
303    write LEX;
304    $that = ++$test;
305    write LEX;
306    close LEX or die "Could not close: $!";
307    curr_test($test + 1);
308}
309# LEX_INTERPNORMAL test
310my %e = ( a => 1 );
311format OUT4 =
312@<<<<<<
313"$e{a}"
314.
315open   OUT4, ">Op_write.tmp" or die "Can't create Op_write.tmp";
316write (OUT4);
317close  OUT4 or die "Could not close: $!";
318is cat('Op_write.tmp'), "1\n" and unlink_all "Op_write.tmp";
319
320# More LEX_INTERPNORMAL
321format OUT4a=
322@<<<<<<<<<<<<<<<
323"${; use
324     strict; \'Nasdaq dropping like flies'}"
325.
326open   OUT4a, ">Op_write.tmp" or die "Can't create Op_write.tmp";
327write (OUT4a);
328close  OUT4a or die "Could not close: $!";
329is cat('Op_write.tmp'), "Nasdaq dropping\n", 'skipspace inside "${...}"'
330    and unlink_all "Op_write.tmp";
331
332our $test1;
333eval <<'EOFORMAT';
334format OUT10 =
335@####.## @0###.##
336$test1, $test1
337.
338EOFORMAT
339
340open(OUT10, '>Op_write.tmp') || die "Can't create Op_write.tmp";
341
342$test1 = 12.95;
343write(OUT10);
344close OUT10 or die "Could not close: $!";
345
346$right = "   12.95 00012.95\n";
347is cat('Op_write.tmp'), $right and unlink_all 'Op_write.tmp';
348
349eval <<'EOFORMAT';
350format OUT11 =
351@0###.##
352$test1
353@ 0#
354$test1
355@0 #
356$test1
357.
358EOFORMAT
359
360open(OUT11, '>Op_write.tmp') || die "Can't create Op_write.tmp";
361
362$test1 = 12.95;
363write(OUT11);
364close OUT11 or die "Could not close: $!";
365
366$right =
367"00012.95
3681 0#
36910 #\n";
370is cat('Op_write.tmp'), $right and unlink_all 'Op_write.tmp';
371
372{
373    my $test = curr_test();
374    my $el;
375    format OUT12 =
376ok ^<<<<<<<<<<<<<<~~ # sv_chop() naze
377$el
378.
379    my %hash = ($test => 3);
380    open(OUT12, '>Op_write.tmp') || die "Can't create Op_write.tmp";
381
382    for $el (keys %hash) {
383	write(OUT12);
384    }
385    close OUT12 or die "Could not close: $!";
386    print cat('Op_write.tmp');
387    curr_test($test + 1);
388}
389
390{
391    my $test = curr_test();
392    # Bug report and testcase by Alexey Tourbin
393    my $v;
394    tie $v, 'Tie::StdScalar';
395    $v = $test;
396    format OUT13 =
397ok ^<<<<<<<<< ~~
398$v
399.
400    open(OUT13, '>Op_write.tmp') || die "Can't create Op_write.tmp";
401    write(OUT13);
402    close OUT13 or die "Could not close: $!";
403    print cat('Op_write.tmp');
404    curr_test($test + 1);
405}
406
407{   # test 14
408    # Bug #24774 format without trailing \n failed assertion, but this
409    # must fail since we have a trailing ; in the eval'ed string (WL)
410    my @v = ('k');
411    eval "format OUT14 = \n@\n\@v";
412    like $@, qr/Format not terminated/;
413}
414
415{   # test 15
416    # text lost in ^<<< field with \r in value (WL)
417    my $txt = "line 1\rline 2";
418    format OUT15 =
419^<<<<<<<<<<<<<<<<<<
420$txt
421^<<<<<<<<<<<<<<<<<<
422$txt
423.
424    open(OUT15, '>Op_write.tmp') || die "Can't create Op_write.tmp";
425    write(OUT15);
426    close OUT15 or die "Could not close: $!";
427    my $res = cat('Op_write.tmp');
428    is $res, "line 1\nline 2\n";
429}
430
431{   # test 16: multiple use of a variable in same line with ^<
432    my $txt = "this_is_block_1 this_is_block_2 this_is_block_3 this_is_block_4";
433    format OUT16 =
434^<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<
435$txt,             $txt
436^<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<
437$txt,             $txt
438.
439    open(OUT16, '>Op_write.tmp') || die "Can't create Op_write.tmp";
440    write(OUT16);
441    close OUT16 or die "Could not close: $!";
442    my $res = cat('Op_write.tmp');
443    is $res, <<EOD;
444this_is_block_1   this_is_block_2
445this_is_block_3   this_is_block_4
446EOD
447}
448
449{   # test 17: @* "should be on a line of its own", but it should work
450    # cleanly with literals before and after. (WL)
451
452    my $txt = "This is line 1.\nThis is the second line.\nThird and last.\n";
453    format OUT17 =
454Here we go: @* That's all, folks!
455            $txt
456.
457    open(OUT17, '>Op_write.tmp') || die "Can't create Op_write.tmp";
458    write(OUT17);
459    close OUT17 or die "Could not close: $!";
460    my $res = cat('Op_write.tmp');
461    chomp( $txt );
462    my $exp = <<EOD;
463Here we go: $txt That's all, folks!
464EOD
465    is $res, $exp;
466}
467
468{   # test 18: @# and ~~ would cause runaway format, but we now
469    # catch this while compiling (WL)
470
471    format OUT18 =
472@######## ~~
47310
474.
475    open(OUT18, '>Op_write.tmp') || die "Can't create Op_write.tmp";
476    eval { write(OUT18); };
477    like $@,  qr/Repeated format line will never terminate/;
478    close OUT18 or die "Could not close: $!";
479}
480
481{   # test 19: \0 in an evel'ed format, doesn't cause empty lines (WL)
482    my $v = 'gaga';
483    eval "format OUT19 = \n" .
484         '@<<<' . "\0\n" .
485         '$v' .   "\n" .
486         '@<<<' . "\0\n" .
487         '$v' . "\n.\n";
488    open(OUT19, '>Op_write.tmp') || die "Can't create Op_write.tmp";
489    write(OUT19);
490    close OUT19 or die "Could not close: $!";
491    my $res = cat('Op_write.tmp');
492    is $res, <<EOD;
493gaga\0
494gaga\0
495EOD
496}
497
498{   # test 20: hash accesses; single '}' must not terminate format '}' (WL)
499    my %h = ( xkey => 'xval', ykey => 'yval' );
500    format OUT20 =
501@>>>> @<<<< ~~
502each %h
503@>>>> @<<<<
504$h{xkey}, $h{ykey}
505@>>>> @<<<<
506{ $h{xkey}, $h{ykey}
507}
508}
509.
510    my $exp = '';
511    while( my( $k, $v ) = each( %h ) ){
512	$exp .= sprintf( "%5s %s\n", $k, $v );
513    }
514    $exp .= sprintf( "%5s %s\n", $h{xkey}, $h{ykey} );
515    $exp .= sprintf( "%5s %s\n", $h{xkey}, $h{ykey} );
516    $exp .= "}\n";
517    open(OUT20, '>Op_write.tmp') || die "Can't create Op_write.tmp";
518    write(OUT20);
519    close OUT20 or die "Could not close: $!";
520    my $res = cat('Op_write.tmp');
521    is $res, $exp;
522}
523
524
525#####################
526## Section 2
527## numeric formatting
528#####################
529
530curr_test($bas_tests + 1);
531
532for my $tref ( @NumTests ){
533    my $writefmt = shift( @$tref );
534    while (@$tref) {
535	my $val      = shift @$tref;
536	my $expected = shift @$tref;
537        my $writeres = swrite( $writefmt, $val );
538	if (ref $expected) {
539	    like $writeres, $expected, $writefmt;
540	} else {
541	    is $writeres, $expected, $writefmt;
542	}
543    }
544}
545
546
547#####################################
548## Section 3
549## Easiest to add new tests just here
550#####################################
551
552# DAPM. Exercise a couple of error codepaths
553
554{
555    local $~ = '';
556    eval { write };
557    like $@, qr/Undefined format ""/, 'format with 0-length name';
558
559    $~ = "\0foo";
560    eval { write };
561    like $@, qr/Undefined format "\0foo"/,
562	'no such format beginning with null';
563
564    $~ = "NOSUCHFORMAT";
565    eval { write };
566    like $@, qr/Undefined format "NOSUCHFORMAT"/, 'no such format';
567}
568
569select +(select(OUT21), do {
570    open(OUT21, '>Op_write.tmp') || die "Can't create Op_write.tmp";
571
572    format OUT21 =
573@<<
574$_
575.
576
577    local $^ = '';
578    local $= = 1;
579    $_ = "aataaaaaaaaaaaaaa"; eval { write(OUT21) };
580    like $@, qr/Undefined top format ""/, 'top format with 0-length name';
581
582    $^ = "\0foo";
583    # For some reason, we have to do this twice to get the error again.
584    $_ = "aataaaaaaaaaaaaaa"; eval { write(OUT21) };
585    $_ = "aataaaaaaaaaaaaaa"; eval { write(OUT21) };
586    like $@, qr/Undefined top format "\0foo"/,
587	'no such top format beginning with null';
588
589    $^ = "NOSUCHFORMAT";
590    $_ = "aataaaaaaaaaaaaaa"; eval { write(OUT21) };
591    $_ = "aataaaaaaaaaaaaaa"; eval { write(OUT21) };
592    like $@, qr/Undefined top format "NOSUCHFORMAT"/, 'no such top format';
593
594    # reset things;
595    eval { write(OUT21) };
596    undef $^A;
597
598    close OUT21 or die "Could not close: $!";
599})[0];
600
601
602
603# [perl #119847],  [perl #119849], [perl #119851]
604# Non-real vars like tied, overloaded and refs could, when stringified,
605# fail to be processed properly, causing infinite loops on ~~, utf8
606# warnings etc, ad nauseum.
607
608
609my $u22a = "N" x 8;
610
611format OUT22a =
612'^<<<<<<<<'~~
613$u22a
614.
615
616is_format_utf8(\*OUT22a,
617               "'NNNNNNNN '\n");
618
619
620my $u22b = "N" x 8;
621utf8::upgrade($u22b);
622
623format OUT22b =
624'^<<<<<<<<'~~
625$u22b
626.
627
628is_format_utf8(\*OUT22b,
629               "'NNNNNNNN '\n");
630
631my $u22c = "\x{FF}" x 8;
632
633format OUT22c =
634'^<<<<<<<<'~~
635$u22c
636.
637
638is_format_utf8(\*OUT22c,
639               "'\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF} '\n");
640
641my $u22d = "\x{FF}" x 8;
642utf8::upgrade($u22d);
643
644format OUT22d =
645'^<<<<<<<<'~~
646$u22d
647.
648
649is_format_utf8(\*OUT22d,
650               "'\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF} '\n");
651
652my $u22e = "\x{100}" x 8;
653
654format OUT22e =
655'^<<<<<<<<'~~
656$u22e
657.
658
659is_format_utf8(\*OUT22e,
660               "'\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} '\n");
661
662
663my $u22f = "N" x 8;
664
665format OUT22f =
666'^<'~~
667$u22f
668.
669
670is_format_utf8(\*OUT22f,
671               "'NN'\n"x4);
672
673
674my $u22g = "N" x 8;
675utf8::upgrade($u22g);
676
677format OUT22g =
678'^<'~~
679$u22g
680.
681
682is_format_utf8(\*OUT22g,
683               "'NN'\n"x4);
684
685my $u22h = "\x{FF}" x 8;
686
687format OUT22h =
688'^<'~~
689$u22h
690.
691
692is_format_utf8(\*OUT22h,
693               "'\x{FF}\x{FF}'\n"x4);
694
695my $u22i = "\x{FF}" x 8;
696utf8::upgrade($u22i);
697
698format OUT22i =
699'^<'~~
700$u22i
701.
702
703is_format_utf8(\*OUT22i,
704               "'\x{FF}\x{FF}'\n"x4);
705
706my $u22j = "\x{100}" x 8;
707
708format OUT22j =
709'^<'~~
710$u22j
711.
712
713is_format_utf8(\*OUT22j,
714               "'\x{100}\x{100}'\n"x4);
715
716
717tie my $u23a, 'Tie::StdScalar';
718$u23a = "N" x 8;
719
720format OUT23a =
721'^<<<<<<<<'~~
722$u23a
723.
724
725is_format_utf8(\*OUT23a,
726               "'NNNNNNNN '\n");
727
728
729tie my $u23b, 'Tie::StdScalar';
730$u23b = "N" x 8;
731utf8::upgrade($u23b);
732
733format OUT23b =
734'^<<<<<<<<'~~
735$u23b
736.
737
738is_format_utf8(\*OUT23b,
739               "'NNNNNNNN '\n");
740
741tie my $u23c, 'Tie::StdScalar';
742$u23c = "\x{FF}" x 8;
743
744format OUT23c =
745'^<<<<<<<<'~~
746$u23c
747.
748
749is_format_utf8(\*OUT23c,
750               "'\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF} '\n");
751
752tie my $u23d, 'Tie::StdScalar';
753my $temp = "\x{FF}" x 8;
754utf8::upgrade($temp);
755$u23d = $temp;
756
757format OUT23d =
758'^<<<<<<<<'~~
759$u23d
760.
761
762is_format_utf8(\*OUT23d,
763               "'\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF} '\n");
764
765tie my $u23e, 'Tie::StdScalar';
766$u23e = "\x{100}" x 8;
767
768format OUT23e =
769'^<<<<<<<<'~~
770$u23e
771.
772
773is_format_utf8(\*OUT23e,
774               "'\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} '\n");
775
776tie my $u23f, 'Tie::StdScalar';
777$u23f = "N" x 8;
778
779format OUT23f =
780'^<'~~
781$u23f
782.
783
784is_format_utf8(\*OUT23f,
785               "'NN'\n"x4);
786
787
788tie my $u23g, 'Tie::StdScalar';
789my $temp = "N" x 8;
790utf8::upgrade($temp);
791$u23g = $temp;
792
793format OUT23g =
794'^<'~~
795$u23g
796.
797
798is_format_utf8(\*OUT23g,
799               "'NN'\n"x4);
800
801tie my $u23h, 'Tie::StdScalar';
802$u23h = "\x{FF}" x 8;
803
804format OUT23h =
805'^<'~~
806$u23h
807.
808
809is_format_utf8(\*OUT23h,
810               "'\x{FF}\x{FF}'\n"x4);
811
812$temp = "\x{FF}" x 8;
813utf8::upgrade($temp);
814tie my $u23i, 'Tie::StdScalar';
815$u23i = $temp;
816
817format OUT23i =
818'^<'~~
819$u23i
820.
821
822is_format_utf8(\*OUT23i,
823               "'\x{FF}\x{FF}'\n"x4);
824
825tie my $u23j, 'Tie::StdScalar';
826$u23j = "\x{100}" x 8;
827
828format OUT23j =
829'^<'~~
830$u23j
831.
832
833is_format_utf8(\*OUT23j,
834               "'\x{100}\x{100}'\n"x4);
835
836{
837    package UTF8Toggle;
838
839    sub TIESCALAR {
840        my $class = shift;
841        my $value = shift;
842        my $state = shift||0;
843        return bless [$value, $state], $class;
844    }
845
846    sub FETCH {
847        my $self = shift;
848        $self->[1] = ! $self->[1];
849        if ($self->[1]) {
850           utf8::downgrade($self->[0]);
851        } else {
852           utf8::upgrade($self->[0]);
853        }
854        $self->[0];
855    }
856
857   sub STORE {
858       my $self = shift;
859       $self->[0] = shift;
860    }
861}
862
863tie my $u24a, 'UTF8Toggle';
864$u24a = "N" x 8;
865
866format OUT24a =
867'^<<<<<<<<'~~
868$u24a
869.
870
871is_format_utf8(\*OUT24a,
872               "'NNNNNNNN '\n");
873
874
875tie my $u24b, 'UTF8Toggle';
876$u24b = "N" x 8;
877utf8::upgrade($u24b);
878
879format OUT24b =
880'^<<<<<<<<'~~
881$u24b
882.
883
884is_format_utf8(\*OUT24b,
885               "'NNNNNNNN '\n");
886
887tie my $u24c, 'UTF8Toggle';
888$u24c = "\x{FF}" x 8;
889
890format OUT24c =
891'^<<<<<<<<'~~
892$u24c
893.
894
895is_format_utf8(\*OUT24c,
896               "'\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF} '\n");
897
898tie my $u24d, 'UTF8Toggle', 1;
899$u24d = "\x{FF}" x 8;
900
901format OUT24d =
902'^<<<<<<<<'~~
903$u24d
904.
905
906is_format_utf8(\*OUT24d,
907               "'\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF} '\n");
908
909
910
911tie my $u24f, 'UTF8Toggle';
912$u24f = "N" x 8;
913
914format OUT24f =
915'^<'~~
916$u24f
917.
918
919is_format_utf8(\*OUT24f,
920               "'NN'\n"x4);
921
922
923tie my $u24g, 'UTF8Toggle';
924my $temp = "N" x 8;
925utf8::upgrade($temp);
926$u24g = $temp;
927
928format OUT24g =
929'^<'~~
930$u24g
931.
932
933is_format_utf8(\*OUT24g,
934               "'NN'\n"x4);
935
936tie my $u24h, 'UTF8Toggle';
937$u24h = "\x{FF}" x 8;
938
939format OUT24h =
940'^<'~~
941$u24h
942.
943
944is_format_utf8(\*OUT24h,
945               "'\x{FF}\x{FF}'\n"x4);
946
947tie my $u24i, 'UTF8Toggle', 1;
948$u24i = "\x{FF}" x 8;
949
950format OUT24i =
951'^<'~~
952$u24i
953.
954
955is_format_utf8(\*OUT24i,
956               "'\x{FF}\x{FF}'\n"x4);
957
958{
959    package OS;
960    use overload '""' => sub { ${$_[0]}; };
961
962    sub new {
963        my ($class, $value) = @_;
964        bless \$value, $class;
965    }
966}
967
968my $u25a = OS->new("N" x 8);
969
970format OUT25a =
971'^<<<<<<<<'~~
972$u25a
973.
974
975is_format_utf8(\*OUT25a,
976               "'NNNNNNNN '\n");
977
978
979my $temp = "N" x 8;
980utf8::upgrade($temp);
981my $u25b = OS->new($temp);
982
983format OUT25b =
984'^<<<<<<<<'~~
985$u25b
986.
987
988is_format_utf8(\*OUT25b,
989               "'NNNNNNNN '\n");
990
991my $u25c = OS->new("\x{FF}" x 8);
992
993format OUT25c =
994'^<<<<<<<<'~~
995$u25c
996.
997
998is_format_utf8(\*OUT25c,
999               "'\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF} '\n");
1000
1001$temp = "\x{FF}" x 8;
1002utf8::upgrade($temp);
1003my $u25d = OS->new($temp);
1004
1005format OUT25d =
1006'^<<<<<<<<'~~
1007$u25d
1008.
1009
1010is_format_utf8(\*OUT25d,
1011               "'\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF} '\n");
1012
1013my $u25e = OS->new("\x{100}" x 8);
1014
1015format OUT25e =
1016'^<<<<<<<<'~~
1017$u25e
1018.
1019
1020is_format_utf8(\*OUT25e,
1021               "'\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100}\x{100} '\n");
1022
1023
1024my $u25f = OS->new("N" x 8);
1025
1026format OUT25f =
1027'^<'~~
1028$u25f
1029.
1030
1031is_format_utf8(\*OUT25f,
1032               "'NN'\n"x4);
1033
1034
1035$temp = "N" x 8;
1036utf8::upgrade($temp);
1037my $u25g = OS->new($temp);
1038
1039format OUT25g =
1040'^<'~~
1041$u25g
1042.
1043
1044is_format_utf8(\*OUT25g,
1045               "'NN'\n"x4);
1046
1047my $u25h = OS->new("\x{FF}" x 8);
1048
1049format OUT25h =
1050'^<'~~
1051$u25h
1052.
1053
1054is_format_utf8(\*OUT25h,
1055               "'\x{FF}\x{FF}'\n"x4);
1056
1057$temp = "\x{FF}" x 8;
1058utf8::upgrade($temp);
1059my $u25i = OS->new($temp);
1060
1061format OUT25i =
1062'^<'~~
1063$u25i
1064.
1065
1066is_format_utf8(\*OUT25i,
1067               "'\x{FF}\x{FF}'\n"x4);
1068
1069my $u25j = OS->new("\x{100}" x 8);
1070
1071format OUT25j =
1072'^<'~~
1073$u25j
1074.
1075
1076is_format_utf8(\*OUT25j,
1077               "'\x{100}\x{100}'\n"x4);
1078
1079{
1080    package OS::UTF8Toggle;
1081    use overload '""' => sub {
1082        my $self = shift;
1083        $self->[1] = ! $self->[1];
1084        if ($self->[1]) {
1085            utf8::downgrade($self->[0]);
1086        } else {
1087            utf8::upgrade($self->[0]);
1088        }
1089        $self->[0];
1090    };
1091
1092    sub new {
1093        my ($class, $value, $state) = @_;
1094        bless [$value, $state], $class;
1095    }
1096}
1097
1098
1099my $u26a = OS::UTF8Toggle->new("N" x 8);
1100
1101format OUT26a =
1102'^<<<<<<<<'~~
1103$u26a
1104.
1105
1106is_format_utf8(\*OUT26a,
1107               "'NNNNNNNN '\n");
1108
1109
1110my $u26b = OS::UTF8Toggle->new("N" x 8, 1);
1111
1112format OUT26b =
1113'^<<<<<<<<'~~
1114$u26b
1115.
1116
1117is_format_utf8(\*OUT26b,
1118               "'NNNNNNNN '\n");
1119
1120my $u26c = OS::UTF8Toggle->new("\x{FF}" x 8);
1121
1122format OUT26c =
1123'^<<<<<<<<'~~
1124$u26c
1125.
1126
1127is_format_utf8(\*OUT26c,
1128               "'\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF} '\n");
1129
1130my $u26d = OS::UTF8Toggle->new("\x{FF}" x 8, 1);
1131
1132format OUT26d =
1133'^<<<<<<<<'~~
1134$u26d
1135.
1136
1137is_format_utf8(\*OUT26d,
1138               "'\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF}\x{FF} '\n");
1139
1140
1141my $u26f = OS::UTF8Toggle->new("N" x 8);
1142
1143format OUT26f =
1144'^<'~~
1145$u26f
1146.
1147
1148is_format_utf8(\*OUT26f,
1149               "'NN'\n"x4);
1150
1151
1152my $u26g = OS::UTF8Toggle->new("N" x 8, 1);
1153
1154format OUT26g =
1155'^<'~~
1156$u26g
1157.
1158
1159is_format_utf8(\*OUT26g,
1160               "'NN'\n"x4);
1161
1162my $u26h = OS::UTF8Toggle->new("\x{FF}" x 8);
1163
1164format OUT26h =
1165'^<'~~
1166$u26h
1167.
1168
1169is_format_utf8(\*OUT26h,
1170               "'\x{FF}\x{FF}'\n"x4);
1171
1172my $u26i = OS::UTF8Toggle->new("\x{FF}" x 8, 1);
1173
1174format OUT26i =
1175'^<'~~
1176$u26i
1177.
1178
1179is_format_utf8(\*OUT26i,
1180               "'\x{FF}\x{FF}'\n"x4);
1181
1182
1183
1184{
1185    my $zero = $$ - $$;
1186
1187    package Number;
1188
1189    sub TIESCALAR {
1190        my $class = shift;
1191        my $value = shift;
1192        return bless \$value, $class;
1193    }
1194
1195    # The return value should always be SvNOK() only:
1196    sub FETCH {
1197        my $self = shift;
1198        # avoid "" getting converted to "0" and thus
1199        # causing an infinite loop
1200        return "" unless length ($$self);
1201        return $$self - 0.5 + $zero + 0.5;
1202    }
1203
1204   sub STORE {
1205       my $self = shift;
1206       $$self = shift;
1207    }
1208
1209   package ONumber;
1210
1211   use overload '""' => sub {
1212        my $self = shift;
1213        return $$self - 0.5 + $zero + 0.5;
1214    };
1215
1216    sub new {
1217       my $class = shift;
1218       my $value = shift;
1219       return bless \$value, $class;
1220   }
1221}
1222
1223my $v27a = 1/256;
1224
1225format OUT27a =
1226'^<<<<<<<<<'~~
1227$v27a
1228.
1229
1230is_format_utf8(\*OUT27a,
1231               "'0.00390625'\n");
1232
1233my $v27b = 1/256;
1234
1235format OUT27b =
1236'^<'~~
1237$v27b
1238.
1239
1240is_format_utf8(\*OUT27b,
1241               "'0.'\n'00'\n'39'\n'06'\n'25'\n");
1242
1243tie my $v27c, 'Number', 1/256;
1244
1245format OUT27c =
1246'^<<<<<<<<<'~~
1247$v27c
1248.
1249
1250is_format_utf8(\*OUT27c,
1251               "'0.00390625'\n");
1252
1253my $v27d = 1/256;
1254
1255format OUT27d =
1256'^<'~~
1257$v27d
1258.
1259
1260is_format_utf8(\*OUT27d,
1261               "'0.'\n'00'\n'39'\n'06'\n'25'\n");
1262
1263my $v27e = ONumber->new(1/256);
1264
1265format OUT27e =
1266'^<<<<<<<<<'~~
1267$v27e
1268.
1269
1270is_format_utf8(\*OUT27e,
1271               "'0.00390625'\n");
1272
1273my $v27f = ONumber->new(1/256);
1274
1275format OUT27f =
1276'^<'~~
1277$v27f
1278.
1279
1280is_format_utf8(\*OUT27f,
1281               "'0.'\n'00'\n'39'\n'06'\n'25'\n");
1282
1283{
1284    package Ref;
1285    use overload '""' => sub {
1286	return ${$_[0]};
1287    };
1288
1289    sub new {
1290       my $class = shift;
1291       my $value = shift;
1292       return bless \$value, $class;
1293   }
1294}
1295
1296my $v28a = {};
1297
1298format OUT28a =
1299'^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<'~~
1300$v28a
1301.
1302
1303
1304# 'HASH(0x1716b60)     '
1305my $qr_hash   = qr/^'HASH\(0x[0-9a-f]+\)\s+'\n$/;
1306
1307# 'HASH'
1308# '(0x1'
1309# '716b'
1310# 'c0) '
1311my $qr_hash_m = qr/^'HASH'\n('[0-9a-fx() ]{4}'\n)+$/;
1312
1313like_format_utf8(\*OUT28a, $qr_hash);
1314
1315my $v28b = {};
1316
1317format OUT28b =
1318'^<<<'~~
1319$v28b
1320.
1321
1322like_format_utf8(\*OUT28b, $qr_hash_m);
1323
1324
1325tie my $v28c, 'Tie::StdScalar';
1326$v28c = {};
1327
1328format OUT28c =
1329'^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<'~~
1330$v28c
1331.
1332
1333like_format_utf8(\*OUT28c, $qr_hash);
1334
1335tie my $v28d, 'Tie::StdScalar';
1336$v28d = {};
1337
1338format OUT28d =
1339'^<<<'~~
1340$v28d
1341.
1342
1343like_format_utf8(\*OUT28d, $qr_hash_m);
1344
1345my $v28e = Ref->new({});
1346
1347format OUT28e =
1348'^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<'~~
1349$v28e
1350.
1351
1352like_format_utf8(\*OUT28e, $qr_hash);
1353
1354my $v28f = Ref->new({});
1355
1356format OUT28f =
1357'^<<<'~~
1358$v28f
1359.
1360
1361like_format_utf8(\*OUT28f, $qr_hash_m);
1362
1363
1364
1365{
1366  package Count;
1367
1368  sub TIESCALAR {
1369    my $class = shift;
1370    bless [shift, 0, 0], $class;
1371  }
1372
1373  sub FETCH {
1374    my $self = shift;
1375    ++$self->[1];
1376    $self->[0];
1377  }
1378
1379  sub STORE {
1380    my $self = shift;
1381    ++$self->[2];
1382    $self->[0] = shift;
1383  }
1384}
1385
1386{
1387  my ($pound_utf8, $pm_utf8) = map { my $a = "$_\x{100}"; chop $a; $a}
1388    my ($pound, $pm) = ("\xA3", "\xB1");
1389
1390  foreach my $first ('N', $pound, $pound_utf8) {
1391    foreach my $base ('N', $pm, $pm_utf8) {
1392      foreach my $second ($base, "$base\n", "$base\nMoo!", "$base\nMoo!\n",
1393			  "$base\nMoo!\n",) {
1394	foreach (['^*', qr/(.+)/], ['@*', qr/(.*?)$/s]) {
1395	  my ($format, $re) = @$_;
1396	  $format = "1^*2 3${format}4";
1397	  foreach my $class ('', 'Count') {
1398	    my $name = qq{swrite("$format", "$first", "$second") class="$class"};
1399	    $name =~ s/\n/\\n/g;
1400	    $name =~ s{(.)}{
1401			ord($1) > 126 ? sprintf("\\x{%x}",ord($1)) : $1
1402		    }ge;
1403
1404	    $first =~ /(.+)/ or die $first;
1405	    my $expect = "1${1}2";
1406	    $second =~ $re or die $second;
1407	    $expect .= " 3${1}4";
1408
1409	    if ($class) {
1410	      my $copy1 = $first;
1411	      my $copy2;
1412	      tie $copy2, $class, $second;
1413	      is swrite("$format", $copy1, $copy2), $expect, $name;
1414	      my $obj = tied $copy2;
1415	      is $obj->[1], 1, 'value read exactly once';
1416	    } else {
1417	      my ($copy1, $copy2) = ($first, $second);
1418	      is swrite("$format", $copy1, $copy2), $expect, $name;
1419	    }
1420	  }
1421	}
1422      }
1423    }
1424  }
1425}
1426
1427{
1428  # This will fail an assertion in 5.10.0 built with -DDEBUGGING (because
1429  # pp_formline attempts to set SvCUR() on an SVt_RV). I suspect that it will
1430  # be doing something similarly out of bounds on everything from 5.000
1431  my $ref = [];
1432  my $exp = ">$ref<";
1433  is swrite('>^*<', $ref), $exp;
1434  $ref = [];
1435  my $exp = ">$ref<";
1436  is swrite('>@*<', $ref), $exp;
1437}
1438
1439format EMPTY =
1440.
1441
1442my $test = curr_test();
1443
1444format Comment =
1445ok @<<<<<
1446$test
1447.
1448
1449
1450# RT #8698 format bug with undefined _TOP
1451
1452open STDOUT_DUP, ">&STDOUT";
1453my $oldfh = select STDOUT_DUP;
1454$= = 10;
1455{
1456  local $~ = "Comment";
1457  write;
1458  curr_test($test + 1);
1459  is $-, 9;
1460  is $^, "STDOUT_DUP_TOP";
1461}
1462select $oldfh;
1463close STDOUT_DUP;
1464
1465*CmT =  *{$::{Comment}}{FORMAT};
1466ok  defined *{$::{CmT}}{FORMAT}, "glob assign";
1467
1468
1469# RT #91032: Check that "non-real" strings like tie and overload work,
1470# especially that they re-compile the pattern on each FETCH, and that
1471# they don't overrun the buffer
1472
1473
1474{
1475    package RT91032;
1476
1477    sub TIESCALAR { bless [] }
1478    my $i = 0;
1479    sub FETCH { $i++; "A$i @> Z\n" }
1480
1481    use overload '""' => \&FETCH;
1482
1483    tie my $f, 'RT91032';
1484
1485    formline $f, "a";
1486    formline $f, "bc";
1487    ::is $^A, "A1  a Z\nA2 bc Z\n", "RT 91032: tied";
1488    $^A = '';
1489
1490    my $g = bless []; # has overloaded stringify
1491    formline $g, "de";
1492    formline $g, "f";
1493    ::is $^A, "A3 de Z\nA4  f Z\n", "RT 91032: overloaded";
1494    $^A = '';
1495
1496    my $h = [];
1497    formline $h, "junk1";
1498    formline $h, "junk2";
1499    ::is ref($h), 'ARRAY', "RT 91032: array ref still a ref";
1500    ::like "$h", qr/^ARRAY\(0x[0-9a-f]+\)$/, "RT 91032: array stringifies ok";
1501    ::is $^A, "$h$h","RT 91032: stringified array";
1502    $^A = '';
1503
1504    # used to overwrite the ~~ in the *original SV with spaces. Naughty!
1505
1506    my $orig = my $format = "^<<<<< ~~\n";
1507    my $abc = "abc";
1508    formline $format, $abc;
1509    $^A ='';
1510    ::is $format, $orig, "RT91032: don't overwrite orig format string";
1511
1512    # check that ~ and ~~ are displayed correctly as whitespace,
1513    # under the influence of various different types of border
1514
1515    for my $n (1,2) {
1516	for my $lhs (' ', 'Y', '^<<<', '^|||', '^>>>') {
1517	    for my $rhs ('', ' ', 'Z', '^<<<', '^|||', '^>>>') {
1518		my $fmt = "^<B$lhs" . ('~' x $n) . "$rhs\n";
1519		my $sfmt = ($fmt =~ s/~/ /gr);
1520		my ($a, $bc, $stop);
1521		($a, $bc, $stop) = ('a', 'bc', 's');
1522		# $stop is to stop '~~' deleting the whole line
1523		formline $sfmt, $stop, $a, $bc;
1524		my $exp = $^A;
1525		$^A = '';
1526		($a, $bc, $stop) = ('a', 'bc', 's');
1527		formline $fmt, $stop, $a, $bc;
1528		my $got = $^A;
1529		$^A = '';
1530		$fmt =~ s/\n/\\n/;
1531		::is($got, $exp, "chop munging: [$fmt]");
1532	    }
1533	}
1534    }
1535}
1536
1537# check that '~  (delete current line if empty) works when
1538# the target gets upgraded to uft8 (and re-allocated) midstream.
1539
1540{
1541    my $format = "\x{100}@~\n"; # format is utf8
1542    # this target is not utf8, but will expand (and get reallocated)
1543    # when upgraded to utf8.
1544    my $orig = "\x80\x81\x82";
1545    local $^A = $orig;
1546    my $empty = "";
1547    formline $format, $empty;
1548    is $^A , $orig, "~ and realloc";
1549
1550    # check similarly that trailing blank removal works ok
1551
1552    $format = "@<\n\x{100}"; # format is utf8
1553    chop $format;
1554    $orig = "   ";
1555    $^A = $orig;
1556    formline $format, "  ";
1557    is $^A, "$orig\n", "end-of-line blanks and realloc";
1558
1559    # and check this doesn't overflow the buffer
1560
1561    local $^A = '';
1562    $format = "@* @####\n";
1563    $orig = "x" x 100 . "\n";
1564    formline $format, $orig, 12345;
1565    is $^A, ("x" x 100) . " 12345\n", "\@* doesn't overflow";
1566
1567    # ...nor this (RT #130703).
1568    # Under 'use bytes', the two bytes (c2, 80) making up each \x80 char
1569    # each get expanded to two bytes (so four in total per \x80 char); the
1570    # buffer growth wasn't accounting for this doubling in size
1571
1572    {
1573        local $^A = '';
1574        my $format = "X\n\x{100}" . ("\x80" x 200);
1575        my $expected = $format;
1576        utf8::encode($expected);
1577        use bytes;
1578        formline($format);
1579        is $^A, $expected, "RT #130703";
1580    }
1581
1582    # further buffer overflows with RT #130703
1583
1584    {
1585        local $^A = '';
1586        my $n = 200;
1587        my $long = 'x' x 300;
1588        my $numf = ('@###' x $n);
1589        my $expected = $long . "\n" . ("   1" x $n);
1590        formline("@*\n$numf", $long, ('1') x $n);
1591
1592        is $^A, $expected, "RT #130703 part 2";
1593    }
1594
1595
1596    # make sure it can cope with formats > 64k
1597
1598    $format = 'x' x 65537;
1599    $^A = '';
1600    formline $format;
1601    # don't use 'is' here, as the diag output will be too long!
1602    ok $^A eq $format, ">64K";
1603}
1604
1605
1606SKIP: {
1607    skip_if_miniperl('miniperl does not support scalario');
1608    my $buf = "";
1609    open my $fh, ">", \$buf;
1610    my $old_fh = select $fh;
1611    local $~ = "CmT";
1612    write;
1613    select $old_fh;
1614    close $fh;
1615    is $buf, "ok $test\n", "write to duplicated format";
1616}
1617
1618format caret_A_test_TOP =
1619T
1620.
1621
1622format caret_A_test =
1623L1
1624L2
1625L3
1626L4
1627.
1628
1629SKIP: {
1630    skip_if_miniperl('miniperl does not support scalario');
1631    my $buf = "";
1632    open my $fh, ">", \$buf;
1633    my $old_fh = select $fh;
1634    local $^ = "caret_A_test_TOP";
1635    local $~ = "caret_A_test";
1636    local $= = 3;
1637    local $^A = "A1\nA2\nA3\nA4\n";
1638    write;
1639    select $old_fh;
1640    close $fh;
1641    is $buf, "T\nA1\nA2\n\fT\nA3\nA4\n\fT\nL1\nL2\n\fT\nL3\nL4\n",
1642		    "assign to ^A sets FmLINES";
1643}
1644
1645fresh_perl_like(<<'EOP', qr/^Format STDOUT redefined at/, {stderr => 1}, '#64562 - Segmentation fault with redefined formats and warnings');
1646#!./perl
1647
1648use strict;
1649use warnings; # crashes!
1650
1651format =
1652.
1653
1654write;
1655
1656format =
1657.
1658
1659write;
1660EOP
1661
1662fresh_perl_is(<<'EOP', ">ARRAY<\ncrunch_eth\n", {stderr => 1}, '#79532 - formline coerces its arguments');
1663use strict;
1664use warnings;
1665my $zamm = ['crunch_eth'];
1666formline $zamm;
1667printf ">%s<\n", ref $zamm;
1668print "$zamm->[0]\n";
1669EOP
1670
1671# [perl #129125] - detected by -fsanitize=address or valgrind
1672# the compiled format would be freed when the format string was modified
1673# by the chop operator
1674fresh_perl_is(<<'EOP', "^", { stderr => 1 }, '#129125 - chop on format');
1675my $x = '^@';
1676formline$x=>$x;
1677print $^A;
1678EOP
1679
1680fresh_perl_is(<<'EOP', '<^< xx AA><xx ^<><>', { stderr => 1 }, '#129125 - chop on format, later values');
1681my $x = '^< xx ^<';
1682my $y = 'AA';
1683formline $x => $x, $y;
1684print "<$^A><$x><$y>";
1685EOP
1686
1687
1688# [perl #73690]
1689
1690select +(select(RT73690), do {
1691    open(RT73690, '>Op_write.tmp') || die "Can't create Op_write.tmp";
1692    format RT73690 =
1693@<< @<<
169411, 22
1695.
1696
1697    my @ret;
1698
1699    @ret = write;
1700    is(scalar(@ret), 1);
1701    ok($ret[0]);
1702    @ret = scalar(write);
1703    is(scalar(@ret), 1);
1704    ok($ret[0]);
1705    @ret = write(RT73690);
1706    is(scalar(@ret), 1);
1707    ok($ret[0]);
1708    @ret = scalar(write(RT73690));
1709    is(scalar(@ret), 1);
1710    ok($ret[0]);
1711
1712    @ret = ('a', write, 'z');
1713    is(scalar(@ret), 3);
1714    is($ret[0], 'a');
1715    ok($ret[1]);
1716    is($ret[2], 'z');
1717    @ret = ('b', scalar(write), 'y');
1718    is(scalar(@ret), 3);
1719    is($ret[0], 'b');
1720    ok($ret[1]);
1721    is($ret[2], 'y');
1722    @ret = ('c', write(RT73690), 'x');
1723    is(scalar(@ret), 3);
1724    is($ret[0], 'c');
1725    ok($ret[1]);
1726    is($ret[2], 'x');
1727    @ret = ('d', scalar(write(RT73690)), 'w');
1728    is(scalar(@ret), 3);
1729    is($ret[0], 'd');
1730    ok($ret[1]);
1731    is($ret[2], 'w');
1732
1733    @ret = do { write; 'foo' };
1734    is(scalar(@ret), 1);
1735    is($ret[0], 'foo');
1736    @ret = do { scalar(write); 'bar' };
1737    is(scalar(@ret), 1);
1738    is($ret[0], 'bar');
1739    @ret = do { write(RT73690); 'baz' };
1740    is(scalar(@ret), 1);
1741    is($ret[0], 'baz');
1742    @ret = do { scalar(write(RT73690)); 'quux' };
1743    is(scalar(@ret), 1);
1744    is($ret[0], 'quux');
1745
1746    @ret = ('a', do { write; 'foo' }, 'z');
1747    is(scalar(@ret), 3);
1748    is($ret[0], 'a');
1749    is($ret[1], 'foo');
1750    is($ret[2], 'z');
1751    @ret = ('b', do { scalar(write); 'bar' }, 'y');
1752    is(scalar(@ret), 3);
1753    is($ret[0], 'b');
1754    is($ret[1], 'bar');
1755    is($ret[2], 'y');
1756    @ret = ('c', do { write(RT73690); 'baz' }, 'x');
1757    is(scalar(@ret), 3);
1758    is($ret[0], 'c');
1759    is($ret[1], 'baz');
1760    is($ret[2], 'x');
1761    @ret = ('d', do { scalar(write(RT73690)); 'quux' }, 'w');
1762    is(scalar(@ret), 3);
1763    is($ret[0], 'd');
1764    is($ret[1], 'quux');
1765    is($ret[2], 'w');
1766
1767    close RT73690 or die "Could not close: $!";
1768})[0];
1769
1770select +(select(RT73690_2), do {
1771    open(RT73690_2, '>Op_write.tmp') || die "Can't create Op_write.tmp";
1772    format RT73690_2 =
1773@<< @<<
1774return
1775.
1776
1777    my @ret;
1778
1779    @ret = write;
1780    is(scalar(@ret), 1);
1781    ok(!$ret[0]);
1782    @ret = scalar(write);
1783    is(scalar(@ret), 1);
1784    ok(!$ret[0]);
1785    @ret = write(RT73690_2);
1786    is(scalar(@ret), 1);
1787    ok(!$ret[0]);
1788    @ret = scalar(write(RT73690_2));
1789    is(scalar(@ret), 1);
1790    ok(!$ret[0]);
1791
1792    @ret = ('a', write, 'z');
1793    is(scalar(@ret), 3);
1794    is($ret[0], 'a');
1795    ok(!$ret[1]);
1796    is($ret[2], 'z');
1797    @ret = ('b', scalar(write), 'y');
1798    is(scalar(@ret), 3);
1799    is($ret[0], 'b');
1800    ok(!$ret[1]);
1801    is($ret[2], 'y');
1802    @ret = ('c', write(RT73690_2), 'x');
1803    is(scalar(@ret), 3);
1804    is($ret[0], 'c');
1805    ok(!$ret[1]);
1806    is($ret[2], 'x');
1807    @ret = ('d', scalar(write(RT73690_2)), 'w');
1808    is(scalar(@ret), 3);
1809    is($ret[0], 'd');
1810    ok(!$ret[1]);
1811    is($ret[2], 'w');
1812
1813    @ret = do { write; 'foo' };
1814    is(scalar(@ret), 1);
1815    is($ret[0], 'foo');
1816    @ret = do { scalar(write); 'bar' };
1817    is(scalar(@ret), 1);
1818    is($ret[0], 'bar');
1819    @ret = do { write(RT73690_2); 'baz' };
1820    is(scalar(@ret), 1);
1821    is($ret[0], 'baz');
1822    @ret = do { scalar(write(RT73690_2)); 'quux' };
1823    is(scalar(@ret), 1);
1824    is($ret[0], 'quux');
1825
1826    @ret = ('a', do { write; 'foo' }, 'z');
1827    is(scalar(@ret), 3);
1828    is($ret[0], 'a');
1829    is($ret[1], 'foo');
1830    is($ret[2], 'z');
1831    @ret = ('b', do { scalar(write); 'bar' }, 'y');
1832    is(scalar(@ret), 3);
1833    is($ret[0], 'b');
1834    is($ret[1], 'bar');
1835    is($ret[2], 'y');
1836    @ret = ('c', do { write(RT73690_2); 'baz' }, 'x');
1837    is(scalar(@ret), 3);
1838    is($ret[0], 'c');
1839    is($ret[1], 'baz');
1840    is($ret[2], 'x');
1841    @ret = ('d', do { scalar(write(RT73690_2)); 'quux' }, 'w');
1842    is(scalar(@ret), 3);
1843    is($ret[0], 'd');
1844    is($ret[1], 'quux');
1845    is($ret[2], 'w');
1846
1847    close RT73690_2 or die "Could not close: $!";
1848})[0];
1849
1850open(UNDEF, '>Op_write.tmp') || die "Can't create Op_write.tmp";
1851select +(select(UNDEF), $~ = "UNDEFFORMAT")[0];
1852format UNDEFFORMAT =
1853@
1854undef *UNDEFFORMAT
1855.
1856write UNDEF;
1857pass "active format cannot be freed";
1858
1859select +(select(UNDEF), $~ = "UNDEFFORMAT2")[0];
1860format UNDEFFORMAT2 =
1861@
1862close UNDEF or die "Could not close: $!"; undef *UNDEF
1863.
1864write UNDEF;
1865pass "freeing current handle in format";
1866undef $^A;
1867
1868ok !eval q|
1869format foo {
1870@<<<
1871$a
1872}
1873;1
1874|, 'format foo { ... } is not allowed';
1875
1876ok !eval q|
1877format =
1878@<<<
1879}
1880;1
1881|, 'format = ... } is not allowed';
1882
1883open(NEST, '>Op_write.tmp') || die "Can't create Op_write.tmp";
1884format NEST =
1885@<<<
1886{
1887    my $birds = "birds";
1888    local *NEST = *BIRDS{FORMAT};
1889    write NEST;
1890    format BIRDS =
1891@<<<<<
1892$birds;
1893.
1894    "nest"
1895}
1896.
1897write NEST;
1898close NEST or die "Could not close: $!";
1899is cat('Op_write.tmp'), "birds\nnest\n", 'nested formats';
1900
1901# A compilation error should not create a format
1902eval q|
1903format ERROR =
1904@
1905@_ =~ s///
1906.
1907|;
1908eval { write ERROR };
1909like $@, qr'Undefined format',
1910    'formats with compilation errors are not created';
1911
1912# This syntax error used to cause a crash, double free, or a least
1913# a bad read.
1914# See the long-winded explanation at:
1915#   https://rt.perl.org/rt3/Ticket/Display.html?id=43425#txn-1144500
1916eval q|
1917format =
1918@
1919use;format
1920strict
1921.
1922|;
1923pass('no crash with invalid use/format inside format');
1924
1925
1926# Low-precedence operators on argument line
1927format AND =
1928@
19290 and die
1930.
1931$- = $=;
1932ok eval { local $~ = "AND"; print "# "; write; 1 },
1933    "low-prec ops on arg line" or diag $@;
1934
1935# Anonymous hashes
1936open(HASH, '>Op_write.tmp') || die "Can't create Op_write.tmp";
1937format HASH =
1938@<<<
1939${{qw[ Sun 0 Mon 1 Tue 2 Wed 3 Thu 4 Fri 5 Sat 6 ]}}{"Wed"}
1940.
1941write HASH;
1942close HASH or die "Could not close: $!";
1943is cat('Op_write.tmp'), "3\n", 'anonymous hashes';
1944
1945open(HASH2, '>Op_write.tmp') || die "Can't create Op_write.tmp";
1946format HASH2 =
1947@<<<
1948+{foo=>"bar"}
1949.
1950write HASH2;
1951close HASH2 or die "Could not close: $!";
1952is cat('Op_write.tmp'), "HASH\n", '+{...} is interpreted as anon hash';
1953
1954# Anonymous hashes
1955open(BLOCK, '>Op_write.tmp') || die "Can't create Op_write.tmp";
1956format BLOCK =
1957@<<< @<<<
1958{foo=>"bar"} # this is a block, not a hash!
1959.
1960write BLOCK;
1961close BLOCK or die "Could not close: $!";
1962is cat('Op_write.tmp'), "foo  bar\n", 'initial { is always BLOCK';
1963
1964# pragmata inside argument line
1965open(STRICT, '>Op_write.tmp') || die "Can't create Op_write.tmp";
1966format STRICT =
1967@<<<
1968no strict; $foo
1969.
1970$::foo = 'oof::$';
1971write STRICT;
1972close STRICT or die "Could not close: $!";
1973is cat('Op_write.tmp'), "oof:\n", 'pragmata on format line';
1974
1975SKIP: {
1976   skip "no weak refs" unless eval { require Scalar::Util };
1977   sub Potshriggley {
1978format Potshriggley =
1979.
1980   }
1981   Scalar::Util::weaken(my $x = *Potshriggley{FORMAT});
1982   undef *Potshriggley;
1983   is $x, undef, 'formats in subs do not leak';
1984}
1985
1986fresh_perl_is(<<'EOP', <<'EXPECT',
1987use warnings 'syntax' ;
1988format STDOUT =
1989^*|^*
1990my $x = q/dd/, $x
1991.
1992write;
1993EOP
1994dd|
1995EXPECT
1996	      { stderr => 1 }, '#123245 panic in sv_chop');
1997
1998fresh_perl_is(<<'EOP', <<'EXPECT',
1999use warnings 'syntax' ;
2000format STDOUT =
2001^*|^*
2002my $x = q/dd/
2003.
2004write;
2005EOP
2006Not enough format arguments at - line 4.
2007dd|
2008EXPECT
2009	      { stderr => 1 }, '#123245 different panic in sv_chop');
2010
2011fresh_perl_is(<<'EOP', <<'EXPECT',
2012format STDOUT =
2013# x at the end to make the spaces visible
2014@... x
2015q/a/
2016.
2017write;
2018EOP
2019a    x
2020EXPECT
2021	      { stderr => 1 }, '#123538 crash in FF_MORE');
2022
2023{
2024    $^A = "";
2025    my $a = *globcopy;
2026    my $r = eval { formline "^<<", $a };
2027    is $@, "";
2028    ok $r, "^ format with glob copy";
2029    is $^A, "*ma", "^ format with glob copy";
2030    is $a, "in::globcopy", "^ format with glob copy";
2031}
2032
2033{
2034    $^A = "";
2035    my $r = eval { formline "^<<", *realglob };
2036    like $@, qr/\AModification of a read-only value attempted /;
2037    is $r, undef, "^ format with real glob";
2038    is $^A, "*ma", "^ format with real glob";
2039    is ref(\*realglob), "GLOB";
2040}
2041
2042$^A = "";
2043
2044# [perl #130722] assertion failure
2045fresh_perl_is('for(1..2){formline*0}', '', { stderr => 1 } , "#130722 - assertion failure");
2046
2047#############################
2048## Section 4
2049## Add new tests *above* here
2050#############################
2051
2052# scary format testing from H.Merijn Brand
2053
2054# Just a complete test for format, including top-, left- and bottom marging
2055# and format detection through glob entries
2056
2057if ($^O eq 'VMS' || $^O eq 'MSWin32' || $^O eq 'dos' ||
2058    ($^O eq 'os2' and not eval '$OS2::can_fork')) {
2059  $test = curr_test();
2060 SKIP: {
2061      skip "'|-' and '-|' not supported", $tests - $test + 1;
2062  }
2063  exit(0);
2064}
2065
2066
2067$^  = "STDOUT_TOP";
2068$=  =  7;		# Page length
2069$-  =  0;		# Lines left
2070my $ps = $^L; $^L = "";	# Catch the page separator
2071my $tm =  1;		# Top margin (empty lines before first output)
2072my $bm =  2;		# Bottom marging (empty lines between last text and footer)
2073my $lm =  4;		# Left margin (indent in spaces)
2074
2075# -----------------------------------------------------------------------
2076#
2077# execute the rest of the script in a child process. The parent reads the
2078# output from the child and compares it with <DATA>.
2079
2080my @data = <DATA>;
2081
2082select ((select (STDOUT), $| = 1)[0]); # flush STDOUT
2083
2084my $opened = open FROM_CHILD, "-|";
2085unless (defined $opened) {
2086    fail "open gave $!";
2087    exit 0;
2088}
2089
2090if ($opened) {
2091    # in parent here
2092
2093    pass 'open';
2094    my $s = " " x $lm;
2095    while (<FROM_CHILD>) {
2096	unless (@data) {
2097	    fail 'too much output';
2098	    exit;
2099	}
2100	s/^/$s/;
2101	my $exp = shift @data;
2102	is $_, $exp;
2103    }
2104    close FROM_CHILD;
2105    is "@data", "", "correct length of output";
2106    exit;
2107}
2108
2109# in child here
2110$::NO_ENDING = 1;
2111
2112    select ((select (STDOUT), $| = 1)[0]);
2113$tm = "\n" x $tm;
2114$= -= $bm + 1; # count one for the trailing "----"
2115my $lastmin = 0;
2116
2117my @E;
2118
2119sub wryte
2120{
2121    $lastmin = $-;
2122    write;
2123    } # wryte;
2124
2125sub footer
2126{
2127    $% == 1 and return "";
2128
2129    $lastmin < $= and print "\n" x $lastmin;
2130    print "\n" x $bm, "----\n", $ps;
2131    $lastmin = $-;
2132    "";
2133    } # footer
2134
2135# Yes, this is sick ;-)
2136format TOP =
2137@* ~
2138@{[footer]}
2139@* ~
2140$tm
2141.
2142
2143format ENTRY =
2144@ @<<<<~~
2145@{(shift @E)||["",""]}
2146.
2147
2148format EOR =
2149- -----
2150.
2151
2152sub has_format ($)
2153{
2154    my $fmt = shift;
2155    exists $::{$fmt} or return 0;
2156    $^O eq "MSWin32" or return defined *{$::{$fmt}}{FORMAT};
2157    open my $null, "> /dev/null" or die;
2158    my $fh = select $null;
2159    local $~ = $fmt;
2160    eval "write";
2161    select $fh;
2162    $@?0:1;
2163    } # has_format
2164
2165$^ = has_format ("TOP") ? "TOP" : "EMPTY";
2166has_format ("ENTRY") or die "No format defined for ENTRY";
2167foreach my $e ( [ map { [ $_, "Test$_"   ] } 1 .. 7 ],
2168		[ map { [ $_, "${_}tseT" ] } 1 .. 5 ]) {
2169    @E = @$e;
2170    local $~ = "ENTRY";
2171    wryte;
2172    has_format ("EOR") or next;
2173    local $~ = "EOR";
2174    wryte;
2175    }
2176if (has_format ("EOF")) {
2177    local $~ = "EOF";
2178    wryte;
2179    }
2180
2181close STDOUT;
2182
2183# That was test 48.
2184
2185__END__
2186
2187    1 Test1
2188    2 Test2
2189    3 Test3
2190
2191
2192    ----
2193
2194    4 Test4
2195    5 Test5
2196    6 Test6
2197
2198
2199    ----
2200
2201    7 Test7
2202    - -----
2203
2204
2205
2206    ----
2207
2208    1 1tseT
2209    2 2tseT
2210    3 3tseT
2211
2212
2213    ----
2214
2215    4 4tseT
2216    5 5tseT
2217    - -----
2218