Update IPC-Cmd to CPAN version 0.76
[perl.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 --version`, $?) ? 'cc' : 'ccache cc',
57      ld => 'cc',
58      ($linux64 ? (libpth => \@paths) : ()),
59     );
60
61 unless(GetOptions(\%options,
62                   'target=s', 'make=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', 'A=s@', 'l', 'w',
66                   'check-args', 'check-shebang!', 'usage|help|?', 'validate',
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 @ARGV = ('sh', '-c', 'cd t && ./perl TEST base/*.t')
85     if $options{validate} && !@ARGV;
86
87 pod2usage(exitval => 255, verbose => 1) if $options{usage};
88 pod2usage(exitval => 255, verbose => 1)
89     unless @ARGV || $match || $options{'test-build'} || defined $options{'one-liner'};
90 pod2usage(exitval => 255, verbose => 1)
91     if !$options{'one-liner'} && ($options{l} || $options{w});
92
93 check_shebang($ARGV[0]) if $options{'check-shebang'} && @ARGV;
94
95 exit 0 if $options{'check-args'};
96
97 =head1 NAME
98
99 bisect.pl - use git bisect to pinpoint changes
100
101 =head1 SYNOPSIS
102
103     # When did this become an error?
104     .../Porting/bisect.pl -e 'my $a := 2;'
105     # When did this stop being an error?
106     .../Porting/bisect.pl --expect-fail -e '1 // 2'
107     # When did this stop matching?
108     .../Porting/bisect.pl --match '\b(?:PL_)hash_seed_set\b'
109     # When did this start matching?
110     .../Porting/bisect.pl --expect-fail --match '\buseithreads\b'
111     # When did this test program stop working?
112     .../Porting/bisect.pl -- ./perl -Ilib ../test_prog.pl
113     # When did this first become valid syntax?
114     .../Porting/bisect.pl --target=miniperl --end=v5.10.0 \
115          --expect-fail -e 'my $a := 2;'
116     # What was the last revision to build with these options?
117     .../Porting/bisect.pl --test-build -Dd_dosuid
118
119 =head1 DESCRIPTION
120
121 Together F<bisect.pl> and F<bisect-runner.pl> attempt to automate the use
122 of C<git bisect> as much as possible. With one command (and no other files)
123 it's easy to find out
124
125 =over 4
126
127 =item *
128
129 Which commit caused this example code to break?
130
131 =item *
132
133 Which commit caused this example code to start working?
134
135 =item *
136
137 Which commit added the first to match this regex?
138
139 =item *
140
141 Which commit removed the last to match this regex?
142
143 =back
144
145 usually without needing to know which versions of perl to use as start and
146 end revisions.
147
148 By default F<bisect.pl> will process all options, then use the rest of the
149 command line as arguments to list C<system> to run a test case. By default,
150 the test case should pass (exit with 0) on earlier perls, and fail (exit
151 non-zero) on I<blead>. F<bisect.pl> will use F<bisect-runner.pl> to find the
152 earliest stable perl version on which the test case passes, check that it
153 fails on blead, and then use F<bisect-runner.pl> with C<git bisect run> to
154 find the commit which caused the failure.
155
156 Because the test case is the complete argument to C<system>, it is easy to
157 run something other than the F<perl> built, if necessary. If you need to run
158 the perl built, you'll probably need to invoke it as C<./perl -Ilib ...>
159
160 You need a clean checkout to run a bisect, and you can't use the checkout
161 which contains F<Porting/bisect.pl> (because C<git bisect>) will check out
162 a revision before F<Porting/bisect-runner.pl> was added, which
163 C<git bisect run> needs). If your working checkout is called F<perl>, the
164 simplest solution is to make a local clone, and run from that. I<i.e.>:
165
166     cd ..
167     git clone perl perl2
168     cd perl2
169     ../perl/Porting/bisect.pl ...
170
171 By default, F<bisect-runner.pl> will automatically disable the build of
172 L<DB_File> for commits earlier than ccb44e3bf3be2c30, as it's not practical
173 to patch DB_File 1.70 and earlier to build with current Berkeley DB headers.
174 (ccb44e3bf3be2c30 was in September 1999, between 5.005_62 and 5.005_63.)
175 If your F<db.h> is old enough you can override this with C<-Unoextensions>.
176
177 =head1 OPTIONS
178
179 =over 4
180
181 =item *
182
183 --start I<commit-ish>
184
185 Earliest revision to test, as a I<commit-ish> (a tag, commit or anything
186 else C<git> understands as a revision). If not specified, F<bisect.pl> will
187 search stable perl releases until it finds one where the test case passes.
188 The default is to search from 5.002 to 5.14.0. If F<bisect.pl> detects that
189 the checkout is on a case insensitive file system, it will search from
190 5.005 to 5.14.0
191
192 =item *
193
194 --end I<commit-ish>
195
196 Most recent revision to test, as a I<commit-ish>. If not specified, defaults
197 to I<blead>.
198
199 =item *
200
201 --target I<target>
202
203 F<Makefile> target (or equivalent) needed, to run the test case. If specified,
204 this should be one of
205
206 =over 4
207
208 =item *
209
210 I<config.sh>
211
212 Just run F<./Configure>
213
214 =item *
215
216 I<config.h>
217
218 Run the various F<*.SH> files to generate F<Makefile>, F<config.h>, I<etc>.
219
220 =item *
221
222 I<miniperl>
223
224 Build F<miniperl>.
225
226 =item *
227
228 I<lib/Config.pm>
229
230 Use F<miniperl> to build F<lib/Config.pm>
231
232 =item *
233
234 I<Fcntl>
235
236 Build F<lib/auto/Fcntl/Fnctl.so> (strictly, C<.$Config{so}>). As L<Fcntl>
237 is simple XS module present since 5.000, this provides a fast test of
238 whether XS modules can be built. Note, XS modules are built by F<miniperl>,
239 hence this target will not build F<perl>.
240
241 =item *
242
243 I<perl>
244
245 Build F<perl>. This also builds pure-Perl modules in F<cpan>, F<dist> and
246 F<ext>. XS modules (such as L<Fcntl>) are not built.
247
248 =item *
249
250 I<test_prep>
251
252 Build everything needed to run the tests. This is the default if we're
253 running test code, but is time consuming, as it means building all
254 XS modules. For older F<Makefile>s, the previous name of C<test-prep>
255 is automatically substituted. For very old F<Makefile>s, C<make test> is
256 run, as there is no target provided to just get things ready, and for 5.004
257 and earlier the tests run very quickly.
258
259 =back
260
261 =item *
262
263 --one-liner 'code to run'
264
265 =item *
266
267 -e 'code to run'
268
269 Example code to run, just like you'd use with C<perl -e>.
270
271 This prepends C<./perl -Ilib -e 'code to run'> to the test case given,
272 or F<./miniperl> if I<target> is C<miniperl>.
273
274 (Usually you'll use C<-e> instead of providing a test case in the
275 non-option arguments to F<bisect.pl>)
276
277 C<-E> intentionally isn't supported, as it's an error in 5.8.0 and earlier,
278 which interferes with detecting errors in the example code itself.
279
280 =item *
281
282 -l
283
284 Add C<-l> to the command line with C<-e>
285
286 This will automatically append a newline to every output line of your testcase.
287 Note that you can't specify an argument to F<perl>'s C<-l> with this, as it's
288 not feasible to emulate F<perl>'s somewhat quirky switch parsing with
289 L<Getopt::Long>. If you need the full flexibility of C<-l>, you need to write
290 a full test case, instead of using C<bisect.pl>'s C<-e> shortcut.
291
292 =item *
293
294 -w
295
296 Add C<-w> to the command line with C<-e>
297
298 It's not valid to pass C<-l> or C<-w> to C<bisect.pl> unless you are also
299 using C<-e>
300
301 =item *
302
303 --expect-fail
304
305 The test case should fail for the I<start> revision, and pass for the I<end>
306 revision. The bisect run will find the first commit where it passes.
307
308 =item *
309
310 -Dnoextensions=Encode
311
312 =item *
313
314 -Uusedevel
315
316 =item *
317
318 -Accflags=-DNO_MATHOMS
319
320 Arguments to pass to F<Configure>. Repeated C<-A> arguments are passed
321 through as is. C<-D> and C<-U> are processed in order, and override
322 previous settings for the same parameter. F<bisect-runner.pl> emulates
323 C<-Dnoextensions> when F<Configure> itself does not provide it, as it's
324 often very useful to be able to disable some XS extensions.
325
326 =item *
327
328 --make I<make-prog>
329
330 The C<make> command to use. If this not set, F<make> is used. If this is
331 set, it also adds a C<-Dmake=...> else some recursive make invocations
332 in extensions may fail. Typically one would use this as C<--make gmake>
333 to use F<gmake> in place of the system F<make>.
334
335 =item *
336
337 --jobs I<jobs>
338
339 =item *
340
341 -j I<jobs>
342
343 Number of C<make> jobs to run in parallel. If F</proc/cpuinfo> exists and
344 can be parsed, or F</sbin/sysctl> exists and reports C<hw.ncpu>, or
345 F</usr/bin/getconf> exists and reports C<_NPROCESSORS_ONLN> defaults to 1 +
346 I<number of CPUs>. Otherwise defaults to 2.
347
348 =item *
349
350 --match pattern
351
352 Instead of running a test program to determine I<pass> or I<fail>, pass
353 if the given regex matches, and hence search for the commit that removes
354 the last matching file.
355
356 If no I<target> is specified, the match is against all files in the
357 repository (which is fast). If a I<target> is specified, that target is
358 built, and the match is against only the built files. C<--expect-fail> can
359 be used with C<--match> to search for a commit that adds files that match.
360
361 =item *
362
363 --test-build
364
365 Test that the build completes, without running any test case.
366
367 By default, if the build for the desired I<target> fails to complete,
368 F<bisect-runner.pl> reports a I<skip> back to C<git bisect>, the assumption
369 being that one wants to find a commit which changed state "builds && passes"
370 to "builds && fails". If instead one is interested in which commit broke the
371 build (possibly for particular F<Configure> options), use I<--test-build>
372 to treat a build failure as a failure, not a "skip".
373
374 Often this option isn't as useful as it first seems, because I<any> build
375 failure will be reported to C<git bisect> as a failure, not just the failure
376 that you're interested in. Generally, to debug a particular problem, it's
377 more useful to use a I<target> that builds properly at the point of interest,
378 and then a test case that runs C<make>. For example:
379
380     .../Porting/bisect.pl --start=perl-5.000 --end=perl-5.002 \
381         --expect-fail --force-manifest --target=miniperl make perl
382
383 will find the first revision capable of building L<DynaLoader> and then
384 F<perl>, without becoming confused by revisions where F<miniperl> won't
385 even link.
386
387 =item *
388
389 --force-manifest
390
391 By default, a build will "skip" if any files listed in F<MANIFEST> are not
392 present. Usually this is useful, as it avoids false-failures. However, there
393 are some long ranges of commits where listed files are missing, which can
394 cause a bisect to abort because all that remain are skipped revisions.
395
396 In these cases, particularly if the test case uses F<miniperl> and no modules,
397 it may be more useful to force the build to continue, even if files
398 F<MANIFEST> are missing.
399
400 =item *
401
402 --force-regen
403
404 Run C<make regen_headers> before building F<miniperl>. This may fix a build
405 that otherwise would skip because the generated headers at that revision
406 are stale. It's not the default because it conceals this error in the true
407 state of such revisions.
408
409 =item *
410
411 --expect-pass [0|1]
412
413 C<--expect-pass=0> is equivalent to C<--expect-fail>. I<1> is the default.
414
415 =item *
416
417 --no-clean
418
419 Tell F<bisect-runner.pl> not to clean up after the build. This allows one
420 to use F<bisect-runner.pl> to build the current particular perl revision for
421 interactive testing, or for debugging F<bisect-runner.pl>.
422
423 Passing this to F<bisect.pl> will likely cause the bisect to fail badly.
424
425 =item *
426
427 --validate
428
429 Test that all stable revisions can be built. By default, attempts to build
430 I<blead>, I<v5.14.0> .. I<perl-5.002> (or I<perl5.005> on a case insensitive
431 file system). Stops at the first failure, without
432 cleaning the checkout. Use I<--start> to specify the earliest revision to
433 test, I<--end> to specify the most recent. Useful for validating a new
434 OS/CPU/compiler combination. For example
435
436     ../perl/Porting/bisect.pl --validate -le 'print "Hello from $]"'
437
438 If no testcase is specified, the default is to use F<t/TEST> to run
439 F<t/base/*.t>
440
441 =item *
442
443 --check-args
444
445 Validate the options and arguments, and exit silently if they are valid.
446
447 =item *
448
449 --check-shebang
450
451 Validate that the test case isn't an executable file with a
452 C<#!/usr/bin/perl> line (or similar). As F<bisect-runner.pl> does B<not>
453 prepend C<./perl> to the test case, a I<#!> line specifying an external
454 F<perl> binary will cause the test case to always run with I<that> F<perl>,
455 not the F<perl> built by the bisect runner. Likely this is not what you
456 wanted. If your test case is actually a wrapper script to run other
457 commands, you should run it with an explicit interpreter, to be clear. For
458 example, instead of C<../perl/Porting/bisect.pl ~/test/testcase.pl> you'd
459 run C<../perl/Porting/bisect.pl /usr/bin/perl ~/test/testcase.pl>
460
461 =item *
462
463 --usage
464
465 =item *
466
467 --help
468
469 =item *
470
471 -?
472
473 Display the usage information and exit.
474
475 =back
476
477 =cut
478
479 die "$0: Can't build $target" if defined $target && !grep {@targets} $target;
480
481 $j = "-j$j" if $j =~ /\A\d+\z/;
482
483 if (exists $options{make}) {
484     if (!exists $defines{make}) {
485         $defines{make} = $options{make};
486     }
487 } else {
488     $options{make} = 'make';
489 }
490
491 # Sadly, however hard we try, I don't think that it will be possible to build
492 # modules in ext/ on x86_64 Linux before commit e1666bf5602ae794 on 1999/12/29,
493 # which updated to MakeMaker 3.7, which changed from using a hard coded ld
494 # in the Makefile to $(LD). On x86_64 Linux the "linker" is gcc.
495
496 sub open_or_die {
497     my $file = shift;
498     my $mode = @_ ? shift : '<';
499     open my $fh, $mode, $file or croak("Can't open $file: $!");
500     ${*$fh{SCALAR}} = $file;
501     return $fh;
502 }
503
504 sub close_or_die {
505     my $fh = shift;
506     return if close $fh;
507     croak("Can't close: $!") unless ref $fh eq 'GLOB';
508     croak("Can't close ${*$fh{SCALAR}}: $!");
509 }
510
511 sub extract_from_file {
512     my ($file, $rx, $default) = @_;
513     my $fh = open_or_die($file);
514     while (<$fh>) {
515         my @got = $_ =~ $rx;
516         return wantarray ? @got : $got[0]
517             if @got;
518     }
519     return $default if defined $default;
520     return;
521 }
522
523 sub edit_file {
524     my ($file, $munger) = @_;
525     local $/;
526     my $fh = open_or_die($file);
527     my $orig = <$fh>;
528     die "Can't read $file: $!" unless defined $orig && close $fh;
529     my $new = $munger->($orig);
530     return if $new eq $orig;
531     $fh = open_or_die($file, '>');
532     print $fh $new or die "Can't print to $file: $!";
533     close_or_die($fh);
534 }
535
536 # AIX supplies a pre-historic patch program, which certainly predates Linux
537 # and is probably older than NT. It can't cope with unified diffs. Meanwhile,
538 # it's hard enough to get git diff to output context diffs, let alone git show,
539 # and nearly all the patches embedded here are unified. So it seems that the
540 # path of least resistance is to convert unified diffs to context diffs:
541
542 sub process_hunk {
543     my ($from_out, $to_out, $has_from, $has_to, $delete, $add) = @_;
544     ++$$has_from if $delete;
545     ++$$has_to if $add;
546
547     if ($delete && $add) {
548         $$from_out .= "! $_\n" foreach @$delete;
549         $$to_out .= "! $_\n" foreach @$add;
550     } elsif ($delete) {
551         $$from_out .= "- $_\n" foreach @$delete;
552     } elsif ($add) {
553          $$to_out .= "+ $_\n" foreach @$add;
554     }
555 }
556
557 # This isn't quite general purpose, as it can't cope with
558 # '\ No newline at end of file'
559 sub ud2cd {
560     my $diff_in = shift;
561     my $diff_out = '';
562
563     # Stuff before the diff
564     while ($diff_in =~ s/\A(?!\*\*\* )(?!--- )([^\n]*\n?)//ms && length $1) {
565         $diff_out .= $1;
566     }
567
568     if (!length $diff_in) {
569         die "That didn't seem to be a diff";
570     }
571
572     if ($diff_in =~ /\A\*\*\* /ms) {
573         warn "Seems to be a context diff already\n";
574         return $diff_out . $diff_in;
575     }
576
577     # Loop for files
578  FILE: while (1) {
579         if ($diff_in =~ s/\A((?:diff |index )[^\n]+\n)//ms) {
580             $diff_out .= $1;
581             next;
582         }
583         if ($diff_in !~ /\A--- /ms) {
584             # Stuff after the diff;
585             return $diff_out . $diff_in;
586         }
587         $diff_in =~ s/\A([^\n]+\n?)//ms;
588         my $line = $1;
589         die "Can't parse '$line'" unless $line =~ s/\A--- /*** /ms;
590         $diff_out .= $line;
591         $diff_in =~ s/\A([^\n]+\n?)//ms;
592         $line = $1;
593         die "Can't parse '$line'" unless $line =~ s/\A\+\+\+ /--- /ms;
594         $diff_out .= $line;
595
596         # Loop for hunks
597         while (1) {
598             next FILE
599                 unless $diff_in =~ s/\A\@\@ (-([0-9]+),([0-9]+) \+([0-9]+),([0-9]+)) \@\@[^\n]*\n?//;
600             my ($hunk, $from_start, $from_count, $to_start, $to_count)
601                 = ($1, $2, $3, $4, $5);
602             my $from_end = $from_start + $from_count - 1;
603             my $to_end = $to_start + $to_count - 1;
604             my ($from_out, $to_out, $has_from, $has_to, $add, $delete);
605             while (length $diff_in && ($from_count || $to_count)) {
606                 die "Confused in $hunk" unless $diff_in =~ s/\A([^\n]*)\n//ms;
607                 my $line = $1;
608                 $line = ' ' unless length $line;
609                 if ($line =~ /^ .*/) {
610                     process_hunk(\$from_out, \$to_out, \$has_from, \$has_to,
611                                  $delete, $add);
612                     undef $delete;
613                     undef $add;
614                     $from_out .= " $line\n";
615                     $to_out .= " $line\n";
616                     --$from_count;
617                     --$to_count;
618                 } elsif ($line =~ /^-(.*)/) {
619                     push @$delete, $1;
620                     --$from_count;
621                 } elsif ($line =~ /^\+(.*)/) {
622                     push @$add, $1;
623                     --$to_count;
624                 } else {
625                     die "Can't parse '$line' as part of hunk $hunk";
626                 }
627             }
628             process_hunk(\$from_out, \$to_out, \$has_from, \$has_to,
629                          $delete, $add);
630             die "No lines in hunk $hunk"
631                 unless length $from_out || length $to_out;
632             die "No changes in hunk $hunk"
633                 unless $has_from || $has_to;
634             $diff_out .= "***************\n";
635             $diff_out .= "*** $from_start,$from_end ****\n";
636             $diff_out .= $from_out if $has_from;
637             $diff_out .= "--- $to_start,$to_end ----\n";
638             $diff_out .= $to_out if $has_to;
639         }
640     }
641 }
642
643 {
644     my $use_context;
645
646     sub placate_patch_prog {
647         my $patch = shift;
648
649         if (!defined $use_context) {
650             my $version = `patch -v 2>&1`;
651             die "Can't run `patch -v`, \$?=$?, bailing out"
652                 unless defined $version;
653             if ($version =~ /Free Software Foundation/) {
654                 $use_context = 0;
655             } elsif ($version =~ /Header: patch\.c,v.*\blwall\b/) {
656                 # The system patch is older than Linux, and probably older than
657                 # Windows NT.
658                 $use_context = 1;
659             } else {
660                 # Don't know.
661                 $use_context = 0;
662             }
663         }
664
665         return $use_context ? ud2cd($patch) : $patch;
666     }
667 }
668
669 sub apply_patch {
670     my ($patch, $what, $files) = @_;
671     $what = 'patch' unless defined $what;
672     unless (defined $files) {
673         $patch =~ m!^--- a/(\S+)\n\+\+\+ b/\1!sm;
674         $files = " $1";
675     }
676     my $patch_to_use = placate_patch_prog($patch);
677     open my $fh, '|-', 'patch', '-p1' or die "Can't run patch: $!";
678     print $fh $patch_to_use;
679     return if close $fh;
680     print STDERR "Patch is <<'EOPATCH'\n${patch}EOPATCH\n";
681     print STDERR "\nConverted to a context diff <<'EOCONTEXT'\n${patch_to_use}EOCONTEXT\n"
682         if $patch_to_use ne $patch;
683     die "Can't $what$files: $?, $!";
684 }
685
686 sub apply_commit {
687     my ($commit, @files) = @_;
688     my $patch = `git show $commit @files`;
689     if (!defined $patch) {
690         die "Can't get commit $commit for @files: $?" if @files;
691         die "Can't get commit $commit: $?";
692     }
693     apply_patch($patch, "patch $commit", @files ? " for @files" : '');
694 }
695
696 sub revert_commit {
697     my ($commit, @files) = @_;
698     my $patch = `git show -R $commit @files`;
699     if (!defined $patch) {
700         die "Can't get revert commit $commit for @files: $?" if @files;
701         die "Can't get revert commit $commit: $?";
702     }
703     apply_patch($patch, "revert $commit", @files ? " for @files" : '');
704 }
705
706 sub checkout_file {
707     my ($file, $commit) = @_;
708     $commit ||= 'blead';
709     system "git show $commit:$file > $file </dev/null"
710         and die "Could not extract $file at revision $commit";
711 }
712
713 sub check_shebang {
714     my $file = shift;
715     return unless -e $file;
716     if (!-x $file) {
717         die "$file is not executable.
718 system($file, ...) is always going to fail.
719
720 Bailing out";
721     }
722     my $fh = open_or_die($file);
723     my $line = <$fh>;
724     return unless $line =~ m{\A#!(/\S+/perl\S*)\s};
725     die "$file will always be run by $1
726 It won't be tested by the ./perl we build.
727 If you intended to run it with that perl binary, please change your
728 test case to
729
730     $1 @ARGV
731
732 If you intended to test it with the ./perl we build, please change your
733 test case to
734
735     ./perl -Ilib @ARGV
736
737 [You may also need to add -- before ./perl to prevent that -Ilib as being
738 parsed as an argument to bisect.pl]
739
740 Bailing out";
741 }
742
743 sub clean {
744     if ($options{clean}) {
745         # Needed, because files that are build products in this checked out
746         # version might be in git in the next desired version.
747         system 'git clean -dxf </dev/null';
748         # Needed, because at some revisions the build alters checked out files.
749         # (eg pod/perlapi.pod). Also undoes any changes to makedepend.SH
750         system 'git reset --hard HEAD </dev/null';
751     }
752 }
753
754 sub skip {
755     my $reason = shift;
756     clean();
757     warn "skipping - $reason";
758     exit 125;
759 }
760
761 sub report_and_exit {
762     my ($ret, $pass, $fail, $desc) = @_;
763
764     clean();
765
766     my $got = ($options{'expect-pass'} ? !$ret : $ret) ? 'good' : 'bad';
767     if ($ret) {
768         print "$got - $fail $desc\n";
769     } else {
770         print "$got - $pass $desc\n";
771     }
772
773     exit($got eq 'bad');
774 }
775
776 sub match_and_exit {
777     my $target = shift;
778     my $matches = 0;
779     my $re = qr/$match/;
780     my @files;
781
782     {
783         local $/ = "\0";
784         @files = defined $target ? `git ls-files -o -z`: `git ls-files -z`;
785         chomp @files;
786     }
787
788     foreach my $file (@files) {
789         my $fh = open_or_die($file);
790         while (<$fh>) {
791             if ($_ =~ $re) {
792                 ++$matches;
793                 if (tr/\t\r\n -~\200-\377//c) {
794                     print "Binary file $file matches\n";
795                 } else {
796                     $_ .= "\n" unless /\n\z/;
797                     print "$file: $_";
798                 }
799             }
800         }
801         close_or_die($fh);
802     }
803     report_and_exit(!$matches,
804                     $matches == 1 ? '1 match for' : "$matches matches for",
805                     'no matches for', $match);
806 }
807
808 # Not going to assume that system perl is yet new enough to have autodie
809 system 'git clean -dxf </dev/null' and die;
810
811 if (!defined $target) {
812     match_and_exit() if $match;
813     $target = 'test_prep';
814 }
815
816 skip('no Configure - is this the //depot/perlext/Compiler branch?')
817     unless -f 'Configure';
818
819 my $case_insensitive;
820 {
821     my ($dev_C, $ino_C) = stat 'Configure';
822     die "Could not stat Configure: $!" unless defined $dev_C;
823     my ($dev_c, $ino_c) = stat 'configure';
824     ++$case_insensitive
825         if defined $dev_c && $dev_C == $dev_c && $ino_C == $ino_c;
826 }
827
828 # This changes to PERL_VERSION in 4d8076ea25903dcb in 1999
829 my $major
830     = extract_from_file('patchlevel.h',
831                         qr/^#define\s+(?:PERL_VERSION|PATCHLEVEL)\s+(\d+)\s/,
832                         0);
833
834 patch_Configure();
835 patch_hints();
836
837 # if Encode is not needed for the test, you can speed up the bisect by
838 # excluding it from the runs with -Dnoextensions=Encode
839 # ccache is an easy win. Remove it if it causes problems.
840 # Commit 1cfa4ec74d4933da adds ignore_versioned_solibs to Configure, and sets it
841 # to true in hints/linux.sh
842 # On dromedary, from that point on, Configure (by default) fails to find any
843 # libraries, because it scans /usr/local/lib /lib /usr/lib, which only contain
844 # versioned libraries. Without -lm, the build fails.
845 # Telling /usr/local/lib64 /lib64 /usr/lib64 works from that commit onwards,
846 # until commit faae14e6e968e1c0 adds it to the hints.
847 # However, prior to 1cfa4ec74d4933da telling Configure the truth doesn't work,
848 # because it will spot versioned libraries, pass them to the compiler, and then
849 # bail out pretty early on. Configure won't let us override libswanted, but it
850 # will let us override the entire libs list.
851
852 unless (extract_from_file('Configure', 'ignore_versioned_solibs')) {
853     # Before 1cfa4ec74d4933da, so force the libs list.
854
855     my @libs;
856     # This is the current libswanted list from Configure, less the libs removed
857     # by current hints/linux.sh
858     foreach my $lib (qw(sfio socket inet nsl nm ndbm gdbm dbm db malloc dl dld
859                         ld sun m crypt sec util c cposix posix ucb BSD)) {
860         foreach my $dir (@paths) {
861             next unless -f "$dir/lib$lib.so";
862             push @libs, "-l$lib";
863             last;
864         }
865     }
866     $defines{libs} = \@libs unless exists $defines{libs};
867 }
868
869 $defines{usenm} = undef
870     if $major < 2 && !exists $defines{usenm};
871
872 my ($missing, $created_dirs);
873 ($missing, $created_dirs) = force_manifest()
874     if $options{'force-manifest'};
875
876 my @ARGS = '-dEs';
877 foreach my $key (sort keys %defines) {
878     my $val = $defines{$key};
879     if (ref $val) {
880         push @ARGS, "-D$key=@$val";
881     } elsif (!defined $val) {
882         push @ARGS, "-U$key";
883     } elsif (!length $val) {
884         push @ARGS, "-D$key";
885     } else {
886         $val = "" if $val eq "\0";
887         push @ARGS, "-D$key=$val";
888     }
889 }
890 push @ARGS, map {"-A$_"} @{$options{A}};
891
892 # </dev/null because it seems that some earlier versions of Configure can
893 # call commands in a way that now has them reading from stdin (and hanging)
894 my $pid = fork;
895 die "Can't fork: $!" unless defined $pid;
896 if (!$pid) {
897     open STDIN, '<', '/dev/null';
898     # If a file in MANIFEST is missing, Configure asks if you want to
899     # continue (the default being 'n'). With stdin closed or /dev/null,
900     # it exits immediately and the check for config.sh below will skip.
901     exec './Configure', @ARGS;
902     die "Failed to start Configure: $!";
903 }
904 waitpid $pid, 0
905     or die "wait for Configure, pid $pid failed: $!";
906
907 patch_SH();
908
909 if (-f 'config.sh') {
910     # Emulate noextensions if Configure doesn't support it.
911     fake_noextensions()
912         if $major < 10 && $defines{noextensions};
913     system './Configure -S </dev/null' and die;
914 }
915
916 if ($target =~ /config\.s?h/) {
917     match_and_exit($target) if $match && -f $target;
918     report_and_exit(!-f $target, 'could build', 'could not build', $target)
919         if $options{'test-build'};
920
921     skip("could not build $target") unless -f $target;
922
923     my $ret = system @ARGV;
924     report_and_exit($ret, 'zero exit from', 'non-zero exit from', "@ARGV");
925 } elsif (!-f 'config.sh') {
926     # Skip if something went wrong with Configure
927
928     skip('could not build config.sh');
929 }
930
931 force_manifest_cleanup($missing, $created_dirs)
932         if $missing;
933
934 if($options{'force-regen'}
935    && extract_from_file('Makefile', qr/\bregen_headers\b/)) {
936     # regen_headers was added in e50aee73b3d4c555, patch.1m for perl5.001
937     # It's not worth faking it for earlier revisions.
938     system "make regen_headers </dev/null"
939         and die;
940 }
941
942 patch_C();
943 patch_ext();
944
945 # Parallel build for miniperl is safe
946 system "$options{make} $j miniperl </dev/null";
947
948 # This is the file we expect make to create
949 my $expected_file = $target =~ /^test/ ? 't/perl'
950     : $target eq 'Fcntl' ? "lib/auto/Fcntl/Fcntl.$Config{so}"
951     : $target;
952 # This is the target we tell make to build in order to get $expected_file
953 my $real_target = $target eq 'Fcntl' ? $expected_file : $target;
954
955 if ($target ne 'miniperl') {
956     # Nearly all parallel build issues fixed by 5.10.0. Untrustworthy before that.
957     $j = '' if $major < 10;
958
959     if ($real_target eq 'test_prep') {
960         if ($major < 8) {
961             # test-prep was added in 5.004_01, 3e3baf6d63945cb6.
962             # renamed to test_prep in 2001 in 5fe84fd29acaf55c.
963             # earlier than that, just make test. It will be fast enough.
964             $real_target = extract_from_file('Makefile.SH',
965                                              qr/^(test[-_]prep):/,
966                                              'test');
967         }
968     }
969
970     system "$options{make} $j $real_target </dev/null";
971 }
972
973 my $expected_file_found = $expected_file =~ /perl$/
974     ? -x $expected_file : -r $expected_file;
975
976 if ($expected_file_found && $expected_file eq 't/perl') {
977     # Check that it isn't actually pointing to ../miniperl, which will happen
978     # if the sanity check ./miniperl -Ilib -MExporter -e '<?>' fails, and
979     # Makefile tries to run minitest.
980
981     # Of course, helpfully sometimes it's called ../perl, other times .././perl
982     # and who knows if that list is exhaustive...
983     my ($dev0, $ino0) = stat 't/perl';
984     my ($dev1, $ino1) = stat 'perl';
985     unless (defined $dev0 && defined $dev1 && $dev0 == $dev1 && $ino0 == $ino1) {
986         undef $expected_file_found;
987         my $link = readlink $expected_file;
988         warn "'t/perl' => '$link', not 'perl'";
989         die "Could not realink t/perl: $!" unless defined $link;
990     }
991 }
992
993 if ($options{'test-build'}) {
994     report_and_exit(!$expected_file_found, 'could build', 'could not build',
995                     $real_target);
996 } elsif (!$expected_file_found) {
997     skip("could not build $real_target");
998 }
999
1000 match_and_exit($real_target) if $match;
1001
1002 if (defined $options{'one-liner'}) {
1003     my $exe = $target =~ /^(?:perl$|test)/ ? 'perl' : 'miniperl';
1004     unshift @ARGV, '-e', $options{'one-liner'};
1005     unshift @ARGV, '-l' if $options{l};
1006     unshift @ARGV, '-w' if $options{w};
1007     unshift @ARGV, "./$exe", '-Ilib';
1008 }
1009
1010 # This is what we came here to run:
1011
1012 if (exists $Config{ldlibpthname}) {
1013     require Cwd;
1014     my $varname = $Config{ldlibpthname};
1015     my $cwd = Cwd::getcwd();
1016     if (defined $ENV{$varname}) {
1017         $ENV{$varname} = $cwd . $Config{path_sep} . $ENV{$varname};
1018     } else {
1019         $ENV{$varname} = $cwd;
1020     }
1021 }
1022
1023 my $ret = system @ARGV;
1024
1025 report_and_exit($ret, 'zero exit from', 'non-zero exit from', "@ARGV");
1026
1027 ############################################################################
1028 #
1029 # Patching, editing and faking routines only below here.
1030 #
1031 ############################################################################
1032
1033 sub fake_noextensions {
1034     edit_file('config.sh', sub {
1035                   my @lines = split /\n/, shift;
1036                   my @ext = split /\s+/, $defines{noextensions};
1037                   foreach (@lines) {
1038                       next unless /^extensions=/ || /^dynamic_ext/;
1039                       foreach my $ext (@ext) {
1040                           s/\b$ext( )?\b/$1/;
1041                       }
1042                   }
1043                   return join "\n", @lines;
1044               });
1045 }
1046
1047 sub force_manifest {
1048     my (@missing, @created_dirs);
1049     my $fh = open_or_die('MANIFEST');
1050     while (<$fh>) {
1051         next unless /^(\S+)/;
1052         # -d is special case needed (at least) between 27332437a2ed1941 and
1053         # bf3d9ec563d25054^ inclusive, as manifest contains ext/Thread/Thread
1054         push @missing, $1
1055             unless -f $1 || -d $1;
1056     }
1057     close_or_die($fh);
1058
1059     foreach my $pathname (@missing) {
1060         my @parts = split '/', $pathname;
1061         my $leaf = pop @parts;
1062         my $path = '.';
1063         while (@parts) {
1064             $path .= '/' . shift @parts;
1065             next if -d $path;
1066             mkdir $path, 0700 or die "Can't create $path: $!";
1067             unshift @created_dirs, $path;
1068         }
1069         $fh = open_or_die($pathname, '>');
1070         close_or_die($fh);
1071         chmod 0, $pathname or die "Can't chmod 0 $pathname: $!";
1072     }
1073     return \@missing, \@created_dirs;
1074 }
1075
1076 sub force_manifest_cleanup {
1077     my ($missing, $created_dirs) = @_;
1078     # This is probably way too paranoid:
1079     my @errors;
1080     require Fcntl;
1081     foreach my $file (@$missing) {
1082         my (undef, undef, $mode, undef, undef, undef, undef, $size)
1083             = stat $file;
1084         if (!defined $mode) {
1085             push @errors, "Added file $file has been deleted by Configure";
1086             next;
1087         }
1088         if (Fcntl::S_IMODE($mode) != 0) {
1089             push @errors,
1090                 sprintf 'Added file %s had mode changed by Configure to %03o',
1091                     $file, $mode;
1092         }
1093         if ($size != 0) {
1094             push @errors,
1095                 "Added file $file had sized changed by Configure to $size";
1096         }
1097         unlink $file or die "Can't unlink $file: $!";
1098     }
1099     foreach my $dir (@$created_dirs) {
1100         rmdir $dir or die "Can't rmdir $dir: $!";
1101     }
1102     skip("@errors")
1103         if @errors;
1104 }
1105
1106 sub patch_Configure {
1107     if ($major < 1) {
1108         if (extract_from_file('Configure',
1109                               qr/^\t\t\*=\*\) echo "\$1" >> \$optdef;;$/)) {
1110             # This is "        Spaces now allowed in -D command line options.",
1111             # part of commit ecfc54246c2a6f42
1112             apply_patch(<<'EOPATCH');
1113 diff --git a/Configure b/Configure
1114 index 3d3b38d..78ffe16 100755
1115 --- a/Configure
1116 +++ b/Configure
1117 @@ -652,7 +777,8 @@ while test $# -gt 0; do
1118                         echo "$me: use '-U symbol=', not '-D symbol='." >&2
1119                         echo "$me: ignoring -D $1" >&2
1120                         ;;
1121 -               *=*) echo "$1" >> $optdef;;
1122 +               *=*) echo "$1" | \
1123 +                               sed -e "s/'/'\"'\"'/g" -e "s/=\(.*\)/='\1'/" >> $optdef;;
1124                 *) echo "$1='define'" >> $optdef;;
1125                 esac
1126                 shift
1127 EOPATCH
1128         }
1129
1130         if (extract_from_file('Configure', qr/^if \$contains 'd_namlen' \$xinc\b/)) {
1131             # Configure's original simple "grep" for d_namlen falls foul of the
1132             # approach taken by the glibc headers:
1133             # #ifdef _DIRENT_HAVE_D_NAMLEN
1134             # # define _D_EXACT_NAMLEN(d) ((d)->d_namlen)
1135             #
1136             # where _DIRENT_HAVE_D_NAMLEN is not defined on Linux.
1137             # This is also part of commit ecfc54246c2a6f42
1138             apply_patch(<<'EOPATCH');
1139 diff --git a/Configure b/Configure
1140 index 3d3b38d..78ffe16 100755
1141 --- a/Configure
1142 +++ b/Configure
1143 @@ -3935,7 +4045,8 @@ $rm -f try.c
1144  
1145  : see if the directory entry stores field length
1146  echo " "
1147 -if $contains 'd_namlen' $xinc >/dev/null 2>&1; then
1148 +$cppstdin $cppflags $cppminus < "$xinc" > try.c
1149 +if $contains 'd_namlen' try.c >/dev/null 2>&1; then
1150         echo "Good, your directory entry keeps length information in d_namlen." >&4
1151         val="$define"
1152  else
1153 EOPATCH
1154         }
1155     }
1156
1157     if ($major < 2
1158         && !extract_from_file('Configure',
1159                               qr/Try to guess additional flags to pick up local libraries/)) {
1160         my $mips = extract_from_file('Configure',
1161                                      qr!(''\) if (?:\./)?mips; then)!);
1162         # This is part of perl-5.001n. It's needed, to add -L/usr/local/lib to
1163         # theld flags if libraries are found there. It shifts the code to set up
1164         # libpth earlier, and then adds the code to add libpth entries to
1165         # ldflags
1166         # mips was changed to ./mips in ecfc54246c2a6f42, perl5.000 patch.0g
1167         apply_patch(sprintf <<'EOPATCH', $mips);
1168 diff --git a/Configure b/Configure
1169 index 53649d5..0635a6e 100755
1170 --- a/Configure
1171 +++ b/Configure
1172 @@ -2749,6 +2749,52 @@ EOM
1173         ;;
1174  esac
1175  
1176 +: Set private lib path
1177 +case "$plibpth" in
1178 +'') if ./mips; then
1179 +               plibpth="$incpath/usr/lib /usr/local/lib /usr/ccs/lib"
1180 +       fi;;
1181 +esac
1182 +case "$libpth" in
1183 +' ') dlist='';;
1184 +'') dlist="$plibpth $glibpth";;
1185 +*) dlist="$libpth";;
1186 +esac
1187 +
1188 +: Now check and see which directories actually exist, avoiding duplicates
1189 +libpth=''
1190 +for xxx in $dlist
1191 +do
1192 +    if $test -d $xxx; then
1193 +               case " $libpth " in
1194 +               *" $xxx "*) ;;
1195 +               *) libpth="$libpth $xxx";;
1196 +               esac
1197 +    fi
1198 +done
1199 +$cat <<'EOM'
1200 +
1201 +Some systems have incompatible or broken versions of libraries.  Among
1202 +the directories listed in the question below, please remove any you
1203 +know not to be holding relevant libraries, and add any that are needed.
1204 +Say "none" for none.
1205 +
1206 +EOM
1207 +case "$libpth" in
1208 +'') dflt='none';;
1209 +*)
1210 +       set X $libpth
1211 +       shift
1212 +       dflt=${1+"$@"}
1213 +       ;;
1214 +esac
1215 +rp="Directories to use for library searches?"
1216 +. ./myread
1217 +case "$ans" in
1218 +none) libpth=' ';;
1219 +*) libpth="$ans";;
1220 +esac
1221 +
1222  : flags used in final linking phase
1223  case "$ldflags" in
1224  '') if ./venix; then
1225 @@ -2765,6 +2811,23 @@ case "$ldflags" in
1226         ;;
1227  *) dflt="$ldflags";;
1228  esac
1229 +
1230 +: Possible local library directories to search.
1231 +loclibpth="/usr/local/lib /opt/local/lib /usr/gnu/lib"
1232 +loclibpth="$loclibpth /opt/gnu/lib /usr/GNU/lib /opt/GNU/lib"
1233 +
1234 +: Try to guess additional flags to pick up local libraries.
1235 +for thislibdir in $libpth; do
1236 +       case " $loclibpth " in
1237 +       *" $thislibdir "*)
1238 +               case "$dflt " in 
1239 +               "-L$thislibdir ") ;;
1240 +               *)  dflt="$dflt -L$thislibdir" ;;
1241 +               esac
1242 +               ;;
1243 +       esac
1244 +done
1245 +
1246  echo " "
1247  rp="Any additional ld flags (NOT including libraries)?"
1248  . ./myread
1249 @@ -2828,52 +2891,6 @@ n) echo "OK, that should do.";;
1250  esac
1251  $rm -f try try.* core
1252  
1253 -: Set private lib path
1254 -case "$plibpth" in
1255 -%s
1256 -               plibpth="$incpath/usr/lib /usr/local/lib /usr/ccs/lib"
1257 -       fi;;
1258 -esac
1259 -case "$libpth" in
1260 -' ') dlist='';;
1261 -'') dlist="$plibpth $glibpth";;
1262 -*) dlist="$libpth";;
1263 -esac
1264 -
1265 -: Now check and see which directories actually exist, avoiding duplicates
1266 -libpth=''
1267 -for xxx in $dlist
1268 -do
1269 -    if $test -d $xxx; then
1270 -               case " $libpth " in
1271 -               *" $xxx "*) ;;
1272 -               *) libpth="$libpth $xxx";;
1273 -               esac
1274 -    fi
1275 -done
1276 -$cat <<'EOM'
1277 -
1278 -Some systems have incompatible or broken versions of libraries.  Among
1279 -the directories listed in the question below, please remove any you
1280 -know not to be holding relevant libraries, and add any that are needed.
1281 -Say "none" for none.
1282 -
1283 -EOM
1284 -case "$libpth" in
1285 -'') dflt='none';;
1286 -*)
1287 -       set X $libpth
1288 -       shift
1289 -       dflt=${1+"$@"}
1290 -       ;;
1291 -esac
1292 -rp="Directories to use for library searches?"
1293 -. ./myread
1294 -case "$ans" in
1295 -none) libpth=' ';;
1296 -*) libpth="$ans";;
1297 -esac
1298 -
1299  : compute shared library extension
1300  case "$so" in
1301  '')
1302 EOPATCH
1303     }
1304
1305     if ($major < 5 && extract_from_file('Configure',
1306                                         qr!if \$cc \$ccflags try\.c -o try >/dev/null 2>&1; then!)) {
1307         # Analogous to the more general fix of dfe9444ca7881e71
1308         # Without this flags such as -m64 may not be passed to this compile,
1309         # which results in a byteorder of '1234' instead of '12345678', which
1310         # can then cause crashes.
1311
1312         if (extract_from_file('Configure', qr/xxx_prompt=y/)) {
1313             # 8e07c86ebc651fe9 or later
1314             # ("This is my patch  patch.1n  for perl5.001.")
1315             apply_patch(<<'EOPATCH');
1316 diff --git a/Configure b/Configure
1317 index 62249dd..c5c384e 100755
1318 --- a/Configure
1319 +++ b/Configure
1320 @@ -8247,7 +8247,7 @@ main()
1321  }
1322  EOCP
1323         xxx_prompt=y
1324 -       if $cc $ccflags try.c -o try >/dev/null 2>&1 && ./try > /dev/null; then
1325 +       if $cc $ccflags $ldflags try.c -o try >/dev/null 2>&1 && ./try > /dev/null; then
1326                 dflt=`./try`
1327                 case "$dflt" in
1328                 [1-4][1-4][1-4][1-4]|12345678|87654321)
1329 EOPATCH
1330         } else {
1331             apply_patch(<<'EOPATCH');
1332 diff --git a/Configure b/Configure
1333 index 53649d5..f1cd64a 100755
1334 --- a/Configure
1335 +++ b/Configure
1336 @@ -6362,7 +6362,7 @@ main()
1337         printf("\n");
1338  }
1339  EOCP
1340 -       if $cc $ccflags try.c -o try >/dev/null 2>&1 ; then
1341 +       if $cc $ccflags $ldflags try.c -o try >/dev/null 2>&1 ; then
1342                 dflt=`./try`
1343                 case "$dflt" in
1344                 ????|????????) echo "(The test program ran ok.)";;
1345 EOPATCH
1346         }
1347     }
1348
1349     if ($major < 6 && !extract_from_file('Configure',
1350                                          qr!^\t-A\)$!)) {
1351         # This adds the -A option to Configure, which is incredibly useful
1352         # Effectively this is commits 02e93a22d20fc9a5, 5f83a3e9d818c3ad,
1353         # bde6b06b2c493fef, f7c3111703e46e0c and 2 lines of trailing whitespace
1354         # removed by 613d6c3e99b9decc, but applied at slightly different
1355         # locations to ensure a clean patch back to 5.000
1356         # Note, if considering patching to the intermediate revisions to fix
1357         # bugs in -A handling, f7c3111703e46e0c is from 2002, and hence
1358         # $major == 8
1359
1360         # To add to the fun, early patches add -K and -O options, and it's not
1361         # trivial to get patch to put the C<. ./posthint.sh> in the right place
1362         edit_file('Configure', sub {
1363                       my $code = shift;
1364                       $code =~ s/(optstr = ")([^"]+";\s*# getopt-style specification)/$1A:$2/
1365                           or die "Substitution failed";
1366                       $code =~ s!^(: who configured the system)!
1367 touch posthint.sh
1368 . ./posthint.sh
1369
1370 $1!ms
1371                           or die "Substitution failed";
1372                       return $code;
1373                   });
1374         apply_patch(<<'EOPATCH');
1375 diff --git a/Configure b/Configure
1376 index 4b55fa6..60c3c64 100755
1377 --- a/Configure
1378 +++ b/Configure
1379 @@ -1150,6 +1150,7 @@ set X `for arg in "$@"; do echo "X$arg"; done |
1380  eval "set $*"
1381  shift
1382  rm -f options.awk
1383 +rm -f posthint.sh
1384  
1385  : set up default values
1386  fastread=''
1387 @@ -1172,6 +1173,56 @@ while test $# -gt 0; do
1388         case "$1" in
1389         -d) shift; fastread=yes;;
1390         -e) shift; alldone=cont;;
1391 +       -A)
1392 +           shift
1393 +           xxx=''
1394 +           yyy="$1"
1395 +           zzz=''
1396 +           uuu=undef
1397 +           case "$yyy" in
1398 +            *=*) zzz=`echo "$yyy"|sed 's!=.*!!'`
1399 +                 case "$zzz" in
1400 +                 *:*) zzz='' ;;
1401 +                 *)   xxx=append
1402 +                      zzz=" "`echo "$yyy"|sed 's!^[^=]*=!!'`
1403 +                      yyy=`echo "$yyy"|sed 's!=.*!!'` ;;
1404 +                 esac
1405 +                 ;;
1406 +            esac
1407 +            case "$xxx" in
1408 +            '')  case "$yyy" in
1409 +                 *:*) xxx=`echo "$yyy"|sed 's!:.*!!'`
1410 +                      yyy=`echo "$yyy"|sed 's!^[^:]*:!!'`
1411 +                      zzz=`echo "$yyy"|sed 's!^[^=]*=!!'`
1412 +                      yyy=`echo "$yyy"|sed 's!=.*!!'` ;;
1413 +                 *)   xxx=`echo "$yyy"|sed 's!:.*!!'`
1414 +                      yyy=`echo "$yyy"|sed 's!^[^:]*:!!'` ;;
1415 +                 esac
1416 +                 ;;
1417 +            esac
1418 +           case "$xxx" in
1419 +           append)
1420 +               echo "$yyy=\"\${$yyy}$zzz\""    >> posthint.sh ;;
1421 +           clear)
1422 +               echo "$yyy=''"                  >> posthint.sh ;;
1423 +           define)
1424 +               case "$zzz" in
1425 +               '') zzz=define ;;
1426 +               esac
1427 +               echo "$yyy='$zzz'"              >> posthint.sh ;;
1428 +           eval)
1429 +               echo "eval \"$yyy=$zzz\""       >> posthint.sh ;;
1430 +           prepend)
1431 +               echo "$yyy=\"$zzz\${$yyy}\""    >> posthint.sh ;;
1432 +           undef)
1433 +               case "$zzz" in
1434 +               '') zzz="$uuu" ;;
1435 +               esac
1436 +               echo "$yyy=$zzz"                >> posthint.sh ;;
1437 +            *)  echo "$me: unknown -A command '$xxx', ignoring -A $1" >&2 ;;
1438 +           esac
1439 +           shift
1440 +           ;;
1441         -f)
1442                 shift
1443                 cd ..
1444 EOPATCH
1445     }
1446
1447     if ($major < 8 && $^O eq 'aix') {
1448         edit_file('Configure', sub {
1449                       my $code = shift;
1450                       # Replicate commit a8c676c69574838b
1451                       # Whitespace allowed at the ends of /lib/syscalls.exp lines
1452                       # and half of commit c6912327ae30e6de
1453                       # AIX syscalls.exp scan: the syscall might be marked 32, 3264, or 64
1454                       $code =~ s{(\bsed\b.*\bsyscall)(?:\[0-9\]\*)?(\$.*/lib/syscalls\.exp)}
1455                                 {$1 . "[0-9]*[ \t]*" . $2}e;
1456                       return $code;
1457                   });
1458     }
1459
1460     if ($major < 8 && !extract_from_file('Configure',
1461                                          qr/^\t\tif test ! -t 0; then$/)) {
1462         # Before dfe9444ca7881e71, Configure would refuse to run if stdin was
1463         # not a tty. With that commit, the tty requirement was dropped for -de
1464         # and -dE
1465         # Commit aaeb8e512e8e9e14 dropped the tty requirement for -S
1466         # For those older versions, it's probably easiest if we simply remove
1467         # the sanity test.
1468         edit_file('Configure', sub {
1469                       my $code = shift;
1470                       $code =~ s/test ! -t 0/test Perl = rules/;
1471                       return $code;
1472                   });
1473     }
1474
1475     if ($major == 8 || $major == 9) {
1476         # Fix symbol detection to that of commit 373dfab3839ca168 if it's any
1477         # intermediate version 5129fff43c4fe08c or later, as the intermediate
1478         # versions don't work correctly on (at least) Sparc Linux.
1479         # 5129fff43c4fe08c adds the first mention of mistrustnm.
1480         # 373dfab3839ca168 removes the last mention of lc=""
1481         edit_file('Configure', sub {
1482                       my $code = shift;
1483                       return $code
1484                           if $code !~ /\btc="";/; # 373dfab3839ca168 or later
1485                       return $code
1486                           if $code !~ /\bmistrustnm\b/; # before 5129fff43c4fe08c
1487                       my $fixed = <<'EOC';
1488
1489 : is a C symbol defined?
1490 csym='tlook=$1;
1491 case "$3" in
1492 -v) tf=libc.tmp; tdc="";;
1493 -a) tf=libc.tmp; tdc="[]";;
1494 *) tlook="^$1\$"; tf=libc.list; tdc="()";;
1495 esac;
1496 tx=yes;
1497 case "$reuseval-$4" in
1498 true-) ;;
1499 true-*) tx=no; eval "tval=\$$4"; case "$tval" in "") tx=yes;; esac;;
1500 esac;
1501 case "$tx" in
1502 yes)
1503         tval=false;
1504         if $test "$runnm" = true; then
1505                 if $contains $tlook $tf >/dev/null 2>&1; then
1506                         tval=true;
1507                 elif $test "$mistrustnm" = compile -o "$mistrustnm" = run; then
1508                         echo "void *(*(p()))$tdc { extern void *$1$tdc; return &$1; } int main() { if(p()) return(0); else return(1); }"> try.c;
1509                         $cc -o try $optimize $ccflags $ldflags try.c >/dev/null 2>&1 $libs && tval=true;
1510                         $test "$mistrustnm" = run -a -x try && { $run ./try$_exe >/dev/null 2>&1 || tval=false; };
1511                         $rm -f try$_exe try.c core core.* try.core;
1512                 fi;
1513         else
1514                 echo "void *(*(p()))$tdc { extern void *$1$tdc; return &$1; } int main() { if(p()) return(0); else return(1); }"> try.c;
1515                 $cc -o try $optimize $ccflags $ldflags try.c $libs >/dev/null 2>&1 && tval=true;
1516                 $rm -f try$_exe try.c;
1517         fi;
1518         ;;
1519 *)
1520         case "$tval" in
1521         $define) tval=true;;
1522         *) tval=false;;
1523         esac;
1524         ;;
1525 esac;
1526 eval "$2=$tval"'
1527
1528 EOC
1529                       $code =~ s/\n: is a C symbol defined\?\n.*?\neval "\$2=\$tval"'\n\n/$fixed/sm
1530                           or die "substitution failed";
1531                       return $code;
1532                   });
1533     }
1534
1535     if ($major < 10
1536         && extract_from_file('Configure', qr/^set malloc\.h i_malloc$/)) {
1537         # This is commit 01d07975f7ef0e7d, trimmed, with $compile inlined as
1538         # prior to bd9b35c97ad661cc Configure had the malloc.h test before the
1539         # definition of $compile.
1540         apply_patch(<<'EOPATCH');
1541 diff --git a/Configure b/Configure
1542 index 3d2e8b9..6ce7766 100755
1543 --- a/Configure
1544 +++ b/Configure
1545 @@ -6743,5 +6743,22 @@ set d_dosuid
1546  
1547  : see if this is a malloc.h system
1548 -set malloc.h i_malloc
1549 -eval $inhdr
1550 +: we want a real compile instead of Inhdr because some systems have a
1551 +: malloc.h that just gives a compile error saying to use stdlib.h instead
1552 +echo " "
1553 +$cat >try.c <<EOCP
1554 +#include <stdlib.h>
1555 +#include <malloc.h>
1556 +int main () { return 0; }
1557 +EOCP
1558 +set try
1559 +if $cc $optimize $ccflags $ldflags -o try $* try.c $libs > /dev/null 2>&1; then
1560 +    echo "<malloc.h> found." >&4
1561 +    val="$define"
1562 +else
1563 +    echo "<malloc.h> NOT found." >&4
1564 +    val="$undef"
1565 +fi
1566 +$rm -f try.c try
1567 +set i_malloc
1568 +eval $setvar
1569  
1570 EOPATCH
1571     }
1572 }
1573
1574 sub patch_hints {
1575     if ($^O eq 'freebsd') {
1576         # There are rather too many version-specific FreeBSD hints fixes to
1577         # patch individually. Also, more than once the FreeBSD hints file has
1578         # been written in what turned out to be a rather non-future-proof style,
1579         # with case statements treating the most recent version as the
1580         # exception, instead of treating previous versions' behaviour explicitly
1581         # and changing the default to cater for the current behaviour. (As
1582         # strangely, future versions inherit the current behaviour.)
1583         checkout_file('hints/freebsd.sh');
1584     } elsif ($^O eq 'darwin') {
1585         if ($major < 8) {
1586             # We can't build on darwin without some of the data in the hints
1587             # file. Probably less surprising to use the earliest version of
1588             # hints/darwin.sh and then edit in place just below, than use
1589             # blead's version, as that would create a discontinuity at
1590             # f556e5b971932902 - before it, hints bugs would be "fixed", after
1591             # it they'd resurface. This way, we should give the illusion of
1592             # monotonic bug fixing.
1593             my $faking_it;
1594             if (!-f 'hints/darwin.sh') {
1595                 checkout_file('hints/darwin.sh', 'f556e5b971932902');
1596                 ++$faking_it;
1597             }
1598
1599             edit_file('hints/darwin.sh', sub {
1600                       my $code = shift;
1601                       # Part of commit 8f4f83badb7d1ba9, which mostly undoes
1602                       # commit 0511a818910f476c.
1603                       $code =~ s/^cppflags='-traditional-cpp';$/cppflags="\${cppflags} -no-cpp-precomp"/m;
1604                       # commit 14c11978e9b52e08/803bb6cc74d36a3f
1605                       # Without this, code in libperl.bundle links against op.o
1606                       # in preference to opmini.o on the linker command line,
1607                       # and hence miniperl tries to use File::Glob instead of
1608                       # csh
1609                       $code =~ s/^(lddlflags=)/ldflags="\${ldflags} -flat_namespace"\n$1/m;
1610                       # f556e5b971932902 also patches Makefile.SH with some
1611                       # special case code to deal with useshrplib for darwin.
1612                       # Given that post 5.8.0 the darwin hints default was
1613                       # changed to false, and it would be very complex to splice
1614                       # in that code in various versions of Makefile.SH back
1615                       # to 5.002, lets just turn it off.
1616                       $code =~ s/^useshrplib='true'/useshrplib='false'/m
1617                           if $faking_it;
1618
1619                       # Part of commit d235852b65d51c44
1620                       # Don't do this on a case sensitive HFS+ partition, as it
1621                       # breaks the build for 5.003 and earlier.
1622                       if ($case_insensitive
1623                           && $code !~ /^firstmakefile=GNUmakefile/) {
1624                           $code .= "\nfirstmakefile=GNUmakefile;\n";
1625                       }
1626
1627                       return $code;
1628                   });
1629         }
1630     } elsif ($^O eq 'netbsd') {
1631         if ($major < 6) {
1632             # These are part of commit 099685bc64c7dbce
1633             edit_file('hints/netbsd.sh', sub {
1634                           my $code = shift;
1635                           my $fixed = <<'EOC';
1636 case "$osvers" in
1637 0.9|0.8*)
1638         usedl="$undef"
1639         ;;
1640 *)
1641         if [ -f /usr/libexec/ld.elf_so ]; then
1642                 d_dlopen=$define
1643                 d_dlerror=$define
1644                 ccdlflags="-Wl,-E -Wl,-R${PREFIX}/lib $ccdlflags"
1645                 cccdlflags="-DPIC -fPIC $cccdlflags"
1646                 lddlflags="--whole-archive -shared $lddlflags"
1647         elif [ "`uname -m`" = "pmax" ]; then
1648 # NetBSD 1.3 and 1.3.1 on pmax shipped an 'old' ld.so, which will not work.
1649                 d_dlopen=$undef
1650         elif [ -f /usr/libexec/ld.so ]; then
1651                 d_dlopen=$define
1652                 d_dlerror=$define
1653                 ccdlflags="-Wl,-R${PREFIX}/lib $ccdlflags"
1654 # we use -fPIC here because -fpic is *NOT* enough for some of the
1655 # extensions like Tk on some netbsd platforms (the sparc is one)
1656                 cccdlflags="-DPIC -fPIC $cccdlflags"
1657                 lddlflags="-Bforcearchive -Bshareable $lddlflags"
1658         else
1659                 d_dlopen=$undef
1660         fi
1661         ;;
1662 esac
1663 EOC
1664                           $code =~ s/^case "\$osvers" in\n0\.9\|0\.8.*?^esac\n/$fixed/ms;
1665                           return $code;
1666                       });
1667         }
1668     } elsif ($^O eq 'openbsd') {
1669         if ($major < 8) {
1670             checkout_file('hints/openbsd.sh', '43051805d53a3e4c')
1671                 unless -f 'hints/openbsd.sh';
1672             my $which = extract_from_file('hints/openbsd.sh',
1673                                           qr/# from (2\.8|3\.1) onwards/,
1674                                           '');
1675             if ($which eq '') {
1676                 my $was = extract_from_file('hints/openbsd.sh',
1677                                             qr/(lddlflags="(?:-Bforcearchive )?-Bshareable)/);
1678                 # This is commit 154d43cbcf57271c and parts of 5c75dbfa77b0949c
1679                 # and 29b5585702e5e025
1680                 apply_patch(sprintf <<'EOPATCH', $was);
1681 diff --git a/hints/openbsd.sh b/hints/openbsd.sh
1682 index a7d8bf2..5b79709 100644
1683 --- a/hints/openbsd.sh
1684 +++ b/hints/openbsd.sh
1685 @@ -37,7 +37,25 @@ OpenBSD.alpha|OpenBSD.mips|OpenBSD.powerpc|OpenBSD.vax)
1686         # we use -fPIC here because -fpic is *NOT* enough for some of the
1687         # extensions like Tk on some OpenBSD platforms (ie: sparc)
1688         cccdlflags="-DPIC -fPIC $cccdlflags"
1689 -       %s $lddlflags"
1690 +       case "$osvers" in
1691 +       [01].*|2.[0-7]|2.[0-7].*)
1692 +               lddlflags="-Bshareable $lddlflags"
1693 +               ;;
1694 +       2.[8-9]|3.0)
1695 +               ld=${cc:-cc}
1696 +               lddlflags="-shared -fPIC $lddlflags"
1697 +               ;;
1698 +       *) # from 3.1 onwards
1699 +               ld=${cc:-cc}
1700 +               lddlflags="-shared -fPIC $lddlflags"
1701 +               libswanted=`echo $libswanted | sed 's/ dl / /'`
1702 +               ;;
1703 +       esac
1704 +
1705 +       # We need to force ld to export symbols on ELF platforms.
1706 +       # Without this, dlopen() is crippled.
1707 +       ELF=`${cc:-cc} -dM -E - </dev/null | grep __ELF__`
1708 +       test -n "$ELF" && ldflags="-Wl,-E $ldflags"
1709         ;;
1710  esac
1711  
1712 EOPATCH
1713             } elsif ($which eq '2.8') {
1714                 # This is parts of 5c75dbfa77b0949c and 29b5585702e5e025, and
1715                 # possibly eb9cd59d45ad2908
1716                 my $was = extract_from_file('hints/openbsd.sh',
1717                                             qr/lddlflags="(-shared(?: -fPIC)?) \$lddlflags"/);
1718
1719                 apply_patch(sprintf <<'EOPATCH', $was);
1720 --- a/hints/openbsd.sh  2011-10-21 17:25:20.000000000 +0200
1721 +++ b/hints/openbsd.sh  2011-10-21 16:58:43.000000000 +0200
1722 @@ -44,11 +44,21 @@
1723         [01].*|2.[0-7]|2.[0-7].*)
1724                 lddlflags="-Bshareable $lddlflags"
1725                 ;;
1726 -       *) # from 2.8 onwards
1727 +       2.[8-9]|3.0)
1728                 ld=${cc:-cc}
1729 -               lddlflags="%s $lddlflags"
1730 +               lddlflags="-shared -fPIC $lddlflags"
1731 +               ;;
1732 +       *) # from 3.1 onwards
1733 +               ld=${cc:-cc}
1734 +               lddlflags="-shared -fPIC $lddlflags"
1735 +               libswanted=`echo $libswanted | sed 's/ dl / /'`
1736                 ;;
1737         esac
1738 +
1739 +       # We need to force ld to export symbols on ELF platforms.
1740 +       # Without this, dlopen() is crippled.
1741 +       ELF=`${cc:-cc} -dM -E - </dev/null | grep __ELF__`
1742 +       test -n "$ELF" && ldflags="-Wl,-E $ldflags"
1743         ;;
1744  esac
1745  
1746 EOPATCH
1747             } elsif ($which eq '3.1'
1748                      && !extract_from_file('hints/openbsd.sh',
1749                                            qr/We need to force ld to export symbols on ELF platforms/)) {
1750                 # This is part of 29b5585702e5e025
1751                 apply_patch(<<'EOPATCH');
1752 diff --git a/hints/openbsd.sh b/hints/openbsd.sh
1753 index c6b6bc9..4839d04 100644
1754 --- a/hints/openbsd.sh
1755 +++ b/hints/openbsd.sh
1756 @@ -54,6 +54,11 @@ alpha-2.[0-8]|mips-*|vax-*|powerpc-2.[0-7]|m88k-*)
1757                 libswanted=`echo $libswanted | sed 's/ dl / /'`
1758                 ;;
1759         esac
1760 +
1761 +       # We need to force ld to export symbols on ELF platforms.
1762 +       # Without this, dlopen() is crippled.
1763 +       ELF=`${cc:-cc} -dM -E - </dev/null | grep __ELF__`
1764 +       test -n "$ELF" && ldflags="-Wl,-E $ldflags"
1765         ;;
1766  esac
1767  
1768 EOPATCH
1769             }
1770         }
1771     } elsif ($^O eq 'linux') {
1772         if ($major < 1) {
1773             # sparc linux seems to need the -Dbool=char -DHAS_BOOL part of
1774             # perl5.000 patch.0n: [address Configure and build issues]
1775             edit_file('hints/linux.sh', sub {
1776                           my $code = shift;
1777                           $code =~ s!-I/usr/include/bsd!-Dbool=char -DHAS_BOOL!g;
1778                           return $code;
1779                       });
1780         }
1781
1782         if ($major <= 9) {
1783             if (`uname -sm` =~ qr/^Linux sparc/) {
1784                 if (extract_from_file('hints/linux.sh', qr/sparc-linux/)) {
1785                     # Be sure to use -fPIC not -fpic on Linux/SPARC
1786                     apply_commit('f6527d0ef0c13ad4');
1787                 } elsif(!extract_from_file('hints/linux.sh',
1788                                            qr/^sparc-linux\)$/)) {
1789                     my $fh = open_or_die('hints/linux.sh', '>>');
1790                     print $fh <<'EOT' or die $!;
1791
1792 case "`uname -m`" in
1793 sparc*)
1794         case "$cccdlflags" in
1795         *-fpic*) cccdlflags="`echo $cccdlflags|sed 's/-fpic/-fPIC/'`" ;;
1796         *)       cccdlflags="$cccdlflags -fPIC" ;;
1797         esac
1798         ;;
1799 esac
1800 EOT
1801                     close_or_die($fh);
1802                 }
1803             }
1804         }
1805     }
1806 }
1807
1808 sub patch_SH {
1809     # Cwd.xs added in commit 0d2079faa739aaa9. Cwd.pm moved to ext/ 8 years
1810     # later in commit 403f501d5b37ebf0
1811     if ($major > 0 && <*/Cwd/Cwd.xs>) {
1812         if ($major < 10
1813             && !extract_from_file('Makefile.SH', qr/^extra_dep=''$/)) {
1814             # The Makefile.PL for Unicode::Normalize needs
1815             # lib/unicore/CombiningClass.pl. Even without a parallel build, we
1816             # need a dependency to ensure that it builds. This is a variant of
1817             # commit 9f3ef600c170f61e. Putting this for earlier versions gives
1818             # us a spot on which to hang the edits below
1819             apply_patch(<<'EOPATCH');
1820 diff --git a/Makefile.SH b/Makefile.SH
1821 index f61d0db..6097954 100644
1822 --- a/Makefile.SH
1823 +++ b/Makefile.SH
1824 @@ -155,10 +155,20 @@ esac
1825  
1826  : Prepare dependency lists for Makefile.
1827  dynamic_list=' '
1828 +extra_dep=''
1829  for f in $dynamic_ext; do
1830      : the dependency named here will never exist
1831        base=`echo "$f" | sed 's/.*\///'`
1832 -    dynamic_list="$dynamic_list lib/auto/$f/$base.$dlext"
1833 +    this_target="lib/auto/$f/$base.$dlext"
1834 +    dynamic_list="$dynamic_list $this_target"
1835 +
1836 +    : Parallel makes reveal that we have some interdependencies
1837 +    case $f in
1838 +       Math/BigInt/FastCalc) extra_dep="$extra_dep
1839 +$this_target: lib/auto/List/Util/Util.$dlext" ;;
1840 +       Unicode/Normalize) extra_dep="$extra_dep
1841 +$this_target: lib/unicore/CombiningClass.pl" ;;
1842 +    esac
1843  done
1844  
1845  static_list=' '
1846 @@ -987,2 +997,9 @@ n_dummy $(nonxs_ext):       miniperl$(EXE_EXT) preplibrary $(DYNALOADER) FORCE
1847         @$(LDLIBPTH) sh ext/util/make_ext nonxs $@ MAKE=$(MAKE) LIBPERL_A=$(LIBPERL)
1848 +!NO!SUBS!
1849 +
1850 +$spitshell >>Makefile <<EOF
1851 +$extra_dep
1852 +EOF
1853 +
1854 +$spitshell >>Makefile <<'!NO!SUBS!'
1855  
1856 EOPATCH
1857         }
1858
1859         if ($major == 11) {
1860             if (extract_from_file('patchlevel.h',
1861                                   qr/^#include "unpushed\.h"/)) {
1862                 # I had thought it easier to detect when building one of the 52
1863                 # commits with the original method of incorporating the git
1864                 # revision and drop parallel make flags. Commits shown by
1865                 # git log 46807d8e809cc127^..dcff826f70bf3f64^ ^d4fb0a1f15d1a1c4
1866                 # However, it's not actually possible to make miniperl for that
1867                 # configuration as-is, because the file .patchnum is only made
1868                 # as a side effect of target 'all'
1869                 # I also don't think that it's "safe" to simply run
1870                 # make_patchnum.sh before the build. We need the proper
1871                 # dependency rules in the Makefile to *stop* it being run again
1872                 # at the wrong time.
1873                 # This range is important because contains the commit that
1874                 # merges Schwern's y2038 work.
1875                 apply_patch(<<'EOPATCH');
1876 diff --git a/Makefile.SH b/Makefile.SH
1877 index 9ad8b6f..106e721 100644
1878 --- a/Makefile.SH
1879 +++ b/Makefile.SH
1880 @@ -540,9 +544,14 @@ sperl.i: perl.c $(h)
1881  
1882  .PHONY: all translators utilities make_patchnum
1883  
1884 -make_patchnum:
1885 +make_patchnum: lib/Config_git.pl
1886 +
1887 +lib/Config_git.pl: make_patchnum.sh
1888         sh $(shellflags) make_patchnum.sh
1889  
1890 +# .patchnum, unpushed.h and lib/Config_git.pl are built by make_patchnum.sh
1891 +unpushed.h .patchnum: lib/Config_git.pl
1892 +
1893  # make sure that we recompile perl.c if .patchnum changes
1894  perl$(OBJ_EXT): .patchnum unpushed.h
1895  
1896 EOPATCH
1897             } elsif (-f '.gitignore'
1898                      && extract_from_file('.gitignore', qr/^\.patchnum$/)) {
1899                 # 8565263ab8a47cda to 46807d8e809cc127^ inclusive.
1900                 edit_file('Makefile.SH', sub {
1901                               my $code = shift;
1902                               $code =~ s/^make_patchnum:\n/make_patchnum: .patchnum
1903
1904 .sha1: .patchnum
1905
1906 .patchnum: make_patchnum.sh
1907 /m;
1908                               return $code;
1909                           });
1910             } elsif (-f 'lib/.gitignore'
1911                      && extract_from_file('lib/.gitignore',
1912                                           qr!^/Config_git.pl!)
1913                      && !extract_from_file('Makefile.SH',
1914                                         qr/^uudmap\.h.*:bitcount.h$/)) {
1915                 # Between commits and dcff826f70bf3f64 and 0f13ebd5d71f8177^
1916                 edit_file('Makefile.SH', sub {
1917                               my $code = shift;
1918                               # Bug introduced by 344af494c35a9f0f
1919                               # fixed in 0f13ebd5d71f8177
1920                               $code =~ s{^(pod/perlapi\.pod) (pod/perlintern\.pod): }
1921                                         {$1: $2\n\n$2: }m;
1922                               # Bug introduced by efa50c51e3301a2c
1923                               # fixed in 0f13ebd5d71f8177
1924                               $code =~ s{^(uudmap\.h) (bitcount\.h): }
1925                                         {$1: $2\n\n$2: }m;
1926
1927                               # The rats nest of getting git_version.h correct
1928
1929                               if ($code =~ s{git_version\.h: stock_git_version\.h
1930 \tcp stock_git_version\.h git_version\.h}
1931                                             {}m) {
1932                                   # before 486cd780047ff224
1933
1934                                   # We probably can't build between
1935                                   # 953f6acfa20ec275^ and 8565263ab8a47cda
1936                                   # inclusive, but all commits in that range
1937                                   # relate to getting make_patchnum.sh working,
1938                                   # so it is extremely unlikely to be an
1939                                   # interesting bisect target. They will skip.
1940
1941                                   # No, don't spawn a submake if
1942                                   # make_patchnum.sh or make_patchnum.pl fails
1943                                   $code =~ s{\|\| \$\(MAKE\) miniperl.*}
1944                                             {}m;
1945                                   $code =~ s{^\t(sh.*make_patchnum\.sh.*)}
1946                                             {\t-$1}m;
1947
1948                                   # Use an external perl to run make_patchnum.pl
1949                                   # because miniperl still depends on
1950                                   # git_version.h
1951                                   $code =~ s{^\t.*make_patchnum\.pl}
1952                                             {\t-$^X make_patchnum.pl}m;
1953
1954
1955                                   # "Truth in advertising" - running
1956                                   # make_patchnum generates 2 files.
1957                                   $code =~ s{^make_patchnum:.*}{
1958 make_patchnum: lib/Config_git.pl
1959
1960 git_version.h: lib/Config_git.pl
1961
1962 perlmini\$(OBJ_EXT): git_version.h
1963
1964 lib/Config_git.pl:}m;
1965                               }
1966                               # Right, now we've corrected Makefile.SH to
1967                               # correctly describe how lib/Config_git.pl and
1968                               # git_version.h are made, we need to fix the rest
1969
1970                               # This emulates commit 2b63e250843b907e
1971                               # This might duplicate the rule stating that
1972                               # git_version.h depends on lib/Config_git.pl
1973                               # This is harmless.
1974                               $code =~ s{^(?:lib/Config_git\.pl )?git_version\.h: (.* make_patchnum\.pl.*)}
1975                                         {git_version.h: lib/Config_git.pl
1976
1977 lib/Config_git.pl: $1}m;
1978
1979                               # This emulates commits 0f13ebd5d71f8177 and
1980                               # and a04d4598adc57886. It ensures that
1981                               # lib/Config_git.pl is built before configpm,
1982                               # and that configpm is run exactly once.
1983                               $code =~ s{^(\$\(.*?\) )?(\$\(CONFIGPOD\))(: .*? configpm Porting/Glossary)( lib/Config_git\.pl)?}{
1984                                   # If present, other files depend on $(CONFIGPOD)
1985                                   ($1 ? "$1: $2\n\n" : '')
1986                                       # Then the rule we found
1987                                       . $2 . $3
1988                                           # Add dependency if not there
1989                                           . ($4 ? $4 : ' lib/Config_git.pl')
1990                               }me;
1991
1992                               return $code;
1993                           });
1994             }
1995         }
1996
1997         if ($major < 14) {
1998             # Commits dc0655f797469c47 and d11a62fe01f2ecb2
1999             edit_file('Makefile.SH', sub {
2000                           my $code = shift;
2001                           foreach my $ext (qw(Encode SDBM_File)) {
2002                               next if $code =~ /\b$ext\) extra_dep=/s;
2003                               $code =~ s!(\) extra_dep="\$extra_dep
2004 \$this_target: .*?" ;;)
2005 (    esac
2006 )!$1
2007         $ext) extra_dep="\$extra_dep
2008 \$this_target: lib/auto/Cwd/Cwd.\$dlext" ;;
2009 $2!;
2010                           }
2011                           return $code;
2012                       });
2013         }
2014     }
2015
2016     if ($major == 7) {
2017         # Remove commits 9fec149bb652b6e9 and 5bab1179608f81d8, which add/amend
2018         # rules to automatically run regen scripts that rebuild C headers. These
2019         # cause problems because a git checkout doesn't preserve relative file
2020         # modification times, hence the regen scripts may fire. This will
2021         # obscure whether the repository had the correct generated headers
2022         # checked in.
2023         # Also, the dependency rules for running the scripts were not correct,
2024         # which could cause spurious re-builds on re-running make, and can cause
2025         # complete build failures for a parallel make.
2026         if (extract_from_file('Makefile.SH',
2027                               qr/Writing it this way gives make a big hint to always run opcode\.pl before/)) {
2028             apply_commit('70c6e6715e8fec53');
2029         } elsif (extract_from_file('Makefile.SH',
2030                                    qr/^opcode\.h opnames\.h pp_proto\.h pp\.sym: opcode\.pl$/)) {
2031             revert_commit('9fec149bb652b6e9');
2032         }
2033     }
2034
2035     if ($^O eq 'aix' && $major >= 11 && $major <= 15
2036         && extract_from_file('makedef.pl', qr/^use Config/)) {
2037         edit_file('Makefile.SH', sub {
2038                       # The AIX part of commit e6807d8ab22b761c
2039                       # It's safe to substitute lib/Config.pm for config.sh
2040                       # as lib/Config.pm depends on config.sh
2041                       # If the tree is post e6807d8ab22b761c, the substitution
2042                       # won't match, which is harmless.
2043                       my $code = shift;
2044                       $code =~ s{^(perl\.exp:.* )config\.sh(\b.*)}
2045                                 {$1 . '$(CONFIGPM)' . $2}me;
2046                       return $code;
2047                   });
2048     }
2049
2050     # There was a bug in makedepend.SH which was fixed in version 96a8704c.
2051     # Symptom was './makedepend: 1: Syntax error: Unterminated quoted string'
2052     # Remove this if you're actually bisecting a problem related to
2053     # makedepend.SH
2054     # If you do this, you may need to add in code to correct the output of older
2055     # makedepends, which don't correctly filter newer gcc output such as
2056     # <built-in>
2057     checkout_file('makedepend.SH');
2058
2059     if ($major < 4 && -f 'config.sh'
2060         && !extract_from_file('config.sh', qr/^trnl=/)) {
2061         # This seems to be necessary to avoid makedepend becoming confused,
2062         # and hanging on stdin. Seems that the code after
2063         # make shlist || ...here... is never run.
2064         edit_file('makedepend.SH', sub {
2065                       my $code = shift;
2066                       $code =~ s/^trnl='\$trnl'$/trnl='\\n'/m;
2067                       return $code;
2068                   });
2069     }
2070 }
2071
2072 sub patch_C {
2073     # This is ordered by $major, as it's likely that different platforms may
2074     # well want to share code.
2075
2076     if ($major == 2 && extract_from_file('perl.c', qr/^\tfclose\(e_fp\);$/)) {
2077         # need to patch perl.c to avoid calling fclose() twice on e_fp when
2078         # using -e
2079         # This diff is part of commit ab821d7fdc14a438. The second close was
2080         # introduced with perl-5.002, commit a5f75d667838e8e7
2081         # Might want a6c477ed8d4864e6 too, for the corresponding change to
2082         # pp_ctl.c (likely without this, eval will have "fun")
2083         apply_patch(<<'EOPATCH');
2084 diff --git a/perl.c b/perl.c
2085 index 03c4d48..3c814a2 100644
2086 --- a/perl.c
2087 +++ b/perl.c
2088 @@ -252,6 +252,7 @@ setuid perl scripts securely.\n");
2089  #ifndef VMS  /* VMS doesn't have environ array */
2090      origenviron = environ;
2091  #endif
2092 +    e_tmpname = Nullch;
2093  
2094      if (do_undump) {
2095  
2096 @@ -405,6 +406,7 @@ setuid perl scripts securely.\n");
2097      if (e_fp) {
2098         if (Fflush(e_fp) || ferror(e_fp) || fclose(e_fp))
2099             croak("Can't write to temp file for -e: %s", Strerror(errno));
2100 +       e_fp = Nullfp;
2101         argc++,argv--;
2102         scriptname = e_tmpname;
2103      }
2104 @@ -470,10 +472,10 @@ setuid perl scripts securely.\n");
2105      curcop->cop_line = 0;
2106      curstash = defstash;
2107      preprocess = FALSE;
2108 -    if (e_fp) {
2109 -       fclose(e_fp);
2110 -       e_fp = Nullfp;
2111 +    if (e_tmpname) {
2112         (void)UNLINK(e_tmpname);
2113 +       Safefree(e_tmpname);
2114 +       e_tmpname = Nullch;
2115      }
2116  
2117      /* now that script is parsed, we can modify record separator */
2118 @@ -1369,7 +1371,7 @@ SV *sv;
2119         scriptname = xfound;
2120      }
2121  
2122 -    origfilename = savepv(e_fp ? "-e" : scriptname);
2123 +    origfilename = savepv(e_tmpname ? "-e" : scriptname);
2124      curcop->cop_filegv = gv_fetchfile(origfilename);
2125      if (strEQ(origfilename,"-"))
2126         scriptname = "";
2127
2128 EOPATCH
2129     }
2130
2131     if ($major < 3 && $^O eq 'openbsd'
2132         && !extract_from_file('pp_sys.c', qr/BSD_GETPGRP/)) {
2133         # Part of commit c3293030fd1b7489
2134         apply_patch(<<'EOPATCH');
2135 diff --git a/pp_sys.c b/pp_sys.c
2136 index 4608a2a..f0c9d1d 100644
2137 --- a/pp_sys.c
2138 +++ b/pp_sys.c
2139 @@ -2903,8 +2903,8 @@ PP(pp_getpgrp)
2140         pid = 0;
2141      else
2142         pid = SvIVx(POPs);
2143 -#ifdef USE_BSDPGRP
2144 -    value = (I32)getpgrp(pid);
2145 +#ifdef BSD_GETPGRP
2146 +    value = (I32)BSD_GETPGRP(pid);
2147  #else
2148      if (pid != 0)
2149         DIE("POSIX getpgrp can't take an argument");
2150 @@ -2933,8 +2933,8 @@ PP(pp_setpgrp)
2151      }
2152  
2153      TAINT_PROPER("setpgrp");
2154 -#ifdef USE_BSDPGRP
2155 -    SETi( setpgrp(pid, pgrp) >= 0 );
2156 +#ifdef BSD_SETPGRP
2157 +    SETi( BSD_SETPGRP(pid, pgrp) >= 0 );
2158  #else
2159      if ((pgrp != 0) || (pid != 0)) {
2160         DIE("POSIX setpgrp can't take an argument");
2161 EOPATCH
2162     }
2163
2164     if ($major < 4 && $^O eq 'openbsd') {
2165         my $bad;
2166         # Need changes from commit a6e633defa583ad5.
2167         # Commits c07a80fdfe3926b5 and f82b3d4130164d5f changed the same part
2168         # of perl.h
2169
2170         if (extract_from_file('perl.h',
2171                               qr/^#ifdef HAS_GETPGRP2$/)) {
2172             $bad = <<'EOBAD';
2173 ***************
2174 *** 57,71 ****
2175   #define TAINT_PROPER(s)       if (tainting) taint_proper(no_security, s)
2176   #define TAINT_ENV()   if (tainting) taint_env()
2177   
2178 ! #ifdef HAS_GETPGRP2
2179 ! #   ifndef HAS_GETPGRP
2180 ! #     define HAS_GETPGRP
2181 ! #   endif
2182 ! #endif
2183
2184 ! #ifdef HAS_SETPGRP2
2185 ! #   ifndef HAS_SETPGRP
2186 ! #     define HAS_SETPGRP
2187 ! #   endif
2188   #endif
2189   
2190 EOBAD
2191         } elsif (extract_from_file('perl.h',
2192                                    qr/Gack, you have one but not both of getpgrp2/)) {
2193             $bad = <<'EOBAD';
2194 ***************
2195 *** 56,76 ****
2196   #define TAINT_PROPER(s)       if (tainting) taint_proper(no_security, s)
2197   #define TAINT_ENV()   if (tainting) taint_env()
2198   
2199 ! #if defined(HAS_GETPGRP2) && defined(HAS_SETPGRP2)
2200 ! #   define getpgrp getpgrp2
2201 ! #   define setpgrp setpgrp2
2202 ! #   ifndef HAS_GETPGRP
2203 ! #     define HAS_GETPGRP
2204 ! #   endif
2205 ! #   ifndef HAS_SETPGRP
2206 ! #     define HAS_SETPGRP
2207 ! #   endif
2208 ! #   ifndef USE_BSDPGRP
2209 ! #     define USE_BSDPGRP
2210 ! #   endif
2211 ! #else
2212 ! #   if defined(HAS_GETPGRP2) || defined(HAS_SETPGRP2)
2213 !       #include "Gack, you have one but not both of getpgrp2() and setpgrp2()."
2214 ! #   endif
2215   #endif
2216   
2217 EOBAD
2218         } elsif (extract_from_file('perl.h',
2219                                    qr/^#ifdef USE_BSDPGRP$/)) {
2220             $bad = <<'EOBAD'
2221 ***************
2222 *** 91,116 ****
2223   #define TAINT_PROPER(s)       if (tainting) taint_proper(no_security, s)
2224   #define TAINT_ENV()   if (tainting) taint_env()
2225   
2226 ! #ifdef USE_BSDPGRP
2227 ! #   ifdef HAS_GETPGRP
2228 ! #       define BSD_GETPGRP(pid) getpgrp((pid))
2229 ! #   endif
2230 ! #   ifdef HAS_SETPGRP
2231 ! #       define BSD_SETPGRP(pid, pgrp) setpgrp((pid), (pgrp))
2232 ! #   endif
2233 ! #else
2234 ! #   ifdef HAS_GETPGRP2
2235 ! #       define BSD_GETPGRP(pid) getpgrp2((pid))
2236 ! #       ifndef HAS_GETPGRP
2237 ! #         define HAS_GETPGRP
2238 ! #     endif
2239 ! #   endif
2240 ! #   ifdef HAS_SETPGRP2
2241 ! #       define BSD_SETPGRP(pid, pgrp) setpgrp2((pid), (pgrp))
2242 ! #       ifndef HAS_SETPGRP
2243 ! #         define HAS_SETPGRP
2244 ! #     endif
2245 ! #   endif
2246   #endif
2247   
2248   #ifndef _TYPES_               /* If types.h defines this it's easy. */
2249 EOBAD
2250         }
2251         if ($bad) {
2252             apply_patch(<<"EOPATCH");
2253 *** a/perl.h    2011-10-21 09:46:12.000000000 +0200
2254 --- b/perl.h    2011-10-21 09:46:12.000000000 +0200
2255 $bad--- 91,144 ----
2256   #define TAINT_PROPER(s)       if (tainting) taint_proper(no_security, s)
2257   #define TAINT_ENV()   if (tainting) taint_env()
2258   
2259 ! /* XXX All process group stuff is handled in pp_sys.c.  Should these 
2260 !    defines move there?  If so, I could simplify this a lot. --AD  9/96.
2261 ! */
2262 ! /* Process group stuff changed from traditional BSD to POSIX.
2263 !    perlfunc.pod documents the traditional BSD-style syntax, so we'll
2264 !    try to preserve that, if possible.
2265 ! */
2266 ! #ifdef HAS_SETPGID
2267 ! #  define BSD_SETPGRP(pid, pgrp)      setpgid((pid), (pgrp))
2268 ! #else
2269 ! #  if defined(HAS_SETPGRP) && defined(USE_BSD_SETPGRP)
2270 ! #    define BSD_SETPGRP(pid, pgrp)    setpgrp((pid), (pgrp))
2271 ! #  else
2272 ! #    ifdef HAS_SETPGRP2  /* DG/UX */
2273 ! #      define BSD_SETPGRP(pid, pgrp)  setpgrp2((pid), (pgrp))
2274 ! #    endif
2275 ! #  endif
2276 ! #endif
2277 ! #if defined(BSD_SETPGRP) && !defined(HAS_SETPGRP)
2278 ! #  define HAS_SETPGRP  /* Well, effectively it does . . . */
2279 ! #endif
2280
2281 ! /* getpgid isn't POSIX, but at least Solaris and Linux have it, and it makes
2282 !     our life easier :-) so we'll try it.
2283 ! */
2284 ! #ifdef HAS_GETPGID
2285 ! #  define BSD_GETPGRP(pid)            getpgid((pid))
2286 ! #else
2287 ! #  if defined(HAS_GETPGRP) && defined(USE_BSD_GETPGRP)
2288 ! #    define BSD_GETPGRP(pid)          getpgrp((pid))
2289 ! #  else
2290 ! #    ifdef HAS_GETPGRP2  /* DG/UX */
2291 ! #      define BSD_GETPGRP(pid)                getpgrp2((pid))
2292 ! #    endif
2293 ! #  endif
2294 ! #endif
2295 ! #if defined(BSD_GETPGRP) && !defined(HAS_GETPGRP)
2296 ! #  define HAS_GETPGRP  /* Well, effectively it does . . . */
2297 ! #endif
2298
2299 ! /* These are not exact synonyms, since setpgrp() and getpgrp() may 
2300 !    have different behaviors, but perl.h used to define USE_BSDPGRP
2301 !    (prior to 5.003_05) so some extension might depend on it.
2302 ! */
2303 ! #if defined(USE_BSD_SETPGRP) || defined(USE_BSD_GETPGRP)
2304 ! #  ifndef USE_BSDPGRP
2305 ! #    define USE_BSDPGRP
2306 ! #  endif
2307   #endif
2308   
2309   #ifndef _TYPES_               /* If types.h defines this it's easy. */
2310 EOPATCH
2311         }
2312     }
2313
2314     if ($major == 4 && extract_from_file('scope.c', qr/\(SV\*\)SSPOPINT/)) {
2315         # [PATCH] 5.004_04 +MAINT_TRIAL_1 broken when sizeof(int) != sizeof(void)
2316         # Fixes a bug introduced in 161b7d1635bc830b
2317         apply_commit('9002cb76ec83ef7f');
2318     }
2319
2320     if ($major == 4 && extract_from_file('av.c', qr/AvARRAY\(av\) = 0;/)) {
2321         # Fixes a bug introduced in 1393e20655efb4bc
2322         apply_commit('e1c148c28bf3335b', 'av.c');
2323     }
2324
2325     if ($major == 4) {
2326         my $rest = extract_from_file('perl.c', qr/delimcpy(.*)/);
2327         if (defined $rest and $rest !~ /,$/) {
2328             # delimcpy added in fc36a67e8855d031, perl.c refactored to use it.
2329             # bug introduced in 2a92aaa05aa1acbf, fixed in 8490252049bf42d3
2330             # code then moved to util.c in commit 491527d0220de34e
2331             apply_patch(<<'EOPATCH');
2332 diff --git a/perl.c b/perl.c
2333 index 4eb69e3..54bbb00 100644
2334 --- a/perl.c
2335 +++ b/perl.c
2336 @@ -1735,7 +1735,7 @@ SV *sv;
2337             if (len < sizeof tokenbuf)
2338                 tokenbuf[len] = '\0';
2339  #else  /* ! (atarist || DOSISH) */
2340 -           s = delimcpy(tokenbuf, tokenbuf + sizeof tokenbuf, s, bufend
2341 +           s = delimcpy(tokenbuf, tokenbuf + sizeof tokenbuf, s, bufend,
2342                          ':',
2343                          &len);
2344  #endif /* ! (atarist || DOSISH) */
2345 EOPATCH
2346         }
2347     }
2348
2349     if ($major == 4 && $^O eq 'linux') {
2350         # Whilst this is fixed properly in f0784f6a4c3e45e1 which provides the
2351         # Configure probe, it's easier to back out the problematic changes made
2352         # in these previous commits:
2353         if (extract_from_file('doio.c',
2354                               qr!^/\* XXX REALLY need metaconfig test \*/$!)) {
2355             revert_commit('4682965a1447ea44', 'doio.c');
2356         }
2357         if (my $token = extract_from_file('doio.c',
2358                                           qr!^#if (defined\(__sun(?:__)?\)) && defined\(__svr4__\) /\* XXX Need metaconfig test \*/$!)) {
2359             my $patch = `git show -R 9b599b2a63d2324d doio.c`;
2360             $patch =~ s/defined\(__sun__\)/$token/g;
2361             apply_patch($patch);
2362         }
2363         if (extract_from_file('doio.c',
2364                               qr!^/\* linux \(and Solaris2\?\) uses :$!)) {
2365             revert_commit('8490252049bf42d3', 'doio.c');
2366         }
2367         if (extract_from_file('doio.c',
2368                               qr/^          unsemds.buf = &semds;$/)) {
2369             revert_commit('8e591e46b4c6543e');
2370         }
2371         if (extract_from_file('doio.c',
2372                               qr!^#ifdef __linux__      /\* XXX Need metaconfig test \*/$!)) {
2373             # Reverts part of commit 3e3baf6d63945cb6
2374             apply_patch(<<'EOPATCH');
2375 diff --git b/doio.c a/doio.c
2376 index 62b7de9..0d57425 100644
2377 --- b/doio.c
2378 +++ a/doio.c
2379 @@ -1333,9 +1331,6 @@ SV **sp;
2380      char *a;
2381      I32 id, n, cmd, infosize, getinfo;
2382      I32 ret = -1;
2383 -#ifdef __linux__       /* XXX Need metaconfig test */
2384 -    union semun unsemds;
2385 -#endif
2386  
2387      id = SvIVx(*++mark);
2388      n = (optype == OP_SEMCTL) ? SvIVx(*++mark) : 0;
2389 @@ -1364,29 +1359,11 @@ SV **sp;
2390             infosize = sizeof(struct semid_ds);
2391         else if (cmd == GETALL || cmd == SETALL)
2392         {
2393 -#ifdef __linux__       /* XXX Need metaconfig test */
2394 -/* linux uses :
2395 -   int semctl (int semid, int semnun, int cmd, union semun arg)
2396 -
2397 -       union semun {
2398 -            int val;
2399 -            struct semid_ds *buf;
2400 -            ushort *array;
2401 -       };
2402 -*/
2403 -            union semun semds;
2404 -           if (semctl(id, 0, IPC_STAT, semds) == -1)
2405 -#else
2406             struct semid_ds semds;
2407             if (semctl(id, 0, IPC_STAT, &semds) == -1)
2408 -#endif
2409                 return -1;
2410             getinfo = (cmd == GETALL);
2411 -#ifdef __linux__       /* XXX Need metaconfig test */
2412 -           infosize = semds.buf->sem_nsems * sizeof(short);
2413 -#else
2414             infosize = semds.sem_nsems * sizeof(short);
2415 -#endif
2416                 /* "short" is technically wrong but much more portable
2417                    than guessing about u_?short(_t)? */
2418         }
2419 @@ -1429,12 +1406,7 @@ SV **sp;
2420  #endif
2421  #ifdef HAS_SEM
2422      case OP_SEMCTL:
2423 -#ifdef __linux__       /* XXX Need metaconfig test */
2424 -        unsemds.buf = (struct semid_ds *)a;
2425 -       ret = semctl(id, n, cmd, unsemds);
2426 -#else
2427         ret = semctl(id, n, cmd, (struct semid_ds *)a);
2428 -#endif
2429         break;
2430  #endif
2431  #ifdef HAS_SHM
2432 EOPATCH
2433         }
2434         # Incorrect prototype added as part of 8ac853655d9b7447, fixed as part
2435         # of commit dc45a647708b6c54, with at least one intermediate
2436         # modification. Correct prototype for gethostbyaddr has socklen_t
2437         # second. Linux has uint32_t first for getnetbyaddr.
2438         # Easiest just to remove, instead of attempting more complex patching.
2439         # Something similar may be needed on other platforms.
2440         edit_file('pp_sys.c', sub {
2441                       my $code = shift;
2442                       $code =~ s/^    struct hostent \*(?:PerlSock_)?gethostbyaddr\([^)]+\);$//m;
2443                       $code =~ s/^    struct netent \*getnetbyaddr\([^)]+\);$//m;
2444                       return $code;
2445                   });
2446     }
2447
2448     if ($major < 5 && $^O eq 'aix'
2449         && !extract_from_file('pp_sys.c',
2450                               qr/defined\(HOST_NOT_FOUND\) && !defined\(h_errno\)/)) {
2451         # part of commit dc45a647708b6c54
2452         # Andy Dougherty's configuration patches (Config_63-01 up to 04).
2453         apply_patch(<<'EOPATCH')
2454 diff --git a/pp_sys.c b/pp_sys.c
2455 index c2fcb6f..efa39fb 100644
2456 --- a/pp_sys.c
2457 +++ b/pp_sys.c
2458 @@ -54,7 +54,7 @@ extern "C" int syscall(unsigned long,...);
2459  #endif
2460  #endif
2461  
2462 -#ifdef HOST_NOT_FOUND
2463 +#if defined(HOST_NOT_FOUND) && !defined(h_errno)
2464  extern int h_errno;
2465  #endif
2466  
2467 EOPATCH
2468     }
2469
2470     if ($major == 5
2471         && `git rev-parse HEAD` eq "22c35a8c2392967a5ba6b5370695be464bd7012c\n") {
2472         # Commit 22c35a8c2392967a is significant,
2473         # "phase 1 of somewhat major rearrangement of PERL_OBJECT stuff"
2474         # but doesn't build due to 2 simple errors. blead in this broken state
2475         # was merged to the cfgperl branch, and then these were immediately
2476         # corrected there. cfgperl (with the fixes) was merged back to blead.
2477         # The resultant rather twisty maze of commits looks like this:
2478
2479 =begin comment
2480
2481 * | |   commit 137225782c183172f360c827424b9b9f8adbef0e
2482 |\ \ \  Merge: 22c35a8 2a8ee23
2483 | |/ /  Author: Gurusamy Sarathy <gsar@cpan.org>
2484 | | |   Date:   Fri Oct 30 17:38:36 1998 +0000
2485 | | |
2486 | | |       integrate cfgperl tweaks into mainline
2487 | | |
2488 | | |       p4raw-id: //depot/perl@2144
2489 | | |
2490 | * | commit 2a8ee23279873759693fa83eca279355db2b665c
2491 | | | Author: Jarkko Hietaniemi <jhi@iki.fi>
2492 | | | Date:   Fri Oct 30 13:27:39 1998 +0000
2493 | | |
2494 | | |     There can be multiple yacc/bison errors.
2495 | | |
2496 | | |     p4raw-id: //depot/cfgperl@2143
2497 | | |
2498 | * | commit 93fb2ac393172fc3e2c14edb20b718309198abbc
2499 | | | Author: Jarkko Hietaniemi <jhi@iki.fi>
2500 | | | Date:   Fri Oct 30 13:18:43 1998 +0000
2501 | | |
2502 | | |     README.posix-bc update.
2503 | | |
2504 | | |     p4raw-id: //depot/cfgperl@2142
2505 | | |
2506 | * | commit 4ec43091e8e6657cb260b5e563df30aaa154effe
2507 | | | Author: Jarkko Hietaniemi <jhi@iki.fi>
2508 | | | Date:   Fri Oct 30 09:12:59 1998 +0000
2509 | | |
2510 | | |     #2133 fallout.
2511 | | |
2512 | | |     p4raw-id: //depot/cfgperl@2141
2513 | | |
2514 | * |   commit 134ca994cfefe0f613d43505a885e4fc2100b05c
2515 | |\ \  Merge: 7093112 22c35a8
2516 | |/ /  Author: Jarkko Hietaniemi <jhi@iki.fi>
2517 |/| |   Date:   Fri Oct 30 08:43:18 1998 +0000
2518 | | |
2519 | | |       Integrate from mainperl.
2520 | | |
2521 | | |       p4raw-id: //depot/cfgperl@2140
2522 | | |
2523 * | | commit 22c35a8c2392967a5ba6b5370695be464bd7012c
2524 | | | Author: Gurusamy Sarathy <gsar@cpan.org>
2525 | | | Date:   Fri Oct 30 02:51:39 1998 +0000
2526 | | |
2527 | | |     phase 1 of somewhat major rearrangement of PERL_OBJECT stuff
2528 | | |     (objpp.h is gone, embed.pl now does some of that); objXSUB.h
2529 | | |     should soon be automated also; the global variables that
2530 | | |     escaped the PL_foo conversion are now reined in; renamed
2531 | | |     MAGIC in regcomp.h to REG_MAGIC to avoid collision with the
2532 | | |     type of same name; duplicated lists of pp_things in various
2533 | | |     places is now gone; result has only been tested on win32
2534 | | |
2535 | | |     p4raw-id: //depot/perl@2133
2536
2537 =end comment
2538
2539 =cut
2540
2541         # and completely confuses git bisect (and at least me), causing it to
2542         # the bisect run to confidently return the wrong answer, an unrelated
2543         # commit on the cfgperl branch.
2544
2545         apply_commit('4ec43091e8e6657c');
2546     }
2547
2548     if ($major == 5
2549         && extract_from_file('pp_sys.c', qr/PERL_EFF_ACCESS_R_OK/)
2550         && !extract_from_file('pp_sys.c', qr/XXX Configure test needed for eaccess/)) {
2551         # Between 5ff3f7a4e03a6b10 and c955f1177b2e311d^
2552         # This is the meat of commit c955f1177b2e311d (without the other
2553         # indenting changes that would cause a conflict).
2554         # Without this 538 revisions won't build on (at least) Linux
2555         apply_patch(<<'EOPATCH');
2556 diff --git a/pp_sys.c b/pp_sys.c
2557 index d60c8dc..867dee4 100644
2558 --- a/pp_sys.c
2559 +++ b/pp_sys.c
2560 @@ -198,9 +198,18 @@ static char zero_but_true[ZBTLEN + 1] = "0 but true";
2561  #   if defined(I_SYS_SECURITY)
2562  #       include <sys/security.h>
2563  #   endif
2564 -#   define PERL_EFF_ACCESS_R_OK(p) (eaccess((p), R_OK, ACC_SELF))
2565 -#   define PERL_EFF_ACCESS_W_OK(p) (eaccess((p), W_OK, ACC_SELF))
2566 -#   define PERL_EFF_ACCESS_X_OK(p) (eaccess((p), X_OK, ACC_SELF))
2567 +    /* XXX Configure test needed for eaccess */
2568 +#   ifdef ACC_SELF
2569 +        /* HP SecureWare */
2570 +#       define PERL_EFF_ACCESS_R_OK(p) (eaccess((p), R_OK, ACC_SELF))
2571 +#       define PERL_EFF_ACCESS_W_OK(p) (eaccess((p), W_OK, ACC_SELF))
2572 +#       define PERL_EFF_ACCESS_X_OK(p) (eaccess((p), X_OK, ACC_SELF))
2573 +#   else
2574 +        /* SCO */
2575 +#       define PERL_EFF_ACCESS_R_OK(p) (eaccess((p), R_OK))
2576 +#       define PERL_EFF_ACCESS_W_OK(p) (eaccess((p), W_OK))
2577 +#       define PERL_EFF_ACCESS_X_OK(p) (eaccess((p), X_OK))
2578 +#   endif
2579  #endif
2580  
2581  #if !defined(PERL_EFF_ACCESS_R_OK) && defined(HAS_ACCESSX) && defined(ACC_SELF)
2582 EOPATCH
2583     }
2584
2585     if ($major == 5
2586         && extract_from_file('mg.c', qr/If we're still on top of the stack, pop us off/)
2587         && !extract_from_file('mg.c', qr/PL_savestack_ix -= popval/)) {
2588         # Fix up commit 455ece5e082708b1:
2589         # SSNEW() API for allocating memory on the savestack
2590         # Message-Id: <tqemtae338.fsf@puma.genscan.com>
2591         # Subject: [PATCH 5.005_51] (was: why SAVEDESTRUCTOR()...)
2592         apply_commit('3c8a44569607336e', 'mg.c');
2593     }
2594
2595     if ($major == 5) {
2596         if (extract_from_file('doop.c', qr/croak\(no_modify\);/)
2597             && extract_from_file('doop.c', qr/croak\(PL_no_modify\);/)) {
2598             # Whilst the log suggests that this would only fix 5 commits, in
2599             # practice this area of history is a complete tarpit, and git bisect
2600             # gets very confused by the skips in the middle of the back and
2601             # forth merging between //depot/perl and //depot/cfgperl
2602             apply_commit('6393042b638dafd3');
2603         }
2604
2605         # One error "fixed" with another:
2606         if (extract_from_file('pp_ctl.c',
2607                               qr/\Qstatic void *docatch_body _((void *o));\E/)) {
2608             apply_commit('5b51e982882955fe');
2609         }
2610         # Which is then fixed by this:
2611         if (extract_from_file('pp_ctl.c',
2612                               qr/\Qstatic void *docatch_body _((valist\E/)) {
2613             apply_commit('47aa779ee4c1a50e');
2614         }
2615
2616         if (extract_from_file('thrdvar.h', qr/PERLVARI\(Tprotect/)
2617             && !extract_from_file('embedvar.h', qr/PL_protect/)) {
2618             # Commit 312caa8e97f1c7ee didn't update embedvar.h
2619             apply_commit('e0284a306d2de082', 'embedvar.h');
2620         }
2621     }
2622
2623     if ($major == 5
2624         && extract_from_file('sv.c',
2625                              qr/PerlDir_close\(IoDIRP\((?:\(IO\*\))?sv\)\);/)
2626         && !(extract_from_file('toke.c',
2627                                qr/\QIoDIRP(FILTER_DATA(AvFILLp(PL_rsfp_filters))) = NULL\E/)
2628              || extract_from_file('toke.c',
2629                                   qr/\QIoDIRP(datasv) = (DIR*)NULL;\E/))) {
2630         # Commit 93578b34124e8a3b, //depot/perl@3298
2631         # close directory handles properly when localized,
2632         # tweaked slightly by commit 1236053a2c722e2b,
2633         # add test case for change#3298
2634         #
2635         # The fix is the last part of:
2636         #
2637         # various fixes for clean build and test on win32; configpm broken,
2638         # needed to open myconfig.SH rather than myconfig; sundry adjustments
2639         # to bytecode stuff; tweaks to DYNAMIC_ENV_FETCH code to make it
2640         # work under win32; getenv_sv() changed to getenv_len() since SVs
2641         # aren't visible in the lower echelons; remove bogus exports from
2642         # config.sym; PERL_OBJECT-ness for C++ exception support; null out
2643         # IoDIRP in filter_del() or sv_free() will attempt to close it
2644         #
2645         # The changed code is modified subsequently by commit e0c198038146b7a4
2646         apply_commit('a6c403648ecd5cc7', 'toke.c');
2647     }
2648
2649     if ($major < 6 && $^O eq 'netbsd'
2650         && !extract_from_file('unixish.h',
2651                               qr/defined\(NSIG\).*defined\(__NetBSD__\)/)) {
2652         apply_patch(<<'EOPATCH')
2653 diff --git a/unixish.h b/unixish.h
2654 index 2a6cbcd..eab2de1 100644
2655 --- a/unixish.h
2656 +++ b/unixish.h
2657 @@ -89,7 +89,7 @@
2658   */
2659  /* #define ALTERNATE_SHEBANG "#!" / **/
2660  
2661 -#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
2662 +#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX) || defined(__NetBSD__)
2663  # include <signal.h>
2664  #endif
2665  
2666 EOPATCH
2667     }
2668
2669     if (($major >= 7 || $major <= 9) && $^O eq 'openbsd'
2670         && `uname -m` eq "sparc64\n"
2671         # added in 2000 by commit cb434fcc98ac25f5:
2672         && extract_from_file('regexec.c',
2673                              qr!/\* No need to save/restore up to this paren \*/!)
2674         # re-indented in 2006 by commit 95b2444054382532:
2675         && extract_from_file('regexec.c', qr/^\t\tCURCUR cc;$/)) {
2676         # Need to work around a bug in (at least) OpenBSD's 4.6's sparc64 #
2677         # compiler ["gcc (GCC) 3.3.5 (propolice)"]. Between commits
2678         # 3ec562b0bffb8b8b (2002) and 1a4fad37125bac3e^ (2005) the darling thing
2679         # fails to compile any code for the statement cc.oldcc = PL_regcc;
2680         #
2681         # If you refactor the code to "fix" that, or force the issue using set
2682         # in the debugger, the stack smashing detection code fires on return
2683         # from S_regmatch(). Turns out that the compiler doesn't allocate any
2684         # (or at least enough) space for cc.
2685         #
2686         # Restore the "uninitialised" value for cc before function exit, and the
2687         # stack smashing code is placated.  "Fix" 3ec562b0bffb8b8b (which
2688         # changes the size of auto variables used elsewhere in S_regmatch), and
2689         # the crash is visible back to bc517b45fdfb539b (which also changes
2690         # buffer sizes). "Unfix" 1a4fad37125bac3e and the crash is visible until
2691         # 5b47454deb66294b.  Problem goes away if you compile with -O, or hack
2692         # the code as below.
2693         #
2694         # Hence this turns out to be a bug in (old) gcc. Not a security bug we
2695         # still need to fix.
2696         apply_patch(<<'EOPATCH');
2697 diff --git a/regexec.c b/regexec.c
2698 index 900b491..6251a0b 100644
2699 --- a/regexec.c
2700 +++ b/regexec.c
2701 @@ -2958,7 +2958,11 @@ S_regmatch(pTHX_ regnode *prog)
2702                                 I,I
2703   *******************************************************************/
2704         case CURLYX: {
2705 -               CURCUR cc;
2706 +           union {
2707 +               CURCUR hack_cc;
2708 +               char hack_buff[sizeof(CURCUR) + 1];
2709 +           } hack;
2710 +#define cc hack.hack_cc
2711                 CHECKPOINT cp = PL_savestack_ix;
2712                 /* No need to save/restore up to this paren */
2713                 I32 parenfloor = scan->flags;
2714 @@ -2983,6 +2987,7 @@ S_regmatch(pTHX_ regnode *prog)
2715                 n = regmatch(PREVOPER(next));   /* start on the WHILEM */
2716                 regcpblow(cp);
2717                 PL_regcc = cc.oldcc;
2718 +#undef cc
2719                 saySAME(n);
2720             }
2721             /* NOT REACHED */
2722 EOPATCH
2723 }
2724
2725     if ($major < 8 && $^O eq 'openbsd'
2726         && !extract_from_file('perl.h', qr/include <unistd\.h>/)) {
2727         # This is part of commit 3f270f98f9305540, applied at a slightly
2728         # different location in perl.h, where the context is stable back to
2729         # 5.000
2730         apply_patch(<<'EOPATCH');
2731 diff --git a/perl.h b/perl.h
2732 index 9418b52..b8b1a7c 100644
2733 --- a/perl.h
2734 +++ b/perl.h
2735 @@ -496,6 +496,10 @@ register struct op *Perl_op asm(stringify(OP_IN_REGISTER));
2736  #   include <sys/param.h>
2737  #endif
2738  
2739 +/* If this causes problems, set i_unistd=undef in the hint file.  */
2740 +#ifdef I_UNISTD
2741 +#   include <unistd.h>
2742 +#endif
2743  
2744  /* Use all the "standard" definitions? */
2745  #if defined(STANDARD_C) && defined(I_STDLIB)
2746 EOPATCH
2747     }
2748 }
2749
2750 sub patch_ext {
2751     if (-f 'ext/POSIX/Makefile.PL'
2752         && extract_from_file('ext/POSIX/Makefile.PL',
2753                              qr/Explicitly avoid including/)) {
2754         # commit 6695a346c41138df, which effectively reverts 170888cff5e2ffb7
2755
2756         # PERL5LIB is populated by make_ext.pl with paths to the modules we need
2757         # to run, don't override this with "../../lib" since that may not have
2758         # been populated yet in a parallel build.
2759         apply_commit('6695a346c41138df');
2760     }
2761
2762     if (-f 'ext/Hash/Util/Makefile.PL'
2763         && extract_from_file('ext/Hash/Util/Makefile.PL',
2764                              qr/\bDIR\b.*'FieldHash'/)) {
2765         # ext/Hash/Util/Makefile.PL should not recurse to FieldHash's Makefile.PL
2766         # *nix, VMS and Win32 all know how to (and have to) call the latter directly.
2767         # As is, targets in ext/Hash/Util/FieldHash get called twice, which may result
2768         # in race conditions, and certainly messes up make clean; make distclean;
2769         apply_commit('550428fe486b1888');
2770     }
2771
2772     if ($major < 8 && $^O eq 'darwin' && !-f 'ext/DynaLoader/dl_dyld.xs') {
2773         checkout_file('ext/DynaLoader/dl_dyld.xs', 'f556e5b971932902');
2774         apply_patch(<<'EOPATCH');
2775 diff -u a/ext/DynaLoader/dl_dyld.xs~ a/ext/DynaLoader/dl_dyld.xs
2776 --- a/ext/DynaLoader/dl_dyld.xs~        2011-10-11 21:41:27.000000000 +0100
2777 +++ b/ext/DynaLoader/dl_dyld.xs 2011-10-11 21:42:20.000000000 +0100
2778 @@ -41,6 +41,35 @@
2779  #include "perl.h"
2780  #include "XSUB.h"
2781  
2782 +#ifndef pTHX
2783 +#  define pTHX         void
2784 +#  define pTHX_
2785 +#endif
2786 +#ifndef aTHX
2787 +#  define aTHX
2788 +#  define aTHX_
2789 +#endif
2790 +#ifndef dTHX
2791 +#  define dTHXa(a)     extern int Perl___notused(void)
2792 +#  define dTHX         extern int Perl___notused(void)
2793 +#endif
2794 +
2795 +#ifndef Perl_form_nocontext
2796 +#  define Perl_form_nocontext form
2797 +#endif
2798 +
2799 +#ifndef Perl_warn_nocontext
2800 +#  define Perl_warn_nocontext warn
2801 +#endif
2802 +
2803 +#ifndef PTR2IV
2804 +#  define PTR2IV(p)    (IV)(p)
2805 +#endif
2806 +
2807 +#ifndef get_av
2808 +#  define get_av perl_get_av
2809 +#endif
2810 +
2811  #define DL_LOADONCEONLY
2812  
2813  #include "dlutils.c"   /* SaveError() etc      */
2814 @@ -185,7 +191,7 @@
2815      CODE:
2816      DLDEBUG(1,PerlIO_printf(Perl_debug_log, "dl_load_file(%s,%x):\n", filename,flags));
2817      if (flags & 0x01)
2818 -       Perl_warn(aTHX_ "Can't make loaded symbols global on this platform while loading %s",filename);
2819 +       Perl_warn_nocontext("Can't make loaded symbols global on this platform while loading %s",filename);
2820      RETVAL = dlopen(filename, mode) ;
2821      DLDEBUG(2,PerlIO_printf(Perl_debug_log, " libref=%x\n", RETVAL));
2822      ST(0) = sv_newmortal() ;
2823 EOPATCH
2824         if ($major < 4 && !extract_from_file('util.c', qr/^form/m)) {
2825             apply_patch(<<'EOPATCH');
2826 diff -u a/ext/DynaLoader/dl_dyld.xs~ a/ext/DynaLoader/dl_dyld.xs
2827 --- a/ext/DynaLoader/dl_dyld.xs~        2011-10-11 21:56:25.000000000 +0100
2828 +++ b/ext/DynaLoader/dl_dyld.xs 2011-10-11 22:00:00.000000000 +0100
2829 @@ -60,6 +60,18 @@
2830  #  define get_av perl_get_av
2831  #endif
2832  
2833 +static char *
2834 +form(char *pat, ...)
2835 +{
2836 +    char *retval;
2837 +    va_list args;
2838 +    va_start(args, pat);
2839 +    vasprintf(&retval, pat, &args);
2840 +    va_end(args);
2841 +    SAVEFREEPV(retval);
2842 +    return retval;
2843 +}
2844 +
2845  #define DL_LOADONCEONLY
2846  
2847  #include "dlutils.c"   /* SaveError() etc      */
2848 EOPATCH
2849         }
2850     }
2851
2852     if ($major < 10) {
2853         if (!extract_from_file('ext/DB_File/DB_File.xs',
2854                                qr!^#else /\* Berkeley DB Version > 2 \*/$!)) {
2855             # This DB_File.xs is really too old to patch up.
2856             # Skip DB_File, unless we're invoked with an explicit -Unoextensions
2857             if (!exists $defines{noextensions}) {
2858                 $defines{noextensions} = 'DB_File';
2859             } elsif (defined $defines{noextensions}) {
2860                 $defines{noextensions} .= ' DB_File';
2861             }
2862         } elsif (!extract_from_file('ext/DB_File/DB_File.xs',
2863                                     qr/^#ifdef AT_LEAST_DB_4_1$/)) {
2864             # This line is changed by commit 3245f0580c13b3ab
2865             my $line = extract_from_file('ext/DB_File/DB_File.xs',
2866                                          qr/^(        status = \(?RETVAL->dbp->open\)?\(RETVAL->dbp, name, NULL, RETVAL->type, $)/);
2867             apply_patch(<<"EOPATCH");
2868 diff --git a/ext/DB_File/DB_File.xs b/ext/DB_File/DB_File.xs
2869 index 489ba96..fba8ded 100644
2870 --- a/ext/DB_File/DB_File.xs
2871 +++ b/ext/DB_File/DB_File.xs
2872 \@\@ -183,4 +187,8 \@\@
2873  #endif
2874  
2875 +#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
2876 +#    define AT_LEAST_DB_4_1
2877 +#endif
2878 +
2879  /* map version 2 features & constants onto their version 1 equivalent */
2880  
2881 \@\@ -1334,7 +1419,12 \@\@ SV *   sv ;
2882  #endif
2883  
2884 +#ifdef AT_LEAST_DB_4_1
2885 +        status = (RETVAL->dbp->open)(RETVAL->dbp, NULL, name, NULL, RETVAL->type, 
2886 +                               Flags, mode) ; 
2887 +#else
2888  $line
2889                                 Flags, mode) ; 
2890 +#endif
2891         /* printf("open returned %d %s\\n", status, db_strerror(status)) ; */
2892  
2893 EOPATCH
2894         }
2895     }
2896
2897     if ($major < 10 and -f 'ext/IPC/SysV/SysV.xs') {
2898         edit_file('ext/IPC/SysV/SysV.xs', sub {
2899                       my $xs = shift;
2900                       my $fixed = <<'EOFIX';
2901
2902 #include <sys/types.h>
2903 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
2904 #ifndef HAS_SEM
2905 #   include <sys/ipc.h>
2906 #endif
2907 #   ifdef HAS_MSG
2908 #       include <sys/msg.h>
2909 #   endif
2910 #   ifdef HAS_SHM
2911 #       if defined(PERL_SCO) || defined(PERL_ISC)
2912 #           include <sys/sysmacros.h>   /* SHMLBA */
2913 #       endif
2914 #      include <sys/shm.h>
2915 #      ifndef HAS_SHMAT_PROTOTYPE
2916            extern Shmat_t shmat (int, char *, int);
2917 #      endif
2918 #      if defined(HAS_SYSCONF) && defined(_SC_PAGESIZE)
2919 #          undef  SHMLBA /* not static: determined at boot time */
2920 #          define SHMLBA sysconf(_SC_PAGESIZE)
2921 #      elif defined(HAS_GETPAGESIZE)
2922 #          undef  SHMLBA /* not static: determined at boot time */
2923 #          define SHMLBA getpagesize()
2924 #      endif
2925 #   endif
2926 #endif
2927 EOFIX
2928                       $xs =~ s!
2929 #include <sys/types\.h>
2930 .*
2931 (#ifdef newCONSTSUB|/\* Required)!$fixed$1!ms;
2932                       return $xs;
2933                   });
2934     }
2935 }
2936
2937 # Local variables:
2938 # cperl-indent-level: 4
2939 # indent-tabs-mode: nil
2940 # End:
2941 #
2942 # ex: set ts=8 sts=4 sw=4 et: