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# Update man pages. 27 28use strict; 29use warnings; 30use Tie::File; 31 32# Data from the command line. 33 34my $curlver = $ARGV[0]; 35my $curldate = $ARGV[1]; 36 37# Directories and extensions. 38 39my @dirlist = ("docs/", "docs/libcurl/", "docs/libcurl/opts/", "tests/"); 40my @extlist = (".1", ".3"); 41my @excludelist = ("mk-ca-bundle.1", "template.3"); 42 43# Subroutines 44 45sub printargs{ 46 # Print arguments and exit. 47 48 print "usage: updatemanpages.pl <version> <date>\n"; 49 exit; 50} 51 52sub getthline{ 53 # Process file looking for .TH section. 54 55 my $filename = shift; 56 my $file_handle; 57 my $file_line; 58 59 # Open the file. 60 61 open($file_handle, $filename); 62 63 # Look for the .TH section, process it into an array, 64 # modify it and write to file. 65 66 tie(my @file_data, 'Tie::File', $filename); 67 foreach my $file_data_line(@file_data) { 68 if($file_data_line =~ /^.TH/) { 69 $file_line = $file_data_line; 70 last; 71 } 72 } 73 74 # Close the file. 75 76 close($file_handle); 77 return $file_line; 78} 79 80sub extractth{ 81 # Extract .TH section as an array. 82 83 my $input = shift; 84 85 # Split the line into an array. 86 87 my @tharray; 88 my $inputsize = length($input); 89 my $inputcurrent = ""; 90 my $quotemode = 0; 91 92 for(my $inputseek = 0; $inputseek < $inputsize; $inputseek++) { 93 94 if(substr($input, $inputseek, 1) eq " " && $quotemode eq 0) { 95 push(@tharray, $inputcurrent); 96 $inputcurrent = ""; 97 next; 98 } 99 100 $inputcurrent = $inputcurrent . substr($input, $inputseek, 1); 101 102 if(substr($input, $inputseek, 1) eq "\"") { 103 if($quotemode eq 0) { 104 $quotemode = 1; 105 } 106 else { 107 $quotemode = 0; 108 } 109 } 110 } 111 112 if($inputcurrent ne "") { 113 push(@tharray, $inputcurrent); 114 } 115 116 return @tharray; 117} 118 119sub getdate{ 120 # Get the date from the .TH section. 121 122 my $filename = shift; 123 my $thline; 124 my @tharray; 125 my $date = ""; 126 127 $thline = getthline($filename); 128 129 # Return nothing if there is no .TH section found. 130 131 if(!$thline || $thline eq "") { 132 return ""; 133 } 134 135 @tharray = extractth($thline); 136 137 # Remove the quotes at the start and end. 138 139 $date = substr($tharray[3], 1, -1); 140 return $date; 141} 142 143sub processth{ 144 # Process .TH section. 145 146 my $input = shift; 147 my $date = shift; 148 149 # Split the line into an array. 150 151 my @tharray = extractth($input); 152 153 # Alter the date. 154 155 my $itemdate = "\""; 156 $itemdate .= $date; 157 $itemdate .= "\""; 158 $tharray[3] = $itemdate; 159 160 # Alter the item version. 161 162 my $itemver = $tharray[4]; 163 my $itemname = ""; 164 165 for(my $itemnameseek = 1; 166 $itemnameseek < length($itemver); 167 $itemnameseek++) { 168 if(substr($itemver, $itemnameseek, 1) eq " " || 169 substr($itemver, $itemnameseek, 1) eq "\"") { 170 last; 171 } 172 $itemname .= substr($itemver, $itemnameseek, 1); 173 } 174 175 $itemver = "\""; 176 $itemver .= $itemname; 177 $itemver .= " "; 178 $itemver .= $curlver; 179 $itemver .= "\""; 180 181 $tharray[4] = $itemver; 182 183 my $thoutput = ""; 184 185 foreach my $thvalue (@tharray) { 186 $thoutput .= $thvalue; 187 $thoutput .= " "; 188 } 189 $thoutput =~ s/\s+$//; 190 $thoutput .= "\n"; 191 192 # Return updated string. 193 194 return $thoutput; 195} 196 197sub processfile{ 198 # Process file looking for .TH section. 199 200 my $filename = shift; 201 my $date = shift; 202 my $file_handle; 203 my $file_dist_handle; 204 my $filename_dist; 205 206 # Open a handle for the original file and a second file handle 207 # for the dist file. 208 209 $filename_dist = $filename . ".dist"; 210 211 open($file_handle, $filename); 212 open($file_dist_handle, ">" . $filename_dist); 213 214 # Look for the .TH section, process it into an array, 215 # modify it and write to file. 216 217 tie(my @file_data, 'Tie::File', $filename); 218 foreach my $file_data_line (@file_data) { 219 if($file_data_line =~ /^.TH/) { 220 my $file_dist_line = processth($file_data_line, $date); 221 print $file_dist_handle $file_dist_line . "\n"; 222 } 223 else { 224 print $file_dist_handle $file_data_line . "\n"; 225 } 226 } 227 228 # Close the file. 229 230 close($file_handle); 231 close($file_dist_handle); 232} 233 234# Check that $curlver is set, otherwise print arguments and exit. 235 236if(!$curlver) { 237 printargs(); 238} 239 240# check to see that the git command works, it requires git 2.6 something 241my $gitcheck = `git log -1 --date="format:%B %d, %Y" $dirlist[0] 2>/dev/null`; 242if(length($gitcheck) < 1) { 243 print "git version too old or $dirlist[0] is a bad argument\n"; 244 exit; 245} 246 247# Look in each directory. 248 249my $dir_handle; 250 251foreach my $dirname (@dirlist) { 252 foreach my $extname (@extlist) { 253 # Go through the directory looking for files ending with 254 # the current extension. 255 256 opendir($dir_handle, $dirname); 257 my @filelist = grep(/.$extname$/i, readdir($dir_handle)); 258 259 foreach my $file (@filelist) { 260 # Skip if file is in exclude list. 261 262 if(grep(/^$file$/, @excludelist)) { 263 next; 264 } 265 266 # Load the file and get the date. 267 268 my $filedate; 269 270 # Check if dist version exists and load date from that 271 # file if it does. 272 273 if(-e ($dirname . $file . ".dist")) { 274 $filedate = getdate(($dirname . $file . ".dist")); 275 } 276 else { 277 $filedate = getdate(($dirname . $file)); 278 } 279 280 # Skip if value is empty. 281 282 if(!$filedate || $filedate eq "") { 283 next; 284 } 285 286 # Check the man page in the git repository. 287 288 my $repodata = `LC_TIME=C git log -1 --date="format:%B %d, %Y" \\ 289 --since="$filedate" $dirname$file | grep ^Date:`; 290 291 # If there is output then update the man page 292 # with the new date/version. 293 294 # Process the file if there is output. 295 296 if($repodata) { 297 my $thisdate; 298 if(!$curldate) { 299 if($repodata =~ /^Date: +(.*)/) { 300 $thisdate = $1; 301 } 302 else { 303 print STDERR "Warning: " . ($dirname . $file) . ": found no " . 304 "date\n"; 305 } 306 } 307 else { 308 $thisdate = $curldate; 309 } 310 processfile(($dirname . $file), $thisdate); 311 print $dirname . $file . " page updated to $thisdate\n"; 312 } 313 } 314 closedir($dir_handle); 315 } 316} 317 318__END__ 319 320=pod 321 322=head1 updatemanpages.pl 323 324Updates the man pages with the version number and optional date. If the date 325isn't provided, the last modified date from git is used. 326 327=head2 USAGE 328 329updatemanpages.pl version [date] 330 331=head3 version 332 333Specifies version (required) 334 335=head3 date 336 337Specifies date (optional) 338 339=head2 SETTINGS 340 341=head3 @dirlist 342 343Specifies the list of directories to look for files in. 344 345=head3 @extlist 346 347Specifies the list of files with extensions to process. 348 349=head3 @excludelist 350 351Specifies the list of files to not process. 352 353=head2 NOTES 354 355This script is used during maketgz. 356 357=cut 358