1#!/usr/bin/env perl 2#*************************************************************************** 3# _ _ ____ _ 4# Project ___| | | | _ \| | 5# / __| | | | |_) | | 6# | (__| |_| | _ <| |___ 7# \___|\___/|_| \_\_____| 8# 9# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 10# 11# This software is licensed as described in the file COPYING, which 12# you should have received as part of this distribution. The terms 13# are also available at https://curl.se/docs/copyright.html. 14# 15# You may opt to use, copy, modify, merge, publish, distribute and/or sell 16# copies of the Software, and permit persons to whom the Software is 17# furnished to do so, under the terms of the COPYING file. 18# 19# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 20# KIND, either express or implied. 21# 22# SPDX-License-Identifier: curl 23# 24########################################################################### 25 26=begin comment 27 28This script converts an nroff file to curldown 29 30Example: cd2nroff [options] <file.md> > <file.3> 31 32Note: when converting .nf sections, this tool does not know if the 33section is code or just regular quotes. It then assumes and uses ~~~c 34for code. 35 36=end comment 37=cut 38 39my $nroff2cd = "0.1"; # to keep check 40 41sub single { 42 my ($f)=@_; 43 open(F, "<:crlf", "$f") || 44 return 1; 45 my $line; 46 my $title; 47 my $section; 48 my $source; 49 my @seealso; 50 my @desc; 51 my $header; # non-zero when TH is passed 52 my $quote = 0; # quote state 53 while(<F>) { 54 $line++; 55 my $d = $_; 56 if($_ =~ /^.\\\"/) { 57 # a comment we can ignore 58 next; 59 } 60 if(!$header) { 61 if($d =~ /.so (.*)/) { 62 # this is basically an include, so do that 63 my $f = $1; 64 # remove leading directory 65 $f =~ s/(.*?\/)//; 66 close(F); 67 open(F, "<:crlf", "$f") || return 1; 68 } 69 if($d =~ /^\.TH ([^ ]*) (\d) \"(.*?)\" ([^ \n]*)/) { 70 # header, this needs to be the first thing after leading comments 71 $title = $1; 72 $section = $2; 73 # date is $3 74 $source = $4; 75 # if there are enclosing quotes around source, remove them 76 $source =~ s/[\"\'](.*)[\"\']\z/$1/; 77 $header = 1; 78 79 print <<HEAD 80--- 81c: Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 82SPDX-License-Identifier: curl 83Title: $title 84Section: $section 85Source: $source 86HEAD 87 ; 88 } 89 next; 90 } 91 92 if($quote) { 93 if($d =~ /^\.SH/) { 94 #end of quote without an .fi 95 $quote = 0; 96 push @desc, "~~~\n"; 97 } 98 elsif($d =~ /^\.fi/) { 99 #end of quote 100 $quote = 0; 101 push @desc, "~~~\n"; 102 next; 103 } 104 else { 105 # double-backslashes converted to single ones 106 $d =~ s/\\\\/\\/g; 107 push @desc, $d; 108 next; 109 } 110 } 111 if($d =~ /^\.SH (.*)/) { 112 my $word = $1; 113 # if there are enclosing quotes, remove them first 114 $word =~ s/[\"\'](.*)[\"\']\z/$1/; 115 if($word eq "SEE ALSO") { 116 # we just slurp up this section 117 next; 118 } 119 push @desc, "\n# $word\n\n"; 120 } 121 elsif($d =~ /^\.(RS|RE)/) { 122 # ignore these 123 } 124 elsif($d =~ /^\.IP (.*)/) { 125 my $word = $1; 126 # if there are enclosing quotes, remove them first 127 $word =~ s/[\"\'](.*)[\"\']\z/$1/; 128 push @desc, "\n## $word\n\n"; 129 } 130 elsif($d =~ /^\.IP/) { 131 # .IP with no text we just skip 132 } 133 elsif($d =~ /^\.BR (.*)/) { 134 # only used for SEE ALSO 135 my $word = $1; 136 # remove trailing comma 137 $word =~ s/,\z//; 138 139 for my $s (split(/,/, $word)) { 140 # remove all double quotes 141 $s =~ s/\"//g; 142 # tream leading whitespace 143 $s =~ s/^ +//g; 144 push @seealso, $s; 145 } 146 } 147 elsif($d =~ /^\.I (.*)/) { 148 push @desc, "*$1*\n"; 149 } 150 elsif($d =~ /^\.B (.*)/) { 151 push @desc, "**$1**\n"; 152 } 153 elsif($d =~ /^\.nf/) { 154 push @desc, "~~~c\n"; 155 $quote = 1; 156 } 157 else { 158 # embolden 159 $d =~ s/\\fB(.*?)\\fP/**$1**/g; 160 # links to "curl.*()" are left bare since cd2nroff handles them 161 # specially 162 $d =~ s/\\fI(curl.*?\(3\))\\fP/$1/ig; 163 # emphasize 164 $d =~ s/\\fI(.*?)\\fP/*$1*/g; 165 # emphasize on a split line 166 $d =~ s/\\fI/*/g; 167 # bold on a split line 168 $d =~ s/\\fB/**/g; 169 # remove backslash amp 170 $d =~ s/\\&//g; 171 # remove backslashes 172 $d =~ s/\\//g; 173 # fix single quotes 174 $d =~ s/\(aq/'/g; 175 # fix double quotes 176 $d =~ s/\(dq/\"/g; 177 push @desc, $d; 178 } 179 } 180 close(F); 181 182 print "See-also:\n"; 183 for my $s (sort @seealso) { 184 print " - $s\n" if($s); 185 } 186 print "---\n"; 187 print @desc; 188 189 return !$header; 190} 191 192exit single($ARGV[0]); 193