sl@0: #!/bin/sh sl@0: # The next line is executed by /bin/sh, but not tcl \ sl@0: exec tclsh8.4 "$0" ${1+"$@"} sl@0: sl@0: package require Tcl 8.4 sl@0: sl@0: # Convert Ousterhout format man pages into highly crosslinked sl@0: # hypertext. sl@0: # sl@0: # Along the way detect many unmatched font changes and other odd sl@0: # things. sl@0: # sl@0: # Note well, this program is a hack rather than a piece of software sl@0: # engineering. In that sense it's probably a good example of things sl@0: # that a scripting language, like Tcl, can do well. It is offered as sl@0: # an example of how someone might convert a specific set of man pages sl@0: # into hypertext, not as a general solution to the problem. If you sl@0: # try to use this, you'll be very much on your own. sl@0: # sl@0: # Copyright (c) 1995-1997 Roger E. Critchlow Jr sl@0: # sl@0: # The authors hereby grant permission to use, copy, modify, distribute, sl@0: # and license this software and its documentation for any purpose, provided sl@0: # that existing copyright notices are retained in all copies and that this sl@0: # notice is included verbatim in any distributions. No written agreement, sl@0: # license, or royalty fee is required for any of the authorized uses. sl@0: # Modifications to this software may be copyrighted by their authors sl@0: # and need not follow the licensing terms described here, provided that sl@0: # the new terms are clearly indicated on the first page of each file where sl@0: # they apply. sl@0: # sl@0: # IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY sl@0: # FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES sl@0: # ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY sl@0: # DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE sl@0: # POSSIBILITY OF SUCH DAMAGE. sl@0: # sl@0: # THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, sl@0: # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, sl@0: # FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE sl@0: # IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE sl@0: # NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR sl@0: # MODIFICATIONS. sl@0: # sl@0: # Revisions: sl@0: # May 15, 1995 - initial release sl@0: # May 16, 1995 - added a back to home link to toplevel table of sl@0: # contents. sl@0: # May 18, 1995 - broke toplevel table of contents into separate sl@0: # pages for each section, and broke long table of contents sl@0: # into a one page for each man page. sl@0: # Mar 10, 1996 - updated for tcl7.5b3/tk4.1b3 sl@0: # Apr 14, 1996 - incorporated command line parsing from Tom Tromey, sl@0: # -- thanks Tom. sl@0: # - updated for tcl7.5/tk4.1 final release. sl@0: # - converted to same copyright as the man pages. sl@0: # Sep 14, 1996 - made various modifications for tcl7.6b1/tk4.2b1 sl@0: # Oct 18, 1996 - added tcl7.6/tk4.2 to the list of distributions. sl@0: # Oct 22, 1996 - major hacking on indentation code and elsewhere. sl@0: # Mar 4, 1997 - sl@0: # May 28, 1997 - added tcl8.0b1/tk8.0b1 to the list of distributions sl@0: # - cleaned source for tclsh8.0 execution sl@0: # - renamed output files for windoze installation sl@0: # - added spaces to tables sl@0: # Oct 24, 1997 - moved from 8.0b1 to 8.0 release sl@0: # sl@0: sl@0: set Version "0.32" sl@0: sl@0: proc parse_command_line {} { sl@0: global argv Version sl@0: sl@0: # These variables determine where the man pages come from and where sl@0: # the converted pages go to. sl@0: global tcltkdir tkdir tcldir webdir build_tcl build_tk sl@0: sl@0: # Set defaults based on original code. sl@0: set tcltkdir ../.. sl@0: set tkdir {} sl@0: set tcldir {} sl@0: set webdir ../html sl@0: set build_tcl 0 sl@0: set build_tk 0 sl@0: # Default search version is a glob pattern sl@0: set useversion {{,[8-9].[0-9]{,.[0-9]{,[0-9]}}}} sl@0: sl@0: # Handle arguments a la GNU: sl@0: # --version sl@0: # --useversion= sl@0: # --help sl@0: # --srcdir=/path sl@0: # --htmldir=/path sl@0: sl@0: foreach option $argv { sl@0: switch -glob -- $option { sl@0: --version { sl@0: puts "tcltk-man-html $Version" sl@0: exit 0 sl@0: } sl@0: sl@0: --help { sl@0: puts "usage: tcltk-man-html \[OPTION\] ...\n" sl@0: puts " --help print this help, then exit" sl@0: puts " --version print version number, then exit" sl@0: puts " --srcdir=DIR find tcl and tk source below DIR" sl@0: puts " --htmldir=DIR put generated HTML in DIR" sl@0: puts " --tcl build tcl help" sl@0: puts " --tk build tk help" sl@0: puts " --useversion version of tcl/tk to search for" sl@0: exit 0 sl@0: } sl@0: sl@0: --srcdir=* { sl@0: # length of "--srcdir=" is 9. sl@0: set tcltkdir [string range $option 9 end] sl@0: } sl@0: sl@0: --htmldir=* { sl@0: # length of "--htmldir=" is 10 sl@0: set webdir [string range $option 10 end] sl@0: } sl@0: sl@0: --useversion=* { sl@0: # length of "--useversion=" is 13 sl@0: set useversion [string range $option 13 end] sl@0: } sl@0: sl@0: --tcl { sl@0: set build_tcl 1 sl@0: } sl@0: sl@0: --tk { sl@0: set build_tk 1 sl@0: } sl@0: sl@0: default { sl@0: puts stderr "tcltk-man-html: unrecognized option -- `$option'" sl@0: exit 1 sl@0: } sl@0: } sl@0: } sl@0: sl@0: if {!$build_tcl && !$build_tk} {set build_tcl 1; set build_tk 1} sl@0: sl@0: if {$build_tcl} { sl@0: # Find Tcl. sl@0: set tcldir [lindex [lsort [glob -nocomplain -tails -type d \ sl@0: -directory $tcltkdir tcl$useversion]] end] sl@0: if {$tcldir == ""} then { sl@0: puts stderr "tcltk-man-html: couldn't find Tcl below $tcltkdir" sl@0: exit 1 sl@0: } sl@0: puts "using Tcl source directory $tcldir" sl@0: } sl@0: sl@0: if {$build_tk} { sl@0: # Find Tk. sl@0: set tkdir [lindex [lsort [glob -nocomplain -tails -type d \ sl@0: -directory $tcltkdir tk$useversion]] end] sl@0: if {$tkdir == ""} then { sl@0: puts stderr "tcltk-man-html: couldn't find Tk below $tcltkdir" sl@0: exit 1 sl@0: } sl@0: puts "using Tk source directory $tkdir" sl@0: } sl@0: sl@0: # the title for the man pages overall sl@0: global overall_title sl@0: set overall_title "" sl@0: if {$build_tcl} {append overall_title "[capitalize $tcldir]"} sl@0: if {$build_tcl && $build_tk} {append overall_title "/"} sl@0: if {$build_tk} {append overall_title "[capitalize $tkdir]"} sl@0: append overall_title " Manual" sl@0: } sl@0: sl@0: proc capitalize {string} { sl@0: return [string toupper $string 0] sl@0: } sl@0: sl@0: ## sl@0: ## sl@0: ## sl@0: set manual(report-level) 1 sl@0: sl@0: proc manerror {msg} { sl@0: global manual sl@0: set name {} sl@0: set subj {} sl@0: if {[info exists manual(name)]} { sl@0: set name $manual(name) sl@0: } sl@0: if {[info exists manual(section)] && [string length $manual(section)]} { sl@0: puts stderr "$name: $manual(section): $msg" sl@0: } else { sl@0: puts stderr "$name: $msg" sl@0: } sl@0: } sl@0: sl@0: proc manreport {level msg} { sl@0: global manual sl@0: if {$level < $manual(report-level)} { sl@0: manerror $msg sl@0: } sl@0: } sl@0: sl@0: proc fatal {msg} { sl@0: global manual sl@0: manerror $msg sl@0: exit 1 sl@0: } sl@0: ## sl@0: ## parsing sl@0: ## sl@0: proc unquote arg { sl@0: return [string map [list \" {}] $arg] sl@0: } sl@0: sl@0: proc parse-directive {line codename restname} { sl@0: upvar $codename code $restname rest sl@0: return [regexp {^(\.[.a-zA-Z0-9]*) *(.*)} $line all code rest] sl@0: } sl@0: sl@0: proc process-text {text} { sl@0: global manual sl@0: # preprocess text sl@0: set text [string map [list \ sl@0: {\&} "\t" \ sl@0: {&} {&} \ sl@0: {\\} {\} \ sl@0: {\e} {\} \ sl@0: {\ } { } \ sl@0: {\|} { } \ sl@0: {\0} { } \ sl@0: {\%} {} \ sl@0: "\\\n" "\n" \ sl@0: \" {"} \ sl@0: {<} {<} \ sl@0: {>} {>} \ sl@0: {\(+-} {±} \ sl@0: {\fP} {\fR} \ sl@0: {\.} . \ sl@0: {\(bu} {•} \ sl@0: ] $text] sl@0: regsub -all {\\o'o\^'} $text {\ô} text; # o-circumflex in re_syntax.n sl@0: regsub -all {\\-\\\|\\-} $text -- text; # two hyphens sl@0: regsub -all -- {\\-\\\^\\-} $text -- text; # two hyphens sl@0: regsub -all {\\-} $text - text; # a hyphen sl@0: regsub -all "\\\\\n" $text "\\\\n" text; # backslashed newline sl@0: while {[string first "\\" $text] >= 0} { sl@0: # C R sl@0: if {[regsub {^([^\\]*)\\fC([^\\]*)\\fR(.*)$} $text \ sl@0: {\1\2\3} text]} continue sl@0: # B R sl@0: if {[regsub {^([^\\]*)\\fB([^\\]*)\\fR(.*)$} $text \ sl@0: {\1\2\3} text]} continue sl@0: # B I sl@0: if {[regsub {^([^\\]*)\\fB([^\\]*)\\fI(.*)$} $text \ sl@0: {\1\2\\fI\3} text]} continue sl@0: # I R sl@0: if {[regsub {^([^\\]*)\\fI([^\\]*)\\fR(.*)$} $text \ sl@0: {\1\2\3} text]} continue sl@0: # I B sl@0: if {[regsub {^([^\\]*)\\fI([^\\]*)\\fB(.*)$} $text \ sl@0: {\1\2\\fB\3} text]} continue sl@0: # B B, I I, R R sl@0: if {[regsub {^([^\\]*)\\fB([^\\]*)\\fB(.*)$} $text \ sl@0: {\1\\fB\2\3} ntext] sl@0: || [regsub {^([^\\]*)\\fI([^\\]*)\\fI(.*)$} $text \ sl@0: {\1\\fI\2\3} ntext] sl@0: || [regsub {^([^\\]*)\\fR([^\\]*)\\fR(.*)$} $text \ sl@0: {\1\\fR\2\3} ntext]} { sl@0: manerror "process-text: impotent font change: $text" sl@0: set text $ntext sl@0: continue sl@0: } sl@0: # unrecognized sl@0: manerror "process-text: uncaught backslash: $text" sl@0: set text [string map [list "\\" "#92;"] $text] sl@0: } sl@0: return $text sl@0: } sl@0: ## sl@0: ## pass 2 text input and matching sl@0: ## sl@0: proc open-text {} { sl@0: global manual sl@0: set manual(text-length) [llength $manual(text)] sl@0: set manual(text-pointer) 0 sl@0: } sl@0: proc more-text {} { sl@0: global manual sl@0: return [expr {$manual(text-pointer) < $manual(text-length)}] sl@0: } sl@0: proc next-text {} { sl@0: global manual sl@0: if {[more-text]} { sl@0: set text [lindex $manual(text) $manual(text-pointer)] sl@0: incr manual(text-pointer) sl@0: return $text sl@0: } sl@0: manerror "read past end of text" sl@0: error "fatal" sl@0: } sl@0: proc is-a-directive {line} { sl@0: return [string match .* $line] sl@0: } sl@0: proc split-directive {line opname restname} { sl@0: upvar $opname op $restname rest sl@0: set op [string range $line 0 2] sl@0: set rest [string trim [string range $line 3 end]] sl@0: } sl@0: proc next-op-is {op restname} { sl@0: global manual sl@0: upvar $restname rest sl@0: if {[more-text]} { sl@0: set text [lindex $manual(text) $manual(text-pointer)] sl@0: if {[string equal -length 3 $text $op]} { sl@0: set rest [string range $text 4 end] sl@0: incr manual(text-pointer) sl@0: return 1 sl@0: } sl@0: } sl@0: return 0 sl@0: } sl@0: proc backup-text {n} { sl@0: global manual sl@0: if {$manual(text-pointer)-$n >= 0} { sl@0: incr manual(text-pointer) -$n sl@0: } sl@0: } sl@0: proc match-text args { sl@0: global manual sl@0: set nargs [llength $args] sl@0: if {$manual(text-pointer) + $nargs > $manual(text-length)} { sl@0: return 0 sl@0: } sl@0: set nback 0 sl@0: foreach arg $args { sl@0: if {![more-text]} { sl@0: backup-text $nback sl@0: return 0 sl@0: } sl@0: set arg [string trim $arg] sl@0: set targ [string trim [lindex $manual(text) $manual(text-pointer)]] sl@0: if {[string equal $arg $targ]} { sl@0: incr nback sl@0: incr manual(text-pointer) sl@0: continue sl@0: } sl@0: if {[regexp {^@(\w+)$} $arg all name]} { sl@0: upvar $name var sl@0: set var $targ sl@0: incr nback sl@0: incr manual(text-pointer) sl@0: continue sl@0: } sl@0: if {[regexp -nocase {^(\.[A-Z][A-Z])@(\w+)$} $arg all op name]\ sl@0: && [string equal $op [lindex $targ 0]]} { sl@0: upvar $name var sl@0: set var [lrange $targ 1 end] sl@0: incr nback sl@0: incr manual(text-pointer) sl@0: continue sl@0: } sl@0: backup-text $nback sl@0: return 0 sl@0: } sl@0: return 1 sl@0: } sl@0: proc expand-next-text {n} { sl@0: global manual sl@0: return [join [lrange $manual(text) $manual(text-pointer) \ sl@0: [expr {$manual(text-pointer)+$n-1}]] \n\n] sl@0: } sl@0: ## sl@0: ## pass 2 output sl@0: ## sl@0: proc man-puts {text} { sl@0: global manual sl@0: lappend manual(output-$manual(wing-file)-$manual(name)) $text sl@0: } sl@0: sl@0: ## sl@0: ## build hypertext links to tables of contents sl@0: ## sl@0: proc long-toc {text} { sl@0: global manual sl@0: set here M[incr manual(section-toc-n)] sl@0: set there L[incr manual(long-toc-n)] sl@0: lappend manual(section-toc) \ sl@0: "
$text" sl@0: return "$text" sl@0: } sl@0: proc option-toc {name class switch} { sl@0: global manual sl@0: if {[string equal $manual(section) "WIDGET-SPECIFIC OPTIONS"]} { sl@0: # link the defined option into the long table of contents sl@0: set link [long-toc "$switch, $name, $class"] sl@0: regsub -- "$switch, $name, $class" $link "$switch" link sl@0: return $link sl@0: } elseif {[string equal $manual(name):$manual(section) \ sl@0: "options:DESCRIPTION"]} { sl@0: # link the defined standard option to the long table of sl@0: # contents and make a target for the standard option references sl@0: # from other man pages. sl@0: set first [lindex $switch 0] sl@0: set here M$first sl@0: set there L[incr manual(long-toc-n)] sl@0: set manual(standard-option-$first) "$switch, $name, $class" sl@0: lappend manual(section-toc) "
$switch, $name, $class" sl@0: return "$switch" sl@0: } else { sl@0: error "option-toc in $manual(name) section $manual(section)" sl@0: } sl@0: } sl@0: proc std-option-toc {name} { sl@0: global manual sl@0: if {[info exists manual(standard-option-$name)]} { sl@0: lappend manual(section-toc)
$manual(standard-option-$name) sl@0: return $manual(standard-option-$name) sl@0: } sl@0: set here M[incr manual(section-toc-n)] sl@0: set there L[incr manual(long-toc-n)] sl@0: set other M$name sl@0: lappend manual(section-toc) "
$name" sl@0: return "$name" sl@0: } sl@0: ## sl@0: ## process the widget option section sl@0: ## in widget and options man pages sl@0: ## sl@0: proc output-widget-options {rest} { sl@0: global manual sl@0: man-puts
sl@0: lappend manual(section-toc)
sl@0: backup-text 1 sl@0: set para {} sl@0: while {[next-op-is .OP rest]} { sl@0: switch -exact [llength $rest] { sl@0: 3 { foreach {switch name class} $rest { break } } sl@0: 5 { sl@0: set switch [lrange $rest 0 2] sl@0: set name [lindex $rest 3] sl@0: set class [lindex $rest 4] sl@0: } sl@0: default { sl@0: fatal "bad .OP $rest" sl@0: } sl@0: } sl@0: if {![regexp {^(<.>)([-\w ]+)()$} $switch all oswitch switch cswitch]} { sl@0: if {![regexp {^(<.>)([-\w ]+) or ([-\w ]+)()$} $switch all oswitch switch1 switch2 cswitch]} { sl@0: error "not Switch: $switch" sl@0: } else { sl@0: set switch "$switch1$cswitch or $oswitch$switch2" sl@0: } sl@0: } sl@0: if {![regexp {^(<.>)([\w]*)()$} $name all oname name cname]} { sl@0: error "not Name: $name" sl@0: } sl@0: if {![regexp {^(<.>)([\w]*)()$} $class all oclass class cclass]} { sl@0: error "not Class: $class" sl@0: } sl@0: man-puts "$para
Command-Line Name: $oswitch[option-toc $name $class $switch]$cswitch" sl@0: man-puts "
Database Name: $oname$name$cname" sl@0: man-puts "
Database Class: $oclass$class$cclass" sl@0: man-puts
[next-text] sl@0: set para

sl@0: } sl@0: man-puts

sl@0: lappend manual(section-toc)
sl@0: } sl@0: sl@0: ## sl@0: ## process .RS lists sl@0: ## sl@0: proc output-RS-list {} { sl@0: global manual sl@0: if {[next-op-is .IP rest]} { sl@0: output-IP-list .RS .IP $rest sl@0: if {[match-text .RE .sp .RS @rest .IP @rest2]} { sl@0: man-puts

$rest sl@0: output-IP-list .RS .IP $rest2 sl@0: } sl@0: if {[match-text .RE .sp .RS @rest .RE]} { sl@0: man-puts

$rest sl@0: return sl@0: } sl@0: if {[next-op-is .RE rest]} { sl@0: return sl@0: } sl@0: } sl@0: man-puts

sl@0: while {[more-text]} { sl@0: set line [next-text] sl@0: if {[is-a-directive $line]} { sl@0: split-directive $line code rest sl@0: switch -exact $code { sl@0: .RE { sl@0: break sl@0: } sl@0: .SH - .SS { sl@0: manerror "unbalanced .RS at section end" sl@0: backup-text 1 sl@0: break sl@0: } sl@0: default { sl@0: output-directive $line sl@0: } sl@0: } sl@0: } else { sl@0: man-puts $line sl@0: } sl@0: } sl@0: man-puts
sl@0: } sl@0: sl@0: ## sl@0: ## process .IP lists which may be plain indents, sl@0: ## numeric lists, or definition lists sl@0: ## sl@0: proc output-IP-list {context code rest} { sl@0: global manual sl@0: if {![string length $rest]} { sl@0: # blank label, plain indent, no contents entry sl@0: man-puts
sl@0: while {[more-text]} { sl@0: set line [next-text] sl@0: if {[is-a-directive $line]} { sl@0: split-directive $line code rest sl@0: if {[string equal $code ".IP"] && [string equal $rest {}]} { sl@0: man-puts "

" sl@0: continue sl@0: } sl@0: if {[lsearch {.br .DS .RS} $code] >= 0} { sl@0: output-directive $line sl@0: } else { sl@0: backup-text 1 sl@0: break sl@0: } sl@0: } else { sl@0: man-puts $line sl@0: } sl@0: } sl@0: man-puts

sl@0: } else { sl@0: # labelled list, make contents sl@0: if { sl@0: [string compare $context ".SH"] && sl@0: [string compare $context ".SS"] sl@0: } then { sl@0: man-puts

sl@0: } sl@0: man-puts

sl@0: lappend manual(section-toc)
sl@0: backup-text 1 sl@0: set accept_RE 0 sl@0: set para {} sl@0: while {[more-text]} { sl@0: set line [next-text] sl@0: if {[is-a-directive $line]} { sl@0: split-directive $line code rest sl@0: switch -exact $code { sl@0: .IP { sl@0: if {$accept_RE} { sl@0: output-IP-list .IP $code $rest sl@0: continue sl@0: } sl@0: if {[string equal $manual(section) "ARGUMENTS"] || \ sl@0: [regexp {^\[\d+\]$} $rest]} { sl@0: man-puts "$para
$rest
" sl@0: } elseif {[string equal {•} $rest]} { sl@0: man-puts "$para
$rest " sl@0: } else { sl@0: man-puts "$para
[long-toc $rest]
" sl@0: } sl@0: if {[string equal $manual(name):$manual(section) \ sl@0: "selection:DESCRIPTION"]} { sl@0: if {[match-text .RE @rest .RS .RS]} { sl@0: man-puts
[long-toc $rest]
sl@0: } sl@0: } sl@0: } sl@0: .sp - sl@0: .br - sl@0: .DS - sl@0: .CS { sl@0: output-directive $line sl@0: } sl@0: .RS { sl@0: if {[match-text .RS]} { sl@0: output-directive $line sl@0: incr accept_RE 1 sl@0: } elseif {[match-text .CS]} { sl@0: output-directive .CS sl@0: incr accept_RE 1 sl@0: } elseif {[match-text .PP]} { sl@0: output-directive .PP sl@0: incr accept_RE 1 sl@0: } elseif {[match-text .DS]} { sl@0: output-directive .DS sl@0: incr accept_RE 1 sl@0: } else { sl@0: output-directive $line sl@0: } sl@0: } sl@0: .PP { sl@0: if {[match-text @rest1 .br @rest2 .RS]} { sl@0: # yet another nroff kludge as above sl@0: man-puts "$para
[long-toc $rest1]" sl@0: man-puts "
[long-toc $rest2]
" sl@0: incr accept_RE 1 sl@0: } elseif {[match-text @rest .RE]} { sl@0: # gad, this is getting ridiculous sl@0: if {!$accept_RE} { sl@0: man-puts "

$rest

" sl@0: backup-text 1 sl@0: set para {} sl@0: break sl@0: } else { sl@0: man-puts "

$rest" sl@0: incr accept_RE -1 sl@0: } sl@0: } elseif {$accept_RE} { sl@0: output-directive $line sl@0: } else { sl@0: backup-text 1 sl@0: break sl@0: } sl@0: } sl@0: .RE { sl@0: if {!$accept_RE} { sl@0: backup-text 1 sl@0: break sl@0: } sl@0: incr accept_RE -1 sl@0: } sl@0: default { sl@0: backup-text 1 sl@0: break sl@0: } sl@0: } sl@0: } else { sl@0: man-puts $line sl@0: } sl@0: set para

sl@0: } sl@0: man-puts "$para

" sl@0: lappend manual(section-toc)
sl@0: if {$accept_RE} { sl@0: manerror "missing .RE in output-IP-list" sl@0: } sl@0: } sl@0: } sl@0: ## sl@0: ## handle the NAME section lines sl@0: ## there's only one line in the NAME section, sl@0: ## consisting of a comma separated list of names, sl@0: ## followed by a hyphen and a short description. sl@0: ## sl@0: proc output-name {line} { sl@0: global manual sl@0: # split name line into pieces sl@0: regexp {^([^-]+) - (.*)$} $line all head tail sl@0: # output line to manual page untouched sl@0: man-puts $line sl@0: # output line to long table of contents sl@0: lappend manual(section-toc)
$line
sl@0: # separate out the names for future reference sl@0: foreach name [split $head ,] { sl@0: set name [string trim $name] sl@0: if {[llength $name] > 1} { sl@0: manerror "name has a space: {$name}\nfrom: $line" sl@0: } sl@0: lappend manual(wing-toc) $name sl@0: lappend manual(name-$name) $manual(wing-file)/$manual(name) sl@0: } sl@0: } sl@0: ## sl@0: ## build a cross-reference link if appropriate sl@0: ## sl@0: proc cross-reference {ref} { sl@0: global manual sl@0: if {[string match Tcl_* $ref]} { sl@0: set lref $ref sl@0: } elseif {[string match Tk_* $ref]} { sl@0: set lref $ref sl@0: } elseif {[string equal $ref "Tcl"]} { sl@0: set lref $ref sl@0: } else { sl@0: set lref [string tolower $ref] sl@0: } sl@0: ## sl@0: ## nothing to reference sl@0: ## sl@0: if {![info exists manual(name-$lref)]} { sl@0: foreach name {array file history info interp string trace sl@0: after clipboard grab image option pack place selection tk tkwait update winfo wm} { sl@0: if {[regexp "^$name \[a-z0-9]*\$" $lref] && \ sl@0: [info exists manual(name-$name)] && \ sl@0: [string compare $manual(tail) "$name.n"]} { sl@0: return "$ref" sl@0: } sl@0: } sl@0: if {[lsearch {stdin stdout stderr end} $lref] >= 0} { sl@0: # no good place to send these sl@0: # tcl tokens? sl@0: # also end sl@0: } sl@0: return $ref sl@0: } sl@0: ## sl@0: ## would be a self reference sl@0: ## sl@0: foreach name $manual(name-$lref) { sl@0: if {[lsearch $name $manual(wing-file)/$manual(name)] >= 0} { sl@0: return $ref sl@0: } sl@0: } sl@0: ## sl@0: ## multiple choices for reference sl@0: ## sl@0: if {[llength $manual(name-$lref)] > 1} { sl@0: set tcl_i [lsearch -glob $manual(name-$lref) *TclCmd*] sl@0: set tcl_ref [lindex $manual(name-$lref) $tcl_i] sl@0: set tk_i [lsearch -glob $manual(name-$lref) *TkCmd*] sl@0: set tk_ref [lindex $manual(name-$lref) $tk_i] sl@0: if {$tcl_i >= 0 && "$manual(wing-file)" == {TclCmd} \ sl@0: || "$manual(wing-file)" == {TclLib}} { sl@0: return "$ref" sl@0: } sl@0: if {$tk_i >= 0 && "$manual(wing-file)" == {TkCmd} \ sl@0: || "$manual(wing-file)" == {TkLib}} { sl@0: return "$ref" sl@0: } sl@0: if {"$lref" == {exit} && "$manual(tail)" == {tclsh.1} && $tcl_i >= 0} { sl@0: return "$ref" sl@0: } sl@0: puts stderr "multiple cross reference to $ref in $manual(name-$lref) from $manual(wing-file)/$manual(tail)" sl@0: return $ref sl@0: } sl@0: ## sl@0: ## exceptions, sigh, to the rule sl@0: ## sl@0: switch $manual(tail) { sl@0: canvas.n { sl@0: if {$lref == {focus}} { sl@0: upvar tail tail sl@0: set clue [string first command $tail] sl@0: if {$clue < 0 || $clue > 5} { sl@0: return $ref sl@0: } sl@0: } sl@0: if {[lsearch {bitmap image text} $lref] >= 0} { sl@0: return $ref sl@0: } sl@0: } sl@0: checkbutton.n - sl@0: radiobutton.n { sl@0: if {[lsearch {image} $lref] >= 0} { sl@0: return $ref sl@0: } sl@0: } sl@0: menu.n { sl@0: if {[lsearch {checkbutton radiobutton} $lref] >= 0} { sl@0: return $ref sl@0: } sl@0: } sl@0: options.n { sl@0: if {[lsearch {bitmap image set} $lref] >= 0} { sl@0: return $ref sl@0: } sl@0: } sl@0: regexp.n { sl@0: if {[lsearch {string} $lref] >= 0} { sl@0: return $ref sl@0: } sl@0: } sl@0: source.n { sl@0: if {[lsearch {text} $lref] >= 0} { sl@0: return $ref sl@0: } sl@0: } sl@0: history.n { sl@0: if {[lsearch {exec} $lref] >= 0} { sl@0: return $ref sl@0: } sl@0: } sl@0: return.n { sl@0: if {[lsearch {error continue break} $lref] >= 0} { sl@0: return $ref sl@0: } sl@0: } sl@0: scrollbar.n { sl@0: if {[lsearch {set} $lref] >= 0} { sl@0: return $ref sl@0: } sl@0: } sl@0: } sl@0: ## sl@0: ## return the cross reference sl@0: ## sl@0: return "$ref" sl@0: } sl@0: ## sl@0: ## reference generation errors sl@0: ## sl@0: proc reference-error {msg text} { sl@0: global manual sl@0: puts stderr "$manual(tail): $msg: {$text}" sl@0: return $text sl@0: } sl@0: ## sl@0: ## insert as many cross references into this text string as are appropriate sl@0: ## sl@0: proc insert-cross-references {text} { sl@0: global manual sl@0: ## sl@0: ## we identify cross references by: sl@0: ## ``quotation'' sl@0: ## emboldening sl@0: ## Tcl_ prefix sl@0: ## Tk_ prefix sl@0: ## [a-zA-Z0-9]+ manual entry sl@0: ## and we avoid messing with already anchored text sl@0: ## sl@0: ## sl@0: ## find where each item lives sl@0: ## sl@0: array set offset [list \ sl@0: anchor [string first {} $text] \ sl@0: quote [string first {``} $text] \ sl@0: end-quote [string first {''} $text] \ sl@0: bold [string first {} $text] \ sl@0: end-bold [string first {} $text] \ sl@0: tcl [string first {Tcl_} $text] \ sl@0: tk [string first {Tk_} $text] \ sl@0: Tcl1 [string first {Tcl manual entry} $text] \ sl@0: Tcl2 [string first {Tcl overview manual entry} $text] \ sl@0: ] sl@0: ## sl@0: ## accumulate a list sl@0: ## sl@0: foreach name [array names offset] { sl@0: if {$offset($name) >= 0} { sl@0: set invert($offset($name)) $name sl@0: lappend offsets $offset($name) sl@0: } sl@0: } sl@0: ## sl@0: ## if nothing, then we're done. sl@0: ## sl@0: if {![info exists offsets]} { sl@0: return $text sl@0: } sl@0: ## sl@0: ## sort the offsets sl@0: ## sl@0: set offsets [lsort -integer $offsets] sl@0: ## sl@0: ## see which we want to use sl@0: ## sl@0: switch -exact $invert([lindex $offsets 0]) { sl@0: anchor { sl@0: if {$offset(end-anchor) < 0} { sl@0: return [reference-error {Missing end anchor} $text] sl@0: } sl@0: set head [string range $text 0 $offset(end-anchor)] sl@0: set tail [string range $text [expr {$offset(end-anchor)+1}] end] sl@0: return $head[insert-cross-references $tail] sl@0: } sl@0: quote { sl@0: if {$offset(end-quote) < 0} { sl@0: return [reference-error "Missing end quote" $text] sl@0: } sl@0: if {$invert([lindex $offsets 1]) == "tk"} { sl@0: set offsets [lreplace $offsets 1 1] sl@0: } sl@0: if {$invert([lindex $offsets 1]) == "tcl"} { sl@0: set offsets [lreplace $offsets 1 1] sl@0: } sl@0: switch -exact $invert([lindex $offsets 1]) { sl@0: end-quote { sl@0: set head [string range $text 0 [expr {$offset(quote)-1}]] sl@0: set body [string range $text [expr {$offset(quote)+2}] \ sl@0: [expr {$offset(end-quote)-1}]] sl@0: set tail [string range $text \ sl@0: [expr {$offset(end-quote)+2}] end] sl@0: return "$head``[cross-reference $body]''[insert-cross-references $tail]" sl@0: } sl@0: bold - sl@0: anchor { sl@0: set head [string range $text \ sl@0: 0 [expr {$offset(end-quote)+1}]] sl@0: set tail [string range $text \ sl@0: [expr {$offset(end-quote)+2}] end] sl@0: return "$head[insert-cross-references $tail]" sl@0: } sl@0: } sl@0: return [reference-error "Uncaught quote case" $text] sl@0: } sl@0: bold { sl@0: if {$offset(end-bold) < 0} { return $text } sl@0: if {$invert([lindex $offsets 1]) == "tk"} { sl@0: set offsets [lreplace $offsets 1 1] sl@0: } sl@0: if {$invert([lindex $offsets 1]) == "tcl"} { sl@0: set offsets [lreplace $offsets 1 1] sl@0: } sl@0: switch -exact $invert([lindex $offsets 1]) { sl@0: end-bold { sl@0: set head [string range $text 0 [expr {$offset(bold)-1}]] sl@0: set body [string range $text [expr {$offset(bold)+3}] \ sl@0: [expr {$offset(end-bold)-1}]] sl@0: set tail [string range $text \ sl@0: [expr {$offset(end-bold)+4}] end] sl@0: return "$head[cross-reference $body][insert-cross-references $tail]" sl@0: } sl@0: anchor { sl@0: set head [string range $text \ sl@0: 0 [expr {$offset(end-bold)+3}]] sl@0: set tail [string range $text \ sl@0: [expr {$offset(end-bold)+4}] end] sl@0: return "$head[insert-cross-references $tail]" sl@0: } sl@0: } sl@0: return [reference-error "Uncaught bold case" $text] sl@0: } sl@0: tk { sl@0: set head [string range $text 0 [expr {$offset(tk)-1}]] sl@0: set tail [string range $text $offset(tk) end] sl@0: if {![regexp {^(Tk_\w+)(.*)$} $tail all body tail]} { sl@0: return [reference-error "Tk regexp failed" $text] sl@0: } sl@0: return $head[cross-reference $body][insert-cross-references $tail] sl@0: } sl@0: tcl { sl@0: set head [string range $text 0 [expr {$offset(tcl)-1}]] sl@0: set tail [string range $text $offset(tcl) end] sl@0: if {![regexp {^(Tcl_\w+)(.*)$} $tail all body tail]} { sl@0: return [reference-error {Tcl regexp failed} $text] sl@0: } sl@0: return $head[cross-reference $body][insert-cross-references $tail] sl@0: } sl@0: Tcl1 - sl@0: Tcl2 { sl@0: set off [lindex $offsets 0] sl@0: set head [string range $text 0 [expr {$off-1}]] sl@0: set body Tcl sl@0: set tail [string range $text [expr {$off+3}] end] sl@0: return $head[cross-reference $body][insert-cross-references $tail] sl@0: } sl@0: end-anchor - sl@0: end-bold - sl@0: end-quote { sl@0: return [reference-error "Out of place $invert([lindex $offsets 0])" $text] sl@0: } sl@0: } sl@0: } sl@0: ## sl@0: ## process formatting directives sl@0: ## sl@0: proc output-directive {line} { sl@0: global manual sl@0: # process format directive sl@0: split-directive $line code rest sl@0: switch -exact $code { sl@0: .BS - sl@0: .BE { sl@0: # man-puts
sl@0: } sl@0: .SH - .SS { sl@0: # drain any open lists sl@0: # announce the subject sl@0: set manual(section) $rest sl@0: # start our own stack of stuff sl@0: set manual($manual(name)-$manual(section)) {} sl@0: lappend manual(has-$manual(section)) $manual(name) sl@0: if {[string compare .SS $code]} { sl@0: man-puts "

[long-toc $manual(section)]

" sl@0: } else { sl@0: man-puts "

[long-toc $manual(section)]

" sl@0: } sl@0: # some sections can simply free wheel their way through the text sl@0: # some sections can be processed in their own loops sl@0: switch -exact $manual(section) { sl@0: NAME { sl@0: if {[lsearch {CrtImgType.3 CrtItemType.3 CrtPhImgFmt.3} $manual(tail)] >= 0} { sl@0: # these manual pages have two NAME sections sl@0: if {[info exists manual($manual(tail)-NAME)]} { sl@0: return sl@0: } sl@0: set manual($manual(tail)-NAME) 1 sl@0: } sl@0: set names {} sl@0: while {1} { sl@0: set line [next-text] sl@0: if {[is-a-directive $line]} { sl@0: backup-text 1 sl@0: output-name [join $names { }] sl@0: return sl@0: } else { sl@0: lappend names [string trim $line] sl@0: } sl@0: } sl@0: } sl@0: SYNOPSIS { sl@0: lappend manual(section-toc)
sl@0: while {1} { sl@0: if {[next-op-is .nf rest] sl@0: || [next-op-is .br rest] sl@0: || [next-op-is .fi rest]} { sl@0: continue sl@0: } sl@0: if {[next-op-is .SH rest] sl@0: || [next-op-is .SS rest] sl@0: || [next-op-is .BE rest] sl@0: || [next-op-is .SO rest]} { sl@0: backup-text 1 sl@0: break sl@0: } sl@0: if {[next-op-is .sp rest]} { sl@0: #man-puts

sl@0: continue sl@0: } sl@0: set more [next-text] sl@0: if {[is-a-directive $more]} { sl@0: manerror "in SYNOPSIS found $more" sl@0: backup-text 1 sl@0: break sl@0: } else { sl@0: foreach more [split $more \n] { sl@0: man-puts $more
sl@0: if {[lsearch {TclLib TkLib} $manual(wing-file)] < 0} { sl@0: lappend manual(section-toc)

$more sl@0: } sl@0: } sl@0: } sl@0: } sl@0: lappend manual(section-toc)
sl@0: return sl@0: } sl@0: {SEE ALSO} { sl@0: while {[more-text]} { sl@0: if {[next-op-is .SH rest] || [next-op-is .SS rest]} { sl@0: backup-text 1 sl@0: return sl@0: } sl@0: set more [next-text] sl@0: if {[is-a-directive $more]} { sl@0: manerror "$more" sl@0: backup-text 1 sl@0: return sl@0: } sl@0: set nmore {} sl@0: foreach cr [split $more ,] { sl@0: set cr [string trim $cr] sl@0: if {![regexp {^.*$} $cr]} { sl@0: set cr $cr sl@0: } sl@0: if {[regexp {^(.*)\([13n]\)$} $cr all name]} { sl@0: set cr $name sl@0: } sl@0: lappend nmore $cr sl@0: } sl@0: man-puts [join $nmore {, }] sl@0: } sl@0: return sl@0: } sl@0: KEYWORDS { sl@0: while {[more-text]} { sl@0: if {[next-op-is .SH rest] || [next-op-is .SS rest]} { sl@0: backup-text 1 sl@0: return sl@0: } sl@0: set more [next-text] sl@0: if {[is-a-directive $more]} { sl@0: manerror "$more" sl@0: backup-text 1 sl@0: return sl@0: } sl@0: set keys {} sl@0: foreach key [split $more ,] { sl@0: set key [string trim $key] sl@0: lappend manual(keyword-$key) [list $manual(name) $manual(wing-file)/$manual(name).htm] sl@0: set initial [string toupper [string index $key 0]] sl@0: lappend keys "
$key" sl@0: } sl@0: man-puts [join $keys {, }] sl@0: } sl@0: return sl@0: } sl@0: } sl@0: if {[next-op-is .IP rest]} { sl@0: output-IP-list $code .IP $rest sl@0: return sl@0: } sl@0: if {[next-op-is .PP rest]} { sl@0: return sl@0: } sl@0: return sl@0: } sl@0: .SO { sl@0: if {[match-text @stuff .SE]} { sl@0: output-directive {.SH STANDARD OPTIONS} sl@0: set opts {} sl@0: foreach line [split $stuff \n] { sl@0: foreach option [split $line \t] { sl@0: lappend opts $option sl@0: } sl@0: } sl@0: man-puts
sl@0: lappend manual(section-toc)
sl@0: foreach option [lsort $opts] { sl@0: man-puts "
[std-option-toc $option]" sl@0: } sl@0: man-puts
sl@0: lappend manual(section-toc)
sl@0: } else { sl@0: manerror "unexpected .SO format:\n[expand-next-text 2]" sl@0: } sl@0: } sl@0: .OP { sl@0: output-widget-options $rest sl@0: return sl@0: } sl@0: .IP { sl@0: output-IP-list .IP .IP $rest sl@0: return sl@0: } sl@0: .PP { sl@0: man-puts

sl@0: } sl@0: .RS { sl@0: output-RS-list sl@0: return sl@0: } sl@0: .RE { sl@0: manerror "unexpected .RE" sl@0: return sl@0: } sl@0: .br { sl@0: man-puts
sl@0: return sl@0: } sl@0: .DE { sl@0: manerror "unexpected .DE" sl@0: return sl@0: } sl@0: .DS { sl@0: if {[next-op-is .ta rest]} { sl@0: sl@0: } sl@0: if {[match-text @stuff .DE]} { sl@0: man-puts

$stuff
sl@0: } elseif {[match-text .fi @ul1 @ul2 .nf @stuff .DE]} { sl@0: man-puts "
[lindex $ul1 1][lindex $ul2 1]\n$stuff
" sl@0: } else { sl@0: manerror "unexpected .DS format:\n[expand-next-text 2]" sl@0: } sl@0: return sl@0: } sl@0: .CS { sl@0: if {[next-op-is .ta rest]} { sl@0: sl@0: } sl@0: if {[match-text @stuff .CE]} { sl@0: man-puts
$stuff
sl@0: } else { sl@0: manerror "unexpected .CS format:\n[expand-next-text 2]" sl@0: } sl@0: return sl@0: } sl@0: .CE { sl@0: manerror "unexpected .CE" sl@0: return sl@0: } sl@0: .sp { sl@0: man-puts

sl@0: } sl@0: .ta { sl@0: # these are tab stop settings for short tables sl@0: switch -exact $manual(name):$manual(section) { sl@0: {bind:MODIFIERS} - sl@0: {bind:EVENT TYPES} - sl@0: {bind:BINDING SCRIPTS AND SUBSTITUTIONS} - sl@0: {expr:OPERANDS} - sl@0: {expr:MATH FUNCTIONS} - sl@0: {history:DESCRIPTION} - sl@0: {history:HISTORY REVISION} - sl@0: {re_syntax:BRACKET EXPRESSIONS} - sl@0: {switch:DESCRIPTION} - sl@0: {upvar:DESCRIPTION} { sl@0: return; # fix.me sl@0: } sl@0: default { sl@0: manerror "ignoring $line" sl@0: } sl@0: } sl@0: } sl@0: .nf { sl@0: if {[match-text @more .fi]} { sl@0: foreach more [split $more \n] { sl@0: man-puts $more
sl@0: } sl@0: } elseif {[match-text .RS @more .RE .fi]} { sl@0: man-puts

sl@0: foreach more [split $more \n] { sl@0: man-puts $more
sl@0: } sl@0: man-puts
sl@0: } elseif {[match-text .RS @more .RS @more2 .RE .RE .fi]} { sl@0: man-puts
sl@0: foreach more [split $more \n] { sl@0: man-puts $more
sl@0: } sl@0: man-puts
sl@0: foreach more2 [split $more2 \n] { sl@0: man-puts $more2
sl@0: } sl@0: man-puts
sl@0: } elseif {[match-text .RS @more .RS @more2 .RE @more3 .RE .fi]} { sl@0: man-puts
sl@0: foreach more [split $more \n] { sl@0: man-puts $more
sl@0: } sl@0: man-puts
sl@0: foreach more2 [split $more2 \n] { sl@0: man-puts $more2
sl@0: } sl@0: man-puts
sl@0: foreach more3 [split $more3 \n] { sl@0: man-puts $more3
sl@0: } sl@0: man-puts
sl@0: } elseif {[match-text .sp .RS @more .RS @more2 .sp .RE .RE .fi]} { sl@0: man-puts

sl@0: foreach more [split $more \n] { sl@0: man-puts $more
sl@0: } sl@0: man-puts
sl@0: foreach more2 [split $more2 \n] { sl@0: man-puts $more2
sl@0: } sl@0: man-puts

sl@0: } elseif {[match-text .RS .sp @more .sp .RE .fi]} { sl@0: man-puts

sl@0: foreach more [split $more \n] { sl@0: man-puts $more
sl@0: } sl@0: man-puts

sl@0: } else { sl@0: manerror "ignoring $line" sl@0: } sl@0: } sl@0: .fi { sl@0: manerror "ignoring $line" sl@0: } sl@0: .na - sl@0: .ad - sl@0: .UL - sl@0: .ne { sl@0: manerror "ignoring $line" sl@0: } sl@0: default { sl@0: manerror "unrecognized format directive: $line" sl@0: } sl@0: } sl@0: } sl@0: ## sl@0: ## merge copyright listings sl@0: ## sl@0: proc merge-copyrights {l1 l2} { sl@0: foreach copyright [concat $l1 $l2] { sl@0: if {[regexp {^Copyright +\(c\) +(\d+) +(by +)?(\w.*)$} $copyright all date by who]} { sl@0: lappend dates($who) $date sl@0: continue sl@0: } sl@0: if {[regexp {^Copyright +\(c\) +(\d+)-(\d+) +(by +)?(\w.*)$} $copyright all from to by who]} { sl@0: for {set date $from} {$date <= $to} {incr date} { sl@0: lappend dates($who) $date sl@0: } sl@0: continue sl@0: } sl@0: if {[regexp {^Copyright +\(c\) +(\d+), *(\d+) +(by +)?(\w.*)$} $copyright all date1 date2 by who]} { sl@0: lappend dates($who) $date1 $date2 sl@0: continue sl@0: } sl@0: puts "oops: $copyright" sl@0: } sl@0: foreach who [array names dates] { sl@0: set list [lsort $dates($who)] sl@0: if {[llength $list] == 1 || [lindex $list 0] == [lrange $list end end]} { sl@0: lappend merge "Copyright (c) [lindex $list 0] $who" sl@0: } else { sl@0: lappend merge "Copyright (c) [lindex $list 0]-[lrange $list end end] $who" sl@0: } sl@0: } sl@0: return [lsort $merge] sl@0: } sl@0: sl@0: proc makedirhier {dir} { sl@0: if {![file isdirectory $dir] && \ sl@0: [catch {file mkdir $dir} error]} { sl@0: return -code error "cannot create directory $dir: $error" sl@0: } sl@0: } sl@0: sl@0: ## sl@0: ## foreach of the man directories specified by args sl@0: ## convert manpages into hypertext in the directory sl@0: ## specified by html. sl@0: ## sl@0: proc make-man-pages {html args} { sl@0: global env manual overall_title tcltkdesc sl@0: makedirhier $html sl@0: set manual(short-toc-n) 1 sl@0: set manual(short-toc-fp) [open $html/contents.htm w] sl@0: puts $manual(short-toc-fp) "$overall_title" sl@0: puts $manual(short-toc-fp) "


$overall_title


" sl@0: set manual(merge-copyrights) {} sl@0: foreach arg $args { sl@0: if {$arg == ""} {continue} sl@0: set manual(wing-glob) [lindex $arg 0] sl@0: set manual(wing-name) [lindex $arg 1] sl@0: set manual(wing-file) [lindex $arg 2] sl@0: set manual(wing-description) [lindex $arg 3] sl@0: set manual(wing-copyrights) {} sl@0: makedirhier $html/$manual(wing-file) sl@0: set manual(wing-toc-fp) [open $html/$manual(wing-file)/contents.htm w] sl@0: # whistle sl@0: puts stderr "scanning section $manual(wing-name)" sl@0: # put the entry for this section into the short table of contents sl@0: puts $manual(short-toc-fp) "
$manual(wing-name)
$manual(wing-description)" sl@0: # initialize the wing table of contents sl@0: puts $manual(wing-toc-fp) "$manual(wing-name) Manual" sl@0: puts $manual(wing-toc-fp) "

$manual(wing-name)


" sl@0: # initialize the short table of contents for this section sl@0: set manual(wing-toc) {} sl@0: # initialize the man directory for this section sl@0: makedirhier $html/$manual(wing-file) sl@0: # initialize the long table of contents for this section sl@0: set manual(long-toc-n) 1 sl@0: # get the manual pages for this section sl@0: set manual(pages) [lsort [glob $manual(wing-glob)]] sl@0: if {[lsearch -glob $manual(pages) */options.n] >= 0} { sl@0: set n [lsearch $manual(pages) */options.n] sl@0: set manual(pages) "[lindex $manual(pages) $n] [lreplace $manual(pages) $n $n]" sl@0: } sl@0: # set manual(pages) [lrange $manual(pages) 0 5] sl@0: foreach manual(page) $manual(pages) { sl@0: # whistle sl@0: puts stderr "scanning page $manual(page)" sl@0: set manual(tail) [file tail $manual(page)] sl@0: set manual(name) [file root $manual(tail)] sl@0: set manual(section) {} sl@0: if {[lsearch {case pack-old menubar} $manual(name)] >= 0} { sl@0: # obsolete sl@0: manerror "discarding $manual(name)" sl@0: continue sl@0: } sl@0: set manual(infp) [open $manual(page)] sl@0: set manual(text) {} sl@0: set manual(partial-text) {} sl@0: foreach p {.RS .DS .CS .SO} { sl@0: set manual($p) 0 sl@0: } sl@0: set manual(stack) {} sl@0: set manual(section) {} sl@0: set manual(section-toc) {} sl@0: set manual(section-toc-n) 1 sl@0: set manual(copyrights) {} sl@0: lappend manual(all-pages) $manual(wing-file)/$manual(tail) sl@0: manreport 100 $manual(name) sl@0: while {[gets $manual(infp) line] >= 0} { sl@0: manreport 100 $line sl@0: if {[regexp {^[`'][/\\]} $line]} { sl@0: if {[regexp {Copyright \(c\).*$} $line copyright]} { sl@0: lappend manual(copyrights) $copyright sl@0: } sl@0: # comment sl@0: continue sl@0: } sl@0: if {"$line" == {'}} { sl@0: # comment sl@0: continue sl@0: } sl@0: if {[parse-directive $line code rest]} { sl@0: switch -exact $code { sl@0: .ad - .na - .so - .ne - .AS - .VE - .VS - sl@0: . { sl@0: # ignore sl@0: continue sl@0: } sl@0: } sl@0: if {"$manual(partial-text)" != {}} { sl@0: lappend manual(text) [process-text $manual(partial-text)] sl@0: set manual(partial-text) {} sl@0: } sl@0: switch -exact $code { sl@0: .SH - .SS { sl@0: if {[llength $rest] == 0} { sl@0: gets $manual(infp) rest sl@0: } sl@0: lappend manual(text) "$code [unquote $rest]" sl@0: } sl@0: .TH { sl@0: lappend manual(text) "$code [unquote $rest]" sl@0: } sl@0: .HS - .UL - sl@0: .ta { sl@0: lappend manual(text) "$code [unquote $rest]" sl@0: } sl@0: .BS - .BE - .br - .fi - .sp - sl@0: .nf { sl@0: if {"$rest" != {}} { sl@0: manerror "unexpected argument: $line" sl@0: } sl@0: lappend manual(text) $code sl@0: } sl@0: .AP { sl@0: lappend manual(text) [concat .IP [process-text "[lindex $rest 0] \\fB[lindex $rest 1]\\fR ([lindex $rest 2])"]] sl@0: } sl@0: .IP { sl@0: regexp {^(.*) +\d+$} $rest all rest sl@0: lappend manual(text) ".IP [process-text [unquote [string trim $rest]]]" sl@0: } sl@0: .TP { sl@0: while {[is-a-directive [set next [gets $manual(infp)]]]} { sl@0: manerror "ignoring $next after .TP" sl@0: } sl@0: if {"$next" != {'}} { sl@0: lappend manual(text) ".IP [process-text $next]" sl@0: } sl@0: } sl@0: .OP { sl@0: lappend manual(text) [concat .OP [process-text \ sl@0: "\\fB[lindex $rest 0]\\fR \\fB[lindex $rest 1]\\fR \\fB[lindex $rest 2]\\fR"]] sl@0: } sl@0: .PP - sl@0: .LP { sl@0: lappend manual(text) {.PP} sl@0: } sl@0: .RS { sl@0: incr manual(.RS) sl@0: lappend manual(text) $code sl@0: } sl@0: .RE { sl@0: incr manual(.RS) -1 sl@0: lappend manual(text) $code sl@0: } sl@0: .SO { sl@0: incr manual(.SO) sl@0: lappend manual(text) $code sl@0: } sl@0: .SE { sl@0: incr manual(.SO) -1 sl@0: lappend manual(text) $code sl@0: } sl@0: .DS { sl@0: incr manual(.DS) sl@0: lappend manual(text) $code sl@0: } sl@0: .DE { sl@0: incr manual(.DS) -1 sl@0: lappend manual(text) $code sl@0: } sl@0: .CS { sl@0: incr manual(.CS) sl@0: lappend manual(text) $code sl@0: } sl@0: .CE { sl@0: incr manual(.CS) -1 sl@0: lappend manual(text) $code sl@0: } sl@0: .de { sl@0: while {[gets $manual(infp) line] >= 0} { sl@0: if {[string match "..*" $line]} { sl@0: break sl@0: } sl@0: } sl@0: } sl@0: .. { sl@0: error "found .. outside of .de" sl@0: } sl@0: default { sl@0: manerror "unrecognized format directive: $line" sl@0: } sl@0: } sl@0: } else { sl@0: if {$manual(partial-text) == ""} { sl@0: set manual(partial-text) $line sl@0: } else { sl@0: append manual(partial-text) \n$line sl@0: } sl@0: } sl@0: } sl@0: if {$manual(partial-text) != ""} { sl@0: lappend manual(text) [process-text $manual(partial-text)] sl@0: } sl@0: close $manual(infp) sl@0: # fixups sl@0: if {$manual(.RS) != 0} { sl@0: if {$manual(name) != "selection"} { sl@0: puts "unbalanced .RS .RE" sl@0: } sl@0: } sl@0: if {$manual(.DS) != 0} { sl@0: puts "unbalanced .DS .DE" sl@0: } sl@0: if {$manual(.CS) != 0} { sl@0: puts "unbalanced .CS .CE" sl@0: } sl@0: if {$manual(.SO) != 0} { sl@0: puts "unbalanced .SO .SE" sl@0: } sl@0: # output conversion sl@0: open-text sl@0: if {[next-op-is .HS rest]} { sl@0: set manual($manual(name)-title) \ sl@0: "[lrange $rest 1 end] [lindex $rest 0] manual page" sl@0: while {[more-text]} { sl@0: set line [next-text] sl@0: if {[is-a-directive $line]} { sl@0: output-directive $line sl@0: } else { sl@0: man-puts $line sl@0: } sl@0: } sl@0: man-puts
sl@0: 		foreach copyright $manual(copyrights) {
sl@0: 		    man-puts "Copyright © [lrange $copyright 2 end]"
sl@0: 		}
sl@0: 		man-puts "Copyright © 1995-1997 Roger E. Critchlow Jr.
" sl@0: set manual(wing-copyrights) [merge-copyrights $manual(wing-copyrights) $manual(copyrights)] sl@0: } elseif {[next-op-is .TH rest]} { sl@0: set manual($manual(name)-title) "[lrange $rest 4 end] - [lindex $rest 0] manual page" sl@0: while {[more-text]} { sl@0: set line [next-text] sl@0: if {[is-a-directive $line]} { sl@0: output-directive $line sl@0: } else { sl@0: man-puts $line sl@0: } sl@0: } sl@0: man-puts
sl@0: 		foreach copyright $manual(copyrights) {
sl@0: 		    man-puts "Copyright © [lrange $copyright 2 end]"
sl@0: 		}
sl@0: 		man-puts "Copyright © 1995-1997 Roger E. Critchlow Jr.
" sl@0: set manual(wing-copyrights) [merge-copyrights $manual(wing-copyrights) $manual(copyrights)] sl@0: } else { sl@0: manerror "no .HS or .TH record found" sl@0: } sl@0: # sl@0: # make the long table of contents for this page sl@0: # sl@0: set manual(toc-$manual(wing-file)-$manual(name)) [concat
$manual(section-toc)

] sl@0: } sl@0: sl@0: # sl@0: # make the wing table of contents for the section sl@0: # sl@0: set width 0 sl@0: foreach name $manual(wing-toc) { sl@0: if {[string length $name] > $width} { sl@0: set width [string length $name] sl@0: } sl@0: } sl@0: set perline [expr {120 / $width}] sl@0: set nrows [expr {([llength $manual(wing-toc)]+$perline)/$perline}] sl@0: set n 0 sl@0: catch {unset rows} sl@0: foreach name [lsort $manual(wing-toc)] { sl@0: set tail $manual(name-$name) sl@0: if {[llength $tail] > 1} { sl@0: manerror "$name is defined in more than one file: $tail" sl@0: set tail [lindex $tail [expr {[llength $tail]-1}]] sl@0: } sl@0: set tail [file tail $tail] sl@0: append rows([expr {$n%$nrows}]) \ sl@0: " $name" sl@0: incr n sl@0: } sl@0: puts $manual(wing-toc-fp) sl@0: foreach row [lsort -integer [array names rows]] { sl@0: puts $manual(wing-toc-fp) $rows($row) sl@0: } sl@0: puts $manual(wing-toc-fp)
sl@0: sl@0: # sl@0: # insert wing copyrights sl@0: # sl@0: puts $manual(wing-toc-fp) "
"
sl@0: 	foreach copyright $manual(wing-copyrights) {
sl@0: 	    puts $manual(wing-toc-fp) "Copyright © [lrange $copyright 2 end]"
sl@0: 	}
sl@0: 	puts $manual(wing-toc-fp) "Copyright © 1995-1997 Roger E. Critchlow Jr."
sl@0: 	puts $manual(wing-toc-fp) "
" sl@0: close $manual(wing-toc-fp) sl@0: set manual(merge-copyrights) [merge-copyrights $manual(merge-copyrights) $manual(wing-copyrights)] sl@0: } sl@0: sl@0: ## sl@0: ## build the keyword index. sl@0: ## sl@0: proc strcasecmp {a b} { return [string compare -nocase $a $b] } sl@0: set keys [lsort -command strcasecmp [array names manual keyword-*]] sl@0: makedirhier $html/Keywords sl@0: catch {eval file delete -- [glob $html/Keywords/*]} sl@0: puts $manual(short-toc-fp) "
Keywords
The keywords from the $tcltkdesc man pages." sl@0: set keyfp [open $html/Keywords/contents.htm w] sl@0: puts $keyfp "$tcltkdesc Keywords" sl@0: puts $keyfp "

$tcltkdesc Keywords


" sl@0: foreach a {A B C D E F G H I J K L M N O P Q R S T U V W X Y Z} { sl@0: puts $keyfp "$a" sl@0: set afp [open $html/Keywords/$a.htm w] sl@0: puts $afp "$tcltkdesc Keywords - $a" sl@0: puts $afp "

$tcltkdesc Keywords - $a


" sl@0: foreach b {A B C D E F G H I J K L M N O P Q R S T U V W X Y Z} { sl@0: puts $afp "$b" sl@0: } sl@0: puts $afp "


" sl@0: foreach k $keys { sl@0: if {[string match -nocase "keyword-${a}*" $k]} { sl@0: set k [string range $k 8 end] sl@0: puts $afp "
$k
" sl@0: set refs {} sl@0: foreach man $manual(keyword-$k) { sl@0: set name [lindex $man 0] sl@0: set file [lindex $man 1] sl@0: lappend refs "$name" sl@0: } sl@0: puts $afp [join $refs {, }] sl@0: } sl@0: } sl@0: puts $afp "

"
sl@0: 	# insert merged copyrights
sl@0: 	foreach copyright $manual(merge-copyrights) {
sl@0: 	    puts $afp "Copyright © [lrange $copyright 2 end]"
sl@0: 	}
sl@0: 	puts $afp "Copyright © 1995-1997 Roger E. Critchlow Jr."
sl@0: 	puts $afp "
" sl@0: close $afp sl@0: } sl@0: puts $keyfp "
"
sl@0: 
sl@0:     # insert merged copyrights
sl@0:     foreach copyright $manual(merge-copyrights) {
sl@0: 	puts $keyfp "Copyright © [lrange $copyright 2 end]"
sl@0:     }
sl@0:     puts $keyfp "Copyright © 1995-1997 Roger E. Critchlow Jr."
sl@0:     puts $keyfp 

sl@0: close $keyfp sl@0: sl@0: ## sl@0: ## finish off short table of contents sl@0: ## sl@0: puts $manual(short-toc-fp) {
Source
More information about these man pages.} sl@0: puts $manual(short-toc-fp) "

"
sl@0:     # insert merged copyrights
sl@0:     foreach copyright $manual(merge-copyrights) {
sl@0: 	puts $manual(short-toc-fp) "Copyright © [lrange $copyright 2 end]"
sl@0:     }
sl@0:     puts $manual(short-toc-fp) "Copyright © 1995-1997 Roger E. Critchlow Jr."
sl@0:     puts $manual(short-toc-fp) "
" sl@0: close $manual(short-toc-fp) sl@0: sl@0: ## sl@0: ## output man pages sl@0: ## sl@0: unset manual(section) sl@0: foreach path $manual(all-pages) { sl@0: set manual(wing-file) [file dirname $path] sl@0: set manual(tail) [file tail $path] sl@0: set manual(name) [file root $manual(tail)] sl@0: set text $manual(output-$manual(wing-file)-$manual(name)) sl@0: set ntext 0 sl@0: foreach item $text { sl@0: incr ntext [llength [split $item \n]] sl@0: incr ntext sl@0: } sl@0: set toc $manual(toc-$manual(wing-file)-$manual(name)) sl@0: set ntoc 0 sl@0: foreach item $toc { sl@0: incr ntoc [llength [split $item \n]] sl@0: incr ntoc sl@0: } sl@0: puts stderr "rescanning page $manual(name) $ntoc/$ntext" sl@0: set manual(outfp) [open $html/$manual(wing-file)/$manual(name).htm w] sl@0: puts $manual(outfp) "$manual($manual(name)-title)" sl@0: if {($ntext > 60) && ($ntoc > 32) || [lsearch { sl@0: Hash LinkVar SetVar TraceVar ConfigWidg CrtImgType CrtItemType sl@0: CrtPhImgFmt DoOneEvent GetBitmap GetColor GetCursor GetDash sl@0: GetJustify GetPixels GetVisual ParseArgv QueueEvent sl@0: } $manual(tail)] >= 0} { sl@0: foreach item $toc { sl@0: puts $manual(outfp) $item sl@0: } sl@0: } sl@0: foreach item $text { sl@0: puts $manual(outfp) [insert-cross-references $item] sl@0: } sl@0: puts $manual(outfp) sl@0: close $manual(outfp) sl@0: } sl@0: return {} sl@0: } sl@0: sl@0: parse_command_line sl@0: sl@0: set tcltkdesc ""; set cmdesc ""; set appdir "" sl@0: if {$build_tcl} {append tcltkdesc "Tcl"; append cmdesc "Tcl"; append appdir "$tcldir"} sl@0: if {$build_tcl && $build_tk} {append tcltkdesc "/"; append cmdesc " and "; append appdir ","} sl@0: if {$build_tk} {append tcltkdesc "Tk"; append cmdesc "Tk"; append appdir "$tkdir"} sl@0: sl@0: set usercmddesc "The interpreters which implement $cmdesc." sl@0: set tclcmddesc {The commands which the tclsh interpreter implements.} sl@0: set tkcmddesc {The additional commands which the wish interpreter implements.} sl@0: set tcllibdesc {The C functions which a Tcl extended C program may use.} sl@0: set tklibdesc {The additional C functions which a Tk extended C program may use.} sl@0: sl@0: if {1} { sl@0: if {[catch { sl@0: make-man-pages $webdir \ sl@0: "$tcltkdir/{$appdir}/doc/*.1 \"$tcltkdesc Applications\" UserCmd {$usercmddesc}" \ sl@0: [expr {$build_tcl ? "$tcltkdir/$tcldir/doc/*.n {Tcl Commands} TclCmd {$tclcmddesc}" : ""}] \ sl@0: [expr {$build_tk ? "$tcltkdir/$tkdir/doc/*.n {Tk Commands} TkCmd {$tkcmddesc}" : ""}] \ sl@0: [expr {$build_tcl ? "$tcltkdir/$tcldir/doc/*.3 {Tcl Library} TclLib {$tcllibdesc}" : ""}] \ sl@0: [expr {$build_tk ? "$tcltkdir/$tkdir/doc/*.3 {Tk Library} TkLib {$tklibdesc}" : ""}] sl@0: } error]} { sl@0: puts $error\n$errorInfo sl@0: } sl@0: }