xref: /aosp_15_r20/external/curl/scripts/cd2nroff (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker#!/usr/bin/env perl
2*6236dae4SAndroid Build Coastguard Worker#***************************************************************************
3*6236dae4SAndroid Build Coastguard Worker#                                  _   _ ____  _
4*6236dae4SAndroid Build Coastguard Worker#  Project                     ___| | | |  _ \| |
5*6236dae4SAndroid Build Coastguard Worker#                             / __| | | | |_) | |
6*6236dae4SAndroid Build Coastguard Worker#                            | (__| |_| |  _ <| |___
7*6236dae4SAndroid Build Coastguard Worker#                             \___|\___/|_| \_\_____|
8*6236dae4SAndroid Build Coastguard Worker#
9*6236dae4SAndroid Build Coastguard Worker# Copyright (C) Daniel Stenberg, <[email protected]>, et al.
10*6236dae4SAndroid Build Coastguard Worker#
11*6236dae4SAndroid Build Coastguard Worker# This software is licensed as described in the file COPYING, which
12*6236dae4SAndroid Build Coastguard Worker# you should have received as part of this distribution. The terms
13*6236dae4SAndroid Build Coastguard Worker# are also available at https://curl.se/docs/copyright.html.
14*6236dae4SAndroid Build Coastguard Worker#
15*6236dae4SAndroid Build Coastguard Worker# You may opt to use, copy, modify, merge, publish, distribute and/or sell
16*6236dae4SAndroid Build Coastguard Worker# copies of the Software, and permit persons to whom the Software is
17*6236dae4SAndroid Build Coastguard Worker# furnished to do so, under the terms of the COPYING file.
18*6236dae4SAndroid Build Coastguard Worker#
19*6236dae4SAndroid Build Coastguard Worker# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20*6236dae4SAndroid Build Coastguard Worker# KIND, either express or implied.
21*6236dae4SAndroid Build Coastguard Worker#
22*6236dae4SAndroid Build Coastguard Worker# SPDX-License-Identifier: curl
23*6236dae4SAndroid Build Coastguard Worker#
24*6236dae4SAndroid Build Coastguard Worker###########################################################################
25*6236dae4SAndroid Build Coastguard Worker
26*6236dae4SAndroid Build Coastguard Worker=begin comment
27*6236dae4SAndroid Build Coastguard Worker
28*6236dae4SAndroid Build Coastguard WorkerConverts a curldown file to nroff (manpage).
29*6236dae4SAndroid Build Coastguard Worker
30*6236dae4SAndroid Build Coastguard Worker=end comment
31*6236dae4SAndroid Build Coastguard Worker=cut
32*6236dae4SAndroid Build Coastguard Worker
33*6236dae4SAndroid Build Coastguard Workeruse strict;
34*6236dae4SAndroid Build Coastguard Workeruse warnings;
35*6236dae4SAndroid Build Coastguard Worker
36*6236dae4SAndroid Build Coastguard Workermy $cd2nroff = "0.1"; # to keep check
37*6236dae4SAndroid Build Coastguard Workermy $dir;
38*6236dae4SAndroid Build Coastguard Workermy $extension;
39*6236dae4SAndroid Build Coastguard Workermy $keepfilename;
40*6236dae4SAndroid Build Coastguard Worker
41*6236dae4SAndroid Build Coastguard Workerwhile(@ARGV) {
42*6236dae4SAndroid Build Coastguard Worker    if($ARGV[0] eq "-d") {
43*6236dae4SAndroid Build Coastguard Worker        shift @ARGV;
44*6236dae4SAndroid Build Coastguard Worker        $dir = shift @ARGV;
45*6236dae4SAndroid Build Coastguard Worker    }
46*6236dae4SAndroid Build Coastguard Worker    elsif($ARGV[0] eq "-e") {
47*6236dae4SAndroid Build Coastguard Worker        shift @ARGV;
48*6236dae4SAndroid Build Coastguard Worker        $extension = shift @ARGV;
49*6236dae4SAndroid Build Coastguard Worker    }
50*6236dae4SAndroid Build Coastguard Worker    elsif($ARGV[0] eq "-k") {
51*6236dae4SAndroid Build Coastguard Worker        shift @ARGV;
52*6236dae4SAndroid Build Coastguard Worker        $keepfilename = 1;
53*6236dae4SAndroid Build Coastguard Worker    }
54*6236dae4SAndroid Build Coastguard Worker    elsif($ARGV[0] eq "-h") {
55*6236dae4SAndroid Build Coastguard Worker        print <<HELP
56*6236dae4SAndroid Build Coastguard WorkerUsage: cd2nroff [options] [file.md]
57*6236dae4SAndroid Build Coastguard Worker
58*6236dae4SAndroid Build Coastguard Worker-d <dir> Write the output to the file name from the meta-data in the
59*6236dae4SAndroid Build Coastguard Worker         specified directory, instead of writing to stdout
60*6236dae4SAndroid Build Coastguard Worker-e <ext> If -d is used, this option can provide an added "extension", arbitrary
61*6236dae4SAndroid Build Coastguard Worker         text really, to append to the file name.
62*6236dae4SAndroid Build Coastguard Worker-h       This help text,
63*6236dae4SAndroid Build Coastguard Worker-v       Show version then exit
64*6236dae4SAndroid Build Coastguard WorkerHELP
65*6236dae4SAndroid Build Coastguard Worker            ;
66*6236dae4SAndroid Build Coastguard Worker        exit 0;
67*6236dae4SAndroid Build Coastguard Worker    }
68*6236dae4SAndroid Build Coastguard Worker    elsif($ARGV[0] eq "-v") {
69*6236dae4SAndroid Build Coastguard Worker        print "cd2nroff version $cd2nroff\n";
70*6236dae4SAndroid Build Coastguard Worker        exit 0;
71*6236dae4SAndroid Build Coastguard Worker    }
72*6236dae4SAndroid Build Coastguard Worker    else {
73*6236dae4SAndroid Build Coastguard Worker        last;
74*6236dae4SAndroid Build Coastguard Worker    }
75*6236dae4SAndroid Build Coastguard Worker}
76*6236dae4SAndroid Build Coastguard Worker
77*6236dae4SAndroid Build Coastguard Workeruse POSIX qw(strftime);
78*6236dae4SAndroid Build Coastguard Workermy @ts;
79*6236dae4SAndroid Build Coastguard Workerif (defined($ENV{SOURCE_DATE_EPOCH})) {
80*6236dae4SAndroid Build Coastguard Worker    @ts = gmtime($ENV{SOURCE_DATE_EPOCH});
81*6236dae4SAndroid Build Coastguard Worker} else {
82*6236dae4SAndroid Build Coastguard Worker    @ts = localtime;
83*6236dae4SAndroid Build Coastguard Worker}
84*6236dae4SAndroid Build Coastguard Workermy $date = strftime "%Y-%m-%d", @ts;
85*6236dae4SAndroid Build Coastguard Worker
86*6236dae4SAndroid Build Coastguard Workersub outseealso {
87*6236dae4SAndroid Build Coastguard Worker    my (@sa) = @_;
88*6236dae4SAndroid Build Coastguard Worker    my $comma = 0;
89*6236dae4SAndroid Build Coastguard Worker    my @o;
90*6236dae4SAndroid Build Coastguard Worker    push @o, ".SH SEE ALSO\n";
91*6236dae4SAndroid Build Coastguard Worker    for my $s (sort @sa) {
92*6236dae4SAndroid Build Coastguard Worker        push @o, sprintf "%s.BR $s", $comma ? ",\n": "";
93*6236dae4SAndroid Build Coastguard Worker        $comma = 1;
94*6236dae4SAndroid Build Coastguard Worker    }
95*6236dae4SAndroid Build Coastguard Worker    push @o, "\n";
96*6236dae4SAndroid Build Coastguard Worker    return @o;
97*6236dae4SAndroid Build Coastguard Worker}
98*6236dae4SAndroid Build Coastguard Worker
99*6236dae4SAndroid Build Coastguard Workersub outprotocols {
100*6236dae4SAndroid Build Coastguard Worker    my (@p) = @_;
101*6236dae4SAndroid Build Coastguard Worker    my $comma = 0;
102*6236dae4SAndroid Build Coastguard Worker    my @o;
103*6236dae4SAndroid Build Coastguard Worker    push @o, ".SH PROTOCOLS\n";
104*6236dae4SAndroid Build Coastguard Worker
105*6236dae4SAndroid Build Coastguard Worker    if($p[0] eq "TLS") {
106*6236dae4SAndroid Build Coastguard Worker        push @o, "This functionality affects all TLS based protocols: HTTPS, FTPS, IMAPS, POP3S, SMTPS etc.";
107*6236dae4SAndroid Build Coastguard Worker    }
108*6236dae4SAndroid Build Coastguard Worker    else {
109*6236dae4SAndroid Build Coastguard Worker        my @s = sort @p;
110*6236dae4SAndroid Build Coastguard Worker        push @o, "This functionality affects ";
111*6236dae4SAndroid Build Coastguard Worker        for my $e (sort @s) {
112*6236dae4SAndroid Build Coastguard Worker            push @o, sprintf "%s%s",
113*6236dae4SAndroid Build Coastguard Worker                $comma ? (($e eq $s[-1]) ? " and " : ", "): "",
114*6236dae4SAndroid Build Coastguard Worker                lc($e);
115*6236dae4SAndroid Build Coastguard Worker            $comma = 1;
116*6236dae4SAndroid Build Coastguard Worker        }
117*6236dae4SAndroid Build Coastguard Worker        if($#s == 0) {
118*6236dae4SAndroid Build Coastguard Worker            if($s[0] eq "All") {
119*6236dae4SAndroid Build Coastguard Worker                push @o, " supported protocols";
120*6236dae4SAndroid Build Coastguard Worker            }
121*6236dae4SAndroid Build Coastguard Worker            else {
122*6236dae4SAndroid Build Coastguard Worker                push @o, " only";
123*6236dae4SAndroid Build Coastguard Worker            }
124*6236dae4SAndroid Build Coastguard Worker        }
125*6236dae4SAndroid Build Coastguard Worker    }
126*6236dae4SAndroid Build Coastguard Worker    push @o, "\n";
127*6236dae4SAndroid Build Coastguard Worker    return @o;
128*6236dae4SAndroid Build Coastguard Worker}
129*6236dae4SAndroid Build Coastguard Worker
130*6236dae4SAndroid Build Coastguard Workersub outtls {
131*6236dae4SAndroid Build Coastguard Worker    my (@t) = @_;
132*6236dae4SAndroid Build Coastguard Worker    my $comma = 0;
133*6236dae4SAndroid Build Coastguard Worker    my @o;
134*6236dae4SAndroid Build Coastguard Worker    if($t[0] eq "All") {
135*6236dae4SAndroid Build Coastguard Worker        push @o, "\nAll TLS backends support this option.";
136*6236dae4SAndroid Build Coastguard Worker    }
137*6236dae4SAndroid Build Coastguard Worker    else {
138*6236dae4SAndroid Build Coastguard Worker        push @o, "\nThis option works only with the following TLS backends:\n";
139*6236dae4SAndroid Build Coastguard Worker        my @s = sort @t;
140*6236dae4SAndroid Build Coastguard Worker        for my $e (@s) {
141*6236dae4SAndroid Build Coastguard Worker            push @o, sprintf "%s$e",
142*6236dae4SAndroid Build Coastguard Worker                $comma ? (($e eq $s[-1]) ? " and " : ", "): "";
143*6236dae4SAndroid Build Coastguard Worker            $comma = 1;
144*6236dae4SAndroid Build Coastguard Worker        }
145*6236dae4SAndroid Build Coastguard Worker    }
146*6236dae4SAndroid Build Coastguard Worker    push @o, "\n";
147*6236dae4SAndroid Build Coastguard Worker    return @o;
148*6236dae4SAndroid Build Coastguard Worker}
149*6236dae4SAndroid Build Coastguard Worker
150*6236dae4SAndroid Build Coastguard Workermy %knownprotos = (
151*6236dae4SAndroid Build Coastguard Worker    'DICT' => 1,
152*6236dae4SAndroid Build Coastguard Worker    'FILE' => 1,
153*6236dae4SAndroid Build Coastguard Worker    'FTP' => 1,
154*6236dae4SAndroid Build Coastguard Worker    'FTPS' => 1,
155*6236dae4SAndroid Build Coastguard Worker    'GOPHER' => 1,
156*6236dae4SAndroid Build Coastguard Worker    'GOPHERS' => 1,
157*6236dae4SAndroid Build Coastguard Worker    'HTTP' => 1,
158*6236dae4SAndroid Build Coastguard Worker    'HTTPS' => 1,
159*6236dae4SAndroid Build Coastguard Worker    'IMAP' => 1,
160*6236dae4SAndroid Build Coastguard Worker    'IMAPS' => 1,
161*6236dae4SAndroid Build Coastguard Worker    'LDAP' => 1,
162*6236dae4SAndroid Build Coastguard Worker    'LDAPS' => 1,
163*6236dae4SAndroid Build Coastguard Worker    'MQTT' => 1,
164*6236dae4SAndroid Build Coastguard Worker    'POP3' => 1,
165*6236dae4SAndroid Build Coastguard Worker    'POP3S' => 1,
166*6236dae4SAndroid Build Coastguard Worker    'RTMP' => 1,
167*6236dae4SAndroid Build Coastguard Worker    'RTMPS' => 1,
168*6236dae4SAndroid Build Coastguard Worker    'RTSP' => 1,
169*6236dae4SAndroid Build Coastguard Worker    'SCP' => 1,
170*6236dae4SAndroid Build Coastguard Worker    'SFTP' => 1,
171*6236dae4SAndroid Build Coastguard Worker    'SMB' => 1,
172*6236dae4SAndroid Build Coastguard Worker    'SMBS' => 1,
173*6236dae4SAndroid Build Coastguard Worker    'SMTP' => 1,
174*6236dae4SAndroid Build Coastguard Worker    'SMTPS' => 1,
175*6236dae4SAndroid Build Coastguard Worker    'TELNET' => 1,
176*6236dae4SAndroid Build Coastguard Worker    'TFTP' => 1,
177*6236dae4SAndroid Build Coastguard Worker    'WS' => 1,
178*6236dae4SAndroid Build Coastguard Worker    'WSS' => 1,
179*6236dae4SAndroid Build Coastguard Worker    'TLS' => 1,
180*6236dae4SAndroid Build Coastguard Worker    'TCP' => 1,
181*6236dae4SAndroid Build Coastguard Worker    'QUIC' => 1,
182*6236dae4SAndroid Build Coastguard Worker    'All' => 1
183*6236dae4SAndroid Build Coastguard Worker    );
184*6236dae4SAndroid Build Coastguard Worker
185*6236dae4SAndroid Build Coastguard Workermy %knowntls = (
186*6236dae4SAndroid Build Coastguard Worker    'BearSSL' => 1,
187*6236dae4SAndroid Build Coastguard Worker    'GnuTLS' => 1,
188*6236dae4SAndroid Build Coastguard Worker    'mbedTLS' => 1,
189*6236dae4SAndroid Build Coastguard Worker    'OpenSSL' => 1,
190*6236dae4SAndroid Build Coastguard Worker    'rustls' => 1,
191*6236dae4SAndroid Build Coastguard Worker    'Schannel' => 1,
192*6236dae4SAndroid Build Coastguard Worker    'Secure Transport' => 1,
193*6236dae4SAndroid Build Coastguard Worker    'wolfSSL' => 1,
194*6236dae4SAndroid Build Coastguard Worker    'All' => 1,
195*6236dae4SAndroid Build Coastguard Worker    );
196*6236dae4SAndroid Build Coastguard Worker
197*6236dae4SAndroid Build Coastguard Workersub single {
198*6236dae4SAndroid Build Coastguard Worker    my @seealso;
199*6236dae4SAndroid Build Coastguard Worker    my @proto;
200*6236dae4SAndroid Build Coastguard Worker    my @tls;
201*6236dae4SAndroid Build Coastguard Worker    my $d;
202*6236dae4SAndroid Build Coastguard Worker    my ($f)=@_;
203*6236dae4SAndroid Build Coastguard Worker    my $copyright;
204*6236dae4SAndroid Build Coastguard Worker    my $errors = 0;
205*6236dae4SAndroid Build Coastguard Worker    my $fh;
206*6236dae4SAndroid Build Coastguard Worker    my $line;
207*6236dae4SAndroid Build Coastguard Worker    my $list;
208*6236dae4SAndroid Build Coastguard Worker    my $tlslist;
209*6236dae4SAndroid Build Coastguard Worker    my $section;
210*6236dae4SAndroid Build Coastguard Worker    my $source;
211*6236dae4SAndroid Build Coastguard Worker    my $addedin;
212*6236dae4SAndroid Build Coastguard Worker    my $spdx;
213*6236dae4SAndroid Build Coastguard Worker    my $start = 0;
214*6236dae4SAndroid Build Coastguard Worker    my $title;
215*6236dae4SAndroid Build Coastguard Worker
216*6236dae4SAndroid Build Coastguard Worker    if(defined($f)) {
217*6236dae4SAndroid Build Coastguard Worker        if(!open($fh, "<:crlf", "$f")) {
218*6236dae4SAndroid Build Coastguard Worker            print STDERR "cd2nroff failed to open '$f' for reading: $!\n";
219*6236dae4SAndroid Build Coastguard Worker            return 1;
220*6236dae4SAndroid Build Coastguard Worker        }
221*6236dae4SAndroid Build Coastguard Worker    }
222*6236dae4SAndroid Build Coastguard Worker    else {
223*6236dae4SAndroid Build Coastguard Worker        $f = "STDIN";
224*6236dae4SAndroid Build Coastguard Worker        $fh = \*STDIN;
225*6236dae4SAndroid Build Coastguard Worker        binmode($fh, ":crlf");
226*6236dae4SAndroid Build Coastguard Worker    }
227*6236dae4SAndroid Build Coastguard Worker    while(<$fh>) {
228*6236dae4SAndroid Build Coastguard Worker        $line++;
229*6236dae4SAndroid Build Coastguard Worker        if(!$start) {
230*6236dae4SAndroid Build Coastguard Worker            if(/^---/) {
231*6236dae4SAndroid Build Coastguard Worker                # header starts here
232*6236dae4SAndroid Build Coastguard Worker                $start = 1;
233*6236dae4SAndroid Build Coastguard Worker            }
234*6236dae4SAndroid Build Coastguard Worker            next;
235*6236dae4SAndroid Build Coastguard Worker        }
236*6236dae4SAndroid Build Coastguard Worker        if(/^Title: *(.*)/i) {
237*6236dae4SAndroid Build Coastguard Worker            $title=$1;
238*6236dae4SAndroid Build Coastguard Worker        }
239*6236dae4SAndroid Build Coastguard Worker        elsif(/^Section: *(.*)/i) {
240*6236dae4SAndroid Build Coastguard Worker            $section=$1;
241*6236dae4SAndroid Build Coastguard Worker        }
242*6236dae4SAndroid Build Coastguard Worker        elsif(/^Source: *(.*)/i) {
243*6236dae4SAndroid Build Coastguard Worker            $source=$1;
244*6236dae4SAndroid Build Coastguard Worker        }
245*6236dae4SAndroid Build Coastguard Worker        elsif(/^See-also: +(.*)/i) {
246*6236dae4SAndroid Build Coastguard Worker            $list = 1; # 1 for see-also
247*6236dae4SAndroid Build Coastguard Worker            push @seealso, $1;
248*6236dae4SAndroid Build Coastguard Worker        }
249*6236dae4SAndroid Build Coastguard Worker        elsif(/^See-also: */i) {
250*6236dae4SAndroid Build Coastguard Worker            if($seealso[0]) {
251*6236dae4SAndroid Build Coastguard Worker                print STDERR "$f:$line:1:ERROR: bad See-Also, needs list\n";
252*6236dae4SAndroid Build Coastguard Worker                return 2;
253*6236dae4SAndroid Build Coastguard Worker            }
254*6236dae4SAndroid Build Coastguard Worker            $list = 1; # 1 for see-also
255*6236dae4SAndroid Build Coastguard Worker        }
256*6236dae4SAndroid Build Coastguard Worker        elsif(/^Protocol:/i) {
257*6236dae4SAndroid Build Coastguard Worker            $list = 2; # 2 for protocol
258*6236dae4SAndroid Build Coastguard Worker        }
259*6236dae4SAndroid Build Coastguard Worker        elsif(/^TLS-backend:/i) {
260*6236dae4SAndroid Build Coastguard Worker            $list = 3; # 3 for TLS backend
261*6236dae4SAndroid Build Coastguard Worker        }
262*6236dae4SAndroid Build Coastguard Worker        elsif(/^Added-in: *(.*)/i) {
263*6236dae4SAndroid Build Coastguard Worker            $addedin=$1;
264*6236dae4SAndroid Build Coastguard Worker            if(($addedin !~ /^[0-9.]+[0-9]\z/) &&
265*6236dae4SAndroid Build Coastguard Worker               ($addedin ne "n/a")) {
266*6236dae4SAndroid Build Coastguard Worker                print STDERR "$f:$line:1:ERROR: invalid version number in Added-in line: $addedin\n";
267*6236dae4SAndroid Build Coastguard Worker                return 2;
268*6236dae4SAndroid Build Coastguard Worker            }
269*6236dae4SAndroid Build Coastguard Worker        }
270*6236dae4SAndroid Build Coastguard Worker        elsif(/^ +- (.*)/i) {
271*6236dae4SAndroid Build Coastguard Worker            # the only lists we support are see-also and protocol
272*6236dae4SAndroid Build Coastguard Worker            if($list == 1) {
273*6236dae4SAndroid Build Coastguard Worker                push @seealso, $1;
274*6236dae4SAndroid Build Coastguard Worker            }
275*6236dae4SAndroid Build Coastguard Worker            elsif($list == 2) {
276*6236dae4SAndroid Build Coastguard Worker                push @proto, $1;
277*6236dae4SAndroid Build Coastguard Worker            }
278*6236dae4SAndroid Build Coastguard Worker            elsif($list == 3) {
279*6236dae4SAndroid Build Coastguard Worker                push @tls, $1;
280*6236dae4SAndroid Build Coastguard Worker            }
281*6236dae4SAndroid Build Coastguard Worker            else {
282*6236dae4SAndroid Build Coastguard Worker                print STDERR "$f:$line:1:ERROR: list item without owner?\n";
283*6236dae4SAndroid Build Coastguard Worker                return 2;
284*6236dae4SAndroid Build Coastguard Worker            }
285*6236dae4SAndroid Build Coastguard Worker        }
286*6236dae4SAndroid Build Coastguard Worker        # REUSE-IgnoreStart
287*6236dae4SAndroid Build Coastguard Worker        elsif(/^C: (.*)/i) {
288*6236dae4SAndroid Build Coastguard Worker            $copyright=$1;
289*6236dae4SAndroid Build Coastguard Worker        }
290*6236dae4SAndroid Build Coastguard Worker        elsif(/^SPDX-License-Identifier: (.*)/i) {
291*6236dae4SAndroid Build Coastguard Worker            $spdx=$1;
292*6236dae4SAndroid Build Coastguard Worker        }
293*6236dae4SAndroid Build Coastguard Worker        # REUSE-IgnoreEnd
294*6236dae4SAndroid Build Coastguard Worker        elsif(/^---/) {
295*6236dae4SAndroid Build Coastguard Worker            # end of the header section
296*6236dae4SAndroid Build Coastguard Worker            if(!$title) {
297*6236dae4SAndroid Build Coastguard Worker                print STDERR "$f:$line:1:ERROR: no 'Title:' in $f\n";
298*6236dae4SAndroid Build Coastguard Worker                return 1;
299*6236dae4SAndroid Build Coastguard Worker            }
300*6236dae4SAndroid Build Coastguard Worker            if(!$section) {
301*6236dae4SAndroid Build Coastguard Worker                print STDERR "$f:$line:1:ERROR: no 'Section:' in $f\n";
302*6236dae4SAndroid Build Coastguard Worker                return 2;
303*6236dae4SAndroid Build Coastguard Worker            }
304*6236dae4SAndroid Build Coastguard Worker            if(!$source) {
305*6236dae4SAndroid Build Coastguard Worker                print STDERR "$f:$line:1:ERROR: no 'Source:' in $f\n";
306*6236dae4SAndroid Build Coastguard Worker                return 2;
307*6236dae4SAndroid Build Coastguard Worker            }
308*6236dae4SAndroid Build Coastguard Worker            if(($source eq "libcurl") && !$addedin) {
309*6236dae4SAndroid Build Coastguard Worker                print STDERR "$f:$line:1:ERROR: no 'Added-in:' in $f\n";
310*6236dae4SAndroid Build Coastguard Worker                return 2;
311*6236dae4SAndroid Build Coastguard Worker            }
312*6236dae4SAndroid Build Coastguard Worker            if(!$seealso[0]) {
313*6236dae4SAndroid Build Coastguard Worker                print STDERR "$f:$line:1:ERROR: no 'See-also:' present\n";
314*6236dae4SAndroid Build Coastguard Worker                return 2;
315*6236dae4SAndroid Build Coastguard Worker            }
316*6236dae4SAndroid Build Coastguard Worker            if(!$copyright) {
317*6236dae4SAndroid Build Coastguard Worker                print STDERR "$f:$line:1:ERROR: no 'C:' field present\n";
318*6236dae4SAndroid Build Coastguard Worker                return 2;
319*6236dae4SAndroid Build Coastguard Worker            }
320*6236dae4SAndroid Build Coastguard Worker            if(!$spdx) {
321*6236dae4SAndroid Build Coastguard Worker                print STDERR "$f:$line:1:ERROR: no 'SPDX-License-Identifier:' field present\n";
322*6236dae4SAndroid Build Coastguard Worker                return 2;
323*6236dae4SAndroid Build Coastguard Worker            }
324*6236dae4SAndroid Build Coastguard Worker            if($section == 3) {
325*6236dae4SAndroid Build Coastguard Worker                if(!$proto[0]) {
326*6236dae4SAndroid Build Coastguard Worker                    printf STDERR "$f:$line:1:ERROR: missing Protocol:\n";
327*6236dae4SAndroid Build Coastguard Worker                    exit 2;
328*6236dae4SAndroid Build Coastguard Worker                }
329*6236dae4SAndroid Build Coastguard Worker                my $tls = 0;
330*6236dae4SAndroid Build Coastguard Worker                for my $p (@proto) {
331*6236dae4SAndroid Build Coastguard Worker                    if($p eq "TLS") {
332*6236dae4SAndroid Build Coastguard Worker                        $tls = 1;
333*6236dae4SAndroid Build Coastguard Worker                    }
334*6236dae4SAndroid Build Coastguard Worker                    if(!$knownprotos{$p}) {
335*6236dae4SAndroid Build Coastguard Worker                        printf STDERR "$f:$line:1:ERROR: invalid protocol used: $p:\n";
336*6236dae4SAndroid Build Coastguard Worker                        exit 2;
337*6236dae4SAndroid Build Coastguard Worker                    }
338*6236dae4SAndroid Build Coastguard Worker                }
339*6236dae4SAndroid Build Coastguard Worker                # This is for TLS, require TLS-backend:
340*6236dae4SAndroid Build Coastguard Worker                if($tls) {
341*6236dae4SAndroid Build Coastguard Worker                    if(!$tls[0]) {
342*6236dae4SAndroid Build Coastguard Worker                        printf STDERR "$f:$line:1:ERROR: missing TLS-backend:\n";
343*6236dae4SAndroid Build Coastguard Worker                        exit 2;
344*6236dae4SAndroid Build Coastguard Worker                    }
345*6236dae4SAndroid Build Coastguard Worker                    for my $t (@tls) {
346*6236dae4SAndroid Build Coastguard Worker                        if(!$knowntls{$t}) {
347*6236dae4SAndroid Build Coastguard Worker                            printf STDERR "$f:$line:1:ERROR: invalid TLS backend: $t:\n";
348*6236dae4SAndroid Build Coastguard Worker                            exit 2;
349*6236dae4SAndroid Build Coastguard Worker                        }
350*6236dae4SAndroid Build Coastguard Worker                    }
351*6236dae4SAndroid Build Coastguard Worker                }
352*6236dae4SAndroid Build Coastguard Worker            }
353*6236dae4SAndroid Build Coastguard Worker            last;
354*6236dae4SAndroid Build Coastguard Worker        }
355*6236dae4SAndroid Build Coastguard Worker        else {
356*6236dae4SAndroid Build Coastguard Worker            chomp;
357*6236dae4SAndroid Build Coastguard Worker            print STDERR "$f:$line:1:ERROR: unrecognized header keyword: '$_'\n";
358*6236dae4SAndroid Build Coastguard Worker            $errors++;
359*6236dae4SAndroid Build Coastguard Worker        }
360*6236dae4SAndroid Build Coastguard Worker    }
361*6236dae4SAndroid Build Coastguard Worker
362*6236dae4SAndroid Build Coastguard Worker    if(!$start) {
363*6236dae4SAndroid Build Coastguard Worker        print STDERR "$f:$line:1:ERROR: no header present\n";
364*6236dae4SAndroid Build Coastguard Worker        return 2;
365*6236dae4SAndroid Build Coastguard Worker    }
366*6236dae4SAndroid Build Coastguard Worker
367*6236dae4SAndroid Build Coastguard Worker    my @desc;
368*6236dae4SAndroid Build Coastguard Worker    my $quote = 0;
369*6236dae4SAndroid Build Coastguard Worker    my $blankline = 0;
370*6236dae4SAndroid Build Coastguard Worker    my $header = 0;
371*6236dae4SAndroid Build Coastguard Worker
372*6236dae4SAndroid Build Coastguard Worker    # cut off the leading path from the file name, if any
373*6236dae4SAndroid Build Coastguard Worker    $f =~ s/^(.*[\\\/])//;
374*6236dae4SAndroid Build Coastguard Worker
375*6236dae4SAndroid Build Coastguard Worker    push @desc, ".\\\" generated by cd2nroff $cd2nroff from $f\n";
376*6236dae4SAndroid Build Coastguard Worker    push @desc, ".TH $title $section \"$date\" $source\n";
377*6236dae4SAndroid Build Coastguard Worker    while(<$fh>) {
378*6236dae4SAndroid Build Coastguard Worker        $line++;
379*6236dae4SAndroid Build Coastguard Worker
380*6236dae4SAndroid Build Coastguard Worker        $d = $_;
381*6236dae4SAndroid Build Coastguard Worker
382*6236dae4SAndroid Build Coastguard Worker        if($quote) {
383*6236dae4SAndroid Build Coastguard Worker            if($quote == 4) {
384*6236dae4SAndroid Build Coastguard Worker                # remove the indentation
385*6236dae4SAndroid Build Coastguard Worker                if($d =~ /^    (.*)/) {
386*6236dae4SAndroid Build Coastguard Worker                    push @desc, "$1\n";
387*6236dae4SAndroid Build Coastguard Worker                    next;
388*6236dae4SAndroid Build Coastguard Worker                }
389*6236dae4SAndroid Build Coastguard Worker                else {
390*6236dae4SAndroid Build Coastguard Worker                    # end of quote
391*6236dae4SAndroid Build Coastguard Worker                    $quote = 0;
392*6236dae4SAndroid Build Coastguard Worker                    push @desc, ".fi\n";
393*6236dae4SAndroid Build Coastguard Worker                    next;
394*6236dae4SAndroid Build Coastguard Worker                }
395*6236dae4SAndroid Build Coastguard Worker            }
396*6236dae4SAndroid Build Coastguard Worker            if(/^~~~/) {
397*6236dae4SAndroid Build Coastguard Worker                # end of quote
398*6236dae4SAndroid Build Coastguard Worker                $quote = 0;
399*6236dae4SAndroid Build Coastguard Worker                push @desc, ".fi\n";
400*6236dae4SAndroid Build Coastguard Worker                next;
401*6236dae4SAndroid Build Coastguard Worker            }
402*6236dae4SAndroid Build Coastguard Worker            # convert single backslahes to doubles
403*6236dae4SAndroid Build Coastguard Worker            $d =~ s/\\/\\\\/g;
404*6236dae4SAndroid Build Coastguard Worker            # lines starting with a period needs it escaped
405*6236dae4SAndroid Build Coastguard Worker            $d =~ s/^\./\\&./;
406*6236dae4SAndroid Build Coastguard Worker            push @desc, $d;
407*6236dae4SAndroid Build Coastguard Worker            next;
408*6236dae4SAndroid Build Coastguard Worker        }
409*6236dae4SAndroid Build Coastguard Worker
410*6236dae4SAndroid Build Coastguard Worker        # remove single line HTML comments
411*6236dae4SAndroid Build Coastguard Worker        $d =~ s/<!--.*?-->//g;
412*6236dae4SAndroid Build Coastguard Worker
413*6236dae4SAndroid Build Coastguard Worker        # **bold**
414*6236dae4SAndroid Build Coastguard Worker        $d =~ s/\*\*(\S.*?)\*\*/\\fB$1\\fP/g;
415*6236dae4SAndroid Build Coastguard Worker        # *italics*
416*6236dae4SAndroid Build Coastguard Worker        $d =~ s/\*(\S.*?)\*/\\fI$1\\fP/g;
417*6236dae4SAndroid Build Coastguard Worker
418*6236dae4SAndroid Build Coastguard Worker        if($d =~ /[^\\][\<\>]/) {
419*6236dae4SAndroid Build Coastguard Worker            print STDERR "$f:$line:1:ERROR: un-escaped < or > used\n";
420*6236dae4SAndroid Build Coastguard Worker            $errors++;
421*6236dae4SAndroid Build Coastguard Worker        }
422*6236dae4SAndroid Build Coastguard Worker        # convert backslash-'<' or '> to just the second character
423*6236dae4SAndroid Build Coastguard Worker        $d =~ s/\\([<>])/$1/g;
424*6236dae4SAndroid Build Coastguard Worker
425*6236dae4SAndroid Build Coastguard Worker        # mentions of curl symbols with manpages use italics by default
426*6236dae4SAndroid Build Coastguard Worker        $d =~ s/((lib|)curl([^ ]*\(3\)))/\\fI$1\\fP/gi;
427*6236dae4SAndroid Build Coastguard Worker
428*6236dae4SAndroid Build Coastguard Worker        # backticked becomes italics
429*6236dae4SAndroid Build Coastguard Worker        $d =~ s/\`(.*?)\`/\\fI$1\\fP/g;
430*6236dae4SAndroid Build Coastguard Worker
431*6236dae4SAndroid Build Coastguard Worker        if(/^## (.*)/) {
432*6236dae4SAndroid Build Coastguard Worker            my $word = $1;
433*6236dae4SAndroid Build Coastguard Worker            # if there are enclosing quotes, remove them first
434*6236dae4SAndroid Build Coastguard Worker            $word =~ s/[\"\'\`](.*)[\"\'\`]\z/$1/;
435*6236dae4SAndroid Build Coastguard Worker
436*6236dae4SAndroid Build Coastguard Worker            # enclose in double quotes if there is a space present
437*6236dae4SAndroid Build Coastguard Worker            if($word =~ / /) {
438*6236dae4SAndroid Build Coastguard Worker                push @desc, ".IP \"$word\"\n";
439*6236dae4SAndroid Build Coastguard Worker            }
440*6236dae4SAndroid Build Coastguard Worker            else {
441*6236dae4SAndroid Build Coastguard Worker                push @desc, ".IP $word\n";
442*6236dae4SAndroid Build Coastguard Worker            }
443*6236dae4SAndroid Build Coastguard Worker            $header = 1;
444*6236dae4SAndroid Build Coastguard Worker        }
445*6236dae4SAndroid Build Coastguard Worker        elsif(/^##/) {
446*6236dae4SAndroid Build Coastguard Worker            # end of IP sequence
447*6236dae4SAndroid Build Coastguard Worker            push @desc, ".PP\n";
448*6236dae4SAndroid Build Coastguard Worker            $header = 1;
449*6236dae4SAndroid Build Coastguard Worker        }
450*6236dae4SAndroid Build Coastguard Worker        elsif(/^# (.*)/) {
451*6236dae4SAndroid Build Coastguard Worker            my $word = $1;
452*6236dae4SAndroid Build Coastguard Worker            # if there are enclosing quotes, remove them first
453*6236dae4SAndroid Build Coastguard Worker            $word =~ s/[\"\'](.*)[\"\']\z/$1/;
454*6236dae4SAndroid Build Coastguard Worker
455*6236dae4SAndroid Build Coastguard Worker            if($word eq "PROTOCOLS") {
456*6236dae4SAndroid Build Coastguard Worker                print STDERR "$f:$line:1:WARN: PROTOCOLS section in source file\n";
457*6236dae4SAndroid Build Coastguard Worker            }
458*6236dae4SAndroid Build Coastguard Worker            elsif($word eq "AVAILABILITY") {
459*6236dae4SAndroid Build Coastguard Worker                print STDERR "$f:$line:1:WARN: AVAILABILITY section in source file\n";
460*6236dae4SAndroid Build Coastguard Worker            }
461*6236dae4SAndroid Build Coastguard Worker            elsif($word eq "%PROTOCOLS%") {
462*6236dae4SAndroid Build Coastguard Worker                # insert the generated PROTOCOLS section
463*6236dae4SAndroid Build Coastguard Worker                push @desc, outprotocols(@proto);
464*6236dae4SAndroid Build Coastguard Worker
465*6236dae4SAndroid Build Coastguard Worker                if($proto[0] eq "TLS") {
466*6236dae4SAndroid Build Coastguard Worker                    push @desc, outtls(@tls);
467*6236dae4SAndroid Build Coastguard Worker                }
468*6236dae4SAndroid Build Coastguard Worker                $header = 1;
469*6236dae4SAndroid Build Coastguard Worker                next;
470*6236dae4SAndroid Build Coastguard Worker            }
471*6236dae4SAndroid Build Coastguard Worker            elsif($word eq "%AVAILABILITY%") {
472*6236dae4SAndroid Build Coastguard Worker                if($addedin ne "n/a") {
473*6236dae4SAndroid Build Coastguard Worker                    # insert the generated AVAILABILITY section
474*6236dae4SAndroid Build Coastguard Worker                    push @desc, ".SH AVAILABILITY\n";
475*6236dae4SAndroid Build Coastguard Worker                    push @desc, "Added in curl $addedin\n";
476*6236dae4SAndroid Build Coastguard Worker                }
477*6236dae4SAndroid Build Coastguard Worker                $header = 1;
478*6236dae4SAndroid Build Coastguard Worker                next;
479*6236dae4SAndroid Build Coastguard Worker            }
480*6236dae4SAndroid Build Coastguard Worker            push @desc, ".SH $word\n";
481*6236dae4SAndroid Build Coastguard Worker            $header = 1;
482*6236dae4SAndroid Build Coastguard Worker        }
483*6236dae4SAndroid Build Coastguard Worker        elsif(/^~~~c/) {
484*6236dae4SAndroid Build Coastguard Worker            # start of a code section, not indented
485*6236dae4SAndroid Build Coastguard Worker            $quote = 1;
486*6236dae4SAndroid Build Coastguard Worker            push @desc, "\n" if($blankline && !$header);
487*6236dae4SAndroid Build Coastguard Worker            $header = 0;
488*6236dae4SAndroid Build Coastguard Worker            push @desc, ".nf\n";
489*6236dae4SAndroid Build Coastguard Worker        }
490*6236dae4SAndroid Build Coastguard Worker        elsif(/^~~~/) {
491*6236dae4SAndroid Build Coastguard Worker            # start of a quote section; not code, not indented
492*6236dae4SAndroid Build Coastguard Worker            $quote = 1;
493*6236dae4SAndroid Build Coastguard Worker            push @desc, "\n" if($blankline && !$header);
494*6236dae4SAndroid Build Coastguard Worker            $header = 0;
495*6236dae4SAndroid Build Coastguard Worker            push @desc, ".nf\n";
496*6236dae4SAndroid Build Coastguard Worker        }
497*6236dae4SAndroid Build Coastguard Worker        elsif(/^    (.*)/) {
498*6236dae4SAndroid Build Coastguard Worker            # quoted, indented by 4 space
499*6236dae4SAndroid Build Coastguard Worker            $quote = 4;
500*6236dae4SAndroid Build Coastguard Worker            push @desc, "\n" if($blankline && !$header);
501*6236dae4SAndroid Build Coastguard Worker            $header = 0;
502*6236dae4SAndroid Build Coastguard Worker            push @desc, ".nf\n$1\n";
503*6236dae4SAndroid Build Coastguard Worker        }
504*6236dae4SAndroid Build Coastguard Worker        elsif(/^[ \t]*\n/) {
505*6236dae4SAndroid Build Coastguard Worker            # count and ignore blank lines
506*6236dae4SAndroid Build Coastguard Worker            $blankline++;
507*6236dae4SAndroid Build Coastguard Worker        }
508*6236dae4SAndroid Build Coastguard Worker        else {
509*6236dae4SAndroid Build Coastguard Worker            # don't output newlines if this is the first content after a
510*6236dae4SAndroid Build Coastguard Worker            # header
511*6236dae4SAndroid Build Coastguard Worker            push @desc, "\n" if($blankline && !$header);
512*6236dae4SAndroid Build Coastguard Worker            $blankline = 0;
513*6236dae4SAndroid Build Coastguard Worker            $header = 0;
514*6236dae4SAndroid Build Coastguard Worker
515*6236dae4SAndroid Build Coastguard Worker            # quote minuses in the output
516*6236dae4SAndroid Build Coastguard Worker            $d =~ s/([^\\])-/$1\\-/g;
517*6236dae4SAndroid Build Coastguard Worker            # replace single quotes
518*6236dae4SAndroid Build Coastguard Worker            $d =~ s/\'/\\(aq/g;
519*6236dae4SAndroid Build Coastguard Worker            # handle double quotes first on the line
520*6236dae4SAndroid Build Coastguard Worker            $d =~ s/^(\s*)\"/$1\\&\"/;
521*6236dae4SAndroid Build Coastguard Worker
522*6236dae4SAndroid Build Coastguard Worker            # lines starting with a period needs it escaped
523*6236dae4SAndroid Build Coastguard Worker            $d =~ s/^\./\\&./;
524*6236dae4SAndroid Build Coastguard Worker
525*6236dae4SAndroid Build Coastguard Worker            if($d =~ /^(.*)  /) {
526*6236dae4SAndroid Build Coastguard Worker                printf STDERR "$f:$line:%d:ERROR: 2 spaces detected\n",
527*6236dae4SAndroid Build Coastguard Worker                    length($1);
528*6236dae4SAndroid Build Coastguard Worker                $errors++;
529*6236dae4SAndroid Build Coastguard Worker            }
530*6236dae4SAndroid Build Coastguard Worker            if($d =~ /^[ \t]*\n/) {
531*6236dae4SAndroid Build Coastguard Worker                # replaced away all contents
532*6236dae4SAndroid Build Coastguard Worker                $blankline= 1;
533*6236dae4SAndroid Build Coastguard Worker            }
534*6236dae4SAndroid Build Coastguard Worker            else {
535*6236dae4SAndroid Build Coastguard Worker                push @desc, $d;
536*6236dae4SAndroid Build Coastguard Worker            }
537*6236dae4SAndroid Build Coastguard Worker        }
538*6236dae4SAndroid Build Coastguard Worker    }
539*6236dae4SAndroid Build Coastguard Worker    if($fh != \*STDIN) {
540*6236dae4SAndroid Build Coastguard Worker        close($fh);
541*6236dae4SAndroid Build Coastguard Worker    }
542*6236dae4SAndroid Build Coastguard Worker    push @desc, outseealso(@seealso);
543*6236dae4SAndroid Build Coastguard Worker    if($dir) {
544*6236dae4SAndroid Build Coastguard Worker        if($keepfilename) {
545*6236dae4SAndroid Build Coastguard Worker            $title = $f;
546*6236dae4SAndroid Build Coastguard Worker            $title =~ s/\.[^.]*$//;
547*6236dae4SAndroid Build Coastguard Worker        }
548*6236dae4SAndroid Build Coastguard Worker        my $outfile = "$dir/$title.$section";
549*6236dae4SAndroid Build Coastguard Worker        if(defined($extension)) {
550*6236dae4SAndroid Build Coastguard Worker            $outfile .= $extension;
551*6236dae4SAndroid Build Coastguard Worker        }
552*6236dae4SAndroid Build Coastguard Worker        if(!open(O, ">", $outfile)) {
553*6236dae4SAndroid Build Coastguard Worker            print STDERR "Failed to open $outfile : $!\n";
554*6236dae4SAndroid Build Coastguard Worker            return 1;
555*6236dae4SAndroid Build Coastguard Worker        }
556*6236dae4SAndroid Build Coastguard Worker        print O @desc;
557*6236dae4SAndroid Build Coastguard Worker        close(O);
558*6236dae4SAndroid Build Coastguard Worker    }
559*6236dae4SAndroid Build Coastguard Worker    else {
560*6236dae4SAndroid Build Coastguard Worker        print @desc;
561*6236dae4SAndroid Build Coastguard Worker    }
562*6236dae4SAndroid Build Coastguard Worker    return $errors;
563*6236dae4SAndroid Build Coastguard Worker}
564*6236dae4SAndroid Build Coastguard Worker
565*6236dae4SAndroid Build Coastguard Workerif(@ARGV) {
566*6236dae4SAndroid Build Coastguard Worker    for my $f (@ARGV) {
567*6236dae4SAndroid Build Coastguard Worker        my $r = single($f);
568*6236dae4SAndroid Build Coastguard Worker        if($r) {
569*6236dae4SAndroid Build Coastguard Worker            exit $r;
570*6236dae4SAndroid Build Coastguard Worker        }
571*6236dae4SAndroid Build Coastguard Worker    }
572*6236dae4SAndroid Build Coastguard Worker}
573*6236dae4SAndroid Build Coastguard Workerelse {
574*6236dae4SAndroid Build Coastguard Worker    exit single();
575*6236dae4SAndroid Build Coastguard Worker}
576