Commit beee5465 authored by Fabian Wolff's avatar Fabian Wolff

Import Upstream version 2.3

parent b3492e29
This diff is collapsed.
......@@ -13,13 +13,10 @@ SVG, but EQN is not translated.
Test loads are included in the distribution. The code has been tested
in about the most brutal possible way; it has been run against every
single man page in all sections of a full Fedore Core installation.
single man page in all sections of a full Fedora Core installation.
It lifts over 95% of these pages without requiring any hand-hacking.
There is a detailed change log in the RPM spec file.
doclifter was written under Python 2.2a1. It will not work under Python 1.5.2,
and may not work under 2.1. Upgrade, it will be good for you.
Eric S. Raymond
November 2003
Bugs:
* I haven't come up with a reliable way to distinguish command synopses
from stuff that should be treated as plain text. This has a couple
of consequences:
1. doclifter doesn't recognize command synopses in displays, only in
Synopsis sections.
2. When command synopses have a trailing text section (explanatory
paragraph) doclifter doesn't always detect that and cope well.
* .Xo/.Xc Berkeley macro needs work. See elf.5.
* Look at lwres_getaddrinfo.3 -- good type case for resuming function parse
......@@ -7,16 +17,11 @@ Bugs:
* CA.pl.1ssl -- CA.pl is not properly tagged as a command.
* Why aren't the command synopses in ab.1 and ac.1 parsed correctly?
Edge cases in which we could do better --
* sox(1), soxmix(1)
These are totally hosed.
* qurlinfo(3qt) and others:
operator declaration is seen as text, not structured.
Other things to do:
* Stereotyped .in/ta/ti pattern in emacs.1
......@@ -25,7 +30,7 @@ Other things to do:
Big projects:
* Translate EQN.
* Translate EQN to MathXML.
See the BUGS file for other, more minor problems mainly due to bad markup.
This diff is collapsed.
This diff is collapsed.
Name: doclifter
Version: 2.1
Version: 2.3
Release: 1
URL: http://www.catb.org/~esr/doclifter/
Source0: %{name}-%{version}.tar.gz
License: GPL
Group: Applications/System
Requires: python2
Summary: converts man/mdoc/ms/me/mm documents to DocBook
Summary: Converts man/mdoc/ms/me/mm documents to DocBook
BuildRoot: %{_tmppath}/%{name}-root
BuildArch: noarch
#Keywords: DocBook, man, ms, mm, me, mdoc, lifting, XML, SGML
%description
The doclifter program translates documents written in troff macros to DocBook.
Lifting documents from presentation level to semantic level is hard, and
a really good job requires human polishing. This tool aims to do everything
that can be mechanized, and to preserve in XML comments any troff-level
information that might have structural implications. Also includes manlifter,
a driver script that can be used to convert entire manual-page hierarchies.
The doclifter program translates documents written in troff macros to
DocBook. Lifting documents from presentation level to semantic level
is difficult, and a really good job requires human polishing, but this
tool does about 95% of the work. It aims to do everything that can be
mechanized, and to preserve in XML comments any troff-level
information that might have structural implications. Also includes
manlifter, a driver script that can be used to convert entire
manual-page hierarchies.
%prep
%setup -q
......@@ -44,6 +46,19 @@ cp doclifter.1 manlifter.1 "$RPM_BUILD_ROOT"%{_mandir}/man1/
%{_bindir}/manlifter
%changelog
* Mon Dec 25 2006 Eric S. Raymond <esr@snark.thyrsus.com> - 2.3-1
- Work around a bug in db2man.xsl. Implement Markus Hoenicka's
requested behavior for multiple-file conversions. Implement
translation of groff extended .cc and .c2 requests. Ignore
the .TA macro that occurs duplicatively with .ta in X.org
manual pages. Cope with unresolved .Sx refererences in mdoc.
Handle .Ex and .Ee. Cope with X consortium macro preamble better.
.RS/.RE is now fully handled, no more spurious warnings.
* Sat Jan 15 2005 Eric S. Raymond <esr@snark.thyrsus.com> - 2.2-1
- Have manlifter create subdirectories and the xslfragment
only in batch mode. Use current list indent on block start/end.
* Fri Jan 14 2005 Eric S. Raymond <esr@snark.thyrsus.com> - 2.1-1
- Interrupt handlers are refactored so manlifter can be aborted with
a single ^C; as a result, exit values 4 and 5 have swapped places.
......@@ -253,5 +268,5 @@ cp doclifter.1 manlifter.1 "$RPM_BUILD_ROOT"%{_mandir}/man1/
# The following sets edit modes for GNU EMACS
# Local Variables:
# mode:rpm-spec-mode
# mode:rpm-spec
# End:
This diff is collapsed.
......@@ -3,7 +3,7 @@
# Run doclifter against an entire manual tree.
# Sees all files in section 1 through 9 by default.
import sys, os, getopt, signal, time, re, commands, cStringIO, stat
import sys, os, getopt, signal, time, re, commands, cStringIO, stat, sets
mandir = "/usr/share/man"
patchdir = os.path.abspath("prepatch")
......@@ -11,6 +11,7 @@ outdir = None
patched = 0
makehtml = False
xslfragment = None
processed = sets.Set([])
def manfile(section, basename=""):
"Return a manual file or directory based on section name."
......@@ -123,12 +124,15 @@ def validate(translation):
return (6, output)
return (0, output)
def format(translation, fmt):
def format(translation, fmt, xslfragment):
"Format an XML file to a specified format."
output = ""
here = os.getcwd()
os.chdir(os.path.dirname(translation))
command = "xmlto -m %s %s %s" % (xslfragment, fmt, os.path.basename(translation))
if xslfragment:
command = "xmlto %s %s" % (fmt, os.path.basename(translation))
else:
command = "xmlto -m %s %s %s" % (xslfragment, fmt, os.path.basename(translation))
(bstat, format_out) = commands.getstatusoutput(command)
os.chdir(here)
if format_out:
......@@ -180,6 +184,7 @@ def singlerun(file, options, tmpstem="foo"+`os.getpid()`, batchmode=False):
if os.path.exists(patch):
patched += 1
try:
global processed
tmpstem = os.path.join(outdir, tmpstem)
source = tmpstem + ".man"
# Save work by doing conversions only as needed
......@@ -187,6 +192,7 @@ def singlerun(file, options, tmpstem="foo"+`os.getpid()`, batchmode=False):
if batchmode and os.path.exists(xmlloc):
if os.stat(file).st_mtime < os.lstat(xmlloc).st_mtime:
output += "XML conversion is up to date\n"
processed.discard(withsect)
rebuild_xml = False
htmlloc = os.path.join(subdir, stem + ".html")
if rebuild_xml:
......@@ -195,6 +201,8 @@ def singlerun(file, options, tmpstem="foo"+`os.getpid()`, batchmode=False):
(status, output) = fetch_page(file, localcopy, patch)
if (status):
return (status, output)
# Note the the patch was used
processed.discard(withsect)
# Add any annotations
output += analyze_manpage(localcopy)
# Move the source file into the output directory
......@@ -213,7 +221,7 @@ def singlerun(file, options, tmpstem="foo"+`os.getpid()`, batchmode=False):
# of putting this in its permanent location.
try:
# This will foo up if we ever have to symlink between dirs
if not os.path.exists(subdir):
if batchmode and not os.path.exists(subdir):
os.mkdir(subdir)
except OSError, e:
return(3, output + "Creation of %s failed, errno = %d\n"%(subdir,e.errno))
......@@ -250,7 +258,7 @@ def singlerun(file, options, tmpstem="foo"+`os.getpid()`, batchmode=False):
if batchmode and stat.S_ISLNK(os.lstat(xmlloc).st_mode):
makelink(os.readlink(xmlloc)[:-4]+".html", htmlloc)
else:
(status, more) = format(translation, "xhtml-nochunks")
(status, more) = format(translation, "xhtml-nochunks", xslfragment)
output += more
if status:
if batchmode:
......@@ -291,7 +299,7 @@ def massrun(files, options):
def report(sig, frame, out=sys.stderr):
ftotal = float(total)
elapsed = int(time.time()) - starttime
out.write("\n%%%d of %d files in %02d:%02d:%02d, %d OK, %d patched, %d doclifter errors, %d parser errors, %2.2f%% good.\n" % \
out.write("\n%%%d of %d files in %02d:%02d:%02d, %d OK, %d patched, %d doclifter errors, %d validation failures, %2.2f%% good.\n" % \
(total, eligible,
elapsed/3600, (elapsed % 3600)/60, elapsed % 60,
(total - doclifter_error_count - xmllint_error_count),
......@@ -316,15 +324,15 @@ def massrun(files, options):
(status, output) = test(file=file, options=options)
if status == -1:
break
elif status in (1, 5): # Doclifter parse or internal error
if output.find("is empty") == -1 and output.find("has no text") == -1:
doclifter_error_count = doclifter_error_count + 1
elif status in (1, 4): # Doclifter parse or internal error
if output.find("is empty") == -1 and output.find("has no text") == -1 and output.find("has no content") == -1:
doclifter_error_count += 1
elif status == 2: # .so inclusion
pass
elif status in (3, 4): # File I/O error or keyboard interrupt
elif status in (3, 5): # File I/O error or keyboard interrupt
pass
elif status == 6:
xmllint_error_count = xmllint_error_count + 1
xmllint_error_count += 1
total = total + 1
except KeyboardInterrupt:
pass
......@@ -440,7 +448,7 @@ def statistics():
def errorclean(error_only, pattern):
if pattern:
pattern = re.compile(filter)
pattern = re.compile(pattern)
pagename = re.compile(r"! (.*)=([0-9]+)")
while 1:
header = sys.stdin.readline()
......@@ -495,7 +503,7 @@ citereftemplate = '''
def doclifter_driver(options, arguments):
"Lift old markup to new."
global makehtml, outdir, xslfragment
global makehtml, outdir, xslfragment, patchdir
filelist = []
sections = []
callopts = ""
......@@ -532,14 +540,15 @@ def doclifter_driver(options, arguments):
else:
outdir = '.'
# Clean/create the output directory
if not os.path.exists(outdir):
os.mkdir(outdir)
if not arguments:
if not os.path.exists(outdir):
os.mkdir(outdir)
# Create XSL fragment for making refentries into links
xslfragment = os.path.abspath(os.path.join(outdir, "citerefentry.xsl"))
fp = open(xslfragment, "w")
fp.write(citereftemplate % outdir)
fp.close()
try:
# Create XSL fragment for making refentries into links
xslfragment = os.path.abspath(os.path.join(outdir, "citerefentry.xsl"))
fp = open(xslfragment, "w")
fp.write(citereftemplate % outdir)
fp.close()
# Process args, if present
if arguments:
for file in arguments:
......@@ -558,7 +567,13 @@ def doclifter_driver(options, arguments):
fp.close()
massrun(filelist, callopts)
else:
global processed
processed = sets.Set(map(lambda x: x.replace(".patch", "").replace(".correction", ""), os.listdir(patchdir)))
massrun(sectionfiles(sections), callopts)
if processed:
print "# Patches not used:"
for file in processed:
print file
finally:
pass
#os.remove(xslfragment)
......@@ -575,7 +590,7 @@ if __name__ == "__main__":
if os.path.exists(where):
break
else:
sys.stderr.write("manlifter: can't find doclifter!")
sys.stderr.write("manlifter: can't find doclifter!\n")
sys.exit(1)
# Import it, so we can modify it while the test is running without
# screwing up the results
......
This diff is collapsed.
......@@ -70,7 +70,7 @@ debugging that program.</para>
<para>In either of the above cases, <command>manlifter</command> will
uncompress the file if it has a <filename>.gz</filename>,
<filename>.bz2</filename> or <filename>.Z</filename>suffix on the
<filename>.bz2</filename> or <filename>.Z</filename> suffix on the
name.</para>
<para>Options are as follows:</para>
......@@ -112,7 +112,7 @@ this is <filename>/usr/share/man</filename>.</para></listitem>
<varlistentry>
<term>-o</term>
<listitem><para>Set the output directory into which
XML-DocBooktranslations will be dropped. By default this is
XML-DocBook translations will be dropped. By default this is
<filename>xmlman</filename> under the current directory in batch mode,
or the current directory otherwise.</para></listitem>
</varlistentry>
......@@ -154,7 +154,7 @@ developers.</para></listitem>
output. The file begins with a timestamp line and a blank line,
and ends with a line giving run time and various interesting
statistics. Between these are stanzas, separated by blank lines,
wone for each file on which <command>doclifter</command> was
one for each file on which <command>doclifter</command> was
run.</para>
<para>The first line of each stanza beguns with "! ", followed by the
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment