1# 2# cpmanpages.tcl -- 3# 4# Tool used during build to copy manual pages to master directories. This 5# program knows the internals of the build, so its very specific to this 6# task. 7# 8# It is run in the following manner: 9# 10# cpmanpages ?flags? separator cmd func unix sourceDir targetDir 11# 12# flags are: 13# o -rmcat - remove any existing "cat" files associated with man pages. 14# 15# arguments are: 16# o separator - Either "." or "", the separator in the manual page directory 17# name (/usr/man/man1 vs /usr/man/man.1). 18# o cmd - Section to put the Tcl command manual pages in. (*.n pages). 19# o func - Section to put the Tcl C function manual pages in. (*.3 pages). 20# o unix - Section to put the Tcl Unix command manual pages in. 21# Maybe empty. (*.1 pages). 22# o sourceDir - directory containing manual pages to install. 23# o targetDir - manual directory to install pages in. This is the directory 24# containing the section directories, e.g. /usr/local/man. 25# 26# If any of these strings are quoted with "@" (e.g. @.@), then the two "@" 27# are removed. This is to work around problems with systems were quoted empty 28# strings don't make it past make and shell expansion, resulting in a missing 29# argument. 30#------------------------------------------------------------------------------ 31# Copyright 1992-1999 Karl Lehenbauer and Mark Diekhans. 32# 33# Permission to use, copy, modify, and distribute this software and its 34# documentation for any purpose and without fee is hereby granted, provided 35# that the above copyright notice appear in all copies. Karl Lehenbauer and 36# Mark Diekhans make no representations about the suitability of this 37# software for any purpose. It is provided "as is" without express or 38# implied warranty. 39#------------------------------------------------------------------------------ 40# $Id: cpmanpages.tcl,v 8.4 1999/03/31 06:37:59 markd Exp $ 41#------------------------------------------------------------------------------ 42# 43 44#------------------------------------------------------------------------------ 45# Unquote -- 46# 47# Remove "@" if they quote a string. 48#------------------------------------------------------------------------------ 49 50proc Unquote str { 51 regsub -- {^@(.*)@$} $str {\1} str 52 return $str 53} 54 55#------------------------------------------------------------------------------ 56# CopyManFile -- 57# 58# Called to open a copy a man file. Recursively called to include .so files. 59#------------------------------------------------------------------------------ 60 61proc CopyManFile {sourceFile targetFH} { 62 63 set sourceFH [open $sourceFile r] 64 65 while {[gets $sourceFH line] >= 0} { 66 if [string match {.V[SE]*} $line] continue 67 if [string match {.so *} $line] { 68 set soFile [string trim [crange $line 3 end]] 69 CopyManFile "[file dirname $sourceFile]/$soFile" $targetFH 70 continue 71 } 72 puts $targetFH $line 73 } 74 75 close $sourceFH 76} 77 78#------------------------------------------------------------------------------ 79# CopyManPage -- 80# 81# Copy the specified manual page and change the ownership. The manual page 82# is edited to remove change bars (.VS and .VE macros). Files included with .so 83# are merged in. 84#------------------------------------------------------------------------------ 85 86proc CopyManPage {sourceFile targetFile} { 87 global gzip 88 if ![file exists [file dirname $targetFile]] { 89 mkdir -path [file dirname $targetFile] 90 } 91 catch {file delete $targetFile $targetFile.gz} 92 93 set targetFH [open $targetFile w] 94 CopyManFile $sourceFile $targetFH 95 close $targetFH 96 if $gzip { 97 exec gzip -9f $targetFile 98 } 99} 100 101#------------------------------------------------------------------------------ 102# GetManNames -- 103# 104# Search a manual page (nroff source) for the name line. Parse the name 105# line into all of the functions or commands that it references. This isn't 106# comprehensive, but it works for all of the Tcl, TclX and Tk man pages. 107# 108# Parameters: 109# o manFile (I) - The path to the manual page file. 110# Returns: 111# A list contain the functions or commands or {} if the name line can't be 112# found or parsed. 113#------------------------------------------------------------------------------ 114 115proc GetManNames manFile { 116 117 set manFH [open $manFile] 118 119 # 120 # Search for name line. Once found, grab the next line that is not a 121 # nroff macro. If we end up with a blank line, we didn't find it. 122 # 123 while {[gets $manFH line] >= 0} { 124 if [regexp {^.SH NAME.*$} $line] { 125 break 126 } 127 } 128 while {[gets $manFH line] >= 0} { 129 if {![string match ".*" $line]} break 130 } 131 close $manFH 132 133 set line [string trim $line] 134 if {$line == ""} return 135 136 # 137 # Lets try and parse the name list out of the line 138 # 139 if {![regexp {^(.*)(\\-)} $line {} namePart]} { 140 if {![regexp {^(.*)(-)} $line {} namePart]} return 141 } 142 143 # 144 # This magic converts the name line into a list 145 # 146 147 if {[catch {join [split $namePart ,] " "} namePart] != 0} return 148 149 return $namePart 150 151} 152 153#------------------------------------------------------------------------------ 154# InstallShortMan -- 155# Install a manual page on a system that does not have long file names. 156# 157# Parameters: 158# o sourceFile - Manual page source file path. 159# o targetDir - Directory to install the file in. 160# o extension - Extension to use for the installed file. 161# Returns: 162# A list of the man files created, relative to targetDir. 163#------------------------------------------------------------------------------ 164 165proc InstallShortMan {sourceFile targetDir extension} { 166 167 set manFileName "[file tail [file root $sourceFile]].$extension" 168 169 CopyManPage $sourceFile "$targetDir/$manFileName" 170 171 return $manFileName 172} 173 174#------------------------------------------------------------------------------ 175# InstallLongMan -- 176# Install a manual page on a system that has long file names. 177# 178# Parameters: 179# o sourceFile - Manual page source file path. 180# o targetDir - Directory to install the file in. 181# o extension - Extension to use for the installed file. 182# Returns: 183# A list of the man files created, relative to targetDir. They are all links 184# to the same entry. 185#------------------------------------------------------------------------------ 186 187proc InstallLongMan {sourceFile targetDir extension} { 188 global gzip 189 set manNames [GetManNames $sourceFile] 190 if [lempty $manNames] { 191 set baseName [file tail [file root $sourceFile]] 192 puts stderr "Warning: can't parse NAME line for man page: $sourceFile." 193 puts stderr " Manual page only available as: $baseName" 194 set manNames [list [file tail [file root $sourceFile]]] 195 } 196 197 # Copy file to the first name in the list. 198 199 set firstFilePath $targetDir/[lvarpop manNames].$extension 200 set created [list [file tail $firstFilePath]] 201 202 CopyManPage $sourceFile $firstFilePath 203 204 # Link it to the rest of the names in the list. 205 206 foreach manName $manNames { 207 set targetFile $targetDir/$manName.$extension 208 file delete $targetFile $targetFile.gz 209 if $gzip { 210 set cmd "link $firstFilePath.gz $targetFile.gz" 211 } else { 212 set cmd "link $firstFilePath $targetFile" 213 } 214 if {[catch { 215 eval $cmd 216 } msg] != 0} { 217 puts stderr "error from: $cmd" 218 puts stderr " $msg" 219 } else { 220 lappend created [file tail $targetFile] 221 } 222 } 223 return $created 224} 225 226#------------------------------------------------------------------------------ 227# InstallManPage -- 228# Install a manual page on a system. 229# 230# Parameters: 231# o sourceFile - Manual page source file path. 232# o manDir - Directory to build the directoy containing the manual files in. 233# o section - Section to install the manual page in. 234# Globals 235# o longNames - If long file names are supported. 236# o manSeparator - Character used to seperate man directory name from the 237# section name. 238# o rmcat - true if cat files are to be removed. 239#------------------------------------------------------------------------------ 240 241proc InstallManPage {sourceFile manDir section} { 242 global longNames manSeparator rmcat 243 244 set targetDir "$manDir/man${manSeparator}${section}" 245 246 if $longNames { 247 set files [InstallLongMan $sourceFile $targetDir $section] 248 } else { 249 set files [InstallShortMan $sourceFile $targetDir $section] 250 } 251 252 if $rmcat { 253 foreach file $files { 254 catch { 255 file delete [list $manDir/cat${manSeparator}${section}/$file] 256 } 257 } 258 } 259} 260 261#------------------------------------------------------------------------------ 262# main prorgam 263 264umask 022 265 266# Parse command line args 267 268set rmcat 0 269set gzip 0 270while {[string match -* $argv]} { 271 set opt [lvarpop argv] 272 switch -- $opt { 273 -rmcat {set rmcat 1} 274 -gzip {set gzip 1} 275 default { 276 puts stderr "unknown flag: $opt" 277 } 278 } 279} 280if {[llength $argv] != 6} { 281 puts stderr "wrong # args: cpmanpages ?flags? separator cmd func unix sourceDir targetDir" 282 exit 1 283} 284 285 286set manSeparator [Unquote [lindex $argv 0]] 287set sectionXRef(.n) [Unquote [lindex $argv 1]] 288set sectionXRef(.3) [Unquote [lindex $argv 2]] 289set sectionXRef(.1) [Unquote [lindex $argv 3]] 290set sourceDir [Unquote [lindex $argv 4]] 291set targetDir [Unquote [lindex $argv 5]] 292 293# Remove undefined sections from the array. 294 295foreach sec [array names sectionXRef] { 296 if [lempty sectionXRef($sec)] { 297 unset sectionXRef($sec) 298 } 299} 300 301puts stdout "Copying manual pages from $sourceDir to $targetDir" 302 303# Determine if long file names are available. 304 305if ![file exists $targetDir] { 306 mkdir -path $targetDir 307} 308set testName "$targetDir/TclX-long-test-file-name" 309 310if [catch {open $testName w} fh] { 311 puts stdout "" 312 puts stdout "*** NOTE: long file names do not appear to be available on" 313 puts stdout "*** this system. Attempt to create a long named file in" 314 puts stdout "*** $targetDir returned the error: $errorCode" 315 puts stdout "" 316 set longNames 0 317} else { 318 close $fh 319 file delete $testName 320 set longNames 1 321} 322 323set sourceFiles [glob -- $sourceDir/*.n $sourceDir/*.1 $sourceDir/*.3] 324 325set ignoreFiles {} 326 327# Actually install the files. 328 329foreach sourceFile $sourceFiles { 330 if {[lsearch $ignoreFiles [file tail $sourceFile]] >= 0} continue 331 332 set ext [file extension $sourceFile] 333 if ![info exists sectionXRef($ext)] { 334 puts stderr "WARNING: Don't know how to handle section for $sourceFile," 335 continue 336 } 337 InstallManPage $sourceFile $targetDir $sectionXRef($ext) 338} 339 340 341 342