This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix fatal bug in bisect-runner.pl for some 5.004 revisions.
[perl5.git] / Porting / bisect-runner.pl
1 #!/usr/bin/perl -w
2 use strict;
3
4 use Getopt::Long qw(:config bundling no_auto_abbrev);
5 use Pod::Usage;
6 use Config;
7 use Carp;
8
9 my @targets
10     = qw(config.sh config.h miniperl lib/Config.pm Fcntl perl test_prep);
11
12 my $cpus;
13 if (open my $fh, '<', '/proc/cpuinfo') {
14     while (<$fh>) {
15         ++$cpus if /^processor\s+:\s+\d+$/;
16     }
17 } elsif (-x '/sbin/sysctl') {
18     $cpus = 1 + $1 if `/sbin/sysctl hw.ncpu` =~ /^hw\.ncpu: (\d+)$/;
19 } elsif (-x '/usr/bin/getconf') {
20     $cpus = 1 + $1 if `/usr/bin/getconf _NPROCESSORS_ONLN` =~ /^(\d+)$/;
21 }
22
23 my %options =
24     (
25      jobs => defined $cpus ? $cpus + 1 : 2,
26      'expect-pass' => 1,
27      clean => 1, # mostly for debugging this
28     );
29
30 my $linux64 = `uname -sm` eq "Linux x86_64\n" ? '64' : '';
31
32 my @paths;
33
34 if ($^O eq 'linux') {
35     # This is the search logic for a multi-arch library layout
36     # added to linux.sh in commits 40f026236b9959b7 and dcffd848632af2c7.
37     my $gcc = -x '/usr/bin/gcc' ? '/usr/bin/gcc' : 'gcc';
38
39     foreach (`$gcc -print-search-dirs`) {
40         next unless /^libraries: =(.*)/;
41         foreach (split ':', $1) {
42             next if m/gcc/;
43             next unless -d $_;
44             s!/$!!;
45             push @paths, $_;
46         }
47     }
48 }
49
50 push @paths, map {$_ . $linux64} qw(/usr/local/lib /lib /usr/lib);
51
52 my %defines =
53     (
54      usedevel => '',
55      optimize => '-g',
56      cc => 'ccache cc',
57      ld => 'cc',
58      ($linux64 ? (libpth => \@paths) : ()),
59     );
60
61 unless(GetOptions(\%options,
62                   'target=s', 'jobs|j=i', 'expect-pass=i',
63                   'expect-fail' => sub { $options{'expect-pass'} = 0; },
64                   'clean!', 'one-liner|e=s', 'match=s', 'force-manifest',
65                   'force-regen', 'test-build', 'check-args', 'A=s@', 'l', 'w',
66                   'usage|help|?',
67                   'D=s@' => sub {
68                       my (undef, $val) = @_;
69                       if ($val =~ /\A([^=]+)=(.*)/s) {
70                           $defines{$1} = length $2 ? $2 : "\0";
71                       } else {
72                           $defines{$val} = '';
73                       }
74                   },
75                   'U=s@' => sub {
76                       $defines{$_[1]} = undef;
77                   },
78                  )) {
79     pod2usage(exitval => 255, verbose => 1);
80 }
81
82 my ($target, $j, $match) = @options{qw(target jobs match)};
83
84 pod2usage(exitval => 255, verbose => 1) if $options{usage};
85 pod2usage(exitval => 255, verbose => 1)
86     unless @ARGV || $match || $options{'test-build'} || defined $options{'one-liner'};
87 pod2usage(exitval => 255, verbose => 1)
88     if !$options{'one-liner'} && ($options{l} || $options{w});
89
90 exit 0 if $options{'check-args'};
91
92 =head1 NAME
93
94 bisect.pl - use git bisect to pinpoint changes
95
96 =head1 SYNOPSIS
97
98     # When did this become an error?
99     .../Porting/bisect.pl -e 'my $a := 2;'
100     # When did this stop being an error?
101     .../Porting/bisect.pl --expect-fail -e '1 // 2'
102     # When did this stop matching?
103     .../Porting/bisect.pl --match '\b(?:PL_)hash_seed_set\b'
104     # When did this start matching?
105     .../Porting/bisect.pl --expect-fail --match '\buseithreads\b'
106     # When did this test program stop working?
107     .../Porting/bisect.pl -- ./perl -Ilib ../test_prog.pl
108     # When did this first become valid syntax?
109     .../Porting/bisect.pl --target=miniperl --end=v5.10.0 \
110          --expect-fail -e 'my $a := 2;'
111     # What was the last revision to build with these options?
112     .../Porting/bisect.pl --test-build -Dd_dosuid
113
114 =head1 DESCRIPTION
115
116 Together F<bisect.pl> and F<bisect-runner.pl> attempt to automate the use
117 of C<git bisect> as much as possible. With one command (and no other files)
118 it's easy to find out
119
120 =over 4
121
122 =item *
123
124 Which commit caused this example code to break?
125
126 =item *
127
128 Which commit caused this example code to start working?
129
130 =item *
131
132 Which commit added the first to match this regex?
133
134 =item *
135
136 Which commit removed the last to match this regex?
137
138 =back
139
140 usually without needing to know which versions of perl to use as start and
141 end revisions.
142
143 By default F<bisect.pl> will process all options, then use the rest of the
144 command line as arguments to list C<system> to run a test case. By default,
145 the test case should pass (exit with 0) on earlier perls, and fail (exit
146 non-zero) on I<blead>. F<bisect.pl> will use F<bisect-runner.pl> to find the
147 earliest stable perl version on which the test case passes, check that it
148 fails on blead, and then use F<bisect-runner.pl> with C<git bisect run> to
149 find the commit which caused the failure.
150
151 Because the test case is the complete argument to C<system>, it is easy to
152 run something other than the F<perl> built, if necessary. If you need to run
153 the perl built, you'll probably need to invoke it as C<./perl -Ilib ...>
154
155 You need a clean checkout to run a bisect, and you can't use the checkout
156 which contains F<Porting/bisect.pl> (because C<git bisect>) will check out
157 a revision before F<Porting/bisect-runner.pl> was added, which
158 C<git bisect run> needs). If your working checkout is called F<perl>, the
159 simplest solution is to make a local clone, and run from that. I<i.e.>:
160
161     cd ..
162     git clone perl perl2
163     cd perl2
164     ../perl/Porting/bisect.pl ...
165
166 By default, F<bisect-runner.pl> will automatically disable the build of
167 L<DB_File> for commits earlier than ccb44e3bf3be2c30, as it's not practical
168 to patch DB_File 1.70 and earlier to build with current Berkeley DB headers.
169 (ccb44e3bf3be2c30 was in September 1999, between 5.005_62 and 5.005_63.)
170 If your F<db.h> is old enough you can override this with C<-Unoextensions>.
171
172 =head1 OPTIONS
173
174 =over 4
175
176 =item *
177
178 --start I<commit-ish>
179
180 Earliest revision to test, as a I<commit-ish> (a tag, commit or anything
181 else C<git> understands as a revision). If not specified, F<bisect.pl> will
182 search stable perl releases from 5.002 to 5.14.0 until it finds one where
183 the test case passes.
184
185 =item *
186
187 --end I<commit-ish>
188
189 Most recent revision to test, as a I<commit-ish>. If not specified, defaults
190 to I<blead>.
191
192 =item *
193
194 --target I<target>
195
196 F<Makefile> target (or equivalent) needed, to run the test case. If specified,
197 this should be one of
198
199 =over 4
200
201 =item *
202
203 I<config.sh>
204
205 Just run F<./Configure>
206
207 =item *
208
209 I<config.h>
210
211 Run the various F<*.SH> files to generate F<Makefile>, F<config.h>, I<etc>.
212
213 =item *
214
215 I<miniperl>
216
217 Build F<miniperl>.
218
219 =item *
220
221 I<lib/Config.pm>
222
223 Use F<miniperl> to build F<lib/Config.pm>
224
225 =item *
226
227 I<Fcntl>
228
229 Build F<lib/auto/Fcntl/Fnctl.so> (strictly, C<.$Config{so}>). As L<Fcntl>
230 is simple XS module present since 5.000, this provides a fast test of
231 whether XS modules can be built. Note, XS modules are built by F<miniperl>,
232 hence this target will not build F<perl>.
233
234 =item *
235
236 I<perl>
237
238 Build F<perl>. This also builds pure-Perl modules in F<cpan>, F<dist> and
239 F<ext>. XS modules (such as L<Fcntl>) are not built.
240
241 =item *
242
243 I<test_prep>
244
245 Build everything needed to run the tests. This is the default if we're
246 running test code, but is time consuming, as it means building all
247 XS modules. For older F<Makefile>s, the previous name of C<test-prep>
248 is automatically substituted. For very old F<Makefile>s, C<make test> is
249 run, as there is no target provided to just get things ready, and for 5.004
250 and earlier the tests run very quickly.
251
252 =back
253
254 =item *
255
256 --one-liner 'code to run'
257
258 =item *
259
260 -e 'code to run'
261
262 Example code to run, just like you'd use with C<perl -e>.
263
264 This prepends C<./perl -Ilib -e 'code to run'> to the test case given,
265 or F<./miniperl> if I<target> is C<miniperl>.
266
267 (Usually you'll use C<-e> instead of providing a test case in the
268 non-option arguments to F<bisect.pl>)
269
270 C<-E> intentionally isn't supported, as it's an error in 5.8.0 and earlier,
271 which interferes with detecting errors in the example code itself.
272
273 =item *
274
275 -l
276
277 Add C<-l> to the command line with C<-e>
278
279 This will automatically append a newline to every output line of your testcase.
280 Note that you can't specify an argument to F<perl>'s C<-l> with this, as it's
281 not feasible to emulate F<perl>'s somewhat quirky switch parsing with
282 L<Getopt::Long>. If you need the full flexibility of C<-l>, you need to write
283 a full test case, instead of using C<bisect.pl>'s C<-e> shortcut.
284
285 =item *
286
287 -w
288
289 Add C<-w> to the command line with C<-e>
290
291 It's not valid to pass C<-l> or C<-w> to C<bisect.pl> unless you are also
292 using C<-e>
293
294 =item *
295
296 --expect-fail
297
298 The test case should fail for the I<start> revision, and pass for the I<end>
299 revision. The bisect run will find the first commit where it passes.
300
301 =item *
302
303 -Dnoextensions=Encode
304
305 =item *
306
307 -Uusedevel
308
309 =item *
310
311 -Accflags=-DNO_MATHOMS
312
313 Arguments to pass to F<Configure>. Repeated C<-A> arguments are passed
314 through as is. C<-D> and C<-U> are processed in order, and override
315 previous settings for the same parameter. F<bisect-runner.pl> emulates
316 C<-Dnoextensions> when F<Configure> itself does not provide it, as it's
317 often very useful to be able to disable some XS extensions.
318
319 =item *
320
321 --jobs I<jobs>
322
323 =item *
324
325 -j I<jobs>
326
327 Number of C<make> jobs to run in parallel. If F</proc/cpuinfo> exists and
328 can be parsed, or F</sbin/sysctl> exists and reports C<hw.ncpu>, or
329 F</usr/bin/getconf> exists and reports C<_NPROCESSORS_ONLN> defaults to 1 +
330 I<number of CPUs>. Otherwise defaults to 2.
331
332 =item *
333
334 --match pattern
335
336 Instead of running a test program to determine I<pass> or I<fail>, pass
337 if the given regex matches, and hence search for the commit that removes
338 the last matching file.
339
340 If no I<target> is specified, the match is against all files in the
341 repository (which is fast). If a I<target> is specified, that target is
342 built, and the match is against only the built files. C<--expect-fail> can
343 be used with C<--match> to search for a commit that adds files that match.
344
345 =item *
346
347 --test-build
348
349 Test that the build completes, without running any test case.
350
351 By default, if the build for the desired I<target> fails to complete,
352 F<bisect-runner.pl> reports a I<skip> back to C<git bisect>, the assumption
353 being that one wants to find a commit which changed state "builds && passes"
354 to "builds && fails". If instead one is interested in which commit broke the
355 build (possibly for particular F<Configure> options), use I<--test-build>
356 to treat a build failure as a failure, not a "skip".
357
358 Often this option isn't as useful as it first seems, because I<any> build
359 failure will be reported to C<git bisect> as a failure, not just the failure
360 that you're interested in. Generally, to debug a particular problem, it's
361 more useful to use a I<target> that builds properly at the point of interest,
362 and then a test case that runs C<make>. For example:
363
364     .../Porting/bisect.pl --start=perl-5.000 --end=perl-5.002 \
365         --expect-fail --force-manifest --target=miniperl make perl
366
367 will find the first revision capable of building L<DynaLoader> and then
368 F<perl>, without becoming confused by revisions where F<miniperl> won't
369 even link.
370
371 =item *
372
373 --force-manifest
374
375 By default, a build will "skip" if any files listed in F<MANIFEST> are not
376 present. Usually this is useful, as it avoids false-failures. However, there
377 are some long ranges of commits where listed files are missing, which can
378 cause a bisect to abort because all that remain are skipped revisions.
379
380 In these cases, particularly if the test case uses F<miniperl> and no modules,
381 it may be more useful to force the build to continue, even if files
382 F<MANIFEST> are missing.
383
384 =item *
385
386 --force-regen
387
388 Run C<make regen_headers> before building F<miniperl>. This may fix a build
389 that otherwise would skip because the generated headers at that revision
390 are stale. It's not the default because it conceals this error in the true
391 state of such revisions.
392
393 =item *
394
395 --expect-pass [0|1]
396
397 C<--expect-pass=0> is equivalent to C<--expect-fail>. I<1> is the default.
398
399 =item *
400
401 --no-clean
402
403 Tell F<bisect-runner.pl> not to clean up after the build. This allows one
404 to use F<bisect-runner.pl> to build the current particular perl revision for
405 interactive testing, or for debugging F<bisect-runner.pl>.
406
407 Passing this to F<bisect.pl> will likely cause the bisect to fail badly.
408
409 =item *
410
411 --validate
412
413 Test that all stable revisions can be built. By default, attempts to build
414 I<blead>, I<v5.14.0> .. I<perl-5.002>. Stops at the first failure, without
415 cleaning the checkout. Use I<--start> to specify the earliest revision to
416 test, I<--end> to specify the most recent. Useful for validating a new
417 OS/CPU/compiler combination. For example
418
419     ../perl/Porting/bisect.pl --validate -le 'print "Hello from $]"'
420
421 If no testcase is specified, the default is to use F<t/TEST> to run
422 F<t/base/*.t>
423
424 =item *
425
426 --check-args
427
428 Validate the options and arguments, and exit silently if they are valid.
429
430 =item *
431
432 --usage
433
434 =item *
435
436 --help
437
438 =item *
439
440 -?
441
442 Display the usage information and exit.
443
444 =back
445
446 =cut
447
448 die "$0: Can't build $target" if defined $target && !grep {@targets} $target;
449
450 $j = "-j$j" if $j =~ /\A\d+\z/;
451
452 # Sadly, however hard we try, I don't think that it will be possible to build
453 # modules in ext/ on x86_64 Linux before commit e1666bf5602ae794 on 1999/12/29,
454 # which updated to MakeMaker 3.7, which changed from using a hard coded ld
455 # in the Makefile to $(LD). On x86_64 Linux the "linker" is gcc.
456
457 sub open_or_die {
458     my $file = shift;
459     my $mode = @_ ? shift : '<';
460     open my $fh, $mode, $file or croak("Can't open $file: $!");
461     ${*$fh{SCALAR}} = $file;
462     return $fh;
463 }
464
465 sub close_or_die {
466     my $fh = shift;
467     return if close $fh;
468     croak("Can't close: $!") unless ref $fh eq 'GLOB';
469     croak("Can't close ${*$fh{SCALAR}}: $!");
470 }
471
472 sub extract_from_file {
473     my ($file, $rx, $default) = @_;
474     my $fh = open_or_die($file);
475     while (<$fh>) {
476         my @got = $_ =~ $rx;
477         return wantarray ? @got : $got[0]
478             if @got;
479     }
480     return $default if defined $default;
481     return;
482 }
483
484 sub edit_file {
485     my ($file, $munger) = @_;
486     local $/;
487     my $fh = open_or_die($file);
488     my $orig = <$fh>;
489     die "Can't read $file: $!" unless defined $orig && close $fh;
490     my $new = $munger->($orig);
491     return if $new eq $orig;
492     $fh = open_or_die($file, '>');
493     print $fh $new or die "Can't print to $file: $!";
494     close_or_die($fh);
495 }
496
497 sub apply_patch {
498     my $patch = shift;
499
500     my ($file) = $patch =~ qr!^--- a/(\S+)\n\+\+\+ b/\1!sm;
501     open my $fh, '|-', 'patch', '-p1' or die "Can't run patch: $!";
502     print $fh $patch;
503     return if close $fh;
504     print STDERR "Patch is <<'EOPATCH'\n${patch}EOPATCH\n";
505     die "Can't patch $file: $?, $!";
506 }
507
508 sub apply_commit {
509     my ($commit, @files) = @_;
510     return unless system "git show $commit @files | patch -p1";
511     die "Can't apply commit $commit to @files" if @files;
512     die "Can't apply commit $commit";
513 }
514
515 sub revert_commit {
516     my ($commit, @files) = @_;
517     return unless system "git show -R $commit @files | patch -p1";
518     die "Can't apply revert $commit from @files" if @files;
519     die "Can't apply revert $commit";
520 }
521
522 sub checkout_file {
523     my ($file, $commit) = @_;
524     $commit ||= 'blead';
525     system "git show $commit:$file > $file </dev/null"
526         and die "Could not extract $file at revision $commit";
527 }
528
529 sub clean {
530     if ($options{clean}) {
531         # Needed, because files that are build products in this checked out
532         # version might be in git in the next desired version.
533         system 'git clean -dxf </dev/null';
534         # Needed, because at some revisions the build alters checked out files.
535         # (eg pod/perlapi.pod). Also undoes any changes to makedepend.SH
536         system 'git reset --hard HEAD </dev/null';
537     }
538 }
539
540 sub skip {
541     my $reason = shift;
542     clean();
543     warn "skipping - $reason";
544     exit 125;
545 }
546
547 sub report_and_exit {
548     my ($ret, $pass, $fail, $desc) = @_;
549
550     clean();
551
552     my $got = ($options{'expect-pass'} ? !$ret : $ret) ? 'good' : 'bad';
553     if ($ret) {
554         print "$got - $fail $desc\n";
555     } else {
556         print "$got - $pass $desc\n";
557     }
558
559     exit($got eq 'bad');
560 }
561
562 sub match_and_exit {
563     my $target = shift;
564     my $matches = 0;
565     my $re = qr/$match/;
566     my @files;
567
568     {
569         local $/ = "\0";
570         @files = defined $target ? `git ls-files -o -z`: `git ls-files -z`;
571         chomp @files;
572     }
573
574     foreach my $file (@files) {
575         my $fh = open_or_die($file);
576         while (<$fh>) {
577             if ($_ =~ $re) {
578                 ++$matches;
579                 if (tr/\t\r\n -~\200-\377//c) {
580                     print "Binary file $file matches\n";
581                 } else {
582                     $_ .= "\n" unless /\n\z/;
583                     print "$file: $_";
584                 }
585             }
586         }
587         close_or_die($fh);
588     }
589     report_and_exit(!$matches,
590                     $matches == 1 ? '1 match for' : "$matches matches for",
591                     'no matches for', $match);
592 }
593
594 # Not going to assume that system perl is yet new enough to have autodie
595 system 'git clean -dxf </dev/null' and die;
596
597 if (!defined $target) {
598     match_and_exit() if $match;
599     $target = 'test_prep';
600 }
601
602 skip('no Configure - is this the //depot/perlext/Compiler branch?')
603     unless -f 'Configure';
604
605 # This changes to PERL_VERSION in 4d8076ea25903dcb in 1999
606 my $major
607     = extract_from_file('patchlevel.h',
608                         qr/^#define\s+(?:PERL_VERSION|PATCHLEVEL)\s+(\d+)\s/,
609                         0);
610
611 patch_Configure();
612 patch_hints();
613
614 # if Encode is not needed for the test, you can speed up the bisect by
615 # excluding it from the runs with -Dnoextensions=Encode
616 # ccache is an easy win. Remove it if it causes problems.
617 # Commit 1cfa4ec74d4933da adds ignore_versioned_solibs to Configure, and sets it
618 # to true in hints/linux.sh
619 # On dromedary, from that point on, Configure (by default) fails to find any
620 # libraries, because it scans /usr/local/lib /lib /usr/lib, which only contain
621 # versioned libraries. Without -lm, the build fails.
622 # Telling /usr/local/lib64 /lib64 /usr/lib64 works from that commit onwards,
623 # until commit faae14e6e968e1c0 adds it to the hints.
624 # However, prior to 1cfa4ec74d4933da telling Configure the truth doesn't work,
625 # because it will spot versioned libraries, pass them to the compiler, and then
626 # bail out pretty early on. Configure won't let us override libswanted, but it
627 # will let us override the entire libs list.
628
629 unless (extract_from_file('Configure', 'ignore_versioned_solibs')) {
630     # Before 1cfa4ec74d4933da, so force the libs list.
631
632     my @libs;
633     # This is the current libswanted list from Configure, less the libs removed
634     # by current hints/linux.sh
635     foreach my $lib (qw(sfio socket inet nsl nm ndbm gdbm dbm db malloc dl dld
636                         ld sun m crypt sec util c cposix posix ucb BSD)) {
637         foreach my $dir (@paths) {
638             next unless -f "$dir/lib$lib.so";
639             push @libs, "-l$lib";
640             last;
641         }
642     }
643     $defines{libs} = \@libs unless exists $defines{libs};
644 }
645
646 $defines{usenm} = undef
647     if $major < 2 && !exists $defines{usenm};
648
649 my ($missing, $created_dirs);
650 ($missing, $created_dirs) = force_manifest()
651     if $options{'force-manifest'};
652
653 my @ARGS = '-dEs';
654 foreach my $key (sort keys %defines) {
655     my $val = $defines{$key};
656     if (ref $val) {
657         push @ARGS, "-D$key=@$val";
658     } elsif (!defined $val) {
659         push @ARGS, "-U$key";
660     } elsif (!length $val) {
661         push @ARGS, "-D$key";
662     } else {
663         $val = "" if $val eq "\0";
664         push @ARGS, "-D$key=$val";
665     }
666 }
667 push @ARGS, map {"-A$_"} @{$options{A}};
668
669 # </dev/null because it seems that some earlier versions of Configure can
670 # call commands in a way that now has them reading from stdin (and hanging)
671 my $pid = fork;
672 die "Can't fork: $!" unless defined $pid;
673 if (!$pid) {
674     open STDIN, '<', '/dev/null';
675     # If a file in MANIFEST is missing, Configure asks if you want to
676     # continue (the default being 'n'). With stdin closed or /dev/null,
677     # it exits immediately and the check for config.sh below will skip.
678     exec './Configure', @ARGS;
679     die "Failed to start Configure: $!";
680 }
681 waitpid $pid, 0
682     or die "wait for Configure, pid $pid failed: $!";
683
684 patch_SH();
685
686 if (-f 'config.sh') {
687     # Emulate noextensions if Configure doesn't support it.
688     fake_noextensions()
689         if $major < 10 && $defines{noextensions};
690     system './Configure -S </dev/null' and die;
691 }
692
693 if ($target =~ /config\.s?h/) {
694     match_and_exit($target) if $match && -f $target;
695     report_and_exit(!-f $target, 'could build', 'could not build', $target)
696         if $options{'test-build'};
697
698     my $ret = system @ARGV;
699     report_and_exit($ret, 'zero exit from', 'non-zero exit from', "@ARGV");
700 } elsif (!-f 'config.sh') {
701     # Skip if something went wrong with Configure
702
703     skip('could not build config.sh');
704 }
705
706 force_manifest_cleanup($missing, $created_dirs)
707         if $missing;
708
709 if($options{'force-regen'}
710    && extract_from_file('Makefile', qr/\bregen_headers\b/)) {
711     # regen_headers was added in e50aee73b3d4c555, patch.1m for perl5.001
712     # It's not worth faking it for earlier revisions.
713     system "make regen_headers </dev/null"
714         and die;
715 }
716
717 patch_C();
718 patch_ext();
719
720 # Parallel build for miniperl is safe
721 system "make $j miniperl </dev/null";
722
723 my $expected = $target =~ /^test/ ? 't/perl'
724     : $target eq 'Fcntl' ? "lib/auto/Fcntl/Fcntl.$Config{so}"
725     : $target;
726 my $real_target = $target eq 'Fcntl' ? $expected : $target;
727
728 if ($target ne 'miniperl') {
729     # Nearly all parallel build issues fixed by 5.10.0. Untrustworthy before that.
730     $j = '' if $major < 10;
731
732     if ($real_target eq 'test_prep') {
733         if ($major < 8) {
734             # test-prep was added in 5.004_01, 3e3baf6d63945cb6.
735             # renamed to test_prep in 2001 in 5fe84fd29acaf55c.
736             # earlier than that, just make test. It will be fast enough.
737             $real_target = extract_from_file('Makefile.SH',
738                                              qr/^(test[-_]prep):/,
739                                              'test');
740         }
741     }
742
743     system "make $j $real_target </dev/null";
744 }
745
746 my $missing_target = $expected =~ /perl$/ ? !-x $expected : !-r $expected;
747
748 if ($options{'test-build'}) {
749     report_and_exit($missing_target, 'could build', 'could not build',
750                     $real_target);
751 } elsif ($missing_target) {
752     skip("could not build $real_target");
753 }
754
755 match_and_exit($real_target) if $match;
756
757 if (defined $options{'one-liner'}) {
758     my $exe = $target =~ /^(?:perl$|test)/ ? 'perl' : 'miniperl';
759     unshift @ARGV, '-e', $options{'one-liner'};
760     unshift @ARGV, '-l' if $options{l};
761     unshift @ARGV, '-w' if $options{w};
762     unshift @ARGV, "./$exe", '-Ilib';
763 }
764
765 # This is what we came here to run:
766
767 if (exists $Config{ldlibpthname}) {
768     require Cwd;
769     my $varname = $Config{ldlibpthname};
770     my $cwd = Cwd::getcwd();
771     if (defined $ENV{$varname}) {
772         $ENV{$varname} = $cwd . $Config{path_sep} . $ENV{$varname};
773     } else {
774         $ENV{$varname} = $cwd;
775     }
776 }
777
778 my $ret = system @ARGV;
779
780 report_and_exit($ret, 'zero exit from', 'non-zero exit from', "@ARGV");
781
782 ############################################################################
783 #
784 # Patching, editing and faking routines only below here.
785 #
786 ############################################################################
787
788 sub fake_noextensions {
789     edit_file('config.sh', sub {
790                   my @lines = split /\n/, shift;
791                   my @ext = split /\s+/, $defines{noextensions};
792                   foreach (@lines) {
793                       next unless /^extensions=/ || /^dynamic_ext/;
794                       foreach my $ext (@ext) {
795                           s/\b$ext( )?\b/$1/;
796                       }
797                   }
798                   return join "\n", @lines;
799               });
800 }
801
802 sub force_manifest {
803     my (@missing, @created_dirs);
804     my $fh = open_or_die('MANIFEST');
805     while (<$fh>) {
806         next unless /^(\S+)/;
807         # -d is special case needed (at least) between 27332437a2ed1941 and
808         # bf3d9ec563d25054^ inclusive, as manifest contains ext/Thread/Thread
809         push @missing, $1
810             unless -f $1 || -d $1;
811     }
812     close_or_die($fh);
813
814     foreach my $pathname (@missing) {
815         my @parts = split '/', $pathname;
816         my $leaf = pop @parts;
817         my $path = '.';
818         while (@parts) {
819             $path .= '/' . shift @parts;
820             next if -d $path;
821             mkdir $path, 0700 or die "Can't create $path: $!";
822             unshift @created_dirs, $path;
823         }
824         $fh = open_or_die($pathname, '>');
825         close_or_die($fh);
826         chmod 0, $pathname or die "Can't chmod 0 $pathname: $!";
827     }
828     return \@missing, \@created_dirs;
829 }
830
831 sub force_manifest_cleanup {
832     my ($missing, $created_dirs) = @_;
833     # This is probably way too paranoid:
834     my @errors;
835     require Fcntl;
836     foreach my $file (@$missing) {
837         my (undef, undef, $mode, undef, undef, undef, undef, $size)
838             = stat $file;
839         if (!defined $mode) {
840             push @errors, "Added file $file has been deleted by Configure";
841             next;
842         }
843         if (Fcntl::S_IMODE($mode) != 0) {
844             push @errors,
845                 sprintf 'Added file %s had mode changed by Configure to %03o',
846                     $file, $mode;
847         }
848         if ($size != 0) {
849             push @errors,
850                 "Added file $file had sized changed by Configure to $size";
851         }
852         unlink $file or die "Can't unlink $file: $!";
853     }
854     foreach my $dir (@$created_dirs) {
855         rmdir $dir or die "Can't rmdir $dir: $!";
856     }
857     skip("@errors")
858         if @errors;
859 }
860
861 sub patch_Configure {
862     if ($major < 1) {
863         if (extract_from_file('Configure',
864                               qr/^\t\t\*=\*\) echo "\$1" >> \$optdef;;$/)) {
865             # This is "        Spaces now allowed in -D command line options.",
866             # part of commit ecfc54246c2a6f42
867             apply_patch(<<'EOPATCH');
868 diff --git a/Configure b/Configure
869 index 3d3b38d..78ffe16 100755
870 --- a/Configure
871 +++ b/Configure
872 @@ -652,7 +777,8 @@ while test $# -gt 0; do
873                         echo "$me: use '-U symbol=', not '-D symbol='." >&2
874                         echo "$me: ignoring -D $1" >&2
875                         ;;
876 -               *=*) echo "$1" >> $optdef;;
877 +               *=*) echo "$1" | \
878 +                               sed -e "s/'/'\"'\"'/g" -e "s/=\(.*\)/='\1'/" >> $optdef;;
879                 *) echo "$1='define'" >> $optdef;;
880                 esac
881                 shift
882 EOPATCH
883         }
884
885         if (extract_from_file('Configure', qr/^if \$contains 'd_namlen' \$xinc\b/)) {
886             # Configure's original simple "grep" for d_namlen falls foul of the
887             # approach taken by the glibc headers:
888             # #ifdef _DIRENT_HAVE_D_NAMLEN
889             # # define _D_EXACT_NAMLEN(d) ((d)->d_namlen)
890             #
891             # where _DIRENT_HAVE_D_NAMLEN is not defined on Linux.
892             # This is also part of commit ecfc54246c2a6f42
893             apply_patch(<<'EOPATCH');
894 diff --git a/Configure b/Configure
895 index 3d3b38d..78ffe16 100755
896 --- a/Configure
897 +++ b/Configure
898 @@ -3935,7 +4045,8 @@ $rm -f try.c
899  
900  : see if the directory entry stores field length
901  echo " "
902 -if $contains 'd_namlen' $xinc >/dev/null 2>&1; then
903 +$cppstdin $cppflags $cppminus < "$xinc" > try.c
904 +if $contains 'd_namlen' try.c >/dev/null 2>&1; then
905         echo "Good, your directory entry keeps length information in d_namlen." >&4
906         val="$define"
907  else
908 EOPATCH
909         }
910     }
911
912     if ($major < 2
913         && !extract_from_file('Configure',
914                               qr/Try to guess additional flags to pick up local libraries/)) {
915         my $mips = extract_from_file('Configure',
916                                      qr!(''\) if (?:\./)?mips; then)!);
917         # This is part of perl-5.001n. It's needed, to add -L/usr/local/lib to
918         # theld flags if libraries are found there. It shifts the code to set up
919         # libpth earlier, and then adds the code to add libpth entries to
920         # ldflags
921         # mips was changed to ./mips in ecfc54246c2a6f42, perl5.000 patch.0g
922         apply_patch(sprintf <<'EOPATCH', $mips);
923 diff --git a/Configure b/Configure
924 index 53649d5..0635a6e 100755
925 --- a/Configure
926 +++ b/Configure
927 @@ -2749,6 +2749,52 @@ EOM
928         ;;
929  esac
930  
931 +: Set private lib path
932 +case "$plibpth" in
933 +'') if ./mips; then
934 +               plibpth="$incpath/usr/lib /usr/local/lib /usr/ccs/lib"
935 +       fi;;
936 +esac
937 +case "$libpth" in
938 +' ') dlist='';;
939 +'') dlist="$plibpth $glibpth";;
940 +*) dlist="$libpth";;
941 +esac
942 +
943 +: Now check and see which directories actually exist, avoiding duplicates
944 +libpth=''
945 +for xxx in $dlist
946 +do
947 +    if $test -d $xxx; then
948 +               case " $libpth " in
949 +               *" $xxx "*) ;;
950 +               *) libpth="$libpth $xxx";;
951 +               esac
952 +    fi
953 +done
954 +$cat <<'EOM'
955 +
956 +Some systems have incompatible or broken versions of libraries.  Among
957 +the directories listed in the question below, please remove any you
958 +know not to be holding relevant libraries, and add any that are needed.
959 +Say "none" for none.
960 +
961 +EOM
962 +case "$libpth" in
963 +'') dflt='none';;
964 +*)
965 +       set X $libpth
966 +       shift
967 +       dflt=${1+"$@"}
968 +       ;;
969 +esac
970 +rp="Directories to use for library searches?"
971 +. ./myread
972 +case "$ans" in
973 +none) libpth=' ';;
974 +*) libpth="$ans";;
975 +esac
976 +
977  : flags used in final linking phase
978  case "$ldflags" in
979  '') if ./venix; then
980 @@ -2765,6 +2811,23 @@ case "$ldflags" in
981         ;;
982  *) dflt="$ldflags";;
983  esac
984 +
985 +: Possible local library directories to search.
986 +loclibpth="/usr/local/lib /opt/local/lib /usr/gnu/lib"
987 +loclibpth="$loclibpth /opt/gnu/lib /usr/GNU/lib /opt/GNU/lib"
988 +
989 +: Try to guess additional flags to pick up local libraries.
990 +for thislibdir in $libpth; do
991 +       case " $loclibpth " in
992 +       *" $thislibdir "*)
993 +               case "$dflt " in 
994 +               "-L$thislibdir ") ;;
995 +               *)  dflt="$dflt -L$thislibdir" ;;
996 +               esac
997 +               ;;
998 +       esac
999 +done
1000 +
1001  echo " "
1002  rp="Any additional ld flags (NOT including libraries)?"
1003  . ./myread
1004 @@ -2828,52 +2891,6 @@ n) echo "OK, that should do.";;
1005  esac
1006  $rm -f try try.* core
1007  
1008 -: Set private lib path
1009 -case "$plibpth" in
1010 -%s
1011 -               plibpth="$incpath/usr/lib /usr/local/lib /usr/ccs/lib"
1012 -       fi;;
1013 -esac
1014 -case "$libpth" in
1015 -' ') dlist='';;
1016 -'') dlist="$plibpth $glibpth";;
1017 -*) dlist="$libpth";;
1018 -esac
1019 -
1020 -: Now check and see which directories actually exist, avoiding duplicates
1021 -libpth=''
1022 -for xxx in $dlist
1023 -do
1024 -    if $test -d $xxx; then
1025 -               case " $libpth " in
1026 -               *" $xxx "*) ;;
1027 -               *) libpth="$libpth $xxx";;
1028 -               esac
1029 -    fi
1030 -done
1031 -$cat <<'EOM'
1032 -
1033 -Some systems have incompatible or broken versions of libraries.  Among
1034 -the directories listed in the question below, please remove any you
1035 -know not to be holding relevant libraries, and add any that are needed.
1036 -Say "none" for none.
1037 -
1038 -EOM
1039 -case "$libpth" in
1040 -'') dflt='none';;
1041 -*)
1042 -       set X $libpth
1043 -       shift
1044 -       dflt=${1+"$@"}
1045 -       ;;
1046 -esac
1047 -rp="Directories to use for library searches?"
1048 -. ./myread
1049 -case "$ans" in
1050 -none) libpth=' ';;
1051 -*) libpth="$ans";;
1052 -esac
1053 -
1054  : compute shared library extension
1055  case "$so" in
1056  '')
1057 EOPATCH
1058     }
1059
1060     if ($major < 5 && extract_from_file('Configure',
1061                                         qr!if \$cc \$ccflags try\.c -o try >/dev/null 2>&1; then!)) {
1062         # Analogous to the more general fix of dfe9444ca7881e71
1063         # Without this flags such as -m64 may not be passed to this compile,
1064         # which results in a byteorder of '1234' instead of '12345678', which
1065         # can then cause crashes.
1066
1067         if (extract_from_file('Configure', qr/xxx_prompt=y/)) {
1068             # 8e07c86ebc651fe9 or later
1069             # ("This is my patch  patch.1n  for perl5.001.")
1070             apply_patch(<<'EOPATCH');
1071 diff --git a/Configure b/Configure
1072 index 62249dd..c5c384e 100755
1073 --- a/Configure
1074 +++ b/Configure
1075 @@ -8247,7 +8247,7 @@ main()
1076  }
1077  EOCP
1078         xxx_prompt=y
1079 -       if $cc $ccflags try.c -o try >/dev/null 2>&1 && ./try > /dev/null; then
1080 +       if $cc $ccflags $ldflags try.c -o try >/dev/null 2>&1 && ./try > /dev/null; then
1081                 dflt=`./try`
1082                 case "$dflt" in
1083                 [1-4][1-4][1-4][1-4]|12345678|87654321)
1084 EOPATCH
1085         } else {
1086             apply_patch(<<'EOPATCH');
1087 diff --git a/Configure b/Configure
1088 index 53649d5..f1cd64a 100755
1089 --- a/Configure
1090 +++ b/Configure
1091 @@ -6362,7 +6362,7 @@ main()
1092         printf("\n");
1093  }
1094  EOCP
1095 -       if $cc $ccflags try.c -o try >/dev/null 2>&1 ; then
1096 +       if $cc $ccflags $ldflags try.c -o try >/dev/null 2>&1 ; then
1097                 dflt=`./try`
1098                 case "$dflt" in
1099                 ????|????????) echo "(The test program ran ok.)";;
1100 EOPATCH
1101         }
1102     }
1103
1104     if ($major < 6 && !extract_from_file('Configure',
1105                                          qr!^\t-A\)$!)) {
1106         # This adds the -A option to Configure, which is incredibly useful
1107         # Effectively this is commits 02e93a22d20fc9a5, 5f83a3e9d818c3ad,
1108         # bde6b06b2c493fef, f7c3111703e46e0c and 2 lines of trailing whitespace
1109         # removed by 613d6c3e99b9decc, but applied at slightly different
1110         # locations to ensure a clean patch back to 5.000
1111         # Note, if considering patching to the intermediate revisions to fix
1112         # bugs in -A handling, f7c3111703e46e0c is from 2002, and hence
1113         # $major == 8
1114
1115         # To add to the fun, early patches add -K and -O options, and it's not
1116         # trivial to get patch to put the C<. ./posthint.sh> in the right place
1117         edit_file('Configure', sub {
1118                       my $code = shift;
1119                       $code =~ s/(optstr = ")([^"]+";\s*# getopt-style specification)/$1A:$2/
1120                           or die "Substitution failed";
1121                       $code =~ s!^(: who configured the system)!
1122 touch posthint.sh
1123 . ./posthint.sh
1124
1125 $1!ms
1126                           or die "Substitution failed";
1127                       return $code;
1128                   });
1129         apply_patch(<<'EOPATCH');
1130 diff --git a/Configure b/Configure
1131 index 4b55fa6..60c3c64 100755
1132 --- a/Configure
1133 +++ b/Configure
1134 @@ -1150,6 +1150,7 @@ set X `for arg in "$@"; do echo "X$arg"; done |
1135  eval "set $*"
1136  shift
1137  rm -f options.awk
1138 +rm -f posthint.sh
1139  
1140  : set up default values
1141  fastread=''
1142 @@ -1172,6 +1173,56 @@ while test $# -gt 0; do
1143         case "$1" in
1144         -d) shift; fastread=yes;;
1145         -e) shift; alldone=cont;;
1146 +       -A)
1147 +           shift
1148 +           xxx=''
1149 +           yyy="$1"
1150 +           zzz=''
1151 +           uuu=undef
1152 +           case "$yyy" in
1153 +            *=*) zzz=`echo "$yyy"|sed 's!=.*!!'`
1154 +                 case "$zzz" in
1155 +                 *:*) zzz='' ;;
1156 +                 *)   xxx=append
1157 +                      zzz=" "`echo "$yyy"|sed 's!^[^=]*=!!'`
1158 +                      yyy=`echo "$yyy"|sed 's!=.*!!'` ;;
1159 +                 esac
1160 +                 ;;
1161 +            esac
1162 +            case "$xxx" in
1163 +            '')  case "$yyy" in
1164 +                 *:*) xxx=`echo "$yyy"|sed 's!:.*!!'`
1165 +                      yyy=`echo "$yyy"|sed 's!^[^:]*:!!'`
1166 +                      zzz=`echo "$yyy"|sed 's!^[^=]*=!!'`
1167 +                      yyy=`echo "$yyy"|sed 's!=.*!!'` ;;
1168 +                 *)   xxx=`echo "$yyy"|sed 's!:.*!!'`
1169 +                      yyy=`echo "$yyy"|sed 's!^[^:]*:!!'` ;;
1170 +                 esac
1171 +                 ;;
1172 +            esac
1173 +           case "$xxx" in
1174 +           append)
1175 +               echo "$yyy=\"\${$yyy}$zzz\""    >> posthint.sh ;;
1176 +           clear)
1177 +               echo "$yyy=''"                  >> posthint.sh ;;
1178 +           define)
1179 +               case "$zzz" in
1180 +               '') zzz=define ;;
1181 +               esac
1182 +               echo "$yyy='$zzz'"              >> posthint.sh ;;
1183 +           eval)
1184 +               echo "eval \"$yyy=$zzz\""       >> posthint.sh ;;
1185 +           prepend)
1186 +               echo "$yyy=\"$zzz\${$yyy}\""    >> posthint.sh ;;
1187 +           undef)
1188 +               case "$zzz" in
1189 +               '') zzz="$uuu" ;;
1190 +               esac
1191 +               echo "$yyy=$zzz"                >> posthint.sh ;;
1192 +            *)  echo "$me: unknown -A command '$xxx', ignoring -A $1" >&2 ;;
1193 +           esac
1194 +           shift
1195 +           ;;
1196         -f)
1197                 shift
1198                 cd ..
1199 EOPATCH
1200     }
1201
1202     if ($major < 8 && !extract_from_file('Configure',
1203                                          qr/^\t\tif test ! -t 0; then$/)) {
1204         # Before dfe9444ca7881e71, Configure would refuse to run if stdin was
1205         # not a tty. With that commit, the tty requirement was dropped for -de
1206         # and -dE
1207         # Commit aaeb8e512e8e9e14 dropped the tty requirement for -S
1208         # For those older versions, it's probably easiest if we simply remove
1209         # the sanity test.
1210         edit_file('Configure', sub {
1211                       my $code = shift;
1212                       $code =~ s/test ! -t 0/test Perl = rules/;
1213                       return $code;
1214                   });
1215     }
1216
1217     if ($major == 8 || $major == 9) {
1218         # Fix symbol detection to that of commit 373dfab3839ca168 if it's any
1219         # intermediate version 5129fff43c4fe08c or later, as the intermediate
1220         # versions don't work correctly on (at least) Sparc Linux.
1221         # 5129fff43c4fe08c adds the first mention of mistrustnm.
1222         # 373dfab3839ca168 removes the last mention of lc=""
1223         edit_file('Configure', sub {
1224                       my $code = shift;
1225                       return $code
1226                           if $code !~ /\btc="";/; # 373dfab3839ca168 or later
1227                       return $code
1228                           if $code !~ /\bmistrustnm\b/; # before 5129fff43c4fe08c
1229                       my $fixed = <<'EOC';
1230
1231 : is a C symbol defined?
1232 csym='tlook=$1;
1233 case "$3" in
1234 -v) tf=libc.tmp; tdc="";;
1235 -a) tf=libc.tmp; tdc="[]";;
1236 *) tlook="^$1\$"; tf=libc.list; tdc="()";;
1237 esac;
1238 tx=yes;
1239 case "$reuseval-$4" in
1240 true-) ;;
1241 true-*) tx=no; eval "tval=\$$4"; case "$tval" in "") tx=yes;; esac;;
1242 esac;
1243 case "$tx" in
1244 yes)
1245         tval=false;
1246         if $test "$runnm" = true; then
1247                 if $contains $tlook $tf >/dev/null 2>&1; then
1248                         tval=true;
1249                 elif $test "$mistrustnm" = compile -o "$mistrustnm" = run; then
1250                         echo "void *(*(p()))$tdc { extern void *$1$tdc; return &$1; } int main() { if(p()) return(0); else return(1); }"> try.c;
1251                         $cc -o try $optimize $ccflags $ldflags try.c >/dev/null 2>&1 $libs && tval=true;
1252                         $test "$mistrustnm" = run -a -x try && { $run ./try$_exe >/dev/null 2>&1 || tval=false; };
1253                         $rm -f try$_exe try.c core core.* try.core;
1254                 fi;
1255         else
1256                 echo "void *(*(p()))$tdc { extern void *$1$tdc; return &$1; } int main() { if(p()) return(0); else return(1); }"> try.c;
1257                 $cc -o try $optimize $ccflags $ldflags try.c $libs >/dev/null 2>&1 && tval=true;
1258                 $rm -f try$_exe try.c;
1259         fi;
1260         ;;
1261 *)
1262         case "$tval" in
1263         $define) tval=true;;
1264         *) tval=false;;
1265         esac;
1266         ;;
1267 esac;
1268 eval "$2=$tval"'
1269
1270 EOC
1271                       $code =~ s/\n: is a C symbol defined\?\n.*?\neval "\$2=\$tval"'\n\n/$fixed/sm
1272                           or die "substitution failed";
1273                       return $code;
1274                   });
1275     }
1276
1277     if ($major < 10
1278         && extract_from_file('Configure', qr/^set malloc\.h i_malloc$/)) {
1279         # This is commit 01d07975f7ef0e7d, trimmed, with $compile inlined as
1280         # prior to bd9b35c97ad661cc Configure had the malloc.h test before the
1281         # definition of $compile.
1282         apply_patch(<<'EOPATCH');
1283 diff --git a/Configure b/Configure
1284 index 3d2e8b9..6ce7766 100755
1285 --- a/Configure
1286 +++ b/Configure
1287 @@ -6743,5 +6743,22 @@ set d_dosuid
1288  
1289  : see if this is a malloc.h system
1290 -set malloc.h i_malloc
1291 -eval $inhdr
1292 +: we want a real compile instead of Inhdr because some systems have a
1293 +: malloc.h that just gives a compile error saying to use stdlib.h instead
1294 +echo " "
1295 +$cat >try.c <<EOCP
1296 +#include <stdlib.h>
1297 +#include <malloc.h>
1298 +int main () { return 0; }
1299 +EOCP
1300 +set try
1301 +if $cc $optimize $ccflags $ldflags -o try $* try.c $libs > /dev/null 2>&1; then
1302 +    echo "<malloc.h> found." >&4
1303 +    val="$define"
1304 +else
1305 +    echo "<malloc.h> NOT found." >&4
1306 +    val="$undef"
1307 +fi
1308 +$rm -f try.c try
1309 +set i_malloc
1310 +eval $setvar
1311  
1312 EOPATCH
1313     }
1314 }
1315
1316 sub patch_hints {
1317     if ($^O eq 'freebsd') {
1318         # There are rather too many version-specific FreeBSD hints fixes to
1319         # patch individually. Also, more than once the FreeBSD hints file has
1320         # been written in what turned out to be a rather non-future-proof style,
1321         # with case statements treating the most recent version as the
1322         # exception, instead of treating previous versions' behaviour explicitly
1323         # and changing the default to cater for the current behaviour. (As
1324         # strangely, future versions inherit the current behaviour.)
1325         checkout_file('hints/freebsd.sh');
1326     } elsif ($^O eq 'darwin') {
1327         if ($major < 8) {
1328             # We can't build on darwin without some of the data in the hints
1329             # file. Probably less surprising to use the earliest version of
1330             # hints/darwin.sh and then edit in place just below, than use
1331             # blead's version, as that would create a discontinuity at
1332             # f556e5b971932902 - before it, hints bugs would be "fixed", after
1333             # it they'd resurface. This way, we should give the illusion of
1334             # monotonic bug fixing.
1335             my $faking_it;
1336             if (!-f 'hints/darwin.sh') {
1337                 checkout_file('hints/darwin.sh', 'f556e5b971932902');
1338                 ++$faking_it;
1339             }
1340
1341             edit_file('hints/darwin.sh', sub {
1342                       my $code = shift;
1343                       # Part of commit 8f4f83badb7d1ba9, which mostly undoes
1344                       # commit 0511a818910f476c.
1345                       $code =~ s/^cppflags='-traditional-cpp';$/cppflags="\${cppflags} -no-cpp-precomp"/m;
1346                       # commit 14c11978e9b52e08/803bb6cc74d36a3f
1347                       # Without this, code in libperl.bundle links against op.o
1348                       # in preference to opmini.o on the linker command line,
1349                       # and hence miniperl tries to use File::Glob instead of
1350                       # csh
1351                       $code =~ s/^(lddlflags=)/ldflags="\${ldflags} -flat_namespace"\n$1/m;
1352                       # f556e5b971932902 also patches Makefile.SH with some
1353                       # special case code to deal with useshrplib for darwin.
1354                       # Given that post 5.8.0 the darwin hints default was
1355                       # changed to false, and it would be very complex to splice
1356                       # in that code in various versions of Makefile.SH back
1357                       # to 5.002, lets just turn it off.
1358                       $code =~ s/^useshrplib='true'/useshrplib='false'/m
1359                           if $faking_it;
1360                       return $code;
1361                   });
1362         }
1363     } elsif ($^O eq 'netbsd') {
1364         if ($major < 6) {
1365             # These are part of commit 099685bc64c7dbce
1366             edit_file('hints/netbsd.sh', sub {
1367                           my $code = shift;
1368                           my $fixed = <<'EOC';
1369 case "$osvers" in
1370 0.9|0.8*)
1371         usedl="$undef"
1372         ;;
1373 *)
1374         if [ -f /usr/libexec/ld.elf_so ]; then
1375                 d_dlopen=$define
1376                 d_dlerror=$define
1377                 ccdlflags="-Wl,-E -Wl,-R${PREFIX}/lib $ccdlflags"
1378                 cccdlflags="-DPIC -fPIC $cccdlflags"
1379                 lddlflags="--whole-archive -shared $lddlflags"
1380         elif [ "`uname -m`" = "pmax" ]; then
1381 # NetBSD 1.3 and 1.3.1 on pmax shipped an `old' ld.so, which will not work.
1382                 d_dlopen=$undef
1383         elif [ -f /usr/libexec/ld.so ]; then
1384                 d_dlopen=$define
1385                 d_dlerror=$define
1386                 ccdlflags="-Wl,-R${PREFIX}/lib $ccdlflags"
1387 # we use -fPIC here because -fpic is *NOT* enough for some of the
1388 # extensions like Tk on some netbsd platforms (the sparc is one)
1389                 cccdlflags="-DPIC -fPIC $cccdlflags"
1390                 lddlflags="-Bforcearchive -Bshareable $lddlflags"
1391         else
1392                 d_dlopen=$undef
1393         fi
1394         ;;
1395 esac
1396 EOC
1397                           $code =~ s/^case "\$osvers" in\n0\.9\|0\.8.*?^esac\n/$fixed/ms;
1398                           return $code;
1399                       });
1400         }
1401     } elsif ($^O eq 'openbsd') {
1402         if ($major < 8) {
1403             checkout_file('hints/openbsd.sh', '43051805d53a3e4c')
1404                 unless -f 'hints/openbsd.sh';
1405             my $which = extract_from_file('hints/openbsd.sh',
1406                                           qr/# from (2\.8|3\.1) onwards/,
1407                                           '');
1408             if ($which eq '') {
1409                 my $was = extract_from_file('hints/openbsd.sh',
1410                                             qr/(lddlflags="(?:-Bforcearchive )?-Bshareable)/);
1411                 # This is commit 154d43cbcf57271c and parts of 5c75dbfa77b0949c
1412                 # and 29b5585702e5e025
1413                 apply_patch(sprintf <<'EOPATCH', $was);
1414 diff --git a/hints/openbsd.sh b/hints/openbsd.sh
1415 index a7d8bf2..5b79709 100644
1416 --- a/hints/openbsd.sh
1417 +++ b/hints/openbsd.sh
1418 @@ -37,7 +37,25 @@ OpenBSD.alpha|OpenBSD.mips|OpenBSD.powerpc|OpenBSD.vax)
1419         # we use -fPIC here because -fpic is *NOT* enough for some of the
1420         # extensions like Tk on some OpenBSD platforms (ie: sparc)
1421         cccdlflags="-DPIC -fPIC $cccdlflags"
1422 -       %s $lddlflags"
1423 +       case "$osvers" in
1424 +       [01].*|2.[0-7]|2.[0-7].*)
1425 +               lddlflags="-Bshareable $lddlflags"
1426 +               ;;
1427 +       2.[8-9]|3.0)
1428 +               ld=${cc:-cc}
1429 +               lddlflags="-shared -fPIC $lddlflags"
1430 +               ;;
1431 +       *) # from 3.1 onwards
1432 +               ld=${cc:-cc}
1433 +               lddlflags="-shared -fPIC $lddlflags"
1434 +               libswanted=`echo $libswanted | sed 's/ dl / /'`
1435 +               ;;
1436 +       esac
1437 +
1438 +       # We need to force ld to export symbols on ELF platforms.
1439 +       # Without this, dlopen() is crippled.
1440 +       ELF=`${cc:-cc} -dM -E - </dev/null | grep __ELF__`
1441 +       test -n "$ELF" && ldflags="-Wl,-E $ldflags"
1442         ;;
1443  esac
1444  
1445 EOPATCH
1446             } elsif ($which eq '2.8') {
1447                 # This is parts of 5c75dbfa77b0949c and 29b5585702e5e025, and
1448                 # possibly eb9cd59d45ad2908
1449                 my $was = extract_from_file('hints/openbsd.sh',
1450                                             qr/lddlflags="(-shared(?: -fPIC)?) \$lddlflags"/);
1451
1452                 apply_patch(sprintf <<'EOPATCH', $was);
1453 --- a/hints/openbsd.sh  2011-10-21 17:25:20.000000000 +0200
1454 +++ b/hints/openbsd.sh  2011-10-21 16:58:43.000000000 +0200
1455 @@ -44,11 +44,21 @@
1456         [01].*|2.[0-7]|2.[0-7].*)
1457                 lddlflags="-Bshareable $lddlflags"
1458                 ;;
1459 -       *) # from 2.8 onwards
1460 +       2.[8-9]|3.0)
1461                 ld=${cc:-cc}
1462 -               lddlflags="%s $lddlflags"
1463 +               lddlflags="-shared -fPIC $lddlflags"
1464 +               ;;
1465 +       *) # from 3.1 onwards
1466 +               ld=${cc:-cc}
1467 +               lddlflags="-shared -fPIC $lddlflags"
1468 +               libswanted=`echo $libswanted | sed 's/ dl / /'`
1469                 ;;
1470         esac
1471 +
1472 +       # We need to force ld to export symbols on ELF platforms.
1473 +       # Without this, dlopen() is crippled.
1474 +       ELF=`${cc:-cc} -dM -E - </dev/null | grep __ELF__`
1475 +       test -n "$ELF" && ldflags="-Wl,-E $ldflags"
1476         ;;
1477  esac
1478  
1479 EOPATCH
1480             } elsif ($which eq '3.1'
1481                      && !extract_from_file('hints/openbsd.sh',
1482                                            qr/We need to force ld to export symbols on ELF platforms/)) {
1483                 # This is part of 29b5585702e5e025
1484                 apply_patch(<<'EOPATCH');
1485 diff --git a/hints/openbsd.sh b/hints/openbsd.sh
1486 index c6b6bc9..4839d04 100644
1487 --- a/hints/openbsd.sh
1488 +++ b/hints/openbsd.sh
1489 @@ -54,6 +54,11 @@ alpha-2.[0-8]|mips-*|vax-*|powerpc-2.[0-7]|m88k-*)
1490                 libswanted=`echo $libswanted | sed 's/ dl / /'`
1491                 ;;
1492         esac
1493 +
1494 +       # We need to force ld to export symbols on ELF platforms.
1495 +       # Without this, dlopen() is crippled.
1496 +       ELF=`${cc:-cc} -dM -E - </dev/null | grep __ELF__`
1497 +       test -n "$ELF" && ldflags="-Wl,-E $ldflags"
1498         ;;
1499  esac
1500  
1501 EOPATCH
1502             }
1503         }
1504     } elsif ($^O eq 'linux') {
1505         if ($major < 1) {
1506             # sparc linux seems to need the -Dbool=char -DHAS_BOOL part of
1507             # perl5.000 patch.0n: [address Configure and build issues]
1508             edit_file('hints/linux.sh', sub {
1509                           my $code = shift;
1510                           $code =~ s!-I/usr/include/bsd!-Dbool=char -DHAS_BOOL!g;
1511                           return $code;
1512                       });
1513         }
1514
1515         if ($major <= 9) {
1516             if (`uname -sm` =~ qr/^Linux sparc/) {
1517                 if (extract_from_file('hints/linux.sh', qr/sparc-linux/)) {
1518                     # Be sure to use -fPIC not -fpic on Linux/SPARC
1519                     apply_commit('f6527d0ef0c13ad4');
1520                 } elsif(!extract_from_file('hints/linux.sh',
1521                                            qr/^sparc-linux\)$/)) {
1522                     my $fh = open_or_die('hints/linux.sh', '>>');
1523                     print $fh <<'EOT' or die $!;
1524
1525 case "`uname -m`" in
1526 sparc*)
1527         case "$cccdlflags" in
1528         *-fpic*) cccdlflags="`echo $cccdlflags|sed 's/-fpic/-fPIC/'`" ;;
1529         *)       cccdlflags="$cccdlflags -fPIC" ;;
1530         esac
1531         ;;
1532 esac
1533 EOT
1534                     close_or_die($fh);
1535                 }
1536             }
1537         }
1538     }
1539 }
1540
1541 sub patch_SH {
1542     # Cwd.xs added in commit 0d2079faa739aaa9. Cwd.pm moved to ext/ 8 years
1543     # later in commit 403f501d5b37ebf0
1544     if ($major > 0 && <*/Cwd/Cwd.xs>) {
1545         if ($major < 10
1546             && !extract_from_file('Makefile.SH', qr/^extra_dep=''$/)) {
1547             # The Makefile.PL for Unicode::Normalize needs
1548             # lib/unicore/CombiningClass.pl. Even without a parallel build, we
1549             # need a dependency to ensure that it builds. This is a variant of
1550             # commit 9f3ef600c170f61e. Putting this for earlier versions gives
1551             # us a spot on which to hang the edits below
1552             apply_patch(<<'EOPATCH');
1553 diff --git a/Makefile.SH b/Makefile.SH
1554 index f61d0db..6097954 100644
1555 --- a/Makefile.SH
1556 +++ b/Makefile.SH
1557 @@ -155,10 +155,20 @@ esac
1558  
1559  : Prepare dependency lists for Makefile.
1560  dynamic_list=' '
1561 +extra_dep=''
1562  for f in $dynamic_ext; do
1563      : the dependency named here will never exist
1564        base=`echo "$f" | sed 's/.*\///'`
1565 -    dynamic_list="$dynamic_list lib/auto/$f/$base.$dlext"
1566 +    this_target="lib/auto/$f/$base.$dlext"
1567 +    dynamic_list="$dynamic_list $this_target"
1568 +
1569 +    : Parallel makes reveal that we have some interdependencies
1570 +    case $f in
1571 +       Math/BigInt/FastCalc) extra_dep="$extra_dep
1572 +$this_target: lib/auto/List/Util/Util.$dlext" ;;
1573 +       Unicode/Normalize) extra_dep="$extra_dep
1574 +$this_target: lib/unicore/CombiningClass.pl" ;;
1575 +    esac
1576  done
1577  
1578  static_list=' '
1579 @@ -987,2 +997,9 @@ n_dummy $(nonxs_ext):       miniperl$(EXE_EXT) preplibrary $(DYNALOADER) FORCE
1580         @$(LDLIBPTH) sh ext/util/make_ext nonxs $@ MAKE=$(MAKE) LIBPERL_A=$(LIBPERL)
1581 +!NO!SUBS!
1582 +
1583 +$spitshell >>Makefile <<EOF
1584 +$extra_dep
1585 +EOF
1586 +
1587 +$spitshell >>Makefile <<'!NO!SUBS!'
1588  
1589 EOPATCH
1590         }
1591         if ($major < 14) {
1592             # Commits dc0655f797469c47 and d11a62fe01f2ecb2
1593             edit_file('Makefile.SH', sub {
1594                           my $code = shift;
1595                           foreach my $ext (qw(Encode SDBM_File)) {
1596                               next if $code =~ /\b$ext\) extra_dep=/s;
1597                               $code =~ s!(\) extra_dep="\$extra_dep
1598 \$this_target: .*?" ;;)
1599 (    esac
1600 )!$1
1601         $ext) extra_dep="\$extra_dep
1602 \$this_target: lib/auto/Cwd/Cwd.\$dlext" ;;
1603 $2!;
1604                           }
1605                           return $code;
1606                       });
1607         }
1608     }
1609
1610     if ($major == 7) {
1611         # Remove commits 9fec149bb652b6e9 and 5bab1179608f81d8, which add/amend
1612         # rules to automatically run regen scripts that rebuild C headers. These
1613         # cause problems because a git checkout doesn't preserve relative file
1614         # modification times, hence the regen scripts may fire. This will
1615         # obscure whether the repository had the correct generated headers
1616         # checked in.
1617         # Also, the dependency rules for running the scripts were not correct,
1618         # which could cause spurious re-builds on re-running make, and can cause
1619         # complete build failures for a parallel make.
1620         if (extract_from_file('Makefile.SH',
1621                               qr/Writing it this way gives make a big hint to always run opcode\.pl before/)) {
1622             apply_commit('70c6e6715e8fec53');
1623         } elsif (extract_from_file('Makefile.SH',
1624                                    qr/^opcode\.h opnames\.h pp_proto\.h pp\.sym: opcode\.pl$/)) {
1625             revert_commit('9fec149bb652b6e9');
1626         }
1627     }
1628
1629     # There was a bug in makedepend.SH which was fixed in version 96a8704c.
1630     # Symptom was './makedepend: 1: Syntax error: Unterminated quoted string'
1631     # Remove this if you're actually bisecting a problem related to
1632     # makedepend.SH
1633     # If you do this, you may need to add in code to correct the output of older
1634     # makedepends, which don't correctly filter newer gcc output such as
1635     # <built-in>
1636     checkout_file('makedepend.SH');
1637
1638     if ($major < 4 && -f 'config.sh'
1639         && !extract_from_file('config.sh', qr/^trnl=/)) {
1640         # This seems to be necessary to avoid makedepend becoming confused,
1641         # and hanging on stdin. Seems that the code after
1642         # make shlist || ...here... is never run.
1643         edit_file('makedepend.SH', sub {
1644                       my $code = shift;
1645                       $code =~ s/^trnl='\$trnl'$/trnl='\\n'/m;
1646                       return $code;
1647                   });
1648     }
1649 }
1650
1651 sub patch_C {
1652     # This is ordered by $major, as it's likely that different platforms may
1653     # well want to share code.
1654
1655     if ($major == 2 && extract_from_file('perl.c', qr/^\tfclose\(e_fp\);$/)) {
1656         # need to patch perl.c to avoid calling fclose() twice on e_fp when
1657         # using -e
1658         # This diff is part of commit ab821d7fdc14a438. The second close was
1659         # introduced with perl-5.002, commit a5f75d667838e8e7
1660         # Might want a6c477ed8d4864e6 too, for the corresponding change to
1661         # pp_ctl.c (likely without this, eval will have "fun")
1662         apply_patch(<<'EOPATCH');
1663 diff --git a/perl.c b/perl.c
1664 index 03c4d48..3c814a2 100644
1665 --- a/perl.c
1666 +++ b/perl.c
1667 @@ -252,6 +252,7 @@ setuid perl scripts securely.\n");
1668  #ifndef VMS  /* VMS doesn't have environ array */
1669      origenviron = environ;
1670  #endif
1671 +    e_tmpname = Nullch;
1672  
1673      if (do_undump) {
1674  
1675 @@ -405,6 +406,7 @@ setuid perl scripts securely.\n");
1676      if (e_fp) {
1677         if (Fflush(e_fp) || ferror(e_fp) || fclose(e_fp))
1678             croak("Can't write to temp file for -e: %s", Strerror(errno));
1679 +       e_fp = Nullfp;
1680         argc++,argv--;
1681         scriptname = e_tmpname;
1682      }
1683 @@ -470,10 +472,10 @@ setuid perl scripts securely.\n");
1684      curcop->cop_line = 0;
1685      curstash = defstash;
1686      preprocess = FALSE;
1687 -    if (e_fp) {
1688 -       fclose(e_fp);
1689 -       e_fp = Nullfp;
1690 +    if (e_tmpname) {
1691         (void)UNLINK(e_tmpname);
1692 +       Safefree(e_tmpname);
1693 +       e_tmpname = Nullch;
1694      }
1695  
1696      /* now that script is parsed, we can modify record separator */
1697 @@ -1369,7 +1371,7 @@ SV *sv;
1698         scriptname = xfound;
1699      }
1700  
1701 -    origfilename = savepv(e_fp ? "-e" : scriptname);
1702 +    origfilename = savepv(e_tmpname ? "-e" : scriptname);
1703      curcop->cop_filegv = gv_fetchfile(origfilename);
1704      if (strEQ(origfilename,"-"))
1705         scriptname = "";
1706
1707 EOPATCH
1708     }
1709
1710     if ($major < 3 && $^O eq 'openbsd'
1711         && !extract_from_file('pp_sys.c', qr/BSD_GETPGRP/)) {
1712         # Part of commit c3293030fd1b7489
1713         apply_patch(<<'EOPATCH');
1714 diff --git a/pp_sys.c b/pp_sys.c
1715 index 4608a2a..f0c9d1d 100644
1716 --- a/pp_sys.c
1717 +++ b/pp_sys.c
1718 @@ -2903,8 +2903,8 @@ PP(pp_getpgrp)
1719         pid = 0;
1720      else
1721         pid = SvIVx(POPs);
1722 -#ifdef USE_BSDPGRP
1723 -    value = (I32)getpgrp(pid);
1724 +#ifdef BSD_GETPGRP
1725 +    value = (I32)BSD_GETPGRP(pid);
1726  #else
1727      if (pid != 0)
1728         DIE("POSIX getpgrp can't take an argument");
1729 @@ -2933,8 +2933,8 @@ PP(pp_setpgrp)
1730      }
1731  
1732      TAINT_PROPER("setpgrp");
1733 -#ifdef USE_BSDPGRP
1734 -    SETi( setpgrp(pid, pgrp) >= 0 );
1735 +#ifdef BSD_SETPGRP
1736 +    SETi( BSD_SETPGRP(pid, pgrp) >= 0 );
1737  #else
1738      if ((pgrp != 0) || (pid != 0)) {
1739         DIE("POSIX setpgrp can't take an argument");
1740 EOPATCH
1741     }
1742
1743     if ($major < 4 && $^O eq 'openbsd') {
1744         my $bad;
1745         # Need changes from commit a6e633defa583ad5.
1746         # Commits c07a80fdfe3926b5 and f82b3d4130164d5f changed the same part
1747         # of perl.h
1748
1749         if (extract_from_file('perl.h',
1750                               qr/^#ifdef HAS_GETPGRP2$/)) {
1751             $bad = <<'EOBAD';
1752 ***************
1753 *** 57,71 ****
1754   #define TAINT_PROPER(s)       if (tainting) taint_proper(no_security, s)
1755   #define TAINT_ENV()   if (tainting) taint_env()
1756   
1757 ! #ifdef HAS_GETPGRP2
1758 ! #   ifndef HAS_GETPGRP
1759 ! #     define HAS_GETPGRP
1760 ! #   endif
1761 ! #endif
1762
1763 ! #ifdef HAS_SETPGRP2
1764 ! #   ifndef HAS_SETPGRP
1765 ! #     define HAS_SETPGRP
1766 ! #   endif
1767   #endif
1768   
1769 EOBAD
1770         } elsif (extract_from_file('perl.h',
1771                                    qr/Gack, you have one but not both of getpgrp2/)) {
1772             $bad = <<'EOBAD';
1773 ***************
1774 *** 56,76 ****
1775   #define TAINT_PROPER(s)       if (tainting) taint_proper(no_security, s)
1776   #define TAINT_ENV()   if (tainting) taint_env()
1777   
1778 ! #if defined(HAS_GETPGRP2) && defined(HAS_SETPGRP2)
1779 ! #   define getpgrp getpgrp2
1780 ! #   define setpgrp setpgrp2
1781 ! #   ifndef HAS_GETPGRP
1782 ! #     define HAS_GETPGRP
1783 ! #   endif
1784 ! #   ifndef HAS_SETPGRP
1785 ! #     define HAS_SETPGRP
1786 ! #   endif
1787 ! #   ifndef USE_BSDPGRP
1788 ! #     define USE_BSDPGRP
1789 ! #   endif
1790 ! #else
1791 ! #   if defined(HAS_GETPGRP2) || defined(HAS_SETPGRP2)
1792 !       #include "Gack, you have one but not both of getpgrp2() and setpgrp2()."
1793 ! #   endif
1794   #endif
1795   
1796 EOBAD
1797         } elsif (extract_from_file('perl.h',
1798                                    qr/^#ifdef USE_BSDPGRP$/)) {
1799             $bad = <<'EOBAD'
1800 ***************
1801 *** 91,116 ****
1802   #define TAINT_PROPER(s)       if (tainting) taint_proper(no_security, s)
1803   #define TAINT_ENV()   if (tainting) taint_env()
1804   
1805 ! #ifdef USE_BSDPGRP
1806 ! #   ifdef HAS_GETPGRP
1807 ! #       define BSD_GETPGRP(pid) getpgrp((pid))
1808 ! #   endif
1809 ! #   ifdef HAS_SETPGRP
1810 ! #       define BSD_SETPGRP(pid, pgrp) setpgrp((pid), (pgrp))
1811 ! #   endif
1812 ! #else
1813 ! #   ifdef HAS_GETPGRP2
1814 ! #       define BSD_GETPGRP(pid) getpgrp2((pid))
1815 ! #       ifndef HAS_GETPGRP
1816 ! #         define HAS_GETPGRP
1817 ! #     endif
1818 ! #   endif
1819 ! #   ifdef HAS_SETPGRP2
1820 ! #       define BSD_SETPGRP(pid, pgrp) setpgrp2((pid), (pgrp))
1821 ! #       ifndef HAS_SETPGRP
1822 ! #         define HAS_SETPGRP
1823 ! #     endif
1824 ! #   endif
1825   #endif
1826   
1827   #ifndef _TYPES_               /* If types.h defines this it's easy. */
1828 EOBAD
1829         }
1830         if ($bad) {
1831             apply_patch(<<"EOPATCH");
1832 *** a/perl.h    2011-10-21 09:46:12.000000000 +0200
1833 --- b/perl.h    2011-10-21 09:46:12.000000000 +0200
1834 $bad--- 91,144 ----
1835   #define TAINT_PROPER(s)       if (tainting) taint_proper(no_security, s)
1836   #define TAINT_ENV()   if (tainting) taint_env()
1837   
1838 ! /* XXX All process group stuff is handled in pp_sys.c.  Should these 
1839 !    defines move there?  If so, I could simplify this a lot. --AD  9/96.
1840 ! */
1841 ! /* Process group stuff changed from traditional BSD to POSIX.
1842 !    perlfunc.pod documents the traditional BSD-style syntax, so we'll
1843 !    try to preserve that, if possible.
1844 ! */
1845 ! #ifdef HAS_SETPGID
1846 ! #  define BSD_SETPGRP(pid, pgrp)      setpgid((pid), (pgrp))
1847 ! #else
1848 ! #  if defined(HAS_SETPGRP) && defined(USE_BSD_SETPGRP)
1849 ! #    define BSD_SETPGRP(pid, pgrp)    setpgrp((pid), (pgrp))
1850 ! #  else
1851 ! #    ifdef HAS_SETPGRP2  /* DG/UX */
1852 ! #      define BSD_SETPGRP(pid, pgrp)  setpgrp2((pid), (pgrp))
1853 ! #    endif
1854 ! #  endif
1855 ! #endif
1856 ! #if defined(BSD_SETPGRP) && !defined(HAS_SETPGRP)
1857 ! #  define HAS_SETPGRP  /* Well, effectively it does . . . */
1858 ! #endif
1859
1860 ! /* getpgid isn't POSIX, but at least Solaris and Linux have it, and it makes
1861 !     our life easier :-) so we'll try it.
1862 ! */
1863 ! #ifdef HAS_GETPGID
1864 ! #  define BSD_GETPGRP(pid)            getpgid((pid))
1865 ! #else
1866 ! #  if defined(HAS_GETPGRP) && defined(USE_BSD_GETPGRP)
1867 ! #    define BSD_GETPGRP(pid)          getpgrp((pid))
1868 ! #  else
1869 ! #    ifdef HAS_GETPGRP2  /* DG/UX */
1870 ! #      define BSD_GETPGRP(pid)                getpgrp2((pid))
1871 ! #    endif
1872 ! #  endif
1873 ! #endif
1874 ! #if defined(BSD_GETPGRP) && !defined(HAS_GETPGRP)
1875 ! #  define HAS_GETPGRP  /* Well, effectively it does . . . */
1876 ! #endif
1877
1878 ! /* These are not exact synonyms, since setpgrp() and getpgrp() may 
1879 !    have different behaviors, but perl.h used to define USE_BSDPGRP
1880 !    (prior to 5.003_05) so some extension might depend on it.
1881 ! */
1882 ! #if defined(USE_BSD_SETPGRP) || defined(USE_BSD_GETPGRP)
1883 ! #  ifndef USE_BSDPGRP
1884 ! #    define USE_BSDPGRP
1885 ! #  endif
1886   #endif
1887   
1888   #ifndef _TYPES_               /* If types.h defines this it's easy. */
1889 EOPATCH
1890         }
1891     }
1892
1893     if ($major == 4 && extract_from_file('scope.c', qr/\(SV\*\)SSPOPINT/)) {
1894         # [PATCH] 5.004_04 +MAINT_TRIAL_1 broken when sizeof(int) != sizeof(void)
1895         # Fixes a bug introduced in 161b7d1635bc830b
1896         apply_commit('9002cb76ec83ef7f');
1897     }
1898
1899     if ($major == 4 && extract_from_file('av.c', qr/AvARRAY\(av\) = 0;/)) {
1900         # Fixes a bug introduced in 1393e20655efb4bc
1901         apply_commit('e1c148c28bf3335b', 'av.c');
1902     }
1903
1904     if ($major == 4) {
1905         my $rest = extract_from_file('perl.c', qr/delimcpy(.*)/);
1906         if (defined $rest and $rest !~ /,$/) {
1907             # delimcpy added in fc36a67e8855d031, perl.c refactored to use it.
1908             # bug introduced in 2a92aaa05aa1acbf, fixed in 8490252049bf42d3
1909             # code then moved to util.c in commit 491527d0220de34e
1910             apply_patch(<<'EOPATCH');
1911 diff --git a/perl.c b/perl.c
1912 index 4eb69e3..54bbb00 100644
1913 --- a/perl.c
1914 +++ b/perl.c
1915 @@ -1735,7 +1735,7 @@ SV *sv;
1916             if (len < sizeof tokenbuf)
1917                 tokenbuf[len] = '\0';
1918  #else  /* ! (atarist || DOSISH) */
1919 -           s = delimcpy(tokenbuf, tokenbuf + sizeof tokenbuf, s, bufend
1920 +           s = delimcpy(tokenbuf, tokenbuf + sizeof tokenbuf, s, bufend,
1921                          ':',
1922                          &len);
1923  #endif /* ! (atarist || DOSISH) */
1924 EOPATCH
1925         }
1926     }
1927
1928     if ($major == 4 && $^O eq 'linux') {
1929         # Whilst this is fixed properly in f0784f6a4c3e45e1 which provides the
1930         # Configure probe, it's easier to back out the problematic changes made
1931         # in these previous commits:
1932         if (extract_from_file('doio.c',
1933                               qr!^/\* XXX REALLY need metaconfig test \*/$!)) {
1934             revert_commit('4682965a1447ea44', 'doio.c');
1935         }
1936         if (my $token = extract_from_file('doio.c',
1937                                           qr!^#if (defined\(__sun(?:__)?\)) && defined\(__svr4__\) /\* XXX Need metaconfig test \*/$!)) {
1938             my $patch = `git show -R 9b599b2a63d2324d doio.c`;
1939             $patch =~ s/defined\(__sun__\)/$token/g;
1940             apply_patch($patch);
1941         }
1942         if (extract_from_file('doio.c',
1943                               qr!^/\* linux \(and Solaris2\?\) uses :$!)) {
1944             revert_commit('8490252049bf42d3', 'doio.c');
1945         }
1946         if (extract_from_file('doio.c',
1947                               qr/^          unsemds.buf = &semds;$/)) {
1948             revert_commit('8e591e46b4c6543e');
1949         }
1950         if (extract_from_file('doio.c',
1951                               qr!^#ifdef __linux__      /\* XXX Need metaconfig test \*/$!)) {
1952             # Reverts part of commit 3e3baf6d63945cb6
1953             apply_patch(<<'EOPATCH');
1954 diff --git b/doio.c a/doio.c
1955 index 62b7de9..0d57425 100644
1956 --- b/doio.c
1957 +++ a/doio.c
1958 @@ -1333,9 +1331,6 @@ SV **sp;
1959      char *a;
1960      I32 id, n, cmd, infosize, getinfo;
1961      I32 ret = -1;
1962 -#ifdef __linux__       /* XXX Need metaconfig test */
1963 -    union semun unsemds;
1964 -#endif
1965  
1966      id = SvIVx(*++mark);
1967      n = (optype == OP_SEMCTL) ? SvIVx(*++mark) : 0;
1968 @@ -1364,29 +1359,11 @@ SV **sp;
1969             infosize = sizeof(struct semid_ds);
1970         else if (cmd == GETALL || cmd == SETALL)
1971         {
1972 -#ifdef __linux__       /* XXX Need metaconfig test */
1973 -/* linux uses :
1974 -   int semctl (int semid, int semnun, int cmd, union semun arg)
1975 -
1976 -       union semun {
1977 -            int val;
1978 -            struct semid_ds *buf;
1979 -            ushort *array;
1980 -       };
1981 -*/
1982 -            union semun semds;
1983 -           if (semctl(id, 0, IPC_STAT, semds) == -1)
1984 -#else
1985             struct semid_ds semds;
1986             if (semctl(id, 0, IPC_STAT, &semds) == -1)
1987 -#endif
1988                 return -1;
1989             getinfo = (cmd == GETALL);
1990 -#ifdef __linux__       /* XXX Need metaconfig test */
1991 -           infosize = semds.buf->sem_nsems * sizeof(short);
1992 -#else
1993             infosize = semds.sem_nsems * sizeof(short);
1994 -#endif
1995                 /* "short" is technically wrong but much more portable
1996                    than guessing about u_?short(_t)? */
1997         }
1998 @@ -1429,12 +1406,7 @@ SV **sp;
1999  #endif
2000  #ifdef HAS_SEM
2001      case OP_SEMCTL:
2002 -#ifdef __linux__       /* XXX Need metaconfig test */
2003 -        unsemds.buf = (struct semid_ds *)a;
2004 -       ret = semctl(id, n, cmd, unsemds);
2005 -#else
2006         ret = semctl(id, n, cmd, (struct semid_ds *)a);
2007 -#endif
2008         break;
2009  #endif
2010  #ifdef HAS_SHM
2011 EOPATCH
2012         }
2013         # Incorrect prototype added as part of 8ac853655d9b7447, fixed as part
2014         # of commit dc45a647708b6c54, with at least one intermediate
2015         # modification. Correct prototype for gethostbyaddr has socklen_t
2016         # second. Linux has uint32_t first for getnetbyaddr.
2017         # Easiest just to remove, instead of attempting more complex patching.
2018         # Something similar may be needed on other platforms.
2019         edit_file('pp_sys.c', sub {
2020                       my $code = shift;
2021                       $code =~ s/^    struct hostent \*(?:PerlSock_)?gethostbyaddr\([^)]+\);$//m;
2022                       $code =~ s/^    struct netent \*getnetbyaddr\([^)]+\);$//m;
2023                       return $code;
2024                   });
2025     }
2026
2027     if ($major < 6 && $^O eq 'netbsd'
2028         && !extract_from_file('unixish.h',
2029                               qr/defined\(NSIG\).*defined\(__NetBSD__\)/)) {
2030         apply_patch(<<'EOPATCH')
2031 diff --git a/unixish.h b/unixish.h
2032 index 2a6cbcd..eab2de1 100644
2033 --- a/unixish.h
2034 +++ b/unixish.h
2035 @@ -89,7 +89,7 @@
2036   */
2037  /* #define ALTERNATE_SHEBANG "#!" / **/
2038  
2039 -#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
2040 +#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX) || defined(__NetBSD__)
2041  # include <signal.h>
2042  #endif
2043  
2044 EOPATCH
2045     }
2046
2047     if (($major >= 7 || $major <= 9) && $^O eq 'openbsd'
2048         && `uname -m` eq "sparc64\n"
2049         # added in 2000 by commit cb434fcc98ac25f5:
2050         && extract_from_file('regexec.c',
2051                              qr!/\* No need to save/restore up to this paren \*/!)
2052         # re-indented in 2006 by commit 95b2444054382532:
2053         && extract_from_file('regexec.c', qr/^\t\tCURCUR cc;$/)) {
2054         # Need to work around a bug in (at least) OpenBSD's 4.6's sparc64 #
2055         # compiler ["gcc (GCC) 3.3.5 (propolice)"]. Between commits
2056         # 3ec562b0bffb8b8b (2002) and 1a4fad37125bac3e^ (2005) the darling thing
2057         # fails to compile any code for the statement cc.oldcc = PL_regcc;
2058         #
2059         # If you refactor the code to "fix" that, or force the issue using set
2060         # in the debugger, the stack smashing detection code fires on return
2061         # from S_regmatch(). Turns out that the compiler doesn't allocate any
2062         # (or at least enough) space for cc.
2063         #
2064         # Restore the "uninitialised" value for cc before function exit, and the
2065         # stack smashing code is placated.  "Fix" 3ec562b0bffb8b8b (which
2066         # changes the size of auto variables used elsewhere in S_regmatch), and
2067         # the crash is visible back to bc517b45fdfb539b (which also changes
2068         # buffer sizes). "Unfix" 1a4fad37125bac3e and the crash is visible until
2069         # 5b47454deb66294b.  Problem goes away if you compile with -O, or hack
2070         # the code as below.
2071         #
2072         # Hence this turns out to be a bug in (old) gcc. Not a security bug we
2073         # still need to fix.
2074         apply_patch(<<'EOPATCH');
2075 diff --git a/regexec.c b/regexec.c
2076 index 900b491..6251a0b 100644
2077 --- a/regexec.c
2078 +++ b/regexec.c
2079 @@ -2958,7 +2958,11 @@ S_regmatch(pTHX_ regnode *prog)
2080                                 I,I
2081   *******************************************************************/
2082         case CURLYX: {
2083 -               CURCUR cc;
2084 +           union {
2085 +               CURCUR hack_cc;
2086 +               char hack_buff[sizeof(CURCUR) + 1];
2087 +           } hack;
2088 +#define cc hack.hack_cc
2089                 CHECKPOINT cp = PL_savestack_ix;
2090                 /* No need to save/restore up to this paren */
2091                 I32 parenfloor = scan->flags;
2092 @@ -2983,6 +2987,7 @@ S_regmatch(pTHX_ regnode *prog)
2093                 n = regmatch(PREVOPER(next));   /* start on the WHILEM */
2094                 regcpblow(cp);
2095                 PL_regcc = cc.oldcc;
2096 +#undef cc
2097                 saySAME(n);
2098             }
2099             /* NOT REACHED */
2100 EOPATCH
2101 }
2102
2103     if ($major < 8 && $^O eq 'openbsd'
2104         && !extract_from_file('perl.h', qr/include <unistd\.h>/)) {
2105         # This is part of commit 3f270f98f9305540, applied at a slightly
2106         # different location in perl.h, where the context is stable back to
2107         # 5.000
2108         apply_patch(<<'EOPATCH');
2109 diff --git a/perl.h b/perl.h
2110 index 9418b52..b8b1a7c 100644
2111 --- a/perl.h
2112 +++ b/perl.h
2113 @@ -496,6 +496,10 @@ register struct op *Perl_op asm(stringify(OP_IN_REGISTER));
2114  #   include <sys/param.h>
2115  #endif
2116  
2117 +/* If this causes problems, set i_unistd=undef in the hint file.  */
2118 +#ifdef I_UNISTD
2119 +#   include <unistd.h>
2120 +#endif
2121  
2122  /* Use all the "standard" definitions? */
2123  #if defined(STANDARD_C) && defined(I_STDLIB)
2124 EOPATCH
2125     }
2126 }
2127
2128 sub patch_ext {
2129     if (-f 'ext/POSIX/Makefile.PL'
2130         && extract_from_file('ext/POSIX/Makefile.PL',
2131                              qr/Explicitly avoid including/)) {
2132         # commit 6695a346c41138df, which effectively reverts 170888cff5e2ffb7
2133
2134         # PERL5LIB is populated by make_ext.pl with paths to the modules we need
2135         # to run, don't override this with "../../lib" since that may not have
2136         # been populated yet in a parallel build.
2137         apply_commit('6695a346c41138df');
2138     }
2139
2140     if ($major < 8 && $^O eq 'darwin' && !-f 'ext/DynaLoader/dl_dyld.xs') {
2141         checkout_file('ext/DynaLoader/dl_dyld.xs', 'f556e5b971932902');
2142         apply_patch(<<'EOPATCH');
2143 diff -u a/ext/DynaLoader/dl_dyld.xs~ a/ext/DynaLoader/dl_dyld.xs
2144 --- a/ext/DynaLoader/dl_dyld.xs~        2011-10-11 21:41:27.000000000 +0100
2145 +++ b/ext/DynaLoader/dl_dyld.xs 2011-10-11 21:42:20.000000000 +0100
2146 @@ -41,6 +41,35 @@
2147  #include "perl.h"
2148  #include "XSUB.h"
2149  
2150 +#ifndef pTHX
2151 +#  define pTHX         void
2152 +#  define pTHX_
2153 +#endif
2154 +#ifndef aTHX
2155 +#  define aTHX
2156 +#  define aTHX_
2157 +#endif
2158 +#ifndef dTHX
2159 +#  define dTHXa(a)     extern int Perl___notused(void)
2160 +#  define dTHX         extern int Perl___notused(void)
2161 +#endif
2162 +
2163 +#ifndef Perl_form_nocontext
2164 +#  define Perl_form_nocontext form
2165 +#endif
2166 +
2167 +#ifndef Perl_warn_nocontext
2168 +#  define Perl_warn_nocontext warn
2169 +#endif
2170 +
2171 +#ifndef PTR2IV
2172 +#  define PTR2IV(p)    (IV)(p)
2173 +#endif
2174 +
2175 +#ifndef get_av
2176 +#  define get_av perl_get_av
2177 +#endif
2178 +
2179  #define DL_LOADONCEONLY
2180  
2181  #include "dlutils.c"   /* SaveError() etc      */
2182 @@ -185,7 +191,7 @@
2183      CODE:
2184      DLDEBUG(1,PerlIO_printf(Perl_debug_log, "dl_load_file(%s,%x):\n", filename,flags));
2185      if (flags & 0x01)
2186 -       Perl_warn(aTHX_ "Can't make loaded symbols global on this platform while loading %s",filename);
2187 +       Perl_warn_nocontext("Can't make loaded symbols global on this platform while loading %s",filename);
2188      RETVAL = dlopen(filename, mode) ;
2189      DLDEBUG(2,PerlIO_printf(Perl_debug_log, " libref=%x\n", RETVAL));
2190      ST(0) = sv_newmortal() ;
2191 EOPATCH
2192         if ($major < 4 && !extract_from_file('util.c', qr/^form/m)) {
2193             apply_patch(<<'EOPATCH');
2194 diff -u a/ext/DynaLoader/dl_dyld.xs~ a/ext/DynaLoader/dl_dyld.xs
2195 --- a/ext/DynaLoader/dl_dyld.xs~        2011-10-11 21:56:25.000000000 +0100
2196 +++ b/ext/DynaLoader/dl_dyld.xs 2011-10-11 22:00:00.000000000 +0100
2197 @@ -60,6 +60,18 @@
2198  #  define get_av perl_get_av
2199  #endif
2200  
2201 +static char *
2202 +form(char *pat, ...)
2203 +{
2204 +    char *retval;
2205 +    va_list args;
2206 +    va_start(args, pat);
2207 +    vasprintf(&retval, pat, &args);
2208 +    va_end(args);
2209 +    SAVEFREEPV(retval);
2210 +    return retval;
2211 +}
2212 +
2213  #define DL_LOADONCEONLY
2214  
2215  #include "dlutils.c"   /* SaveError() etc      */
2216 EOPATCH
2217         }
2218     }
2219
2220     if ($major < 10) {
2221         if (!extract_from_file('ext/DB_File/DB_File.xs',
2222                                qr!^#else /\* Berkeley DB Version > 2 \*/$!)) {
2223             # This DB_File.xs is really too old to patch up.
2224             # Skip DB_File, unless we're invoked with an explicit -Unoextensions
2225             if (!exists $defines{noextensions}) {
2226                 $defines{noextensions} = 'DB_File';
2227             } elsif (defined $defines{noextensions}) {
2228                 $defines{noextensions} .= ' DB_File';
2229             }
2230         } elsif (!extract_from_file('ext/DB_File/DB_File.xs',
2231                                     qr/^#ifdef AT_LEAST_DB_4_1$/)) {
2232             # This line is changed by commit 3245f0580c13b3ab
2233             my $line = extract_from_file('ext/DB_File/DB_File.xs',
2234                                          qr/^(        status = \(?RETVAL->dbp->open\)?\(RETVAL->dbp, name, NULL, RETVAL->type, $)/);
2235             apply_patch(<<"EOPATCH");
2236 diff --git a/ext/DB_File/DB_File.xs b/ext/DB_File/DB_File.xs
2237 index 489ba96..fba8ded 100644
2238 --- a/ext/DB_File/DB_File.xs
2239 +++ b/ext/DB_File/DB_File.xs
2240 \@\@ -183,4 +187,8 \@\@
2241  #endif
2242  
2243 +#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
2244 +#    define AT_LEAST_DB_4_1
2245 +#endif
2246 +
2247  /* map version 2 features & constants onto their version 1 equivalent */
2248  
2249 \@\@ -1334,7 +1419,12 \@\@ SV *   sv ;
2250  #endif
2251  
2252 +#ifdef AT_LEAST_DB_4_1
2253 +        status = (RETVAL->dbp->open)(RETVAL->dbp, NULL, name, NULL, RETVAL->type, 
2254 +                               Flags, mode) ; 
2255 +#else
2256  $line
2257                                 Flags, mode) ; 
2258 +#endif
2259         /* printf("open returned %d %s\\n", status, db_strerror(status)) ; */
2260  
2261 EOPATCH
2262         }
2263     }
2264
2265     if ($major < 10 and -f 'ext/IPC/SysV/SysV.xs') {
2266         edit_file('ext/IPC/SysV/SysV.xs', sub {
2267                       my $xs = shift;
2268                       my $fixed = <<'EOFIX';
2269
2270 #include <sys/types.h>
2271 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
2272 #ifndef HAS_SEM
2273 #   include <sys/ipc.h>
2274 #endif
2275 #   ifdef HAS_MSG
2276 #       include <sys/msg.h>
2277 #   endif
2278 #   ifdef HAS_SHM
2279 #       if defined(PERL_SCO) || defined(PERL_ISC)
2280 #           include <sys/sysmacros.h>   /* SHMLBA */
2281 #       endif
2282 #      include <sys/shm.h>
2283 #      ifndef HAS_SHMAT_PROTOTYPE
2284            extern Shmat_t shmat (int, char *, int);
2285 #      endif
2286 #      if defined(HAS_SYSCONF) && defined(_SC_PAGESIZE)
2287 #          undef  SHMLBA /* not static: determined at boot time */
2288 #          define SHMLBA sysconf(_SC_PAGESIZE)
2289 #      elif defined(HAS_GETPAGESIZE)
2290 #          undef  SHMLBA /* not static: determined at boot time */
2291 #          define SHMLBA getpagesize()
2292 #      endif
2293 #   endif
2294 #endif
2295 EOFIX
2296                       $xs =~ s!
2297 #include <sys/types\.h>
2298 .*
2299 (#ifdef newCONSTSUB|/\* Required)!$fixed$1!ms;
2300                       return $xs;
2301                   });
2302     }
2303 }
2304
2305 # Local variables:
2306 # cperl-indent-level: 4
2307 # indent-tabs-mode: nil
2308 # End:
2309 #
2310 # ex: set ts=8 sts=4 sw=4 et: