#! /usr/bin/python
# HTML to manpage converter, written for ftplib.
# This program was written by Richard Braakman <dark@xs4all.nl>
# The author places it in the public domain.

import time
import sys
import string
import os
import errno
import stat
from sgmllib import SGMLParser

class PageParser(SGMLParser):
    def __init__(self, receiver):
	SGMLParser.__init__(self, 0)
	self.receiver = receiver
	self.data = None

    # Data-handling mechanism borrowed from HTMLParser

    def handle_data(self, data):
	if self.data is not None:
	    self.data = self.data + data
	else:
	    self.receiver.add_text(data)

    def save_bgn(self):
        self.data = ''

    def save_end(self):
        data = self.data
        self.data = None
        return string.join(string.split(data))

    def start_html(self, attrs):
	pass
    def end_html(self):
	self.receiver.finish()

    def start_title(self, attrs):
	self.save_bgn()
    def end_title(self):
	# This used to set the title, but it will be the same as
	# the title in the <h1> block anyway, which is more convenient.
	self.save_end()

    def start_h1(self, attrs):
	self.save_bgn()
    def end_h1(self):
	self.receiver.set_title(self.save_end())
	self.receiver.write_intro()

    def start_h2(self, attrs):
	self.save_bgn()
    def end_h2(self):
	self.receiver.make_header(self.save_end())

    def do_p(self, attrs):
	self.receiver.start_paragraph()

    def do_dt(self, attrs):
	self.save_bgn()
    def do_dd(self, attrs):
	self.receiver.start_tab(self.save_end())

    def start_pre(self, attrs):
	self.save_bgn()
    def end_pre(self):
	self.receiver.preformatted(self.save_end())

class PageWriter:
    def __init__(self, outfile):
	self.out = outfile
	self.title = None
	self.mtime = None
	self.need_newline = 0
	self.suppress_paragraph = 0

    def writeout(self, data):
	self.out.write(data)

    def set_time(self, time):
	self.mtime = time

    def prettydate(self):
	return time.strftime('"%d %B %Y"', time.localtime(self.mtime))

    def opt_newline(self):
	if self.need_newline:
	    self.writeout("\n")
	self.need_newline = 0

    def add_text(self, data):
	if len(data) == 0:
	    return
	if data[-1] == " ":
	    data = string.join(string.split(data)) + " "
	else:
	    data = string.join(string.split(data))
        data = data.replace("-", "\-");
	if len(data) == 0:
	    return
        self.writeout(data)
	self.need_newline = 1

    def set_title(self, title):
	self.title = title

    def write_intro(self):
	self.writeout(".\\\" This manual page was generated from the file " +
		      self.title + ".html.\n")
	self.writeout(".TH " + self.title + " 3 " + self.prettydate() +
                      " FTPlib\n")
	self.writeout(".SH NAME\n" + self.title + " \- ");
	self.suppress_paragraph = 1
	self.need_newline = 1

    def preformatted(self, text):
	self.opt_newline
	# Parse include directives
	rb = string.find(text, ">")
	while rb >= 0:
	    self.writeout('.B "' + text[:rb+1] + '"\n.br\n')
	    text = text[rb+2:]
	    rb = string.find(text, ">")
	self.writeout('.sp\n')
	# Next comes a function prototype.
	parmstart = string.index(text, "(")
	if text[parmstart:] == "(void);":
	    self.writeout('.B "' + text + '"\n')
	    return
	parms = string.split(text[parmstart+1:-2], ", ")
	self.writeout('.BI "' + text[:parmstart+1])
	length = parmstart+1
	for i in range(len(parms)):
	    parm = parms[i]
	    if length + len(parm) > 55:
		self.writeout('"\n.RS\n.BI "')
		length = 8
	    else:
		length = length + len(parm) + 2
	    end = string.rindex(parm, " ")
	    while parm[end+1] == "*":
		end = end + 1
	    self.writeout(parm[:end+1] + '" ' + parm[end+1:] + ' "')
	    if i + 1 < len(parms):
		self.writeout(', ')
	self.writeout(text[-2:] + '"\n')

    def make_header(self, header):
	self.opt_newline()
	self.writeout('.SH "' + header + '"\n');

    def start_paragraph(self):
	if self.suppress_paragraph:
	    self.suppress_paragraph = 0
	else:
	    self.opt_newline()
	    self.writeout(".LP\n")

    def start_tab(self, heading):
	self.opt_newline()
	self.writeout('.TP\n.B "' + heading + '"\n')

    def finish(self):
	self.opt_newline()

def convert(filename):
    begin = string.rfind(filename, "/")
    if begin >= 0:
	filename = filename[begin+1:]
    end = string.rindex(filename, ".html")
    return filename[:end] + ".3"

if len(sys.argv) < 3:
    sys.stderr.write("Usage: html2man filenames... dirname\n")
else:
    dirname = sys.argv[-1]
    try:
	os.makedirs(dirname)
    except OSError, e:
	if e.errno <> errno.EEXIST: raise
    for filename in sys.argv[1:-1]:
	outfilename = os.path.join(dirname, convert(filename))
        infile = open(filename, "r")
	outfile = open(outfilename, "w")
	timestamp = os.fstat(infile.fileno())[stat.ST_MTIME]
        receiver = PageWriter(outfile)
        receiver.set_time(timestamp)
        parser = PageParser(receiver)
        parser.feed(infile.read())
	infile.close()
	outfile.close()
	os.utime(outfilename, (timestamp, timestamp))
