Print <ABSENT> if a STACK is NULL.
[openssl.git] / util / process_docs.pl
1 #! /usr/bin/env perl
2 # Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
3 #
4 # Licensed under the OpenSSL license (the "License").  You may not use
5 # this file except in compliance with the License.  You can obtain a copy
6 # in the file LICENSE in the source distribution or at
7 # https://www.openssl.org/source/license.html
8
9 use strict;
10 use warnings;
11
12 use File::Spec::Functions;
13 use File::Basename;
14 use File::Copy;
15 use File::Path;
16 use if $^O ne "VMS", 'File::Glob' => qw/glob/;
17 use Getopt::Long;
18 use Pod::Usage;
19
20 use lib '.';
21 use configdata;
22
23 # We know we are in the 'util' directory and that our perl modules are
24 # in util/perl
25 use lib catdir(dirname($0), "perl");
26 use OpenSSL::Util::Pod;
27
28 my %options = ();
29 GetOptions(\%options,
30            'sourcedir=s',       # Source directory
31            'subdir=s%',         # Subdirectories to look through,
32                                 # with associated section numbers
33            'destdir=s',         # Destination directory
34            #'in=s@',             # Explicit files to process (ignores sourcedir)
35            #'section=i',         # Default section used for --in files
36            'type=s',            # The result type, 'man' or 'html'
37            'remove',            # To remove files rather than writing them
38            'dry-run|n',         # Only output file names on STDOUT
39            'debug|D+',
40           );
41
42 unless ($options{subdir}) {
43     $options{subdir} = { apps   => '1',
44                          crypto => '3',
45                          ssl    => '3' };
46 }
47 unless ($options{sourcedir}) {
48     $options{sourcedir} = catdir($config{sourcedir}, "doc");
49 }
50 pod2usage(1) unless ( defined $options{subdir}
51                       && defined $options{sourcedir}
52                       && defined $options{destdir}
53                       && defined $options{type}
54                       && ($options{type} eq 'man'
55                           || $options{type} eq 'html') );
56
57 if ($options{debug}) {
58     print STDERR "DEBUG: options:\n";
59     print STDERR "DEBUG:   --sourcedir = $options{sourcedir}\n"
60         if defined $options{sourcedir};
61     print STDERR "DEBUG:   --destdir   = $options{destdir}\n"
62         if defined $options{destdir};
63     print STDERR "DEBUG:   --type      = $options{type}\n"
64         if defined $options{type};
65     foreach (keys %{$options{subdir}}) {
66         print STDERR "DEBUG:   --subdir    = $_=$options{subdir}->{$_}\n";
67     }
68     print STDERR "DEBUG:   --remove    = $options{remove}\n"
69         if defined $options{remove};
70     print STDERR "DEBUG:   --debug     = $options{debug}\n"
71         if defined $options{debug};
72     print STDERR "DEBUG:   --dry-run   = $options{\"dry-run\"}\n"
73         if defined $options{"dry-run"};
74 }
75
76 my $symlink_exists = eval { symlink("",""); 1 };
77
78 foreach my $subdir (keys %{$options{subdir}}) {
79     my $section = $options{subdir}->{$subdir};
80     my $podsourcedir = catfile($options{sourcedir}, $subdir);
81     my $podglob = catfile($podsourcedir, "*.pod");
82
83     foreach my $podfile (glob $podglob) {
84         my $podname = basename($podfile, ".pod");
85         my $podpath = catfile($podfile);
86         my %podinfo = extract_pod_info($podpath,
87                                        { debug => $options{debug},
88                                          section => $section });
89         my @podfiles = grep { $_ ne $podname } @{$podinfo{names}};
90
91         my $updir = updir();
92         my $name = uc $podname;
93         my $suffix = { man  => ".$podinfo{section}",
94                        html => ".html" } -> {$options{type}};
95         my $generate = { man  => "pod2man --name=$name --section=$podinfo{section} --center=OpenSSL --release=$config{version} \"$podpath\"",
96                          html => "pod2html \"--podroot=$options{sourcedir}\" --htmldir=$updir --podpath=apps:crypto:ssl \"--infile=$podpath\" \"--title=$podname\""
97                          } -> {$options{type}};
98         my $output_dir = catdir($options{destdir}, "man$podinfo{section}");
99         my $output_file = $podname . $suffix;
100         my $output_path = catfile($output_dir, $output_file);
101
102         if (! $options{remove}) {
103             my @output;
104             print STDERR "DEBUG: Processing, using \"$generate\"\n"
105                 if $options{debug};
106             unless ($options{"dry-run"}) {
107                 @output = `$generate`;
108                 map { s|href="http://man\.he\.net/man|href="../man|g; } @output
109                     if $options{type} eq "html";
110             }
111             print STDERR "DEBUG: Done processing\n" if $options{debug};
112
113             if (! -d $output_dir) {
114                 print STDERR "DEBUG: Creating directory $output_dir\n" if $options{debug};
115                 unless ($options{"dry-run"}) {
116                     mkpath $output_dir
117                         or die "Trying to create directory $output_dir: $!\n";
118                 }
119             }
120             print STDERR "DEBUG: Writing $output_path\n" if $options{debug};
121             unless ($options{"dry-run"}) {
122                 open my $output_fh, '>', $output_path
123                     or die "Trying to write to $output_path: $!\n";
124                 foreach (@output) {
125                     print $output_fh $_;
126                 }
127                 close $output_fh;
128             }
129             print STDERR "DEBUG: Done writing $output_path\n" if $options{debug};
130         } else {
131             print STDERR "DEBUG: Removing $output_path\n" if $options{debug};
132             unless ($options{"dry-run"}) {
133                 while (unlink $output_path) {}
134             }
135         }
136         print "$output_path\n";
137
138         foreach (@podfiles) {
139             my $link_file = $_ . $suffix;
140             my $link_path = catfile($output_dir, $link_file);
141             if (! $options{remove}) {
142                 if ($symlink_exists) {
143                     print STDERR "DEBUG: Linking $link_path -> $output_file\n"
144                         if $options{debug};
145                     unless ($options{"dry-run"}) {
146                         symlink $output_file, $link_path;
147                     }
148                 } else {
149                     print STDERR "DEBUG: Copying $output_path to link_path\n"
150                         if $options{debug};
151                     unless ($options{"dry-run"}) {
152                         copy $output_path, $link_path;
153                     }
154                 }
155             } else {
156                 print STDERR "DEBUG: Removing $link_path\n" if $options{debug};
157                 unless ($options{"dry-run"}) {
158                     while (unlink $link_path) {}
159                 }
160             }
161             print "$link_path -> $output_path\n";
162         }
163     }
164 }
165
166 __END__
167
168 =pod
169
170 =head1 NAME
171
172 process_docs.pl - A script to process OpenSSL docs
173
174 =head1 SYNOPSIS
175
176 B<process_docs.pl>
177 [B<--sourcedir>=I<dir>]
178 B<--destdir>=I<dir>
179 B<--type>=B<man>|B<html>
180 [B<--remove>]
181 [B<--dry-run>|B<-n>]
182 [B<--debug>|B<-D>]
183
184 =head1 DESCRIPTION
185
186 This script looks for .pod files in the subdirectories 'apps', 'crypto'
187 and 'ssl' under the given source directory.
188
189 The OpenSSL configuration data file F<configdata.pm> I<must> reside in
190 the current directory, I<or> perl must have the directory it resides in
191 in its inclusion array.  For the latter variant, a call like this would
192 work:
193
194  perl -I../foo util/process_docs.pl {options ...}
195
196 =head1 OPTIONS
197
198 =over 4
199
200 =item B<--sourcedir>=I<dir>
201
202 Top directory where the source files are found.
203
204 =item B<--destdir>=I<dir>
205
206 Top directory where the resulting files should end up
207
208 =item B<--type>=B<man>|B<html>
209
210 Type of output to produce.  Currently supported are man pages and HTML files.
211
212 =item B<--remove>
213
214 Instead of writing the files, remove them.
215
216 =item B<--dry-run>|B<-n>
217
218 Do not perform any file writing, directory creation or file removal.
219
220 =item B<--debug>|B<-D>
221
222 Print extra debugging output.
223
224 =back
225
226 =head1 COPYRIGHT
227
228 Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved.
229
230 Licensed under the OpenSSL license (the "License").  You may not use
231 this file except in compliance with the License.  You can obtain a copy
232 in the file LICENSE in the source distribution or at
233 https://www.openssl.org/source/license.html
234
235 =cut