$rest
output-IP-list .RS .IP $rest2
}
if {[match-text .RE .sp .RS @rest .RE]} {
man-puts
$rest
return
}
if {[next-op-is .RE rest]} {
return
}
}
man-puts
}
.RS {
output-RS-list
return
}
.RE {
manerror "unexpected .RE"
return
}
.br {
man-puts
return
}
.DE {
manerror "unexpected .DE"
return
}
.DS {
if {[next-op-is .ta rest]} {
# skip the leading .ta directive if it is there
}
if {[match-text @stuff .DE]} {
set td "
$td \t $td] \n$stuff]
man-puts "
"
#man-puts $stuff
} elseif {[match-text .fi @ul1 @ul2 .nf @stuff .DE]} {
man-puts "[lindex $ul1 1][lindex $ul2 1]\n$stuff
"
} else {
manerror "unexpected .DS format:\n[expand-next-text 2]"
}
return
}
.CS {
if {[next-op-is .ta rest]} {
# ???
}
if {[match-text @stuff .CE]} {
man-puts $stuff
} else {
manerror "unexpected .CS format:\n[expand-next-text 2]"
}
return
}
.CE {
manerror "unexpected .CE"
return
}
.sp {
man-puts
}
.ta {
# these are tab stop settings for short tables
switch -exact -- $manual(name):$manual(section) {
{bind:MODIFIERS} -
{bind:EVENT TYPES} -
{bind:BINDING SCRIPTS AND SUBSTITUTIONS} -
{expr:OPERANDS} -
{expr:MATH FUNCTIONS} -
{history:DESCRIPTION} -
{history:HISTORY REVISION} -
{switch:DESCRIPTION} -
{upvar:DESCRIPTION} {
return; # fix.me
}
default {
manerror "ignoring $line"
}
}
}
.nf {
if {[match-text @more .fi]} {
foreach more [split $more \n] {
man-puts $more
}
} elseif {[match-text .RS @more .RE .fi]} {
man-puts
-
foreach more [split $more \n] {
man-puts $more
}
man-puts
} elseif {[match-text .RS @more .RS @more2 .RE .RE .fi]} {
man-puts -
foreach more [split $more \n] {
man-puts $more
}
man-puts -
foreach more2 [split $more2 \n] {
man-puts $more2
}
man-puts
} elseif {[match-text .RS @more .RS @more2 .RE @more3 .RE .fi]} {
man-puts -
foreach more [split $more \n] {
man-puts $more
}
man-puts -
foreach more2 [split $more2 \n] {
man-puts $more2
}
man-puts
-
foreach more3 [split $more3 \n] {
man-puts $more3
}
man-puts
} elseif {[match-text .sp .RS @more .RS @more2 .sp .RE .RE .fi]} {
man-puts -
foreach more [split $more \n] {
man-puts $more
}
man-puts -
foreach more2 [split $more2 \n] {
man-puts $more2
}
man-puts
} elseif {[match-text .RS .sp @more .sp .RE .fi]} {
man-puts
-
foreach more [split $more \n] {
man-puts $more
}
man-puts
} else {
manerror "ignoring $line"
}
}
.fi {
manerror "ignoring $line"
}
.na -
.ad -
.nr -
.if -
.UL -
.ne {
manerror "ignoring $line"
}
.\\\" {
manerror "ignoring comment $line"
}
default {
manerror "unrecognized format directive: $line"
}
}
}
##
## merge copyright listings
##
proc merge-copyrights {l1 l2} {
set merge {}
set re1 {^Copyright +(?:\(c\)|\\\(co|©) +(\w.*?)(?:all rights reserved)?(?:\. )*$}
set re2 {^(\d+) +(?:by +)?(\w.*)$} ;# date who
set re3 {^(\d+)-(\d+) +(?:by +)?(\w.*)$} ;# from to who
set re4 {^(\d+), *(\d+) +(?:by +)?(\w.*)$} ;# date1 date2 who
foreach copyright [concat $l1 $l2] {
if {[regexp -nocase -- $re1 $copyright -> info]} {
set info [string trimright $info ". "] ; # remove extra period
if {[regexp -- $re2 $info -> date who]} {
lappend dates($who) $date
continue
} elseif {[regexp -- $re3 $info -> from to who]} {
for {set date $from} {$date <= $to} {incr date} {
lappend dates($who) $date
}
continue
} elseif {[regexp -- $re3 $info -> date1 date2 who]} {
lappend dates($who) $date1 $date2
continue
}
}
puts "oops: $copyright"
}
foreach who [array names dates] {
set list [lsort -dictionary $dates($who)]
if {[llength $list] == 1 || [lindex $list 0] eq [lrange $list end end]} {
lappend merge "Copyright © [lindex $list 0] $who"
} else {
lappend merge "Copyright © [lindex $list 0]-[lrange $list end end] $who"
}
}
return [lsort -dictionary $merge]
}
proc makedirhier {dir} {
if {![file isdirectory $dir] && \
[catch {file mkdir $dir} error]} {
return -code error "cannot create directory $dir: $error"
}
}
proc addbuffer {args} {
global manual
if {$manual(partial-text) ne ""} {
append manual(partial-text) \n
}
append manual(partial-text) [join $args ""]
}
proc flushbuffer {} {
global manual
if {$manual(partial-text) ne ""} {
lappend manual(text) [process-text $manual(partial-text)]
set manual(partial-text) ""
}
}
##
## foreach of the man directories specified by args
## convert manpages into hypertext in the directory
## specified by html.
##
proc make-man-pages {html args} {
global manual overall_title tcltkdesc
makedirhier $html
set cssfd [open $html/$::CSSFILE w]
puts $cssfd [gencss]
close $cssfd
set manual(short-toc-n) 1
set manual(short-toc-fp) [open $html/[indexfile] w]
puts $manual(short-toc-fp) [htmlhead $overall_title $overall_title]
puts $manual(short-toc-fp) "
"
set manual(merge-copyrights) {}
foreach arg $args {
# preprocess to set up subheader for the rest of the files
if {![llength $arg]} {
continue
}
set name [lindex $arg 1]
set file [lindex $arg 2]
lappend manual(subheader) $name $file
}
foreach arg $args {
if {![llength $arg]} {
continue
}
set manual(wing-glob) [lindex $arg 0]
set manual(wing-name) [lindex $arg 1]
set manual(wing-file) [lindex $arg 2]
set manual(wing-description) [lindex $arg 3]
set manual(wing-copyrights) {}
makedirhier $html/$manual(wing-file)
set manual(wing-toc-fp) [open $html/$manual(wing-file)/[indexfile] w]
# whistle
puts stderr "scanning section $manual(wing-name)"
# put the entry for this section into the short table of contents
puts $manual(short-toc-fp) "- $manual(wing-name)
- $manual(wing-description)
"
# initialize the wing table of contents
puts $manual(wing-toc-fp) [htmlhead $manual(wing-name) \
$manual(wing-name) $overall_title "../[indexfile]"]
# initialize the short table of contents for this section
set manual(wing-toc) {}
# initialize the man directory for this section
makedirhier $html/$manual(wing-file)
# initialize the long table of contents for this section
set manual(long-toc-n) 1
# get the manual pages for this section
set manual(pages) [lsort -dictionary [glob $manual(wing-glob)]]
set n [lsearch -glob $manual(pages) */ttk_widget.n]
if {$n >= 0} {
set manual(pages) "[lindex $manual(pages) $n] [lreplace $manual(pages) $n $n]"
}
set n [lsearch -glob $manual(pages) */options.n]
if {$n >= 0} {
set manual(pages) "[lindex $manual(pages) $n] [lreplace $manual(pages) $n $n]"
}
# set manual(pages) [lrange $manual(pages) 0 5]
set LQ \u201c
set RQ \u201d
foreach manual_page $manual(pages) {
set manual(page) $manual_page
# whistle
puts stderr "scanning page $manual(page)"
set manual(tail) [file tail $manual(page)]
set manual(name) [file root $manual(tail)]
set manual(section) {}
if {$manual(name) in {case pack-old menubar}} {
# obsolete
manerror "discarding $manual(name)"
continue
}
set manual(infp) [open $manual(page)]
set manual(text) {}
set manual(partial-text) {}
foreach p {.RS .DS .CS .SO} {
set manual($p) 0
}
set manual(stack) {}
set manual(section) {}
set manual(section-toc) {}
set manual(section-toc-n) 1
set manual(copyrights) {}
lappend manual(all-pages) $manual(wing-file)/$manual(tail)
manreport 100 $manual(name)
set ignored 0
while {[gets $manual(infp) line] >= 0} {
manreport 100 $line
if {"$line" eq "'\\\" IGNORE"} {
set ignored 1
continue
}
if {"$line" eq "'\\\" END IGNORE"} {
set ignored 0
continue
}
if {$ignored} {
continue
}
if {[regexp {^[`'][/\\]} $line]} {
if {[regexp {Copyright (?:\(c\)|\\\(co).*$} $line copyright]} {
lappend manual(copyrights) $copyright
}
# comment
continue
}
if {"$line" eq {'}} {
# comment
continue
}
if {![parse-directive $line code rest]} {
addbuffer $line
continue
}
switch -exact -- $code {
.ad - .na - .so - .ne - .AS - .VE - .VS - . {
# ignore
continue
}
}
switch -exact -- $code {
.SH - .SS {
flushbuffer
if {[llength $rest] == 0} {
gets $manual(infp) rest
}
lappend manual(text) "$code [unquote $rest]"
}
.TH {
flushbuffer
lappend manual(text) "$code [unquote $rest]"
}
.QW {
set rest [regexp -all -inline {\"(?:[^""]+)\"|\S+} $rest]
addbuffer $LQ [unquote [lindex $rest 0]] $RQ \
[unquote [lindex $rest 1]]
}
.PQ {
set rest [regexp -all -inline {\"(?:[^""]+)\"|\S+} $rest]
addbuffer ( $LQ [unquote [lindex $rest 0]] $RQ \
[unquote [lindex $rest 1]] ) \
[unquote [lindex $rest 2]]
}
.QR {
set rest [regexp -all -inline {\"(?:[^""]+)\"|\S+} $rest]
addbuffer $LQ [unquote [lindex $rest 0]] - \
[unquote [lindex $rest 1]] $RQ \
[unquote [lindex $rest 2]]
}
.MT {
addbuffer $LQ$RQ
}
.HS - .UL - .ta {
flushbuffer
lappend manual(text) "$code [unquote $rest]"
}
.BS - .BE - .br - .fi - .sp - .nf {
flushbuffer
if {"$rest" ne {}} {
manerror "unexpected argument: $line"
}
lappend manual(text) $code
}
.AP {
flushbuffer
lappend manual(text) [concat .IP [process-text "[lindex $rest 0] \\fB[lindex $rest 1]\\fR ([lindex $rest 2])"]]
}
.IP {
flushbuffer
regexp {^(.*) +\d+$} $rest all rest
lappend manual(text) ".IP [process-text [unquote [string trim $rest]]]"
}
.TP {
flushbuffer
while {[is-a-directive [set next [gets $manual(infp)]]]} {
manerror "ignoring $next after .TP"
}
if {"$next" ne {'}} {
lappend manual(text) ".IP [process-text $next]"
}
}
.OP {
flushbuffer
lappend manual(text) [concat .OP [process-text \
"\\fB[lindex $rest 0]\\fR \\fB[lindex $rest 1]\\fR \\fB[lindex $rest 2]\\fR"]]
}
.PP - .LP {
flushbuffer
lappend manual(text) {.PP}
}
.RS {
flushbuffer
incr manual(.RS)
lappend manual(text) $code
}
.RE {
flushbuffer
incr manual(.RS) -1
lappend manual(text) $code
}
.SO {
flushbuffer
incr manual(.SO)
if {[llength $rest] == 0} {
lappend manual(text) "$code options"
} else {
lappend manual(text) "$code [unquote $rest]"
}
}
.SE {
flushbuffer
incr manual(.SO) -1
lappend manual(text) $code
}
.DS {
flushbuffer
incr manual(.DS)
lappend manual(text) $code
}
.DE {
flushbuffer
incr manual(.DS) -1
lappend manual(text) $code
}
.CS {
flushbuffer
incr manual(.CS)
lappend manual(text) $code
}
.CE {
flushbuffer
incr manual(.CS) -1
lappend manual(text) $code
}
.de {
while {[gets $manual(infp) line] >= 0} {
if {[string match "..*" $line]} {
break
}
}
}
.. {
error "found .. outside of .de"
}
default {
flushbuffer
manerror "unrecognized format directive: $line"
}
}
}
flushbuffer
close $manual(infp)
# fixups
if {$manual(.RS) != 0} {
puts "unbalanced .RS .RE"
}
if {$manual(.DS) != 0} {
puts "unbalanced .DS .DE"
}
if {$manual(.CS) != 0} {
puts "unbalanced .CS .CE"
}
if {$manual(.SO) != 0} {
puts "unbalanced .SO .SE"
}
# output conversion
open-text
set haserror 0
if {[next-op-is .HS rest]} {
set manual($manual(name)-title) \
"[lrange $rest 1 end] [lindex $rest 0] manual page"
} elseif {[next-op-is .TH rest]} {
set manual($manual(name)-title) "[lindex $rest 0] manual page - [lrange $rest 4 end]"
} else {
set haserror 1
manerror "no .HS or .TH record found"
}
if {!$haserror} {
while {[more-text]} {
set line [next-text]
if {[is-a-directive $line]} {
output-directive $line
} else {
man-puts $line
}
}
man-puts [copyout $manual(copyrights) "../"]
set manual(wing-copyrights) [merge-copyrights $manual(wing-copyrights) $manual(copyrights)]
}
#
# make the long table of contents for this page
#
set manual(toc-$manual(wing-file)-$manual(name)) [concat $manual(section-toc)
]
}
#
# make the wing table of contents for the section
#
set width 0
foreach name $manual(wing-toc) {
if {[string length $name] > $width} {
set width [string length $name]
}
}
set perline [expr {120 / $width}]
set nrows [expr {([llength $manual(wing-toc)]+$perline)/$perline}]
set n 0
catch {unset rows}
foreach name [lsort -dictionary $manual(wing-toc)] {
set tail $manual(name-$name)
if {[llength $tail] > 1} {
manerror "$name is defined in more than one file: $tail"
set tail [lindex $tail [expr {[llength $tail]-1}]]
}
set tail [file tail $tail]
append rows([expr {$n%$nrows}]) \
" $name"
incr n
}
puts $manual(wing-toc-fp)
foreach row [lsort -integer [array names rows]] {
puts $manual(wing-toc-fp) $rows($row)
}
puts $manual(wing-toc-fp)
#
# insert wing copyrights
#
puts $manual(wing-toc-fp) [copyout $manual(wing-copyrights) "../"]
puts $manual(wing-toc-fp) $::logo
puts $manual(wing-toc-fp) ""
close $manual(wing-toc-fp)
set manual(merge-copyrights) [merge-copyrights $manual(merge-copyrights) $manual(wing-copyrights)]
}
##
## build the keyword index.
##
file delete -force -- $html/Keywords
makedirhier $html/Keywords
set keyfp [open $html/Keywords/[indexfile] w]
puts $keyfp [htmlhead "$tcltkdesc Keywords" "$tcltkdesc Keywords" \
$overall_title "../[indexfile]"]
set letters {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}
# Create header first
set keyheader {}
foreach a $letters {
set keys [array names manual "keyword-\[[string totitle $a$a]\]*"]
if {[llength $keys]} {
lappend keyheader "$a"
} else {
# No keywords for this letter
lappend keyheader $a
}
}
set keyheader "[join $keyheader " |\n"]"
puts $keyfp $keyheader
foreach a $letters {
set keys [array names manual "keyword-\[[string totitle $a$a]\]*"]
if {![llength $keys]} {
continue
}
# Per-keyword page
set afp [open $html/Keywords/$a.htm w]
puts $afp [htmlhead "$tcltkdesc Keywords - $a" \
"$tcltkdesc Keywords - $a" \
$overall_title "../[indexfile]"]
puts $afp $keyheader
puts $afp ""
foreach k [lsort -dictionary $keys] {
set k [string range $k 8 end]
puts $afp "- $k
"
puts $afp "- "
set refs {}
foreach man $manual(keyword-$k) {
set name [lindex $man 0]
set file [lindex $man 1]
lappend refs "$name"
}
puts $afp "[join $refs {, }]
"
}
puts $afp " "
# insert merged copyrights
puts $afp [copyout $manual(merge-copyrights)]
puts $afp $::logo
puts $afp " |