This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perldiag: rewording
[perl5.git] / pod / buildtoc
CommitLineData
41630250
JH
1#!/usr/bin/perl -w
2
3use strict;
d5e2eea9 4use vars qw($masterpodfile %Build %Targets $Verbose $Quiet %Ignore
b0b6bf2b 5 @Master %Readmes %Pods %Aux %Readmepods %Pragmata %Modules
d89d11bb 6 %Copies %Generated $Test);
41630250
JH
7use File::Spec;
8use File::Find;
9use FindBin;
10use Text::Tabs;
11use Text::Wrap;
12use Getopt::Long;
6d664f07 13use Carp;
41630250
JH
14
15no locale;
bac61051 16require 5.010;
41630250 17
d5e2eea9
NC
18{
19 my $Top = File::Spec->catdir($FindBin::Bin, File::Spec->updir);
20
21 sub abs_from_top {
22 my $path = shift;
23 return File::Spec->catdir($Top, split /\//, $path) if $path =~ s!/\z!!;
24 return File::Spec->catfile($Top, split /\//, $path);
25 }
26}
27
28$masterpodfile = abs_from_top('pod.lst');
41630250
JH
29
30# Generate any/all of these files
31# --verbose gives slightly more output
d092c3cd 32# --quiet suppresses routine warnings
41630250
JH
33# --build-all tries to build everything
34# --build-foo updates foo as follows
35# --showfiles shows the files to be changed
5733ee18
NC
36# --test exit if perl.pod, pod.lst, MANIFEST are consistent, and regenerated
37# files are up to date, die otherwise.
41630250
JH
38
39%Targets
40 = (
d5e2eea9
NC
41 toc => 'pod/perltoc.pod',
42 manifest => 'MANIFEST',
43 perlpod => 'pod/perl.pod',
44 vms => 'vms/descrip_mms.template',
45 nmake => 'win32/Makefile',
46 dmake => 'win32/makefile.mk',
47 podmak => 'win32/pod.mak',
48 # plan9 => 'plan9/mkfile'),
49 unix => 'Makefile.SH',
8537f021 50 # TODO: add roffitall
41630250
JH
51 );
52
d5e2eea9
NC
53foreach (values %Targets) {
54 $_ = abs_from_top($_);
55}
56
41630250
JH
57{
58 my @files = keys %Targets;
59 my $filesopts = join(" | ", map { "--build-$_" } "all", sort @files);
60 my $showfiles;
9dce16cd 61 my %build_these;
41630250
JH
62 die <<__USAGE__
63$0: Usage: $0 [--verbose] [--showfiles] $filesopts
64__USAGE__
65 unless @ARGV
66 && GetOptions (verbose => \$Verbose,
d092c3cd 67 quiet => \$Quiet,
41630250 68 showfiles => \$showfiles,
d89d11bb 69 test => \$Test,
9dce16cd
NC
70 map {+"build-$_", \$build_these{$_}} @files, 'all');
71 if ($build_these{all}) {
72 %Build = %Targets;
73 } else {
74 while (my ($file, $want) = each %build_these) {
75 $Build{$file} = $Targets{$file} if $want;
76 }
77 }
41630250
JH
78 if ($showfiles) {
79 print
80 join(" ",
81 sort { lc $a cmp lc $b }
82 map {
83 my ($v, $d, $f) = File::Spec->splitpath($_);
84 my @d;
85 @d = defined $d ? File::Spec->splitdir($d) : ();
86 shift @d if @d;
87 File::Spec->catfile(@d ?
88 (@d == 1 && $d[0] eq '' ? () : @d)
89 : "pod", $f);
9dce16cd 90 } @Targets{@files}),
41630250
JH
91 "\n";
92 exit(0);
93 }
94}
95
96# Don't copy these top level READMEs
97%Ignore
98 = (
41630250
JH
99 micro => 1,
100# vms => 1,
101 );
102
103if ($Verbose) {
9dce16cd 104 print "I'm building $_\n" foreach keys %Build;
41630250
JH
105}
106
bac61051 107open my $master, '<', $masterpodfile or die "$0: Can't open $masterpodfile: $!";
41630250 108
b0b6bf2b
AT
109my ($delta_source, $delta_target);
110
bac61051 111foreach (<$master>) {
41630250
JH
112 next if /^\#/;
113
114 # At least one upper case letter somewhere in the first group
8927c9d8 115 if (/^(\S+)\s(.*)/ && $1 =~ tr/h//) {
41630250
JH
116 # it's a heading
117 my $flags = $1;
8927c9d8 118 $flags =~ tr/h//d;
41630250 119 my %flags = (header => 1);
8927c9d8
NC
120 $flags{toc_omit} = 1 if $flags =~ tr/o//d;
121 $flags{aux} = 1 if $flags =~ tr/a//d;
41630250
JH
122 die "$0: Unknown flag found in heading line: $_" if length $flags;
123 push @Master, [\%flags, $2];
124
125 } elsif (/^(\S*)\s+(\S+)\s+(.*)/) {
126 # it's a section
127 my ($flags, $filename, $desc) = ($1, $2, $3);
128
129 my %flags = (indent => 0);
130 $flags{indent} = $1 if $flags =~ s/(\d+)//;
b0b6bf2b 131 $flags{toc_omit} = 1 if $flags =~ tr/o//d;
41630250 132 $flags{aux} = 1 if $flags =~ tr/a//d;
b0b6bf2b
AT
133
134 if ($flags =~ tr/D//d) {
37ee6528 135 $flags{manifest_omit} = 1;
b0b6bf2b
AT
136 $delta_source = "$filename.pod";
137 }
138 if ($flags =~ tr/d//d) {
37ee6528 139 $flags{perlpod_omit} = 1;
b0b6bf2b
AT
140 $delta_target = "$filename.pod";
141 }
344af494 142 $Generated{"$filename.pod"}++ if $flags =~ tr/g//d;
b0b6bf2b 143
41630250
JH
144 if ($flags =~ tr/r//d) {
145 my $readme = $filename;
146 $readme =~ s/^perl//;
147 $Readmepods{$filename} = $Readmes{$readme} = $desc;
148 $flags{readme} = 1;
149 } elsif ($flags{aux}) {
150 $Aux{$filename} = $desc;
151 } else {
152 $Pods{$filename} = $desc;
153 }
154 die "$0: Unknown flag found in section line: $_" if length $flags;
155 push @Master, [\%flags, $filename, $desc];
156 } elsif (/^$/) {
157 push @Master, undef;
158 } else {
159 die "$0: Malformed line: $_" if $1 =~ tr/A-Z//;
160 }
161}
b0b6bf2b
AT
162if (defined $delta_source) {
163 if (defined $delta_target) {
164 # This way round so that keys can act as a MANIFEST skip list
165 # Targets will aways be in the pod directory. Currently we can only cope
dd0cfdaa 166 # with sources being in the same directory.
b0b6bf2b
AT
167 $Copies{$delta_target} = $delta_source;
168 } else {
169 die "$0: delta source defined but not target";
170 }
171} elsif (defined $delta_target) {
600dcb9e 172 die "$0: delta target defined but not source";
b0b6bf2b 173}
41630250 174
bac61051 175close $master;
41630250
JH
176
177# Sanity cross check
178{
179 my (%disk_pods, @disk_pods);
180 my (@manipods, %manipods);
181 my (@manireadmes, %manireadmes);
182 my (@perlpods, %perlpods);
183 my (%our_pods);
184
185 # Convert these to a list of filenames.
186 foreach (keys %Pods, keys %Readmepods) {
187 $our_pods{"$_.pod"}++;
188 }
189
d5e2eea9
NC
190 opendir my $dh, abs_from_top('pod/');
191 while (readdir $dh) {
192 next unless /\.pod\z/;
193 push @disk_pods, $_;
194 ++$disk_pods{$_};
195 }
41630250 196
b0b6bf2b
AT
197 # Things we copy from won't be in perl.pod
198 # Things we copy to won't be in MANIFEST
b0b6bf2b 199
d5e2eea9
NC
200 my $filename = abs_from_top('MANIFEST');
201 open my $mani, '<', $filename or die "$0: opening $filename failed: $!";
202 while (<$mani>) {
41630250
JH
203 if (m!^pod/([^.]+\.pod)\s+!i) {
204 push @manipods, $1;
205 } elsif (m!^README\.(\S+)\s+!i) {
206 next if $Ignore{$1};
207 push @manireadmes, "perl$1.pod";
208 }
209 }
d5e2eea9 210 close $mani or die $!;
41630250
JH
211 @manipods{@manipods} = @manipods;
212 @manireadmes{@manireadmes} = @manireadmes;
213
d5e2eea9
NC
214 $filename = abs_from_top('pod/perl.pod');
215 open my $perlpod, '<', $filename or die "$0: opening $filename failed: $!\n";
216 while (<$perlpod>) {
41630250
JH
217 if (/^For ease of access, /../^\(If you're intending /) {
218 if (/^\s+(perl\S*)\s+\w/) {
219 push @perlpods, "$1.pod";
220 }
221 }
222 }
d5e2eea9 223 close $perlpod or die $!;
41630250
JH
224 die "$0: could not find the pod listing of perl.pod\n"
225 unless @perlpods;
226 @perlpods{@perlpods} = @perlpods;
227
d89d11bb 228 my @inconsistent;
41630250 229 foreach my $i (sort keys %disk_pods) {
d89d11bb 230 push @inconsistent, "$0: $i exists but is unknown by buildtoc\n"
41630250 231 unless $our_pods{$i};
d89d11bb 232 push @inconsistent, "$0: $i exists but is unknown by ../MANIFEST\n"
344af494 233 if !$manipods{$i} && !$manireadmes{$i} && !$Copies{$i} && !$Generated{$i};
d89d11bb 234 push @inconsistent, "$0: $i exists but is unknown by perl.pod\n"
81e1aac7 235 if !$perlpods{$i} && !exists $Copies{$i};
41630250 236 }
78fb583c 237 my %BuildFiles;
b5f0cad0
RB
238 foreach my $path (values %Build) {
239 (undef, undef, my $file) = File::Spec->splitpath($path);
240 ++$BuildFiles{$file}
241 }
81e1aac7 242
41630250 243 foreach my $i (sort keys %our_pods) {
d89d11bb 244 push @inconsistent, "$0: $i is known by buildtoc but does not exist\n"
78fb583c 245 unless $disk_pods{$i} or $BuildFiles{$i};
41630250
JH
246 }
247 foreach my $i (sort keys %manipods) {
d89d11bb 248 push @inconsistent, "$0: $i is known by ../MANIFEST but does not exist\n"
41630250 249 unless $disk_pods{$i};
d89d11bb 250 push @inconsistent, "$0: $i is known by ../MANIFEST but is marked as generated\n"
344af494 251 if $Generated{$i};
41630250
JH
252 }
253 foreach my $i (sort keys %perlpods) {
d89d11bb 254 push @inconsistent, "$0: $i is known by perl.pod but does not exist\n"
78fb583c 255 unless $disk_pods{$i} or $BuildFiles{$i};
41630250 256 }
d89d11bb 257 if ($Test) {
5733ee18
NC
258 delete $Build{toc};
259 printf "1..%d\n", 1 + scalar keys %Build;
d89d11bb
TC
260 if (@inconsistent) {
261 print "not ok 1\n";
262 die @inconsistent
263 }
264 print "ok 1\n";
d89d11bb
TC
265 }
266 else {
267 warn @inconsistent if @inconsistent;
268 }
41630250
JH
269}
270
0b01631d 271# Find all the modules
15e75242 272if ($Build{toc}) {
41630250 273 my @modpods;
9a8cc8a4 274 find \&getpods => abs_from_top('lib/');
41630250
JH
275
276 sub getpods {
277 if (/\.p(od|m)$/) {
278 my $file = $File::Find::name;
d5e2eea9 279 return if $file =~ qr!/lib/Pod/Functions.pm\z!; # Used only by pod itself
41630250
JH
280 return if $file =~ m!(?:^|/)t/!;
281 return if $file =~ m!lib/Attribute/Handlers/demo/!;
282 return if $file =~ m!lib/Net/FTP/.+\.pm!; # Hi, Graham! :-)
283 return if $file =~ m!lib/Math/BigInt/t/!;
284 return if $file =~ m!/Devel/PPPort/[Hh]arness|lib/Devel/Harness!i;
285 return if $file =~ m!XS/(?:APItest|Typemap)!;
be6d6286
HS
286 my $pod = $file;
287 return if $pod =~ s/pm$/pod/ && -e $pod;
bac61051 288 unless (open my $f, '<', $_) {
41630250
JH
289 warn "$0: bogus <$file>: $!";
290 system "ls", "-l", $file;
291 }
292 else {
293 my $line;
bac61051 294 while ($line = <$f>) {
41630250
JH
295 if ($line =~ /^=head1\s+NAME\b/) {
296 push @modpods, $file;
41630250
JH
297 return;
298 }
299 }
d092c3cd 300 warn "$0: $file: cannot find =head1 NAME\n" unless $Quiet;
41630250
JH
301 }
302 }
303 }
304
305 die "$0: no pods" unless @modpods;
306
307 my %done;
308 for (@modpods) {
11eb54fe
NC
309 my $name = $_;
310 $name =~ s/\.p(m|od)$//;
311 $name =~ s-.*?/lib/--;
312 $name =~ s-/-::-g;
3eb77e4b
NC
313 next if $done{$name}++;
314
41630250
JH
315 if ($name =~ /^[a-z]/) {
316 $Pragmata{$name} = $_;
317 } else {
41630250
JH
318 $Modules{$name} = $_;
319 }
320 }
321}
322
8537f021 323# OK. Now a lot of ancillary function definitions follow
41630250
JH
324# Main program returns at "Do stuff"
325
d871876a
NC
326my $OUT;
327
02cc404a 328sub do_toc {
d5e2eea9 329 my $filename = shift;
41630250 330
c0f8aaaa 331 ($_= <<"EOPOD2B") =~ s/^\t//gm and $OUT .= $_;
41630250 332
97f32038
JH
333 # !!!!!!! DO NOT EDIT THIS FILE !!!!!!!
334 # This file is autogenerated by buildtoc from all the other pods.
335 # Edit those files and run buildtoc --build-toc to effect changes.
97f32038 336
41630250
JH
337 =head1 NAME
338
339 perltoc - perl documentation table of contents
340
341 =head1 DESCRIPTION
342
343 This page provides a brief table of contents for the rest of the Perl
344 documentation set. It is meant to be scanned quickly or grepped
345 through to locate the proper section you're looking for.
346
347 =head1 BASIC DOCUMENTATION
348
349EOPOD2B
350#' make emacs happy
351
352 # All the things in the master list that happen to be pod filenames
84f07fb2 353 foreach (grep {defined $_ && @$_ == 3 && !$_->[0]{toc_omit}} @Master) {
d5e2eea9 354 podset($_->[1], abs_from_top("pod/$_->[1].pod"));
84f07fb2 355 }
41630250
JH
356
357
c0f8aaaa 358 ($_= <<"EOPOD2B") =~ s/^\t//gm and $OUT .= $_;
41630250
JH
359
360
361
362 =head1 PRAGMA DOCUMENTATION
363
364EOPOD2B
365
84f07fb2
NC
366 foreach (sort keys %Pragmata) {
367 podset($_, $Pragmata{$_});
368 }
41630250 369
c0f8aaaa 370 ($_= <<"EOPOD2B") =~ s/^\t//gm and $OUT .= $_;
41630250
JH
371
372
373
374 =head1 MODULE DOCUMENTATION
375
376EOPOD2B
377
84f07fb2
NC
378 foreach (sort keys %Modules) {
379 podset($_, $Modules{$_});
380 }
41630250
JH
381
382 $_= <<"EOPOD2B";
383
384
385 =head1 AUXILIARY DOCUMENTATION
386
387 Here should be listed all the extra programs' documentation, but they
388 don't all have manual pages yet:
389
390 =over 4
391
392EOPOD2B
393
394 $_ .= join "\n", map {"\t=item $_\n"} sort keys %Aux;
395 $_ .= <<"EOPOD2B" ;
396
397 =back
398
399 =head1 AUTHOR
400
401 Larry Wall <F<larry\@wall.org>>, with the help of oodles
402 of other folks.
403
404
405EOPOD2B
406
407 s/^\t//gm;
c0f8aaaa 408 $OUT .= "$_\n";
d871876a 409
39440e4b 410 $OUT =~ s/\n\s+\n/\n\n/gs;
f20404e1 411 $OUT =~ s/\n{3,}/\n\n/g;
b8ce93b8
NC
412
413 $OUT =~ s/([^\n]+)/wrap('', '', $1)/ge;
414
02cc404a 415 return $OUT;
41630250
JH
416}
417
418# Below are all the auxiliary routines for generating perltoc.pod
419
420my ($inhead1, $inhead2, $initem);
421
422sub podset {
84f07fb2 423 my ($pod, $file) = @_;
41630250 424
536d7404
NC
425 local $/ = '';
426
84f07fb2 427 open my $fh, '<', $file or die "Can't open file '$file' for $pod: $!";
0b01631d 428
84f07fb2 429 while(<$fh>) {
16114dde 430 tr/\015//d;
41630250 431 if (s/^=head1 (NAME)\s*/=head2 /) {
41630250 432 unhead1();
c0f8aaaa 433 $OUT .= "\n\n=head2 ";
84f07fb2 434 $_ = <$fh>;
767650bc
NC
435 # Remove svn keyword expansions from the Perl FAQ
436 s/ \(\$Revision: \d+ \$\)//g;
32ebae07 437 if ( /^\s*\Q$pod\E\b/ ) {
41630250 438 s/$pod\.pm/$pod/; # '.pm' in NAME !?
41630250
JH
439 } else {
440 s/^/$pod, /;
41630250 441 }
41630250 442 }
1fa7865d 443 elsif (s/^=head1 (.*)/=item $1/) {
41630250 444 unhead2();
c0f8aaaa 445 $OUT .= "=over 4\n\n" unless $inhead1;
41630250 446 $inhead1 = 1;
1fa7865d 447 $_ .= "\n";
41630250 448 }
1fa7865d 449 elsif (s/^=head2 (.*)/=item $1/) {
41630250 450 unitem();
c0f8aaaa 451 $OUT .= "=over 4\n\n" unless $inhead2;
41630250 452 $inhead2 = 1;
1fa7865d 453 $_ .= "\n";
41630250 454 }
1fa7865d 455 elsif (s/^=item ([^=].*)/$1/) {
41630250
JH
456 next if $pod eq 'perldiag';
457 s/^\s*\*\s*$// && next;
458 s/^\s*\*\s*//;
459 s/\n/ /g;
460 s/\s+$//;
461 next if /^[\d.]+$/;
462 next if $pod eq 'perlmodlib' && /^ftp:/;
c0f8aaaa 463 $OUT .= ", " if $initem;
41630250
JH
464 $initem = 1;
465 s/\.$//;
466 s/^-X\b/-I<X>/;
41630250 467 }
1fa7865d
NC
468 else {
469 unhead1() if /^=cut\s*\n/;
41630250
JH
470 next;
471 }
1fa7865d 472 $OUT .= $_;
41630250
JH
473 }
474}
475
476sub unhead1 {
477 unhead2();
478 if ($inhead1) {
c0f8aaaa 479 $OUT .= "\n\n=back\n\n";
41630250
JH
480 }
481 $inhead1 = 0;
482}
483
484sub unhead2 {
485 unitem();
486 if ($inhead2) {
c0f8aaaa 487 $OUT .= "\n\n=back\n\n";
41630250
JH
488 }
489 $inhead2 = 0;
490}
491
492sub unitem {
493 if ($initem) {
c0f8aaaa 494 $OUT .= "\n\n";
41630250
JH
495 }
496 $initem = 0;
497}
498
41630250
JH
499# End of original buildtoc. From here on are routines to generate new sections
500# for and inplace edit other files
501
502sub generate_perlpod {
503 my @output;
504 my $maxlength = 0;
505 foreach (@Master) {
506 my $flags = $_->[0];
507 next if $flags->{aux};
b0b6bf2b 508 next if $flags->{perlpod_omit};
41630250
JH
509
510 if (@$_ == 2) {
511 # Heading
512 push @output, "=head2 $_->[1]\n";
513 } elsif (@$_ == 3) {
514 # Section
515 my $start = " " x (4 + $flags->{indent}) . $_->[1];
516 $maxlength = length $start if length ($start) > $maxlength;
517 push @output, [$start, $_->[2]];
518 } elsif (@$_ == 0) {
519 # blank line
520 push @output, "\n";
521 } else {
522 die "$0: Illegal length " . scalar @$_;
523 }
524 }
525 # want at least 2 spaces padding
526 $maxlength += 2;
527 $maxlength = ($maxlength + 3) & ~3;
528 # sprintf gives $1.....$2 where ... are spaces:
529 return unexpand (map {ref $_ ? sprintf "%-${maxlength}s%s\n", @$_ : $_}
530 @output);
531}
532
533
534sub generate_manifest {
c69ca1d4 535 # Annoyingly, unexpand doesn't consider it good form to replace a single
41630250
JH
536 # space before a tab with a tab
537 # Annoyingly (2) it returns read only values.
453d7764 538 my @temp = unexpand (map {sprintf "%-32s%s", @$_} @_);
41630250
JH
539 map {s/ \t/\t\t/g; $_} @temp;
540}
541sub generate_manifest_pod {
b0b6bf2b 542 generate_manifest map {["pod/$_.pod", $Pods{$_}]}
3dc608da 543 sort grep {!$Copies{"$_.pod"}} grep {!$Generated{"$_.pod"}} keys %Pods;
41630250
JH
544}
545sub generate_manifest_readme {
dd0cfdaa
NC
546 generate_manifest sort {$a->[0] cmp $b->[0]}
547 ["README.vms", "Notes about installing the VMS port"],
548 map {["README.$_", $Readmes{$_}]} keys %Readmes;
41630250
JH
549}
550
551sub generate_roffitall {
552 (map ({"\t\$maindir/$_.1\t\\"}sort keys %Pods),
553 "\t\t\\",
554 map ({"\t\$maindir/$_.1\t\\"}sort keys %Aux),
555 "\t\t\\",
556 map ({"\t\$libdir/$_.3\t\\"}sort keys %Pragmata),
557 "\t\t\\",
558 map ({"\t\$libdir/$_.3\t\\"}sort keys %Modules),
559 )
560}
561
562sub generate_descrip_mms_1 {
563 local $Text::Wrap::columns = 150;
564 my $count = 0;
565 my @lines = map {"pod" . $count++ . " = $_"}
bae7ea06 566 split /\n/, wrap('', '', join " ", map "[.lib.pods]$_.pod",
41630250
JH
567 sort keys %Pods, keys %Readmepods);
568 @lines, "pod = " . join ' ', map {"\$(pod$_)"} 0 .. $count - 1;
569}
570
571sub generate_descrip_mms_2 {
dd0cfdaa
NC
572 map {<<"SNIP"}
573[.lib.pods]$_.pod : [.pod]$_.pod
574 \@ If F\$Search("[.lib]pods.dir").eqs."" Then Create/Directory [.lib.pods]
575 Copy/NoConfirm/Log \$(MMS\$SOURCE) [.lib.pods]
41630250
JH
576SNIP
577 sort keys %Pods, keys %Readmepods;
578}
579
580sub generate_nmake_1 {
b0b6bf2b
AT
581 # XXX Fix this with File::Spec
582 (map {sprintf "\tcopy ..\\README.%-8s ..\\pod\\perl$_.pod\n", $_}
583 sort keys %Readmes),
584 (map {"\tcopy ..\\pod\\$Copies{$_} ..\\pod\\$_\n"} sort keys %Copies);
41630250
JH
585}
586
587# This doesn't have a trailing newline
588sub generate_nmake_2 {
589 # Spot the special case
590 local $Text::Wrap::columns = 76;
591 my $line = wrap ("\t ", "\t ",
9e64a656 592 join " ", sort keys %Copies, keys %Generated,
dd0cfdaa 593 map {"perl$_.pod"} keys %Readmes);
41630250 594 $line =~ s/$/ \\/mg;
b14c7f9a 595 $line =~ s/ \\$//;
41630250
JH
596 $line;
597}
598
599sub generate_pod_mak {
600 my $variable = shift;
601 my @lines;
602 my $line = join "\\\n", "\U$variable = ",
603 map {"\t$_.$variable\t"} sort keys %Pods;
604 # Special case
605 $line =~ s/.*perltoc.html.*\n//m;
606 $line;
607}
608
6d664f07
NC
609sub verify_contiguous {
610 my ($name, $content, $what) = @_;
611 my $sections = () = $content =~ m/\0+/g;
612 croak("$0: $name contains no $what") if $sections < 1;
613 croak("$0: $name contains discontiguous $what") if $sections > 1;
614}
615
41630250 616sub do_manifest {
131a60d2 617 my ($name, $prev) = @_;
41630250 618 my @manifest =
453d7764 619 grep {! m!^pod/[^.]+\.pod.*!}
131a60d2 620 grep {! m!^README\.(\S+)! || $Ignore{$1}} split "\n", $prev;
453d7764
NC
621 join "\n", (
622 # Dictionary order - fold and handle non-word chars as nothing
623 map { $_->[0] }
624 sort { $a->[1] cmp $b->[1] || $a->[0] cmp $b->[0] }
625 map { my $f = lc $_; $f =~ s/[^a-z0-9\s]//g; [ $_, $f ] }
626 @manifest,
627 &generate_manifest_pod(),
628 &generate_manifest_readme()), '';
41630250
JH
629}
630
631sub do_nmake {
131a60d2 632 my ($name, $makefile) = @_;
41630250 633 $makefile =~ s/^\tcopy \.\.\\README.*\n/\0/gm;
6d664f07 634 verify_contiguous($name, $makefile, 'README copies');
b0b6bf2b
AT
635 # Now remove the other copies that follow
636 1 while $makefile =~ s/\0\tcopy .*\n/\0/gm;
637 $makefile =~ s/\0+/join ("", &generate_nmake_1)/se;
41630250 638
b14c7f9a
SH
639 $makefile =~ s{(-cd \$\(PODDIR\) && del /f[^\n]+).*?(-cd \.\.\\utils && del /f)}
640 {"$1\n" . &generate_nmake_2."\n\t$2"}se;
41630250
JH
641 $makefile;
642}
643
644# shut up used only once warning
645*do_dmake = *do_dmake = \&do_nmake;
646
647sub do_perlpod {
131a60d2 648 my ($name, $pod) = @_;
41630250
JH
649
650 unless ($pod =~ s{(For\ ease\ of\ access,\ .*\n)
651 (?:\s+[a-z]{4,}.*\n # fooo
652 |=head.*\n # =head foo
653 |\s*\n # blank line
654 )+
655 }
656 {$1 . join "", &generate_perlpod}mxe) {
8537f021 657 die "$0: Failed to insert amendments in do_perlpod";
41630250
JH
658 }
659 $pod;
660}
661
662sub do_podmak {
131a60d2 663 my ($name, $body) = @_;
d525b9bc 664 foreach my $variable (qw(pod man html tex)) {
41630250
JH
665 die "$0: could not find $variable in $name"
666 unless $body =~ s{\n\U$variable\E = (?:[^\n]*\\\n)*[^\n]*}
667 {"\n" . generate_pod_mak ($variable)}se;
668 }
669 $body;
670}
671
672sub do_vms {
131a60d2 673 my ($name, $makefile) = @_;
41630250 674 $makefile =~ s/\npod\d* =[^\n]*/\0/gs;
6d664f07 675 verify_contiguous($name, $makefile, 'pod assignments');
41630250
JH
676 $makefile =~ s/\0+/join "\n", '', &generate_descrip_mms_1/se;
677
678 die "$0: $name contains NUL bytes" if $makefile =~ /\0/;
679
600dcb9e
CB
680# Looking for the macro defining the current perldelta:
681#PERLDELTA_CURRENT = [.pod]perl5139delta.pod
682
683 $makefile =~ s/\nPERLDELTA_CURRENT\s+=\s+\Q[.pod]perl\E\d+delta\.pod\n
684 /\0/sx;
685 verify_contiguous($name, $makefile, 'current perldelta macro');
686 $makefile =~ s/\0+/join "\n", '', "PERLDELTA_CURRENT = [.pod]$delta_target", ''/se;
687
41630250 688# Looking for rules like this
bae7ea06
NC
689# [.lib.pods]perl.pod : [.pod]perl.pod
690# @ If F$Search("[.lib]pods.dir").eqs."" Then Create/Directory [.lib.pods]
691# Copy/NoConfirm/Log $(MMS$SOURCE) [.lib.pods]
41630250 692
bae7ea06 693 $makefile =~ s/\n\Q[.lib.pods]\Eperl[^\n\.]*\.pod[^\n]+\n
41630250 694 [^\n]+\n # Another line
bae7ea06 695 [^\n]+\Q[.lib.pods]\E\n # ends [.lib.pods]
41630250 696 /\0/gsx;
6d664f07 697 verify_contiguous($name, $makefile, 'copy rules');
41630250 698 $makefile =~ s/\0+/join "\n", '', &generate_descrip_mms_2/se;
db34a22a 699
41630250
JH
700 $makefile;
701}
702
0dfdcd8a 703sub do_unix {
131a60d2 704 my ($name, $makefile_SH) = @_;
0dfdcd8a 705
7eb47696
NC
706 $makefile_SH =~ s{^(perltoc_pod_prereqs = extra.pods).*}
707 {join ' ', $1, map "pod/$_",
708 sort keys %Copies, grep {!/perltoc/} keys %Generated
709 }mge;
8e7bc40f 710
37ee6528
FR
711# pod/perl511delta.pod: pod/perldelta.pod
712# cd pod && $(LNS) perldelta.pod perl511delta.pod
8e7bc40f
NC
713
714 $makefile_SH =~ s!(
715pod/perl[a-z0-9_]+\.pod: pod/perl[a-z0-9_]+\.pod
e0be038f 716 \$\(LNS\) perl[a-z0-9_]+\.pod pod/perl[a-z0-9_]+\.pod
8e7bc40f 717)+!\0!gm;
0dfdcd8a 718
6d664f07 719 verify_contiguous($name, $makefile_SH, 'copy rules');
0dfdcd8a 720
8e7bc40f
NC
721 my @copy_rules = map "
722pod/$_: pod/$Copies{$_}
e0be038f 723 \$(LNS) $Copies{$_} pod/$_
8e7bc40f 724", keys %Copies;
0dfdcd8a 725
8e7bc40f 726 $makefile_SH =~ s/\0+/join '', @copy_rules/se;
0dfdcd8a
NC
727 $makefile_SH;
728
729}
730
41630250
JH
731# Do stuff
732
733my $built;
734while (my ($target, $name) = each %Targets) {
e94c1c05 735 print "Working on target $target\n" if $Verbose;
41630250
JH
736 next unless $Build{$target};
737 $built++;
02cc404a 738 my ($orig, $mode);
41630250 739 print "Now processing $name\n" if $Verbose;
02cc404a
NC
740 if ($target ne "toc") {
741 local $/;
bac61051
NC
742 open my $thing, '<', $name or die "Can't open $name: $!";
743 binmode $thing;
744 $orig = <$thing>;
02cc404a
NC
745 die "$0: $name contains NUL bytes" if $orig =~ /\0/;
746 }
747
131a60d2 748 my $new = do {
41630250 749 no strict 'refs';
131a60d2 750 &{"do_$target"}($target, $orig);
41630250 751 };
02cc404a
NC
752
753 if (defined $orig) {
754 if ($new eq $orig) {
5733ee18
NC
755 if ($Test) {
756 printf "ok %d # $name is up to date\n", $built + 1;
757 } elsif ($Verbose) {
758 print "Was not modified\n";
759 }
760 next;
761 } elsif ($Test) {
762 printf "not ok %d # $name is up to date\n", $built + 1;
02cc404a
NC
763 next;
764 }
765 $mode = (stat $name)[2] // die "$0: Can't stat $name: $!";
766 rename $name, "$name.old" or die "$0: Can't rename $name to $name.old: $!";
41630250 767 }
02cc404a 768
bac61051
NC
769 open my $thing, '>', $name or die "$0: Can't open $name for writing: $!";
770 binmode $thing;
771 print $thing $new or die "$0: print to $name failed: $!";
772 close $thing or die "$0: close $name failed: $!";
02cc404a
NC
773 if (defined $mode) {
774 chmod $mode & 0777, $name or die "$0: can't chmod $mode $name: $!";
775 }
41630250
JH
776}
777
5733ee18 778warn "$0: was not instructed to build anything\n" unless $built || $Test;