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