Codebase list doclifter / cab1eb0
Import Debian changes 2.3-1 doclifter (2.3-1) unstable; urgency=low * New upstream release (closes: #405632) * debian/copyright: fix FSF address * Bump Standards version Ross Burton authored 17 years ago Fabian Wolff committed 6 years ago
15 changed file(s) with 1507 addition(s) and 956 deletion(s). Raw diff Collapse all Expand all
+193
-170
BUGS less more
44 # Send 3 was on 11 Jul 2004
55 # Send 4 was on 20 Nov 2004
66 # Send 5 was on 14 Jan 2005
7 #
8 # * means there is no patch corresponding to this bug
79 #
810 A Dot or single-quote at start of line turns it into a garbage command.
911 This is a serious error; some lines of your page get silently lost
1921 D Section or macro out of place; this confuses translators.
2022 E My translator trips over a useless command in list markup.
2123 F List structure can be better expressed with .IP
22 G m4 macro syntax in manual page
2324 H Illegal metavariable in a synopsis description.
24 I mdoc name section is not marked up with .Nm and .Nd.
25 I .it macro use is impossible to translate structurally.
2526 J Ambiguous or invalid backslash. This doesn't cause groff a problem.
2627 but it confuses doclifter and may confuse older troff implementations.
2728 K You seem to be distributing a formatted manual page rather than source.
28 This may be a packaging error. I'm looking at what ships in Fedora
29 Core 3.
29 This may be a packaging error.
3030 L List syntax error. This means .IP, .TP or .RS/.RE markup is garbled.
3131 This confuses doclifter, and may also mess up stricter troff
3232 interpreters like groffer and TkMan.
3333 M Macro definition is in a location (such as the Synopsis section)
3434 that confuses translation tools.
35 N A replaceable part of a command synopsis consists of multiple
36 whitespace-separated words. This can't be translated.
37 O Location of a command is overspecified. You have given a name that
38 includes a standard absolute path. This is unnecessary, and likely
39 to be wrong on some of your target systems.
40 P Parentheses used for mandatory grouping are incorrect; use {} instead.
41 Yes, I know this isn't documented anywhere, but over 98% of the manual
42 pages I have examined are consistent with it.
43 Q Specifying the ampersand in the command synopsis of a daemon is
44 unnecessary.
35 O Running text in what should be a Unix command synopsis.
36 The right fix for this is to change the section name.
37 Q You used .UN where .UR is needed.
4538 R English usage errors, apparently the writer is not a native speaker.
4639 S DEPRECATED: in function syntax connot be translated. Also, the
4740 code and examples need to be marked up better.
4841 T There are multiple description lines. This makes it impossible to
4942 translate the page to DocBook. It may also confuse some
5043 implementations of man -k.
51 U Unbalanced group in command synopis, You probably forgot
52 to open or close a [ ] or { } group properly.
53 V Contents of SYNOPSIS is not a synopsis, and can't be parsed.
44 U Unbalanced group in command synopis. You probably forgot
45 to open or close a [ ] or { } group properly.
46 V .DS and .DE tags are swapped around.
5447 W Missing or garbled name section. The most common form of garbling
5548 is a missing - or extra -. Or your manual page may have been generated
5649 by a tool that doesn't emit a NAME section as it should. These
6255 incorrectly.
6356 Y Missing or garbled section header.
6457 Z Garbage character at beginning of file.
65 a Linker options in a function synopsis confuse my parser into thinking
66 it is looking at a command synopsis.
6758 b Manual page is blank
68 c Command synopsis in a non-Synopsis section. DocBook can't
69 handle this.
59 c SYNOPSIS must come before DESCRIPTION or other sections. Otherwise
60 correctness-checking library pages that may have multiple Synopsis
61 subheadings becomes too difficult.
7062 d This old-style C prototype is too hard to parse, best to fix it.
7163 e Garbage generated by docbook2man
7264 f Presentational use of .SH messes up section parsing.
73 g Spaces in string need to be quoted -- otherwise, some non-groff
74 formatters may become confused.
75 h Superfluous .SS markup screws up table translation.
76 i Random text in function synopsis confuses the doclifter parser.
65 g Run-on .B macro.
66 h Your 'man page' is HTML. This may be a packaging error.
67 i Macro invocation in conditional confuses the doclifter parser.
7768 j Parenthesized comments in command synopsis. This is impossible
7869 to translate to DocBook.
7970 k Translated to man+tbl because the content is, in fact, a table.
8071 l Page consists solely of NAME and SYNOPSIS.
81 m Conspicuous abuse of .SS headers. The list structure is better
82 expressed with .TP, .RS, and .RE.
72 m Garbage in the man page probably reflects a bug in the netpbm
73 makeman utility.
8374 n Unbalanced .RS or .RE macro
8475 o TBL markup not used where it should be.
8576 p It is unnecessary to explain basic shell redirects on a man page.
8778 unparseable SYNOPSIS section.
8879 q Formatting file lists as tables in a Synopsis is impossible to
8980 translate into DocBook.
90 r .RS/.RE pairs are interacting badly with .TP lists. troff
91 interpreters other than groff are likely to be confused.
9281 s Example URLs which should *not* be turned into hyperlinks need
9382 an invisible stopper so tools which try to lift URLs from the page
9483 source will pass over them.
9584 t Unclosed .RS, appears to be a broken attempt to express list structure.
96 u Bad syntax in C declaration. Doclifter relies on correct syntax
97 to recognize function syntax.
9885 v Doubled dot before macro command.
99 w Ill-formed .if macro.
100 x Presentational use of .SS within .RS/RE confuses translators looking
101 for structure.
86 x Unclosed .nf needs a .fi
10287 y Page is empty. This probably means there is some sort of glitch in
10388 your build machinery.
10489 z pod2man generates an unbalanced .RS tag. This is a bug.
105 2 Tab-hacking can't be translated cleanly to structure.
106 3 USAGE and SYNOPSIS sections were incorrect.
107 4 SYNOPSIS must come before DESCRIPTION or other sections. Otherwise
108 correctness-checking library pages that may have multiple Synopsis
109 subheadings becomes too difficult.
110 5 Date belongs in .TH header, not before Synopsis.
111 5 Invalid comment is actually an acute accent.
112 6 Marking up a code example as a list rather than a display screws
113 up semantic translation.
114 7 Garbage SH header.
115 8 Run-on .B macro.
116 9 Your 'man page' is HTML. This may be a packaging error.
90 0 This problem reflects a serious bug in db2man.
91 1 Improper line wrap in .ds text.
92 2 Description as well as name is required in a name section.
93 3 Garbled escape sequence
94 4 Unbalanced .RS/.RE.
95 5 Unescaped \d looks like a troff down-motion. This probably messes
96 up the rendering of the page in some environments, and certainly
97 confuses automated translation to XML.
98 6 Garbage non-ASCII character in man-page source.
99 7 Unbalanced highlights. This is not technically an error, but
100 it makes display programs and translators to other formats
101 much more likely to break.
102 8 Use of low-level troff hackery to set special indents can't
103 be translated.
104 9 Macro call is run on to the end of a line.
117105 %%
118 bn|ac.1 |t |
119106 bn|acl_from_text.3,acl_to_text.3 |X |
120107 bn|adjtimex.8 |X |jrv@voyager.mv.com
121 5n|addresses.1,read-expenses.1|cp |pilot-link-devel@pilot-link.org
122 r|aecho.1 |P |netatalk-devel@lists.sourceforge.net
108 5n|read-expenses.1 |O |pilot-link-devel@pilot-link.org
109 5n|addresses.1 |p |pilot-link-devel@pilot-link.org
110 y|aecho.1 | |netatalk-devel@lists.sourceforge.net
123111 5r|afmtodit.1 |M |bug-groff@gnu.org
124112 y|amidi.1,amixer.1,aplay.1,arecord.1 | |Clemens Ladisch <clemens@ladisch.de>
125 3n|amrecover.8 |g |Alan M. McIvor <alan@kauri.auck.irl.cri.nz>
126 2n|animate.1,compare.1,conjure.1,composite.1,convert.1,display.1,identify.1,import.1,mogrify.1,montage.1 |7 |magick-bugs@imagemagick.org
113 n|amrecover.8 |9 |Alan M. McIvor <alan@kauri.auck.irl.cri.nz>
114 y|animate.1,compare.1,conjure.1,composite.1,convert.1,display.1,identify.1,import.1,mogrify.1,montage.1 | |magick-bugs@imagemagick.org
127115 2n|AnyDBM_File.3pm |T |perl-documentation@perl.org
128116 2n|Apache::TestConfig.3pm |T |perl-documentation@perl.org
129 r|apple_cp.1,apple_mv.1,apple_rm.1|O |netatalk-devel@lists.sourceforge.net
117 n|amanda.8,amanda.conf.5,amrestore.8 |A0 |sgw@amanda.org
118 y|apple_cp.1,apple_mv.1,apple_rm.1| |netatalk-devel@lists.sourceforge.net
130119 5n|arp.8 |A |Bernd Eckenfels <net-tools@lina.inka.de>
120 n|ApplicationShell.3 |E |lesstif-discuss@lists.sourceforge.net
121 n|appres.1x |U |xorg@lists.freedesktop.org
122 n|aspell.1 |X |pyro@debian.org
123 n|atmsigd.conf.4 |A |Werner.Almesberger@epfl.ch
131124 3n|authconfig.8 |C |Nalin Dahyabhai <nalin@redhat.com>
132 3n|B::Stash.3pm,Carp::Heavy.3pm,Encode::CJKConstants.3pm,Encode::CN::HZ.3pm,Encode::Config.3pm,Encode::JP::H2Z.3pm,Encode::JP::JIS7.3pm,KR::2022_KR.3pm,Mail::SpamAssassin::Plugin::Hashcash.3pm,Mail::SpamAssassin::Plugin::SPF.3pm,Mail::SpamAssassin::PluginHandler.3pm,NetSNMP::netsnmp_request_infoPtr.3pm,SVN::Fs.3pm |y |perl-documentation@perl.org
125 3n*|B::Stash.3pm,Carp::Heavy.3pm,Encode::CJKConstants.3pm,Encode::CN::HZ.3pm,Encode::Config.3pm,Encode::JP::H2Z.3pm,Encode::JP::JIS7.3pm,KR::2022_KR.3pm,Mail::SpamAssassin::Plugin::Hashcash.3pm,Mail::SpamAssassin::Plugin::SPF.3pm,Mail::SpamAssassin::PluginHandler.3pm,SVN::Fs.3pm |y |perl-documentation@perl.org
133126 y|bash.1 | |bug-bash@gnu.org
134127 y|bgpd.8 | |bug-zebra@gnu.org
135 2n|bzadmin.6,bzfrelay.6,bzfls.6|X |bzflag-dev@lists.sourceforge.net
136 2n|bzfquery.6 |l |bzflag-dev@lists.sourceforge.net
128 n|bitmap.1x |U |xorg@lists.freedesktop.org
129 2n|bzadmin.6 |X |bzflag-dev@lists.sourceforge.net
130 2n*|bzfquery.6 |l |bzflag-dev@lists.sourceforge.net
137131 2n|bzfs.6 |UX |bzflag-dev@lists.sourceforge.net
138 2p|bzflag.6 |Xr |bzflag-dev@lists.sourceforge.net
139132 bn|bzip2.1,bzcat.1,bunzip2.1,bzip2recover.1 |T |
140 4p|cadaver.1 |R |Joe Orton <cadaver@webdav.org>
141 5n|cancel-cups.1,cancel.1,lp.1,lp-cups.1 |UT |papowell@lprng.com
133 4y|cadaver.1 | |Joe Orton <cadaver@webdav.org>
134 n|calcomp.4 |L |xorg@lists.freedesktop.org
135 y|cancel-cups.1,cancel.1,lp.1,lp-cups.1 | |
142136 5n|cannastat.1 |C |Canna@nec.co.jp
143137 5n|cap_get_proc.3 |T |agmorgan@users.sourceforge.net
144 5n|Carp.3pm |T |perl-documentation@perl.org
138 1n|Carp.3pm |T |perl-documentation@perl.org
139 n|ccmakedep.1x |X |cjwatson@debian.org
140 n|cman.5 |8 |
145141 y|CrtImgType.3,Tk_InitImageArgs.3 | |tcl-core@lists.sourceforge.net
146 5n|lpr.1,lpr-cups.1,lpstat.1,lpstat-cups.1|T |papowell@lprng.com
142 5n|lpr.1,lpr-cups.1 |U |papowell@lprng.com
143 y|lpstat.1,lpstat-cups.1| |papowell@lprng.com
147144 bn|cdda2wav.1 |A |
148 bn|cdp.1 |C |
149 3n|cdparanoia.1 |4 |monty@xiph.org
145 3n|cdparanoia.1 |c |monty@xiph.org
150146 5n|cdrdao.1 |E |cdrdao-devel@lists.sourceforge.net
151 bn|chat.8 |XJ |
147 bn|chat.8 |XJ |paulus@samba.org
148 n|chcat.8 |C |dwalsh@redhat.com
152149 bn|chkconfig.8 |X |ewt@redhat.com
153150 5n|chmoddic.1 |C |Canna@nec.co.jp
154151 5n|ci.1 |no |bug-rcs@gnu.org
155 2n|crash.8 |A |fenlason@redhat.com
152 n|citron.4 |34 |support@citron.de
153 y|crash.8 | |fenlason@redhat.com
156154 5n|cshost.1 |C |Canna@nec.co.jp
157155 2p|cscope.1 |B |broeker@users.sourceforge.net
158 1n|cytune.8 |P |faith@cs.unc.edu
159 2n|dasher.1 |8 |dasher@mrao.phy.cam.ac.uk
156 n|cxpm.1x |W |lehors@sophia.inria.fr
157 2n|dasher.1 |g |dasher@mrao.phy.cam.ac.uk
160158 y|dbz.3 | |inn-bugs@isc.org
161159 y|ddd.1 | |ddd@gnu.org
162160 5n|default.session.5 |W |miguel@gnu.org
163161 1n|dhcp6r.8 |f |bug@dhcpv6.org
164162 5n|dicar.1 |X |Canna@nec.co.jp
165 2n|dia.1 |9 |alla@lysator.liu.se
163 2n*|dia.1 |h |alla@lysator.liu.se
164 y|dictionary.5 |L |freeradius-devel@lists.freeradius.org
166165 2n|dictfmt.1 |A |faith@cs.unc.edu
167 bn|diffstat.1 |D |
166 y|diffstat.1 | |
168167 y|dislocate.1 | |Don Libes <libes@nist.gov>
169168 5n|dlpsh.1 |W |pilot-link-devel@pilot-link.org
170 2p|dmraid.8 |C |Heinz Mauelshagen <Mauelshagen@RedHat.com>
169 y|dmraid.8 | |Heinz Mauelshagen <Mauelshagen@RedHat.com>
171170 bn|dpromdic.1 |X |
172171 5n|dvdrecord.1 |v |dvdrtools-devel@nongnu.org
173 3p|dvipdfm.1 |A |mwicks@kettering.edu
172 y|dvipdfm.1 | |mwicks@kettering.edu
173 n|editres.1x |X |xorg@lists.freedesktop.org
174174 5n|epic.1 |X |Jeremy Nelson <jnelson@acronet.net>
175175 y|epoll_ctl.2 | |aeb@cwi.nl, davidel@xmailserver.org
176176 y|epoll.4 | |aeb@cwi.nl, davidel@xmailserver.org
177177 5n|eqn.1,geqn.1 |n |bug-groff@gnu.org
178 2p|eximstats.8 |X |clameter@debian.org,a.phillips@met.no
178 n|error.3 |7 |mtk-manpages@gmx.net
179 y|openais_overview.8,evs_overview.8,cpg_overview.8|W |scd@broked.com
179180 y|expect.1 | |Don Libes <libes@nist.gov>
180 5n|fam.3x |XC |fam@oss.sgi.com
181181 5p|fbset.8 |L |Geert.Uytterhoeven@cs.kuleuven.ac.be, zippel@fh-brandenburg.de
182 n|fence.8,gfs.8,gnbd.8 |W |linux-cluster@redhat.com
182183 4r|fig2dev.1x |X |bvsmith@lbl.gov
183 5n|File::Basename.3pm |T |perl-documentation@perl.org
184 2n|findchip.8,irdadump.8,irdaping.8,irpsion5.8 |e |wehe@tuxmobil.org
185 1n|flock.1 |X |adam@yggdrasil.com
186 5n|fmvj18x_cs.4 |Z |Shingo Fujimoto <shingo@flab.fujitsu.co.jp>
184 y|File::Basename.3pm | |perl-documentation@perl.org
185 2n|findchip.8,irdadump.8,irdaping.8,irpsion5.8,irattach.8|e |wehe@tuxmobil.org
186 y|flock.1 | |adam@yggdrasil.com
187 n|fmtutil.1,fmtutil-sys.1,mktexfmt.1,texconfig.1,texconfig-sys.1,updmap.1,updmap-sys.1|T |te@dbs.uni-hannover.de
187188 5n|foomatic-ppdfile.1 |X |till.kamppeter@gmx.net
188 5n|forw.1 |N |nmh-workers@nongnu.org
189 4p|fsinfo.8 |U |ezk@cs.columbia.edu
190 5n|ftpls.1 |Y |Uwe Ohse <uwe@ohse.de>
191 3n|gaim.1 |A |Rob Flynn <gaim@robflynn.com>
189 y|fsinfo.8 | |ezk@cs.columbia.edu
190 n|g3topbm.1 |C |bryanh@giraffe-data.com
191 y|gaim.1 | |Rob Flynn <gaim@robflynn.com>
192192 2n|gda-config.5 |T |gonzalo@gnome-db.org
193 1n|getcon.3,getexeccon.3|T |russell@coker.com.au
193 y|getcon.3,getexeccon.3 | |russell@coker.com.au
194194 y|GetUid.3 | |tcl-core@lists.sourceforge.net
195195 3n|getcontext.2 |C |mtk-manpages@gmx.net
196196 bn|getrpcport.3 |d |
197 5n|ghostscript.1 |CD |giles@snow.thaumas.net
198 bn|gij.1 |U |
199 2n|gkrellmd.1 |X |bill@gkrellm.net
200 5n|glutAttachMenu.3xglut,glutSetMenu.3xglut,glutSetWindow.3xglut,glutStrokeWidth.3xglut,glutWarpPointer.3xglut |T |mjk@nvidia.com
197 n|gfs_jadd.8 |X |linux-cluster@redhat.com
198 y|ghostscript.1 | |giles@snow.thaumas.net
199 n|giftopnm.1,pnmcolormap.1,libppm.3,pam.5|m |Bryan Henderson <bryanh@giraffe-data.com>
200 y|gij.1 | |
201 y|gkrellmd.1 | |bill@gkrellm.net
202 n|glBegin.3gl,glBitmap.3gl,glBlendFunc.3gl,glCopyPixels.3gl,glDepthFunc.3gl,glDrawBuffer.3gl,glDrawPixels.3gl,glEnableClientState.3gl,glGetString.3gl,glGetTexGen.3gl,glGetTexImage.3gl,glGetTexParameter.3gl,glLight.3gl,glMatrixMode.3gl,glOrtho.3gl,glPixelTransfer.3gl,glRect.3gl,glTexCoord.3gl,glTexEnv.3gl,glTexImage1D.3gl,glTexImage2D.3gl,glTexImage3D.3gl,glXChooseVisual.3gl,glXGetConfig.3gl|X |mesa3d-dev@lists.sourceforge.net
201203 5n|gnome-session.1 |Y |Miguel de Icaza <miguel@gnu.org>
202 5n|gnome-vfs-mime.5 |W |Miguel de Icaza <miguel@gnu.org>
203204 5n|gnome-wm.1 |W |Miguel de Icaza <miguel@gnu.org>
204 5n|gnuserv.1 |C |emacs-devel@gnu.org
205 5n|gob2.1 |A |George Lebl <jirka@5z.com>
205 y|gob2.1 | |George Lebl <jirka@5z.com>
206206 4r|gpic.1,pic.1 |L |bug-groff@gnu.org
207 4p|gpm-types.7 |W |rubini@gnu.org
207 4p|gpm-types.7 |W |Nico Schottelius <nico-gpm@schottelius.org>
208 p|groff.1 | |bug-groff@gnu.org
208209 5n|gsbj.1,gsdj.1,gsdj500.1,gslj.1,gslp.1|C |giles@artifex.com
209 2p|gxine.1 |W |xine-docs@lists.sourceforge.net
210 n|gulm_tool.8 |8 |
210211 5n|hformat.1,hfs.1,hfssh.1,hfsutils.1,hmount.1,xhfs.1 |X |Robert Leslie <rob@mars.org>
211 1n|hidd.1 |W |bluez-devel@lists.sourceforge.net
212 5n|hostname.1 |T |Bernd Eckenfels <net-tools@lina.inka.de>
212 y|hidd.1 | |bluez-devel@lists.sourceforge.net
213 5n|hostname.1 |TA |Bernd Eckenfels <net-tools@lina.inka.de>
213214 2n|htfuzzy.1 |A |htdig-dev@htdig.org
214215 5n|ibod.1 |X |Bjoern Smith <Smith@Compound.SE>
215 5n|identd.8,in.identd.8 |C |Peter Eriksson <pen@lysator.liu.se>
216 n|icc2ps.1,icclink.1,jpegicc.1,tifficc.1 |XRL |shiju.p@gmail.com
216217 y|idna_strerror.3,idna_to_ascii_4i.3,idna_to_ascii_4z.3,idna_to_ascii_8z.3,idna_to_ascii_lz.3,idna_to_unicode_44i.3,idna_to_unicode_4z4z.3,idna_to_unicode_8z4z.3,idna_to_unicode_8z8z.3,idna_to_unicode_8zlz.3,idna_to_unicode_lzlz.3,pr29_4.3,pr29_4z.3,pr29_8z.3,pr29_strerror.3,punycode_decode.3,punycode_strerror.3,stringprep.3,stringprep_4i.3,stringprep_4zi.3,stringprep_check_version.3,stringprep_convert.3,stringprep_locale_charset.3,stringprep_locale_to_utf8.3,stringprep_profile.3,stringprep_strerror.3,stringprep_ucs4_nfkc_normalize.3,stringprep_ucs4_to_utf8.3,stringprep_unichar_to_utf8.3,stringprep_utf8_nfkc_normalize.3,stringprep_utf8_to_locale.3,stringprep_utf8_to_ucs4.3,stringprep_utf8_to_unichar.3,tld_check_4.3,tld_check_4t.3,tld_check_4tz.3,tld_check_4z.3,tld_check_8z.3,tld_check_lz.3,tld_default_table.3,tld_get_4.3,tld_get_4z.3,tld_get_table.3,tld_get_z.3,tld_strerror.3 | |bug-libidn@gnu.org
217218 y|punycode_encode.3 | |bug-libidn@gnu.org
218 5n|imclient.3 |w |cyrus-devel@lists.andrew.cmu.edu
219 1n|inews.1 |W |inn-bugs@isc.org
220 r|infotopam.1,ppmtompeg.1 | |
221 5p|install.1 |j |bug-coreutils@gnu.org
219 y|ImageMagick.1 | |magick-bugs-owner@imagemagick.org
220 y|inews.1 | |inn-bugs@isc.org
221 y|install.1 | |bug-coreutils@gnu.org
222222 2n|ipsec_mailkey.8 |H |hugh@mimosa.com
223223 2n|ipsec_newhostkey.8,ipsec_rsasigkey.8 |C |hugh@mimosa.com
224224 2n|ipsec_pluto.8,ipsec_whack.8,ipsec_addrbytesof.3,ipsec_addrtypeof.3,ipsec_addrcmp.3,ipsec_addrbytesptr.3,ipsec_addrinsubnet.3,ipsec_addrlenof.3,ipsec_addrtoa.3,ipsec_addrtosubnet.3,ipsec_addrtot.3,ipsec_anyaddr.3,ipsec_atoaddr.3,ipsec_atoasr.3,ipsec_atosubnet.3,ipsec_bitstomask.3,ipsec_broadcastof.3,ipsec_copyright_notice.3,ipsec_goodmask.3,ipsec_hostof.3,ipsec_initaddr.3,ipsec_initsaid.3,ipsec_initsubnet.3,ipsec_anyaddr.3,ipsec_isanyaddr.3,ipsec_isloopbackaddr.3,ipsec_isunspecaddr.3,ipsec_loopbackaddr.3,ipsec_maskof.3,ipsec_masktobits.3,ipsec_masktocount.3,ipsec_networkof.3,ipsec_portof.3,ipsec_prng.3,ipsec_rangetoa.3,ipsec_sameaddr.3,ipsec_sameaddrtype.3,ipsec_samesaid.3,ipsec_samesubnet.3,ipsec_samesubnettype.3,ipsec_satot.3,ipsec_setportof.3,ipsec_sockaddrlenof.3,ipsec_sockaddrof.3,ipsec_subnetinsubnet.3,ipsec_subnetishost.3,ipsec_subnetof.3,ipsec_subnettoa.3,ipsec_subnettot.3,ipsec_subnettypeof.3,ipsec_tnatoaddr.3,ipsec_ttoaddr.3,ipsec_ttosa.3,ipsec_unspecaddr.3,ipsec_version.3,ipsec_version_code.3,ipsec_version_string.3,ipsec_ttosubnet.3|T |hugh@mimosa.com
225225 5n|iptraf.8 |X |riker@seul.org
226 3n|iptables.8 |tx |Herve Eychenne <rv@wallfire.org>
227226 5n|irb.1 |W |ruby-doc@ruby-lang.org
228227 y|isadump.8,isaset.8 | |phil@philedelbrock.com
229 5n|keytool.1 |A |Dag Wieers <dag@wieers.com>
228 n|kdesvn-build.1 |s |carlos.woelz@kdemail.net
230229 5n|klogd.8 |X |greg@wind.enjellic.com
231 5n|kwordtrans.1,wordtrans.1 |K |rvm@escomposlinux.org
232 bn|lamboot.1 |X |
230 n|ksh.1 |i |dgk@research.att.com
231 5n*|kwordtrans.1,wordtrans.1 |K |rvm@escomposlinux.org
232 bn|lamboot.1,lamexec.1 |X |
233233 bn|lame.1 |X |
234 5n|latex.1 |h |te@dbs.uni-hannover.de
235 bn|LDP.7 |CL |
234 y|latex.1 | |te@dbs.uni-hannover.de
235 n|latex2html.1 |Q |Manoj Srivastava <srivasta@debian.org>
236 y|LDP.7 | |
236237 5n|less.1 |C |bug-less@gnu.org
238 n|lesstif.1 |WO |lesstif-discuss@lists.sourceforge.net
239 n|libbind-getipnodebyname.3|T |bind9-bugs@isc.org
237240 3n|libpng.3 |S |png-implement@ccrc.wustl.edu
238241 y|libpngpf.3 | |png-implement@ccrc.wustl.edu
239 y|libexpect.3 | |Don Libes <libes@nist.gov>
242 n|libexpect.3 | |Don Libes <libes@nist.gov>
243 n|libmng.3 |7 |gerard@libmng.com
240244 5n|linuxdoc.1 |j |Taketoshi Sano <sano@debian.org>
241 bn|logrotate.8 |X |
242 bn|longrun.1 |W |
243 5n|lpd.8 |X |Patrick Powell <papowell@lprng.com>
245 n|ln.1 |j |bug-coreutils@gnu.org
246 n|lock_gulmd.5,lock_gulmd.8|8 |dwalsh@redhat.com
247 y|logrotate.8 | |
244248 5n|lv.1 |C |nrt@ff.iij4u.or.jp
245249 y|lvreduce.8 | |Heinz Mauelshagen <Linux-LVM@Sistina.com>
246 5n|mag.1 |X |te@dbs.uni-hannover.de
247 r|magicfilter.8 |G |
248 2n|Mail::SpamAssassin::Plugin.3pm |L |perl-documentation@perl.org
249 5n|mail500.8,fax500.8 |T |OpenLDAP-devel@OpenLDAP.org
250 y|mag.1 | |te@dbs.uni-hannover.de
251 n|magma_tool.8 |8 |
252 2n*|Mail::SpamAssassin::Plugin.3pm |L |perl-documentation@perl.org
253 n|makestrs.1x |A |xorg@lists.freedesktop.org
250254 y|man.1,manpath.1 | |mtk-manpages@gmx.net
255 bn|mcs.8 |X |
251256 bn|mdadm.conf.5 |X |
252257 bn|mdadm.8 |X |
253258 5n|mdel.1 |T |mtools@tux.org
254 5n|mh-mts.8 |C |nmh-workers@nongnu.org
259 y|mf.1,inimf.1,virmf.1 | |te@dbs.uni-hannover.de
255260 y|mkoctfile.1 | |jwe@bevo.che.wisc.edu>, edd@debian.org
261 n|mkxauth.1x |C |
256262 y|mkzftree.1 | |hpa@zytor.com
257263 1n|ModPerl::Code.3pm |D |perl-documentation@perl.org
258 y|motd.news.5 |T |inn-bugs@isc.org
259 5n|mozplugger.7 |T |louis@bavoil.net
264 y|motd.news.5 | |inn-bugs@isc.org
265 y|mozplugger.7 | |louis@bavoil.net
260266 y|mpage.1 | |Marcel Mol <marcel@mesa.nl>
267 n|mpcd.8 | |Heikki Vatiainen <hessu@cs.tut.fi>, Sampo Saaristo <s156953@cs.tut.fi>
261268 5n|MPI_Group_free.3 |C |lam-devel@lam.mpi.org
262269 2n|mpiexec.1 |X |lam-devel@lam.mpi.org
263 3n|mplayer.1,mencoder.1|T |
264 3n|mysqladmin.1,mysqld.1|AC |monty@tcx.se
270 y|mysqld.1,mysqld_multi.1,mysqldump.1,mysql_zap.1,mysqladmin.1,mysqlshow.1| |monty@tcx.se
271 n|mysqlmanager.1 |I |monty@tcx.se
272 n|mysqld_safe.1 |T |monty@tcx.se
265273 y|named.conf.5 | |bind9-bugs@isc.org
266 5n|nasm.1,ndisasm.1 |W |nasm-devel@lists.sourceforge.net
274 y|nasm.1,ndisasm.1 | |nasm-devel@lists.sourceforge.net
267275 y|nbp_name.3 | |netatalk-devel@lists.sourceforge.net
268 3n|netsnmp_deprecated.3 |D |net-snmp-coders@lists.sourceforge.net
269276 2n|netsnmp_iterator_info_s.3|s |net-snmp-coders@lists.sourceforge.net
270277 2n|netsnmp_table.3 |X |net-snmp-coders@lists.sourceforge.net
271 3n|netsnmp_todo.3 |y |net-snmp-coders@lists.sourceforge.net
278 3n*|netsnmp_todo.3 |y |net-snmp-coders@lists.sourceforge.net
272279 5n|netdump.8 |L |anderson@redhat.com
273280 2n|netdump-server.8 |C |anderson@redhat.com
274 5n|netstat.8 |m |Bernd Eckenfels <net-tools@lina.inka.de>
275 5n|nfsd.7 |X |neilb@cse.unsw.edu.au
276 4p|nnrp.access.5 |X |inn-bugs@isc.org
281 n|netpbm.1 |m |Bryan Henderson <bryanh@giraffe-data.com>
282 y|netstat.8 | |Bernd Eckenfels <net-tools@lina.inka.de>
283 y|newgrp.1 | |Julianne Frances Haugh <jockgrrl@ix.netcom.com>
284 y|nfsd.7 | |neilb@cse.unsw.edu.au
285 n|nisplus_table.5 |C |wietse@porcupine.org
286 n|NetworkManager.1,NetworkManagerDispatcher.1,nm-tool.1 |W |networkmanager-list@gnome.org
287 n|nfs4_uid_to_name.3 |W |nfsv4@linux-nfs.org
288 n|nmap.1 |As |nmap-hackers@insecure.org
289 n|ntlm_auth.1 |RX |samba-docs@lists.samba.org
277290 5r|ntpdate.1 |C |mills@udel.edu
278 2n|numa.3,numa_all_nodes.3,numa_alloc.3,numa_alloc_interleaved.3,numa_alloc_interleaved_subset.3,numa_alloc_local.3,numa_alloc_onnode.3,numa_available.3,numa_bind.3,numa_error.3,numa_exit_on_error.3,numa_free.3,numa_get_interleave_mask.3,numa_get_interleave_node.3,numa_get_run_node_mask.3,numa_interleave_memory.3,numa_max_node.3,numa_no_nodes.3,numa_node_size.3,numa_node_to_cpus.3,numa_police_memory.3,numa_run_on_node.3,numa_run_on_node_mask.3,numa_set_bind_policy.3,numa_set_interleave_mask.3,numa_set_localalloc.3,numa_get_membind.3,numa_set_membind.3,numa_preferred.3,numa_set_preferred.3,numa_set_strict.3,numa_setlocal_memory.3,numa_tonode_memory.3,numa_tonodemask_memory.3 |u |ak@suse.de
279291 y|octave-config.1 | |jwe@bevo.che.wisc.edu, edd@debian.org
292 n|on_ac_power.1,pm-pmu.1|e |Richard Hughes <richard@hughsie.com>
280293 2r|operator.7 |k |mtk-manpages@gmx.net
281 y|pamfunc.1,pamscale.1,pamslice.1,pamstereogram.1,pbmclean.1 | |Bryan Henderson <bryanh@giraffe-data.com>
282 4r|pbm2ppa.1 |C |Bryan Henderson <bryanh@giraffe-data.com>
283 5n|pclbanner.1 |T |Patrick Powell <papowell@lprng.com>
284 5n|pcrepattern.3,pcrecallout.3|J |perl-documentation@perl.org
285 3n|PDL::BAD2_demo.3pm,PDL::BAD_demo.3pm,PDL::Config.3pm,PDL::Doc::Config|y |perl-documentation@perl.org
294 n|pambayer.1 |U |Bryan Henderson <bryanh@giraffe-data.com>
295 n|pamperspective.1 |mU |Bryan Henderson <bryanh@giraffe-data.com>
296 n|pamstereogram.1 |m |Bryan Henderson <bryanh@giraffe-data.com>
297 n|pamtilt.1 |U |Bryan Henderson <bryanh@giraffe-data.com>
298 y|pamfunc.1,pamscale.1,pamslice.1,pbmclean.1 | |Bryan Henderson <bryanh@giraffe-data.com>
299 n|pammasksharpen.1 |U |Bryan Henderson <bryanh@giraffe-data.com>
300 y|parted.8 | |bug-parted@gnu.org
301 n|pbmtoppa.1,pbm2ppa.1 |m |Bryan Henderson <bryanh@giraffe-data.com>
302 n|pcrepattern.3,pcrecallout.3,pcretest.1,pcrepartial.3,pcreprecompile.3|XJ4 |ph10@cam.ac.uk
303 3n*|PDL::BAD2_demo.3pm,PDL::BAD_demo.3pm,PDL::Config.3pm,PDL::Doc::Config|y |perl-documentation@perl.org
286304 2n|PDL::GSL::INTEG.3pm |D |pdl-porters@jach.hawaii.edu
287305 3n|PDL::MatrixOps.3pm |W |pdl-porters@jach.hawaii.edu
288 3n|pdl.1 |W |pdl-porters@jach.hawaii.edu
289 1n|perl-nocem.8 |V |inn-bugs@isc.org
290 y|pgmabel.1,pgmtopgm.1,pnmstitch.1,pgmmorphconv.1 | |Bryan Henderson <bryanh@giraffe-data.com>
306 y|pdl.1 | |pdl-porters@jach.hawaii.edu
307 1p|perl-nocem.8 |O |inn-bugs@isc.org
308 y|pgmabel.1,pgmtopgm.1,pnmstitch.1,pgmmorphconv.1,pnmtoddif.1,ppmtopj.1 | |Bryan Henderson <bryanh@giraffe-data.com>
309 y|php.1 |W |phpdoc@lists.php.net
291310 5n|pilot-addresses.1 |j |Robert Wittig <bob.wittig@gt.org>
292 5n|pilot-foto.1 |C |pilot-link-devel@pilot-link.org
311 5n|pilot-foto.1 |U |pilot-link-devel@pilot-link.org
293312 4n|pilot-xfer.1 |j |pilot-link-devel@pilot-link.org
294 2n|pipethrough.3 |Ii |mc-devel@gnome.org
313 2y|pipethrough.3 | |mc-devel@gnome.org
314 n|pkg-config.1 |X |
295315 y|play.1 | |
296 5n|plugger.7 |T |Fredrik Hübinette <hubbe@hubbe.net>
297 bn|pmake.1 |6 |
298 y|pnmtoddif.1,ppmtopj.1 | |Bryan Henderson <bryanh@giraffe-data.com>
299 2y|postconf.5 |A |wietse@porcupine.org
300 2n|ps.1 |D |acahalan@cs.uml.edu
316 y|postconf.5 | |wietse@porcupine.org
317 n|powermust.8 |W |Carlos Rodrigues <carlos.efr@mail.telepac.pt>
318 y|ps.1 |D |acahalan@cs.uml.edu
301319 4p|privoxy.1 |j |developers@privoxy.org
302320 5n|ps2epsi.1 |j |giles@artifex.com
303321 5n|ps2pdf.1,ps2pdf12.1,ps2pdf13.1| |giles@artifex.com
304 5n|psbanner.1 |T |Patrick Powell <papowell@lprng.com>
305322 5n|ptx.1 |j |bug-gnu-utils@gnu.org
306 4p|pvmd.1,pvm_shmd.1,pvmd3.1 |CQ |gst@ornl.gov
323 y|pvmd.1,pvm_shmd.1,pvmd3.1 | |gst@ornl.gov
307324 4p|pvm_addmhf.3 |T |gst@ornl.gov
308325 2n|pvm_newcontext.3 |T |gst@ornl.gov
309326 y|quantize.5 | |magick-bugs@imagemagick.org
310 5n|ray_cs.4 |W |Corey Thomas <corey@world.std.com>
311 3n|rcsfile.5 |1 |rcs-bugs@cs.purdue.edu
312 3n|replace.1,isamchk.1,isamlog.1,mysql_zap.1,mysqldump.1,mysqld_multi.1,mysqlshow.1 |23C |monty@tcx.se
327 n|racoon.conf.5 |A |bugs@lists.freeswan.org
328 n|raw2tiff.1,tiffcmp.1,TIFFClose.3tiff |X |tiff@lists.maptools.org
329 3n|rcsfile.5 |X |rcs-bugs@cs.purdue.edu
330 y|replace.1,isamchk.1,isamlog.1| |monty@tcx.se
331 n|rexec.3 |X |
313332 y|rdump.8,dump.8,restore.8,rrestore.8 | |Stelian Pop <stelian@popies.net>
314333 2n|rlm_expr.5 |X |Chris Parker <cparker@segv.org>
315334 2n|rlm_attr_filter.5 |XF |Chris Parker <cparker@segv.org>
316335 4p|roff.7 |A |wl@gnu.org
317336 4p|groff_diff.7 |A |wl@gnu.org
318 2n|sane-artec.5,sane-agfafocus.5|X |sane-devel@lists.alioth.debian.org
319 y|sane-coolscan2.5 | |sane-devel@lists.alioth.debian.org
320 4p|sane-gphoto2.5 |X |sane-devel@lists.alioth.debian.org
321 y|sane-microtek2.5 | |sane-devel@lists.alioth.debian.org
322 2n|saslpasswd.8,sasldblistusers.8|5 |cyrus-bugs+@andrew.cmu.edu
337 y|sane-artec.5,sane-agfafocus.5,sane-coolscan2.5,sane-gphoto2.5,sane-microtek2.5| |sane-devel@lists.alioth.debian.org
323338 3n|sftp.1 |C |Damien Miller <djm@mindrot.org>
324339 y|sane-plustek.5 | |Gerhard Jaeger <gerhard@gjaeger.de>
325 1n|security_load_booleans.3,selinux_binary_policy_path.3|T |dwalsh@redhat.com
340 y|security_load_booleans.3,selinux_binary_policy_path.3| |dwalsh@redhat.com
326341 y|send-uucp.8 | |inn-bugs@isc.org
327 5n|setfdprm.8 |A |fdutils@tux.org
328 2n|set_mempolicy.2 |W |ak@suse.de
342 n|sg_senddiag.8 |C |dgilbert@interlog.com
329343 5n|sgml2lyx.1 |Z |Taketoshi Sano <sano@debian.org>
330344 4p|sgmlpre.1 |E |Taketoshi Sano <sano@debian.org>
331 4p|siggen.8 |C |tripwire-devel@genesis-x.nildram.co.uk
332 3p|sk98lin.4 |A |linux@syskonnect.de
345 y|sk98lin.4 | |linux@syskonnect.de
346 n|slapo-ppolicy.5 |X |OpenLDAP-devel@OpenLDAP.org
333347 2n|slapd.8 |C |OpenLDAP-devel@OpenLDAP.org
334348 y|smartd.8,smartctl.8,smartd.conf.5| |smartmontools-support@lists.sourceforge.net
335349 y|snmpvacm.1 | |net-snmp-coders@lists.sourceforge.net
336350 y|snmpd.conf.5 | |net-snmp-coders@lists.sourceforge.net
337 1n|snmp.conf.5 |A |net-snmp-coders@lists.sourceforge.net
338 1r|spax.1 |UC |schilling@fokus.fraunhofer.de
339 bn|squid.1 |b |
351 y|snmp.conf.5 | |net-snmp-coders@lists.sourceforge.net
352 1n|spax.1 |6 |schilling@fokus.fraunhofer.de
353 bn*|squid.1 |b |
340354 y|squid_ldap_auth.8,squid_ldap_group.8 | |squid-bugs@squid-cache.org
341355 y|ssh-keyscan.1 | |brad@openbsd.org
342356 2n|sshd_config.5,ssh_config.5 |q |brad@openbsd.org
344358 3n|tvtime.xml.5 |X |vektor@dumbterm.net
345359 5n|sysklogd.8 |X |greg@wind.enjellic.com
346360 5n|sz.1 |X |Uwe Ohse <uwe@ohse.de>
347 bn|t1mapper.1 |X |
348 5n|tar.1 |C |bug-gnu-utils@gnu.org
349 5n|Tclx_Init.3,TclX_Main.3,Tclxcmd_Init.3 |C |tcl-core@lists.sourceforge.net
361 5r*|tar.1 |C |bug-gnu-utils@gnu.org
362 n|tidy.1 |X |html-tidy@w3.org
350363 2n|tc-pbfifo.8 |T |ahu@ds9a.nl, uznet@ms2.inr.ac.ru
351 3p|texdoctk.1 |X |bunk@fs.tum.de, ruedas@geophysik.uni-frankfurt.de
364 n|terminfo.5 |x |
365 y|texdoctk.1 | |bunk@fs.tum.de, ruedas@geophysik.uni-frankfurt.de
352366 y|timidity.cfg.5 | |breeze.nagano@nifty.ne.jp, mo@goice.co.jp
353367 y|Tk_Uid.3 | |tcl-core@lists.sourceforge.net
354 3n|Tkx_Init.3,TkX_Main.3|a |tcl-core@lists.sourceforge.net
355 4p|transfig.1x |XU |bvsmith@lbl.gov
368 4n|transfig.1x |XU |bvsmith@lbl.gov
356369 y|tree.1 | |Steve Baker <ice@mama.indstate.edu>
357370 5n|tsclient.1 |W |Miguel de Icaza <miguel@gnu.org>
358371 bn|ttcp.1 |XD |
359372 5n|tune2fs.8 |C |tytso@thunk.org
360373 y|udevd.8,udevsend.8 | |Kay Sievers <kay.sievers@vrfy.org>
361 5p|uuencode.1 |T |bug-gnu-utils@gnu.org
362 bn|updfstab.8 |X |
374 y|uuencode.1 | |bug-gnu-utils@gnu.org
363375 3n|vacuumdb.1 |C |pgsql-docs@postgresql.org
364376 5n|vgsplit.8 |C |lvm-devel@lists.sistina.com
365377 5n|vorbiscomment.1 |C |Christopher L Cheney <ccheney@debian.org>
366378 y|vsftpd.conf.5 | |chris@scary.beasts.org
367379 4r|wget.1 |s |mtortonesi@ing.unife.it
368 5n|wmix.1x |X |timecop@japan.co.jp
369380 bn|wvdial.1 |X |wvdial@nit.ca
381 n|XAllocWMHints.3x |1 |xorg@lists.freedesktop.org
382 n|XvSelectVideoNotify.3x|A |xorg@lists.freedesktop.org
383 n|XmArrowButton.3,XmScrollBar.3,XmArrowButtonGadget.3,XmBulletinBoard.3,XmCascadeButton.3,XmCascadeButtonGadget.3,XmClipboard.3,XmComboBox.3,XmCommand.3,XmDesktop.3,XmDialogShell.3,XmDialogShellExt.3,XmDisplay.3,XmDragContext.3,XmDragIcon.3,XmDragOverShell.3,XmDrawingArea.3,XmDrawnButton.3,XmDropSiteManager.3,XmDropTransfer.3,XmFileSelectionBox.3,XmForm.3,XmFrame.3,XmGadget.3,XmGrabShell.3,XmIconGadget.3,XmSelectionBox.3,XmSeparator.3,XmSeparatorGadget.3,XmSpinBox.3,XmString.3,XmTearOffButton.3,XmText.3,XmTextField.3,XmToggleButton.3,XmToggleButtonGadget.3,XmVendorShell.3,XmWorld.3,XmFrame.3,XmLabel.3,XmLabelGadget.3,XmList.3,XmMainWindow.3,XmManager.3,XmMenuShell.3,XmMessageBox.3,XmPanedWindow.3,XmPrimitive.3,XmProtocol.3,XmPushButton.3,XmPushButtonGadget.3,XmRowColumn.3,XmSash.3,XmScale.3,XmScreen.3,XmScrolledWindow.3,Object.3,Rect.3,OverrideShell.3,LessTifInternals.3,Composite.3,Constraint.3,Core.3,TopLevelShell.3,TransientShell.3,UnNamedObj.3,VendorShell.3,WmShell.3,VirtualBindings.5,Shell.3|2 |lesstif-discuss@lists.sourceforge.net
384 y|XGrabDeviceKey.3x,XIfEvent.3x |X |xorg@lists.freedesktop.org
385 y|XListInputDevices.3x |V |xorg@lists.freedesktop.org
370386 3n|XML::DOM::Element.3pm|z |perl-documentation@perl.org
371387 5n|XML::Encoding.3pm |n |perl-documentation@perl.org,coopercc@netheaven.com
372388 3n|XML::Parser::Style::Objects.3pm|W |perl-documentation@perl.org,coopercc@netheaven.com
373389 3n|XML::Parser::Style::Tree.3pm|W |perl-documentation@perl.org,coopercc@netheaven.com
374390 3n|XML::Parser::Style::Subs.3pm|W |perl-documentation@perl.org,coopercc@netheaven.com
375 4p|x3270if.1,x3270-script.1|PC |Paul.Mattes@usa.net
376 4p|xfs_bmap.8,xfs_check.8|X |linux-xfs@oss.sgi.com
391 n|xdpr.1x |X5 |xorg@lists.freedesktop.org
392 y|xfs_bmap.8,xfs_check.8| |linux-xfs@oss.sgi.com
377393 5n|xinetd.conf.5 |L |bbraun@synack.net
378 5n|xml_pp.1 |W |Michel Rodriguez <mirod@xmltwig.com>
379 5n|xml_spellcheck.1 |y |Michel Rodriguez <mirod@xmltwig.com>
380 3n|xsltproc.1 |C |xslt@gnome.org
394 n|xlsfonts.1x |8 |xorg@lists.freedesktop.org
395 n|xminicom.1 |W |miquels@cistron.nl
396 y|xml_pp.1 | |Michel Rodriguez <mirod@xmltwig.com>
397 y|xml_spellcheck.1 | |Michel Rodriguez <mirod@xmltwig.com>
398 n|xmlto.1 |A |tim@cyberelk.net
399 n|xrdb.1x,xtrap.1x,XQueryExtension.3x |X |xorg@lists.freedesktop.org
400 n|xscreensaver-text.1 |X |jwz@jwz.org
401 n|xset.1x |C |xorg@lists.freedesktop.org
402 y|xsltproc.1 | |xslt@gnome.org
403 n|zone2ldap.1 |W |jeff@snapcase.g-rock.net
381404 bn|zshcompctl.1 |L |
382405 bn|zshmodules.1 |nt |
1212
1313 Test loads are included in the distribution. The code has been tested
1414 in about the most brutal possible way; it has been run against every
15 single man page in all sections of a full Fedore Core installation.
15 single man page in all sections of a full Fedora Core installation.
1616 It lifts over 95% of these pages without requiring any hand-hacking.
1717
1818 There is a detailed change log in the RPM spec file.
1919
20 doclifter was written under Python 2.2a1. It will not work under Python 1.5.2,
21 and may not work under 2.1. Upgrade, it will be good for you.
22
2320 Eric S. Raymond
2421 November 2003
00 Bugs:
1
2 * I haven't come up with a reliable way to distinguish command synopses
3 from stuff that should be treated as plain text. This has a couple
4 of consequences:
5
6 1. doclifter doesn't recognize command synopses in displays, only in
7 Synopsis sections.
8
9 2. When command synopses have a trailing text section (explanatory
10 paragraph) doclifter doesn't always detect that and cope well.
111
212 * .Xo/.Xc Berkeley macro needs work. See elf.5.
313
616
717 * CA.pl.1ssl -- CA.pl is not properly tagged as a command.
818
9 * Why aren't the command synopses in ab.1 and ac.1 parsed correctly?
10
1119 Edge cases in which we could do better --
1220
1321 * sox(1), soxmix(1)
1422 These are totally hosed.
15
16 * qurlinfo(3qt) and others:
17 operator declaration is seen as text, not structured.
1823
1924 Other things to do:
2025
2429
2530 Big projects:
2631
27 * Translate EQN.
32 * Translate EQN to MathXML.
2833
2934 See the BUGS file for other, more minor problems mainly due to bad markup.
3035
0 doclifter (2.3-1) unstable; urgency=low
1
2 * New upstream release (closes: #405632)
3 * debian/copyright: fix FSF address
4 * Bump Standards version
5
6 -- Ross Burton <ross@debian.org> Thu, 11 Jan 2007 14:34:47 +0000
7
08 doclifter (2.1-1) unstable; urgency=low
19
210 * New upstream release
11 Section: devel
22 Priority: optional
33 Maintainer: Ross Burton <ross@debian.org>
4 Build-Depends-Indep: debhelper (>= 4.0.0)
5 Standards-Version: 3.6.1
4 Build-Depends: debhelper (>= 4.0.0)
5 Standards-Version: 3.7.2
66
77 Package: doclifter
88 Architecture: all
1717 GNU General Public License for more details.
1818
1919 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 along with this package; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 02110-1301, USA.
2223
2324 On Debian GNU/Linux systems, the complete text of the GNU General
2425 Public License can be found in `/usr/share/common-licenses/GPL'.
00 doclifter usr/bin
1 manlifter usr/bin
3030 dh_testroot
3131 dh_installdocs
3232 dh_installexamples
33 dh_installman doclifter.1
33 dh_installman doclifter.1 manlifter.1
3434 dh_installchangelogs
3535 dh_link
3636 dh_compress
11 """
22 doclifter: translate man/mdoc/ms/me/mm sources to DocBook.
33
4 by Eric S. Raymond, copyright 2002.
4 By Eric S. Raymond, copyright 2002, 2006.
5 Released as open source the Gnu General Public License.
56
67 This comment is addressed to you if you want to add support for another
78 macro package to doclifter. Or if you have encountered a bug in doclifter
8687 interpret
8788 The request interpreter. Called on every input line that begins
8889 with a command character, that is . or ' not followed by another ' on the
89 samw line.
90 same line.
9091 This method needs to be careful about troff continuation (\c)
9192 characters. If you add trailing markup to a line, or entirely replace the
9293 line, be sure to check for trailing \c first, remove it if present, and
121122 Warning: much of this code is grubby. Alas, the grubbiness is
122123 intrinsic, because the troff request language is grubby.
123124
124 $Id: doclifter,v 1.1294 2005/01/14 06:35:12 esr Exp $
125 $Id: doclifter,v 1.1336 2006/12/22 14:41:03 esr Exp $
125126 """
126127 # Requires Python 2.2a
127128 import sys, os, glob, re, sre, string, exceptions, copy, tempfile, time, pprint
221222 def is_command(line):
222223 # This works around a common bug -- string-enclosing ' at the left margin
223224 return len(line) > 1 and \
224 (line[0] == "." or (line[0] == "'" and line[1:].find("'") == -1))
225 (line[0] == TroffInterpreter.ctrl or (line[0] == TroffInterpreter.ctrl_nobreak and line[1:].find(TroffInterpreter.ctrl_nobreak) == -1))
225226
226227 def is_comment(line):
227228 # The malformed crap people write as troff comments is amazing...
228229 line = line.replace(" ", "").replace("\t", "")
229 return line =="." or line == "'" or line[:3] in (r'.\"', r'/\"', r'./"', r',\"', r".\'", '\'\\"', r'\'\"', r'\".', r"...", r"'''", r"\!.") or line[:2] in (r'."', r".'", r'\"', r"'#", r"\#") or line[:4] in (r'.\\"', r"'.\"")
230 return line == TroffInterpreter.ctrl or line == TroffInterpreter.ctrl_nobreak or line[:3] in (r'.\"', r'/\"', r'./"', r',\"', r".\'", '\'\\"', r'\'\"', r'\".', r"...", r"'''", r"\!.") or line[:2] in (r'."', r".'", r'\"', r"'#", r"\#") or line[:4] in (r'.\\"', r"'.\"")
230231
231232 def match_command(line, tag):
232233 # Cope with the possibility of spaces after the dot
233 if not line or line[0] not in (".", "'"):
234 if not line or line[0] not in (TroffInterpreter.ctrl, TroffInterpreter.ctrl_nobreak):
234235 return False
235236 tokens = line[1:].strip().split()
236237 return tokens and tokens[0] == tag
257258 str = re_compile(r"\f[^P]\fR$").sub(r"\fR", str)
258259 return str
259260
260 def get_troff_char(str):
261 "Extract a leading troff character from the string."
261 def get_xml_char(str):
262 "Extract a leading character or XML escape from the string."
262263 if len(str) == 0:
263264 return ""
264 elif str[0] != "\\":
265 elif str[0] != "&":
265266 return str[0]
266 take = 1
267 if str[1] == '*':
268 take += 1
269 if str[take] == '(':
270 take += 3
271267 else:
272 take += 1
273 return str[:take]
268 take = 1
269 while str[take] != ';':
270 take += 1
271 return str[:take+1]
274272
275273 def make_comment(str):
276274 str = str.replace(r'.\"', "").replace(r'.\\"', "").replace(r'\(co', "(C)")
397395 out += '.\\" | mark %s as %s\n' % (token, tag)
398396 out += '.\\" End doclifter hints.\n'
399397 return out
398
399 class Frame:
400 "Frame state for the list-markup stack."
401 def __init__(self, command, type):
402 self.command = command
403 self.type = type
404 self.count = 0
405 def __repr__(self):
406 return "<Frame: " + `self.__dict__` + ">"
400407
401408 class DocLifter:
402409 "DocBook translation of generic troff macros."
497504 ))
498505 post_translation_patterns = (
499506 # man(7)-style man-page references
500 (re.compile(r"<emphasis remap='[BI]'>([^ ]+)</emphasis>(?:&zerosp;|&thinsp;)?\(([0-9]+)\)"),
507 (re.compile(r"<emphasis remap='[BI]'>([^ ]+)</emphasis>(?:&zerosp;|&thinsp;)?\(([0-9]+[A-Za-z]?)\)"),
501508 r"<citerefentry><refentrytitle>\1</refentrytitle><manvolnum>\2</manvolnum></citerefentry>"),
502509 # Here's where we fold all those continuation lines.
503510 (re.compile("\\\c\n"), ""),
732739 "Pop to new section level."
733740 if section_verbosity in self.verbose:
734741 self.notify("pop_section(%d)" % depth)
742 self.poplist('section-end') # Terminate all list structure
735743 toplevel = (depth == 1) and (self.sectiondepth == 1)
736744 self.troff.nf = False
737745 self.end_paragraph(label="pop_section")
783791 self.nonblanks = 0
784792 def paragraph_break(self, line):
785793 "Are we looking at a paragraph break command?"
786 if line.startswith(".end"):
794 if line.startswith(TroffInterpreter.ctrl + "end"):
787795 return True
788796 elif not is_command(line):
789797 return False
798806 return False
799807 def section_break(self, line):
800808 "Are we looking at a section break command?"
801 if line.startswith(".end"):
809 if line.startswith(TroffInterpreter.ctrl + "end"):
802810 return True
803811 elif not is_command(line):
804812 return False
810818 return True
811819 return False
812820
821 def indent(self):
822 return len(self.stash_indents) * " "
823
813824 def begin_block(self, markup, remap=""):
814825 "Begin a block-context markup section."
815 self.in_block = True
816826 self.end_paragraph(label="begin_block")
817827 if remap and not self.quiet:
818828 remap = " remap='" + remap + "'"
822832 self.warning("Begin display collection")
823833 self.displaystack.append((markup, remap, DisplayParser(self,True,{})))
824834 else:
825 self.emit("<" + markup + remap + ">")
835 self.emit(self.indent() + "<" + markup + remap + ">")
826836 self.need_paragraph()
827837
828 def end_block(self, markup, remap=""):
838 def end_block(self, markup, remap="", ends=None):
829839 "End a block-context markup section."
840 # FIXME: use ends to ignore stray things that look like terminators
830841 if remap and not self.quiet:
831842 remap = " <!-- remap='" + remap + "' -->"
832 if not self.in_block:
833 return
843 self.troff.nf = False
834844 # Turn off all font highlights -- technically incorrect,
835845 # but almost always the right thing to do. We also
836846 # probably need an end-paragraph here, but that will be
837847 # taken care of by close_tags() later on.
838 if self.troff.nf:
839 self.troff.nf = False
848 if self.displaystack:
840849 (beginmarkup, beginremap, display) = self.displaystack.pop()
841850 (parsed, userwarning) = display.transform()
842851 self.emit("<" + beginmarkup + beginremap + ">")
843852 self.emit(parsed + (r"\fR</%s>" % markup + remap))
844853 else:
845 self.emit(r"\fR</%s>" % markup + remap)
854 self.emit(self.indent() + r"\fR</%s>" % markup + remap)
846855 self.need_paragraph()
847 self.in_block = False
848856
849857 def pushlist(self, cmd, type=None):
850858 if io_verbosity in self.verbose:
851859 self.notify("pushlist(%s, %s)" % (cmd, type))
852 self.stash_indents.append([cmd, type, 0])
860 self.stash_indents.append(Frame(cmd, type))
853861
854862 def poplist(self, cmd, backto=None):
855863 "Pop levels off the list stack until we've removed specified command."
856864 if io_verbosity in self.verbose:
857865 self.notify("poplist(%s, %s) %s" % (cmd, backto, self.stash_indents))
858866 while self.stash_indents:
859 (top, listtype, count) = self.stash_indents[-1]
860 if listtype == "variablelist":
867 frame = self.stash_indents[-1]
868 if frame.type == "variablelist":
861869 self.emit_variablelist("end")
862 elif listtype == "itemizedlist":
870 elif frame.type == "itemizedlist":
863871 self.emit_itemizedlist("end")
864 else:
872 elif frame.type == "blockquote":
873 self.end_block("blockquote", remap='RE')
865874 self.stash_indents.pop()
866 if top == backto:
875 else:
876 self.stash_indents.pop()
877 if frame.command == backto:
867878 break
868879 if io_verbosity in self.verbose:
869880 self.notify("after popping %s" % (self.stash_indents,))
870881
871882 def last_tag(self, lookfor):
872883 "What was the last actual tag emitted?"
884 if not self.diversion:
885 return False
873886 back = -1
874887 while True:
875888 backline = self.diversion[back].strip()
887900 self.notify("emit_variablelist(%s) %s"%(cmd, self.stash_indents))
888901 if cmd == "end":
889902 if self.stash_indents:
890 indent = (len(self.stash_indents) * " ")
903 indent = self.indent()
891904 self.stash_indents.pop()
892905 if self.last_tag("<listitem"):
893906 self.emit("<para> <!-- FIXME: blank list item -->")
897910 self.emit("%s</variablelist>" % indent[2:])
898911 return
899912 # All cases below emit a <term> at least
900 if not self.stash_indents or self.stash_indents[-1][0] != cmd:
913 if not self.stash_indents or self.stash_indents[-1].command != cmd:
901914 if self.quiet:
902915 remap = ""
903916 else:
904917 remap = " remap='%s'" % cmd
905 self.emit("%s<variablelist%s>" % (len(self.stash_indents) * " ", remap))
906 self.stash_indents.append([cmd, "variablelist", 0])
907 indent = len(self.stash_indents) * " "
918 self.emit("%s<variablelist%s>" % (self.indent(), remap))
919 self.stash_indents.append(Frame(cmd, "variablelist"))
920 indent = self.indent()
908921 back = self.last_tag("<listitem")
909922 if back:
910923 self.diversion[back] = "<!-- DELETE ME! -->"
911924 else:
912 if self.stash_indents[-1][2] > 0:
925 if self.stash_indents[-1].count > 0:
913926 self.emit("%s</listitem>" % indent)
914927 self.emit("%s</varlistentry>" % indent)
915928 self.emit("%s<varlistentry>" % indent)
916929 self.emit("%s<term>%s</term>" % (indent, fontclose(term)))
917930 self.emit("%s<listitem>" % indent)
918 self.stash_indents[-1][2] += 1
931 self.stash_indents[-1].count += 1
919932 self.need_paragraph()
920933
921934 def emit_itemizedlist(self, cmd, bullet=None):
924937 self.notify("emit_itemizedlist(%s) %s"%(cmd, self.stash_indents))
925938 if cmd == "end":
926939 if self.stash_indents:
927 indent = len(self.stash_indents) * " "
940 indent = self.indent()
928941 self.stash_indents.pop()
929942 if self.last_tag("<listitem"):
930943 self.emit("<para> <!-- FIXME: blank list item -->")
933946 self.emit("%s</itemizedlist>" % indent[2:])
934947 return
935948 # All cases below emit a <listitem> at least
936 if not self.stash_indents or self.stash_indents[-1][0] != cmd:
949 if not self.stash_indents or self.stash_indents[-1].command != cmd:
937950 if self.quiet:
938951 remap = ""
939952 else:
940953 remap = " remap='%s'" % cmd
941 self.emit("%s<itemizedlist%s>" % (len(self.stash_indents) * " ", remap))
942 self.stash_indents.append([cmd, "itemizedlist", 0])
943 indent = len(self.stash_indents) * " "
954 self.emit("%s<itemizedlist%s>" % (self.indent(), remap))
955 self.stash_indents.append(Frame(cmd, "itemizedlist"))
956 indent = self.indent()
944957 back = self.last_tag("<listitem")
945958 if back:
946959 self.diversion[back] = "<!-- DELETE ME! -->"
947960 else:
948 if self.stash_indents[-1][2] > 0:
961 if self.stash_indents[-1].count > 0:
949962 self.emit("%s</listitem>" % indent)
950963 self.emit("%s<listitem override='%s'>" % (indent, bullet))
951 self.stash_indents[-1][2] += 1
964 self.stash_indents[-1].count += 1
952965 self.need_paragraph()
953966
954967 # Highlight handling
10841097 if squashed[0] in "_0123456789":
10851098 squashed = "x" + squashed
10861099 # Hack spaces, smash case, and enforce jade's jength limit
1087 # Allow four digits for disambiguating numbers.
1088 return squashed.replace(" ", "_").lower()[:40]
1100 newid = squashed.replace(" ", "_").lower()[:40]
10891101 else:
10901102 # This case gets hit sometimes on CJK character sets
1091 return "g" + `time.time()`
1103 newid = "g" + `time.time()`
1104 if self.multiarg:
1105 return self.name + "-" + newid
1106 else:
1107 return newid
10921108 def make_id_from_title(self, str):
10931109 id = self.id_from_title(str)
10941110 # We allow duplicate sections, but warn about them
11201136 def id_exists(self, id):
11211137 "Test whether an id already exists"
11221138 return self.idlist.has_key(id)
1123 def TBL(self, enddelim=".TE"):
1139 def TBL(self, enddelim=None):
11241140 "Translate and emit a tbl section."
1141 if enddelim == None:
1142 enddelim = TroffInterpreter.ctrl + "TE"
11251143 # Detect and avoid QT breakage
11261144 if self.find("Trolltech"):
11271145 self.warning("garbage table elided")
12001218 tline = self.lines.pop(0)
12011219 if tline.strip() == enddelim:
12021220 break
1203 elif tline == ".TH":
1221 elif tline == TroffInterpreter.ctrl + "TH":
12041222 lastheaderline = len(data)
12051223 elif tline[-2:] == "T{":
12061224 while self.lines:
13851403 eqnlines.append(line)
13861404 if nondelimlines:
13871405 if self.preamble:
1388 self.emit(make_comment(".EQ"))
1406 self.emit(make_comment(TroffInterpreter.ctrl + "EQ"))
13891407 for line in eqnlines:
13901408 self.emit(make_comment(line))
1391 self.emit(make_comment(".EN"))
1409 self.emit(make_comment(TroffInterpreter.ctrl + "EN"))
13921410 else:
13931411 self.emit("<literallayout remap='EQN'>")
1394 self.emit(".EQ")
1412 self.emit(TroffInterpreter.ctrl + "EQ")
13951413 for line in eqnlines:
13961414 self.emit(line)
1397 self.emit(".EN")
1415 self.emit(TroffInterpreter.ctrl + "EN")
13981416 self.emit("</literallayout>")
13991417
14001418 def PIC(self):
14041422 if not self.pic_seen:
14051423 self.pic_seen = True
14061424 self.warning("pic(1) markup found.")
1407 self.cmdfilter(".PS", ".PE", "pic2plot -T svg")
1425 self.cmdfilter(TroffInterpreter.ctrl + "PS", TroffInterpreter.ctrl + "PE", "pic2plot -T svg")
14081426
14091427 def ignore(self, cmd):
14101428 "Declare that we want to ignore a command."
14201438 if not command:
14211439 return False
14221440 command = command.split()[0] # only look at first token
1423 if command[0] in ".'":
1441 if command[0] in (TroffInterpreter.ctrl,TroffInterpreter.ctrl_nobreak):
14241442 command = command[1:]
14251443 return command in self.ignore_set or (nocomplaints and command in self.complain_set)
14261444
14451463 if self.stash_indents and listbreaker:
14461464 if io_verbosity in self.verbose:
14471465 self.notify("list closer %s: %s"%(command,self.stash_indents))
1448 enclosing = self.stash_indents[-1][0]
1466 enclosing = self.stash_indents[-1].command
14491467 if enclosing in self.listbreak_set and enclosing != command:
14501468 while len(self.stash_indents):
1451 self.poplist(".end", self.stash_indents[-1][0])
1469 # Implicit list closers should not pop us all the way
1470 # out of explicit list structure.
1471 # FIXME: save explicitness bit, don't depend on macro name
1472 if self.stash_indents[-1].command == 'RS':
1473 break
1474 self.poplist(TroffInterpreter.ctrl + "end", self.stash_indents[-1].command)
14521475 # Here is where string expansion gets done:
14531476 stripped = []
14541477 for arg in stripquotes(tokens):
14961519 # pass it through for the interpreters to munch on.
14971520 if line == '':
14981521 if self.body_section() and not self.troff.nf:
1499 self.pushline(".blank")
1522 self.pushline(TroffInterpreter.ctrl + "blank")
15001523 # Treat blank lines in synopses as break commands;
15011524 # see cpio.1 for an example of why this is necessary.
15021525 elif self.in_synopsis():
1503 self.pushline(".br")
1526 self.pushline(TroffInterpreter.ctrl + "br")
15041527 else:
15051528 self.emit('')
15061529 continue
15231546 # who forget that the closing bracket of a conditional is
15241547 # a command. It's probably going to bite us someday.
15251548 if line == r"\}":
1526 self.pushline(".\}")
1549 self.pushline(TroffInterpreter.ctrl + "\}")
15271550 if macro_verbosity in self.verbose:
15281551 self.warning(r"adventitious \} should probably be .\}")
15291552 continue
16641687 "arg":1, "group":1, "cmdsynopsis":1, "command":1,
16651688 "funcsynopsis":1, "funcsynopsisinfo":1, "funcprototype":1, "funcdef":1,
16661689 "paramdef":1, "parameter":1, "function":1, "void":1, "vaargs":1,
1667 "synopsis":1,
1690 "synopsis":1, "symbol":1,
16681691 }
16691692 while True:
16701693 if state == 0: # Looking for <tag>
16811704 elif state == 1: # Found <tag>, looking for next tag
16821705 nexttag = before.find("<")
16831706 if nexttag == -1:
1684 self.error("missing tag after <tag>!")
1707 self.error("tag closer is confused by `%s`!" % before)
1708 break
16851709 after += before[:nexttag]
16861710 before = before[nexttag:]
16871711 # </tag> just closes the scope
17551779 if lines[0].find("Updated: ") > -1:
17561780 date = lines[0][lines[0].find("Updated: ")+10:].strip()
17571781 lines.pop(0)
1782 if not lines:
1783 raise LiftException("plain text where manual page expected", 1)
17581784 inoptions = False
17591785 for i in range(len(lines)):
17601786 if len(lines[i]) == 0:
17611787 continue
17621788 elif lines[i][0] in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
17631789 inoptions = lines[i].startswith("OPTIONS")
1764 lines[i] = ".SH " + lines[i].strip()
1790 lines[i] = TroffInterpreter.ctrl + "SH " + lines[i].strip()
17651791 else:
17661792 lines[i] = lines[i].strip()
17671793 if lines[i].startswith("____________"):
17681794 lines = lines[:i]
17691795 break
17701796 elif inoptions and lines[i][0] == '-':
1771 lines[i] = ".TP\n" + lines[i]
1772 elif lines[i][0] == '.':
1797 lines[i] = TroffInterpreter.ctrl + "TP\n" + lines[i]
1798 elif lines[i][0] == TroffInterpreter.ctrl:
17731799 lines[i] = "\\&" + lines[i]
17741800 name = section = ""
1775 if "." in file:
1776 (name, section) = file.split(".")
1801 if "." in os.path.basename(file):
1802 (name, section) = os.path.basename(file).split(".")
17771803 name = os.path.basename(name)
17781804 th = '.TH "%s" "%s" "%s" "" ""\n' % (name, section, date)
17791805 return th + "\n".join(lines) + "\n"
17801806
1781 def __call__(self, name, file, text):
1807 def __call__(self, name, file, text, multiarg):
17821808 "Translate a string containing troff source to DocBook markup."
1809 self.name = name
17831810 self.file = file
1811 self.multiarg = multiarg
17841812 self.eqnsub = None
17851813 self.preamble = True
17861814 self.body_start = 0
18001828 self.troff = TroffInterpreter(self, self.verbose)
18011829 self.interpreters = [self.troff]
18021830 self.localhints = SemanticHintsRegistry()
1831 # Empty files pass through trivially.
1832 # (This is not a terribly uncommon defect...)
1833 if len(text) == 0:
1834 raise LiftException("%s is empty" % file, 1)
18031835 # Parse semantic hints from the text, if present.
18041836 # Yes, they should go to the global registry.
18051837 global globalhints
18801912 # Split it into lines
18811913 toplevel = text.split("\n")
18821914 # Check for pure inclusions
1915 def is_inclusion(x):
1916 return x[:4] == TroffInterpreter.ctrl + "so "
18831917 nonempty = filter(lambda x: x != "" and not is_comment(x), toplevel)
1884 if len(nonempty) == 1 and nonempty[0][:4] == ".so ":
1918 if len(nonempty) == 1 and is_inclusion(nonempty[0]):
18851919 raise LiftException("see " + nonempty[0].strip()[4:], 2)
1920 elif len(nonempty) > 1 and len(filter(is_inclusion, nonempty)) == len(nonempty):
1921 raise LiftException("%s consists entirely of inclusions" % file, 2)
18861922 # If it's not a pure inclusion, warn if we don't have a macro set.
18871923 if len(self.interpreters) == 1:
1888 stderr.write("doclifter: no macro set recognized\n")
1924 raise LiftException("no macro set recognized", 1)
18891925 # Strip off trailing blank lines, they interact badly with the
18901926 # paragraphing logic.
18911927 while toplevel and toplevel[-1] == "":
18931929 # This actually happens with some generated Perl pages
18941930 # that stop after .TH
18951931 if len(toplevel) <= 1:
1896 raise LiftException("warning: %s is empty" % self.file)
1932 raise LiftException("%s has no content" % self.file)
18971933 # Is there any text at all in this file?
18981934 textcount = 0
18991935 for line in toplevel:
19051941 i = -1
19061942 if not toplevel[i] and is_comment(toplevel[i]):
19071943 i -= 1
1908 toplevel.insert(len(toplevel)-i, ".end")
1944 toplevel.insert(len(toplevel)-i, TroffInterpreter.ctrl + "end")
19091945 # Emit the top-level tag, with an id that will direct the
19101946 # DocBook toolchain to do the right thing.
19111947 if self.toptag:
19481984 # again afterwards. Because body_start is a line index,
19491985 # we have to not insert or delete lines here.
19501986 before = "\n".join(self.output)
1951 after = self.close_tags(before, "para", tight=1)
1952 after = self.close_tags(after, "literallayout", tight=0)
1987 after = self.close_tags(before, "para", tight=True)
1988 after = self.close_tags(after, "literallayout", tight=False)
19531989 self.output = after.split("\n")
19541990 if timing_verbosity in self.verbose:
19551991 now = time.time()
19561992 stderr.write("timing: tag closing = %2.2f\n" % (now-self.basetime,))
19571993 self.basetime = now
1958 # Maybe it's all comments and blanks (result of a bare hints file).
1994 # Maybe it's all comments and blanks (result of a bare hints file).
19591995 # In that case return None to suppress output
1960 if not self.interpreters and not filter(lambda x:x[:4]=="<--" or blankline.match(x),self.output):
1996 if not self.interpreters and not filter(lambda x:x[:4]=="<!--" or blankline.match(x),self.output):
19611997 return None
19621998 if timing_verbosity in self.verbose:
19631999 now = time.time()
20282064 if self.complaints and general_verbosity in self.verbose:
20292065 stderr.write("warning: " + ", ".join(self.complaints.keys()) + " seen\n")
20302066 # Now that we've done escape detection, interpret backslashes
2031 # FIXME: Still need to do interpreatation of \n, \t, etc.
2067 # FIXME: Still need to do interpretation of \n, \t, etc.
20322068 text = text.replace("\\\\", "\\")
20332069 if timing_verbosity in self.verbose:
20342070 now = time.time()
20632099 # This can substantially reduce the amount of manual hackery
20642100 # needed to hand-translate the eqn.
20652101 if self.eqnsub:
2066 text = re.sub(r"<\?start-eqn\?>(.)<\?end-eqn\?>", "<emphasis role='eqn'>\1</emphasis>", text)
2102 text = re.sub(r"<\?start-eqn\?>(.)<\?end-eqn\?>", r"<emphasis role='eqn'>\1</emphasis>", text)
20672103 # Also nuke hair-thin space, at this late stage it shouldn't make
20682104 # any difference. This avoids an apparent bug in the DocBook
20692105 # stylesheets; &hairsp; is documented but not actually defined.
21122148 # Complain about stuff that produces gross motions.
21132149 "ne":1,"mk":1,"rt":1,"ce":1, #"in":1,
21142150 # We could do much of section 10,but these are a sign of trouble.
2115 "ec":1,"eo":1,"uf":1,"cc":1,"c2":1,
2151 "ec":1,"eo":1,"uf":1,
21162152 # We can't handle environments, insertions, or next file.
21172153 "ev":1,"rd":1,"nx":1,"pi":1,
21182154 }
25242560 ("option", "option"),
25252561 ))
25262562
2563 # These are interpreter state which can be modified by the .cc command
2564 ctrl = "."
2565 ctrl_nobreak = "'"
2566
25272567 def __init__(self, source, verbose):
25282568 self.source = source
25292569 self.verbose = verbose
25302570 self.strings = {} # String table for ds, as, rm, rn
25312571 self.macros = {} # String table for de, ae, rm, rn
2532 self.macroend = ".." # Maco ender character as set by .em
2572 self.macroend = ".." # Macro ender character as set by .em
25332573 self.macroargs = [] # Macro argument stack
25342574 self.macronames = [] # Macro name stack (only used in error msgs)
25352575 self.nf = False # Initially we're filling and adjusting
28152855 while self.source.ignorable(self.source.peekline(), nocomplaints=1):
28162856 self.source.emit(make_comment(self.source.popline()))
28172857 next = self.source.peekline()
2818 if next and next[0:3] == ".ft":
2858 if next and next[0:3] == TroffInterpreter.ctrl + "ft":
28192859 cmd = lineparse(self.source.popline())
28202860 if len(cmd) == 1:
28212861 self.source.emit(r"\fR")
28372877 self.source.need_paragraph()
28382878 elif command in ("nf", "NF"): # .NF is an oddly common typo
28392879 self.source.end_paragraph(label="nf")
2840 if self.source.peekline() == ".ft CW":
2880 if self.source.peekline() == TroffInterpreter.ctrl + "ft CW":
28412881 self.source.popline()
28422882 self.source.end_paragraph()
28432883 self.source.emit("<screen> <!-- .nf -->")
28602900 self.source.lines[i] = r"\fU" + self.source.lines[i] + r"\fP"
28612901 elif command == "tr":
28622902 while True:
2863 frompart = get_troff_char(args[0])
2903 frompart = get_xml_char(args[0])
28642904 args[0] = args[0][len(frompart):]
2865 topart = get_troff_char(args[0])
2905 topart = get_xml_char(args[0])
28662906 args[0] = args[0][len(topart):]
28672907 if not frompart:
28682908 break
29352975 value = " ".join(tokens[2:])
29362976 else:
29372977 value = " ".join(tokens[2:])
2978 value = value.replace("'", "&#x27;");
29382979 if self.source.preamble and self.entities_from_strings:
29392980 self.source.localentities.append((stringname, value))
29402981 self.strings[stringname] = "&" + stringname + ";"
29833024 endon = newname
29843025 else:
29853026 endon = self.macroend
2986 if command == ".de" or not name in self.macros:
3027 if command==TroffInterpreter.ctrl+"de" or not name in self.macros:
29873028 self.macros[name] = []
2988 isused = filter(lambda x: x[0:len(name)+1]=="."+name, self.source.lines)
3029 isused = filter(lambda x: x[0:len(name)+1]==TroffInterpreter.ctrl+name, self.source.lines)
29893030 suppressed = False
29903031 for interpreter in self.source.interpreters:
29913032 if name in interpreter.immutable_set.keys():
30643105 if len(tokens) == 1:
30653106 # Cope with a transposition typo...see vmstat(8) for example.
30663107 if command == "if" and self.nf:
3067 self.source.pushline(".fi")
3108 self.source.pushline(TroffInterpreter.ctrl + "fi")
30683109 else:
30693110 self.source.error("malformed conditional %s" % command)
30703111 return True
30883129 # Evidently this is somebody's way of getting "and" into
30893130 # conditionals. Ugh...
30903131 if guardval:
3091 if len(tokens) > 2 and not tokens[2].startswith(r"\{") and tokens[2] != ".if":
3132 if len(tokens) > 2 and not tokens[2].startswith(r"\{") and tokens[2] != TroffInterpreter.ctrl + "if":
30923133 if macro_verbosity in self.verbose:
30933134 self.source.notify("if or ie does one-line pushback")
3094 self.source.pushline(r".\}")
3135 self.source.pushline(TroffInterpreter.ctrl + r"\}")
30953136 if tokens[2].startswith(r"\{"):
30963137 tokens[2] = tokens[2][2:]
30973138 if macro_verbosity in self.verbose:
31303171 # If it's a one-liner and condition false, push back remaining text
31313172 oneliner = len(tokens) > 1 and tokens[1][:2] != r"\{"
31323173 if not condition and oneliner:
3133 self.source.pushline(r".\}")
3174 self.source.pushline(TroffInterpreter.ctrl + r"\}")
31343175 self.source.pushline(" ".join(tokens[1:]))
31353176 # If condition is true we need to do a skip now
31363177 if condition and not oneliner:
31553196 self.source.emit("<!-- " + " ".join(tokens))
31563197 while self.source.lines:
31573198 line = self.source.popline()
3158 if line.startswith("." + args[0]):
3199 if line.startswith(TroffInterpreter.ctrl + args[0]):
31593200 self.source.emit(".%s -->" % args[0], trans=0)
31603201 break
31613202 line = line.replace("--", "&ndash;&ndash;")
31743215 self.macronames.append(command)
31753216 self.source.lines = self.macros[command] + [self.source.lineno] + self.source.lines
31763217 # Extended groff macros
3218 elif command == "cc":
3219 TroffInterpreter.ctrl = args[0]
3220 elif command == "c2":
3221 TroffInterpreter.ctrl_break = args[0]
31773222 elif command == "ab":
31783223 if not args:
31793224 args = ["User Abort"]
31963241 elif command == "PSPIC":
31973242 file = args[0]
31983243 self.source.pushline('<mediaobject>\n<imageobject><imagedata fileref="%s" format="EPS"/></imageobject>\n</mediaobject>' % file)
3244 elif command == "DOCLIFTER-HR":
3245 self.source.emit("<!-- horizontal rule -->")
31993246 # We're done
32003247 else:
32013248 return False
32033250 if len(tokens) > 1 and tokens[-1] == r"\}":
32043251 if macro_verbosity in self.verbose:
32053252 self.source.notify("pushing back a trailing bracket")
3206 self.source.pushline(r".\}")
3253 self.source.pushline(TroffInterpreter.ctrl + r"\}")
32073254 return True
32083255 def conditionally_replace(self, wrapper, standard):
32093256 "Replace a wrapper with a standard macro if the wrapper contains it."
32113258 if not self.source.quiet:
32123259 self.source.emit(make_comment("%s reduced to %s" % (wrapper, standard)))
32133260 m = re_compile("^." + wrapper)
3214 self.source.lines = map(lambda x: m.sub("."+standard, x), self.source.lines)
3261 self.source.lines = map(lambda x: m.sub(TroffInterpreter.ctrl+standard, x), self.source.lines)
32153262 def preprocess(self, text):
32163263 expanded=[]
3264 if chr(0xa0) in text:
3265 # db2man generates these
3266 text = text.replace(chr(0xa0), ' ')
3267 self.source.warning("text contains meta-SP characters, treating as SP")
32173268 for line in text.split("\n"):
32183269 # Fix a common error -- beginning a line with a string quote
32193270 # that isn't supposed to be a non-breaking request (example at
32303281 # XMLify everything
32313282 for (pattern, substitute) in TroffInterpreter.xmlify_patterns:
32323283 line = pattern.sub(substitute, line)
3284 # Handle a grotty special case from spax.1
3285 line = line.replace(r"\l'\n(.lu'", ".DOCLIFTER-HR")
32333286 expanded.append(line)
32343287 return "\n".join(expanded)
32353288 def postprocess(self, text):
32903343 if general_verbosity in self.verbose:
32913344 self.source.notify("Starting from down, I see upward %s" % upward)
32923345 elif downward:
3293 self.source.error("two downward motions in a row %s")
3346 self.source.error("two downward motions in a row")
32943347 raise SystemExit
32953348 else:
32963349 self.source.error("error in vertical-motion match (down)")
33283381 "Skip blank lines and ignorable commands."
33293382 while source.lines:
33303383 line = source.popline()
3331 if line == ".end":
3332 source.pushline(".end")
3384 if line == TroffInterpreter.ctrl + "end":
3385 source.pushline(TroffInterpreter.ctrl + "end")
33333386 break;
33343387 elif line == None:
33353388 break
3336 elif line in ("", ".", "'"): # Skip blank or null lines
3389 elif line in ("", TroffInterpreter.ctrl, TroffInterpreter.ctrl_nobreak): # Skip blank or null lines
33373390 continue
33383391 elif source.paragraph_break(line): # Skip ordinary paragraphs
33393392 continue
33783431 while source.lines:
33793432 line = source.popline()
33803433 # Maybe we're looking at a commented-out entry
3381 if line == ".ig":
3382 savesect.append(".ig")
3434 if line == TroffInterpreter.ctrl + "ig":
3435 savesect.append(TroffInterpreter.ctrl + "ig")
33833436 while True:
33843437 line = source.popline()
33853438 savesect.append(line)
3386 if line == "..":
3439 if line == TroffInterpreter.ctrl + ".":
33873440 break
33883441 continue
33893442 elif line is None:
33903443 break
3391 elif line.startswith(".blank"):
3444 elif line.startswith(TroffInterpreter.ctrl + "blank"):
33923445 # The point is not to end the list on these.
3393 savesect.append(".blank")
3446 savesect.append(TroffInterpreter.ctrl + "blank")
33943447 elif source.section_break(line):
33953448 # Push back any blank lines before the section break.
33963449 # This avoids generating some spurious paragraph()
34513504 nameline = nameline.replace(r" &mdash; ", r' \- ')
34523505 if nameline.find(r" \- ") == -1:
34533506 nameline = nameline.replace("--", r' \- ')
3454 # Apparent pod2man breakage,,,
3507 # Apparent pod2man breakage...
34553508 nameline = nameline.replace(r"&zerosp;-", "\-")
34563509 # SDL pages make this kluge necessary
34573510 if nameline.find(r" \- ") == -1:
35003553 elif self.type == "\n":
35013554 return ""
35023555 else:
3556 res = ""
35033557 for child in self.children:
35043558 res += `child`
3505 return res
3559 return ("<%s>" % self.type) + res + ("</%s>" % self.type)
35063560
35073561 def is_file_or_command_name(tok):
35083562 # Yes, some legitimate commands begin with digits;
42804334 # If the first token is bolded, that probably means it's a command
42814335 # name that doesn't happen to match anything in the name section.
42824336 # Apply this test only when we're in a synopsis section.
4283 if self.source.in_synopsis() and rawline.startswith(r"\fB") or rawline.startswith(r".B "):
4337 if self.source.in_synopsis() and rawline.startswith(r"\fB") or rawline.startswith(TroffInterpreter.ctrl + r"B "):
42844338 return 9
42854339 # Nope, doesn't look like a command synopsis line
42864340 if classify_verbosity in self.source.verbose:
43114365 if arg == None:
43124366 break
43134367 output += " " + `arg` + "\n"
4368 # This is where we short-stop the command-synopsis parser
4369 # from eating trailing text sections.
4370 if `arg` == "<sbr/>" and self.io.lines and \
4371 not self.is_command_synopsis_line(self.io.lines[0]):
4372 break
43144373 return "<cmdsynopsis>\n"+output+"</cmdsynopsis>\n"
43154374 except LiftException, e:
43164375 self.error = "command synopsis parse failed on `%s' (%d): %s" % \
43424401 next = self.io.token_peek()
43434402 if next and next[0] in ('-', '+') or next.startswith("&plusmn;"):
43444403 self.confirmed = True
4404 return True
4405 elif next and self.lastnest and next in ('&amp;', '&bsol;'): # See tex.1
43454406 return True
43464407 else:
43474408 return False
45184579 class DisplayParser:
45194580 "Parse a block into function synopsis, command synopsis or display text."
45204581 old_style_option_glue = re_compile(r"([^A-Za-z]-[A-Za-z]*)(?:\f.)([A-Za-z])")
4521 unparseable = re_compile(r"\$|=&gt;|print|//") # Perl and other nightmares
4582 unparseable = re_compile(r"\$|=&gt;|[^:]//") # Perl and other nightmares
45224583 def __init__(self, source, try_synopsis, refnames={}):
45234584 "Arrange the interpreter to accumulate synopsis lines in this object."
45244585 self.source = source
45974658 else:
45984659 processed.append(line+"\n")
45994660 # Translate troff characters and XMLlify everything.
4661 if classify_verbosity in self.source.verbose:
4662 self.source.notify("Before tokenization: %s\n" % processed)
46004663 self.io = LineTokenizer(processed,
46014664 tokenizer_verbosity in self.source.verbose)
46024665 if classify_verbosity in self.source.verbose:
4603 self.source.notify("Raw: \n" + "".join(self.io.lines))
4666 self.source.notify("After tokenization: \n" + "".join(self.io.lines))
46044667
46054668 # This code is failure-prone. It is coping as best it can with a mess.
46064669 #
47644827 "FM":1,
47654828 # Undocumented, used in the attr(3) man pages
47664829 "Op":1,
4830 # Occurs in X Consortium manpages redundant with .ta,
4831 # but not all such man pages have an identifiable X headers.
4832 "TA":1,
47674833 # .Id is used to embed RCS/SCCS IDs.
47684834 "Id":1,}
47694835 complain_set = {}
47944860 self.seen_DS = False
47954861 self.qt_grotty_hack = False
47964862 self.have_name = False
4797 self.rsre_count = 0
47984863 self.stash_linkender = None
47994864 #self.systype = None
48004865 def fold_highlights(self, cmd, args):
48544919 while True:
48554920 line = self.source.popline()
48564921 # Can't use paragraph_break() here lest we skip .TP or .IP
4857 if line and not line[:3] in (".PP", ".LP", ".P"):
4922 if line and not line[:3] in (TroffInterpreter.ctrl + "PP", TroffInterpreter.ctrl + "LP", TroffInterpreter.ctrl + "P"):
48584923 self.source.pushline(line)
48594924 break
48604925 #self.source.pushline(line)
48754940 self.source.ignore("fi")
48764941 while True:
48774942 line = self.source.popline()
4943 # Cope with some Pod2Man brain-death. It issues lines like
4944 # .IP "\fBfoo\fR \- foo the bar" 4
4945 # using .IP as a crude presentation-level hack
4946 m = re.match('.IP "([^"]*)".*', line)
4947 if m:
4948 line = m.group(1)
48784949 if line is None or self.source.section_break(line):
48794950 self.source.pushline(line)
48804951 break
4881 if line.startswith(".DOCLIFTER-BOOJUM"):
4882 line = line[len(".DOCLIFTER-BOOJUM"):]
4952 if line.startswith(TroffInterpreter.ctrl + "DOCLIFTER-BOOJUM"):
4953 line = line[len(TroffInterpreter.ctrl + "DOCLIFTER-BOOJUM"):]
48834954 if is_comment(line):
48844955 continue
48854956 elif not (is_command(line) and self.source.ignorable(line)):
48974968 self.source.unignore("fi")
48984969 # Skip lines that are blank or consist of a leading dot only
48994970 # (as in groff_mdoc(7)).
4900 while not namelines[0] or namelines[0] == ".":
4971 while not namelines[0] or namelines[0] == TroffInterpreter.ctrl:
49014972 namelines.pop(0)
49024973 try:
49034974 namesect = parse_name_section(" ".join(namelines))
50305101 if self.source.body_section():
50315102 while blankline.match(self.source.peekline()):
50325103 self.source.popline()
5033 self.source.trap_emit(".TP ")
5104 self.source.trap_emit(TroffInterpreter.ctrl + "TP ")
50345105 # Relative indent changes
50355106 elif cmd == "RS":
50365107 # Check for no-ops generated by pod2man.
5037 if self.source.peekline().startswith(".RE"):
5108 if self.source.peekline().startswith(TroffInterpreter.ctrl + "RE"):
50385109 self.source.popline()
50395110 return True
5040 # Else report this.
5041 if not self.source.quiet:
5042 self.source.emit((len(self.source.stash_indents) * " ") + make_comment(" ".join(tokens)))
5043 # Under some circumstances we may be able to ignore these.
5111 # We may be able issue no markup for these.
50445112 # Notably, if we're looking at .RS+.nf, this is
50455113 # just an indented block with no structural significance.
5046 if self.source.peekline() and self.source.peekline().startswith(".nf"):
5114 # Mark it on the stack so a following RE will pop it.
5115 next = self.source.peekline()
5116 if next and next.startswith(TroffInterpreter.ctrl + "nf"):
5117 self.source.pushlist("RS")
50475118 return True
5048 # We can ignore .nf+.RS, too
5119 # No markup for .nf+.RS, too, but
50495120 elif self.source.last_tag("<literallayout"):
5121 self.source.pushlist("RS")
50505122 return True
50515123 # If we're in list content, nest the list a level deeper
50525124 elif self.source.stash_indents:
5053 self.source.pushlist("RS")
5125 if not next.startswith(".TP") and not next.startswith(".IP"):
5126 self.source.begin_block("blockquote", remap='RS')
5127 self.source.pushlist("RS", "blockquote")
50545128 self.source.need_paragraph()
50555129 return True
50565130 # Next check for single-line .RS/.RE blocks.
50575131 # This will fail if the line has a highlight.
50585132 elif not is_command(self.source.peekline()):
50595133 text = self.source.popline()
5060 if self.source.peekline() == ".RE":
5134 if self.source.peekline() == TroffInterpreter.ctrl + "RE":
50615135 self.source.popline()
50625136 self.source.begin_block("literallayout", remap='RS')
50635137 self.source.emit(text)
50665140 else:
50675141 self.source.pushline(text)
50685142 # Fall through
5069 # Nope, could be in some context like a list that
5070 # carries actual structural information. Have to warn about them.
5071 if general_verbosity in self.source.verbose:
5072 self.source.warning(".RS seen")
5073 self.rsre_count += 1
5143 # None of the special cases fired. Punt; treat as blockquote
5144 self.source.pushlist("RS", "blockquote")
5145 self.source.begin_block("blockquote", remap='RS')
50745146 elif cmd == "RE":
5075 # If we're in list content, pop a list level.
5076 if self.source.stash_indents:
5077 self.source.poplist(cmd, "RS")
5078 self.source.need_paragraph()
5079 # Fall through
5080 # Under some circumstances we may be able to ignore these.
5081 # Notably, if the preceding command was a .fi, this is just
5082 # the end of an indented block with no structural significance.
5083 # These checks have to be done *after* looking for list structure,
5084 # otherwise they foo up on sublists that end with a diagram.
5085 elif self.source.diversion and self.source.diversion[-1].find("</literallayout>") > -1:
5086 return True
5087 elif self.source.peekline() and self.source.peekline().startswith(".fi"):
5088 return True
5089 else:
5090 # Nope, have to warn about them.
5091 if general_verbosity in self.source.verbose:
5092 self.source.warning(".RE seen")
5093 self.rsre_count += 1
5094 if not self.source.quiet:
5095 self.source.emit((len(self.source.stash_indents) * " ") + make_comment(".RE"))
5147 self.source.poplist("blockquote", "RS")
5148 self.source.need_paragraph()
50965149 # Hyperlinks
5097 elif cmd == "UE":
5150 elif cmd == "UE": # End of link text
50985151 if self.source.body_section():
50995152 self.source.pushline(self.stash_linkender)
5100 elif cmd == "UN":
5153 elif cmd == "UN": # Anchor for a hyperlink target
51015154 if not args:
51025155 self.source.error("UN macro requires an argument")
51035156 elif self.source.body_section():
5104 if self.source.peekline()[:3] in (".SH", ".SS"):
5157 if self.source.peekline()[:3] in (TroffInterpreter.ctrl + "SH", TroffInterpreter.ctrl + "SS"):
51055158 self.source.stash_id = args[0]
51065159 else:
51075160 self.source.pushline("<anchor id='%s'/>" % self.source.make_id_from_title(tokens[1]))
5108 elif cmd == "UR":
5161 elif cmd == "UR": # Start of link text
51095162 if not args:
51105163 self.source.error("UR macro requires an argument")
51115164 elif self.source.body_section():
51325185 elif cmd == "Ds":
51335186 self.source.begin_block("literallayout", remap="Ds")
51345187 elif cmd == "De":
5135 self.source.end_block("literallayout", remap="De")
5188 self.source.end_block("literallayout", remap="De", ends="Ds")
51365189 elif cmd == "EX":
51375190 self.source.begin_block("literallayout", remap="EX")
51385191 elif cmd == "EE":
5139 self.source.end_block("literallayout", remap="EE")
5192 self.source.end_block("literallayout", remap="EE", ends="EX")
5193 elif cmd == "Ex":
5194 self.source.begin_block("literallayout", remap="Ex")
5195 elif cmd == "Ee":
5196 self.source.end_block("literallayout", remap="Ee", ends="Ex")
51405197 elif cmd == "NT":
51415198 self.source.begin_block("note", remap="NT")
51425199 elif cmd == "NE":
5143 self.source.end_block("note", remap="NE")
5200 self.source.end_block("note", remap="NE", ends="NT")
51445201 elif cmd == "RN":
51455202 self.source.pushline("<keycap>RETURN</keycap>")
51465203 elif cmd == "PN":
51795236 # self.systype = "4.4 Berkeley Distribution"
51805237 # mtools man pages use these...ugh
51815238 elif cmd == "(l":
5182 self.source.pushline(".nf")
5239 self.source.pushline(TroffInterpreter.ctrl + "nf")
51835240 elif cmd == ")l":
5184 self.source.pushline(".fi")
5241 self.source.pushline(TroffInterpreter.ctrl + "fi")
51855242 # DS/DE isn't part of the man macros. Interpret it anyway,
51865243 # as there is an obvious meaning that people try to use.
51875244 elif cmd == "DS":
51885245 # Catch an odd, pointless use of .DS that pops up on a number
51895246 # of SANE manual pages (probably generated from something).
5190 if self.source.peekline() == ".sp\n":
5247 if self.source.peekline() == TroffInterpreter.ctrl + "sp\n":
51915248 self.source.popline()
51925249 self.source.popline()
51935250 elif self.source.find("DE"):
52015258 # Use our reductions as fallbacks
52025259 elif cmd in ManInterpreter.reductions:
52035260 replace_with = ManInterpreter.reductions[cmd]
5204 self.source.pushline("." + replace_with + " " + quoteargs(args))
5261 self.source.pushline(TroffInterpreter.ctrl + replace_with + " " + quoteargs(args))
52055262 # Recover from some common typos
52065263 elif cmd[0] in "BIR" and cmd[1].islower() and len(cmd) > 3:
5207 newtokens = ["." + cmd[:1]] + [cmd[1:]] + tokens[1:]
5264 newtokens = [TroffInterpreter.ctrl + cmd[:1]] + [cmd[1:]] + tokens[1:]
52085265 self.source.warning("rewriting %s as %s" % (tokens, newtokens))
52095266 self.source.pushline(newtokens[0]+" "+quoteargs(newtokens[1:]))
52105267 else:
52285285 # This step makes .TP lists easier to process without a boatload
52295286 # of special-case code. See the handling of .DOCLIFTER-BOOJUM above
52305287 text = re_compile(r"\n\.\s*TP").sub("\n.DOCLIFTER-BOOJUM", text)
5231 # This bizarre thing haoppens on snmpnetstat(1).
5232 # groff(1) accepts it, groffer(1) complains and accepts it
5288 # This bizarre thing happens on snmpnetstat(1).
5289 # groff(1) accepts it, groffer(1) complains and accepts it.
52335290 text = text.replace("\n.I&nbsp;", "\n.I ")
5291 # Some versions of db2man.xsl have a bad bug. Work around it.
5292 text = re_compile("(\\.TH.*)\\.SH NAME").sub(r"\1\n.SH NAME", text)
5293 # Some versions of netpbm makeman have a bad bug. Work around it.
5294 text = re_compile("(\\.UN.*)\\.SH").sub(r"\1\n.SH", text)
5295 # Reverse a transformation that db2man does when translating <note>.
5296 # FIXME: turn the following paragraph into a <note>.
5297 text = text.replace(".it 1 an-trap\n.nr an-no-space-flag 1\n.nr an-break-flag 1\n.br\n", "")
5298 # Brain-damage emitted often by Pod2Man, occasionally by humans
5299 text = re_compile("\\.PD.*\n+(.S[hHsS])").sub("\n\n\\1", text)
5300 text = re_compile("\\.RS.*\n+(.S[hHsS])").sub("\n\n\\1", text)
52345301 return text
52355302 def postprocess(self, text):
5236 if self.rsre_count and not general_verbosity in self.source.verbose:
5237 stderr.write("warning: RS/RE seen.\n")
52385303 # Page might be generated crap with no sections, which can't be lifted.
5239 # This happens with some pod2man paCges.
5304 # This happens with some pod2man pages.
52405305 if not self.source.section_count:
52415306 raise LiftException("no section structure in %s, can't be lifted." % self.source.file)
52425307 elif not self.have_name:
52565321 if foundit > -1:
52575322 before = text[:foundit]
52585323 after = text[foundit:]
5259 after = re.sub(r'([a-z_]+)\(([0-9].?)\)', r'<citerefentry><refentrytitle>\1</refentrytitle><manvolnum>\2</manvolnum></citerefentry>', after)
5324 after = re.sub(r'([a-z0-9_-]+)\(([0-9].?)\)', r'<citerefentry><refentrytitle>\1</refentrytitle><manvolnum>\2</manvolnum></citerefentry>', after)
52605325 text = before + after
52615326 foundit = text.rfind("FILES")
52625327 if foundit > -1:
53045369 elif self.source.in_synopsis():
53055370 self.source.emit("<sbr/>")
53065371 elif cmd == "Sh":
5307 self.source.pushline(quoteargs([".SS"] + args))
5372 self.source.pushline(quoteargs([TroffInterpreter.ctrl + "SS"] + args))
53085373 elif cmd == "Vb":
53095374 if self.source.body_section():
53105375 self.source.begin_block("literallayout", remap="Vb")
53495414 # Some of the X local macros (Ds, De, NT, NE, PN) are Ultrix extensions
53505415 # already handled by ManInterpreter.
53515416 immutable_set = {"FD":1,"FN":1,"IN":1,"ZN":1,"hN":1}
5352 ignore_set = {}
5417 ignore_set = {"IN":1}
53535418 complain_set = {}
53545419 parabreak_set = {}
53555420 sectionbreak_set = {}
53565421 listbreak_set = {}
53575422 translations = ()
5358 reductions = {"IN":"IX"} # Reduce IN to vanilla-man IX.
5423 reductions = {}
53595424 def __init__(self, source, verbose=0):
53605425 self.source = source
53615426 self.verbose = verbose
53685433 # This wants to be a keep, but DocBook can't express that.
53695434 self.source.begin_block("literallayout", remap="FD")
53705435 elif cmd == "FN":
5371 self.source.end_block("literallayout", remap="FN")
5436 self.source.end_block("literallayout", remap="FN", ends="FD")
53725437 elif cmd == "ZN":
5373 self.source.emit("<symbol>%s</symbol>%s" % (args[0], "".join(args[1:])))
5438 self.source.pushline("<symbol role='ZN'>%s</symbol>%s" % (args[0], "".join(args[1:])))
53745439 elif cmd == "Pn":
5375 self.source.emit("%s<symbol>%s</symbol>%s" % (args[0], args[1], "".join(args[2:])))
5440 self.source.pushline("%s<symbol role='Pn'>%s</symbol>%s" % (args[0], args[1], "".join(args[2:])))
53765441 elif cmd == "hN":
5377 self.source.emit("<symbol>&lt;%s&gt;</symbol>%s" % (args[0], "".join(args[1:])))
5442 self.source.pushline("<symbol>&lt;%s&gt;</symbol>%s" % (args[0], "".join(args[1:])))
53785443 elif cmd == "C{":
53795444 self.source.begin_block("programlisting", remap="C{")
53805445 elif cmd == "C}":
5381 self.source.end_block("programlisting", remap="C}")
5446 self.source.end_block("programlisting", remap="C}", ends="C{")
53825447 elif cmd == "NT":
53835448 self.source.begin_block("note", remap="NT")
53845449 elif cmd == "NE":
5385 self.source.end_block("note", remap="NE")
5450 self.source.end_block("note", remap="NE", ends="NT")
53865451 else:
53875452 return False
53885453 return True
53895454 def preprocess(self, text):
53905455 # Detect and strip out standard X macro preamble.
5391 stripped = []
5392 lines = text.split("\n")
5393 while not lines[0].startswith(".na"):
5394 stripped.append(lines.pop(0))
5395 self.source.lineno += 1
5396 while not lines[0].startswith(".ny0"):
5456 if text.find(TroffInterpreter.ctrl + "na") > -1:
5457 stripped = []
5458 lines = text.split("\n")
5459 while not lines[0].startswith(TroffInterpreter.ctrl + "na"):
5460 stripped.append(lines.pop(0))
5461 self.source.lineno += 1
5462 while not lines[0].startswith(TroffInterpreter.ctrl + "ny0"):
5463 lines.pop(0)
5464 self.source.lineno += 1
5465 # Eat trailing .ny0
53975466 lines.pop(0)
53985467 self.source.lineno += 1
5399 # Eat trailing .ny0
5400 lines.pop(0)
5401 self.source.lineno += 1
5402 return "\n".join(stripped + lines)
5468 return "\n".join(stripped + lines)
5469 else:
5470 return text
54035471 def postprocess(self, text):
54045472 return text
54055473
54805548 # argument is present, then a line break is forced before starting
54815549 # the sidebar.
54825550 elif cmd == "VS":
5483 # It's tempting to try translating this as a <sidebar>/
5551 # It's tempting to try translating this as a <sidebar>.
54845552 # Problem is the usage pattern really is presentation-level;
54855553 # .VS/.VE is frequently wrapped around entire major sections.
5486 # There are also nast interactions with list markup.
5554 # There are also nasty interactions with list markup.
54875555 self.source.passthrough(tokens)
54885556 # .VE
54895557 # End of vertical sidebar.
54995567 elif cmd == "SO":
55005568 self.source.push_section(1, 'STANDARD OPTIONS')
55015569 self.source.pushline("l l l l.")
5502 self.source.TBL(".SE")
5570 self.source.TBL(TroffInterpreter.ctrl + "SE")
55035571 elif cmd == "OP":
55045572 # .OP cmdName dbName dbClass
55055573 # Start of description of a specific option. cmdName gives the
57985866 if name_synonyms.match(args[0]):
57995867 self.source.sectname = "Name"
58005868 # Copes with lines that are blank or a dot only (groff_mdoc...)
5801 while self.source.peekline() in ("", ".", "'"):
5869 while self.source.peekline() in ("", TroffInterpreter.ctrl, TroffInterpreter.ctrl_nobreak):
58025870 self.source.popline()
58035871 # Kluge -- it turns out that some web pages (like ash.1)
58045872 # don't use the mandoc macros. Instead they use a Linux-
58295897 self.source.declare_body_start()
58305898 # in case someone forgets to close a list (see mktemp.1).
58315899 for lst in self.liststack:
5832 self.source.pushline(".El")
5900 self.source.pushline(TroffInterpreter.ctrl + "El")
58335901 return True
58345902 if self.source.preamble:
58355903 self.source.preamble = False
58375905 elif command == "Ss":
58385906 # in case someone forgets to close a list
58395907 for lst in self.liststack:
5840 self.source.pushline(".El")
5908 self.source.pushline(TroffInterpreter.ctrl + "El")
58415909 return True
58425910 self.source.push_section(2, " ".join(args))
58435911 elif command == "Pp":
58465914 else:
58475915 self.source.emit("<sbr/>")
58485916 elif command == "Bd":
5849 if self.source.peekline() and self.source.peekline()[0:3] != ".Bl":
5917 if self.source.peekline() and self.source.peekline()[0:3] != TroffInterpreter.ctrl + "Bl":
58505918 self.source.begin_block("literallayout", remap="Bd")
58515919 elif command == "Ed":
58525920 if self.source.troff.nf:
61676235 return self.process_punct(args, self.sthook, 1)
61686236 elif cmd == "Sx":
61696237 title = " ".join(args)
6170 return self.process_punct(args, lambda x: ["<link linkend='%s'>%s</link>" % (self.source.id_from_title(" ".join(x)), " ".join(x))], 0)
6238 return self.process_punct(args, lambda x: ["<link role='Sx' linkend='%s'>%s</link>" % (self.source.id_from_title(" ".join(x)), " ".join(x))], 0)
61716239 elif cmd == "Sy":
61726240 return self.styleargs(args, "emphasis", 'remap="Sy"')
61736241 elif cmd == "Ta":
61836251 elif cmd == "Xc":
61846252 return self.replacemacro(args, "")
61856253 elif cmd == "Xo":
6254 self.source.warning("translation of .Xo/.Xc blocks is unreliable.")
61866255 return self.replacemacro(args, "")
61876256 elif cmd == "Xr":
61886257 return self.process_punct(args, self.xrhook, 0)
63246393 def preprocess(self, text):
63256394 return text
63266395 def postprocess(self, text):
6396 # It's not an error for Sx references to point elsewhere
6397 link_re = re_compile("<link role='Sx' linkend='([A-Za-z_]*)'>([A-Za-z_]*)</link>")
6398 while True:
6399 m = link_re.search(text)
6400 if m:
6401 linkstart = m.start(0)
6402 linkend = m.end(0)
6403 id = m.group(1)
6404 label = m.group(2)
6405 if self.source.id_exists(id):
6406 text = text[:linkstart+6] + text[linkstart+15:]
6407 else:
6408 self.source.warning("unresolved Sx label")
6409 text = text[:linkstart] + \
6410 "<emphasis role='Sx'>%s</emphasis>" % label + \
6411 text[linkend:]
6412 else:
6413 break
63276414 if not self.source.section_count:
63286415 raise LiftException("no mdoc section structure, can't be lifted.")
63296416 return text
65286615 # Some tags can turn into an itemized list.
65296616 if tokens[1] in ip_tag_mapping:
65306617 self.source.pushline(quoteargs(tokens))
6531 gather_itemizedlist(".IP", self.source,
6618 gather_itemizedlist(TroffInterpreter.ctrl + "IP", self.source,
65326619 ip_tag_mapping[tokens[1]])
65336620 # Otherwise, emit a variable list
65346621 else:
66356722 self.source.emit_variablelist("ip", args[1])
66366723 elif cmd == "bp":
66376724 self.source.pushline(quoteargs(tokens))
6638 gather_itemizedlist(".bp", self.source, "bullet")
6725 gather_itemizedlist(TroffInterpreter.ctrl + "bp", self.source, "bullet")
66396726 elif cmd == "np":
66406727 self.source.pushline(quoteargs(tokens))
6641 gather_orderedlist(".np", self.source)
6728 gather_orderedlist(TroffInterpreter.ctrl + "np", self.source)
66426729 elif cmd == "(q":
66436730 self.source.begin_block("blockquote", remap='(q')
66446731 elif cmd == ")q":
70207107 "the F register is turned on": Pod2ManInterpreter,
70217108 "ZN": XManInterpreter,
70227109 "Pn": XManInterpreter,
7110 "ny0": XManInterpreter,
70237111 # These are all of the supported Mwww tags
70247112 "URL": MwwwInterpreter,
70257113 "FTP": MwwwInterpreter,
70527140 def transfile(name, arguments, translate_data, trans_filename=None):
70537141 "Read input sources entire and transform them in memory."
70547142 if not arguments:
7055 outdoc = translate_data(name, "stdin", sys.stdin.read())
7143 outdoc = translate_data(name, "stdin", sys.stdin.read(), False)
70567144 if outdoc:
70577145 stdout.write(outdoc)
70587146 else:
70677155 stderr.write("%s: can't open tempfile" % name)
70687156 return True
70697157 try:
7070 outdoc = translate_data(name, file, indoc)
7158 outdoc = translate_data(name, file, indoc, len(arguments)>1)
70717159 except:
70727160 os.remove(tempfile)
70737161 # Pass the exception upwards
0 .\"Generated by db2man.xsl. Don't modify this, modify the source.
1 .de Sh \" Subsection
2 .br
3 .if t .Sp
4 .ne 5
5 .PP
6 \fB\\$1\fR
7 .PP
8 ..
9 .de Sp \" Vertical space (when we can't use .PP)
10 .if t .sp .5v
11 .if n .sp
12 ..
13 .de Ip \" List item
14 .br
15 .ie \\n(.$>=3 .ne \\$3
16 .el .ne 3
17 .IP "\\$1" \\$2
18 ..
19 .TH "DOCLIFTER" 1 "" "" ""
20 .SH NAME
0 .\" ** You probably do not want to edit this file directly **
1 .\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
2 .\" Instead of manually editing it, you probably should edit the DocBook XML
3 .\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
4 .TH "DOCLIFTER" "1" "12/25/2006" "" ""
5 .\" disable hyphenation
6 .nh
7 .\" disable justification (adjust text to left margin only)
8 .ad l
9 .SH "NAME"
2110 doclifter \- translate troff requests into DocBook
2211 .SH "SYNOPSIS"
23 .ad l
24 .hy 0
2512 .HP 10
2613 \fBdoclifter\fR [\-h\ \fIhintfile\fR] [\-e\ \fIencoding\fR] [\-q] [\-v] [\-I\ \fIpath\fR] [\-D\ \fItoken=type\fR] \fIfile\fR...
27 .ad
28 .hy
29
3014 .SH "DESCRIPTION"
31
32 .PP
33 \fBdoclifter\fR translates documents written in troff macros to DocBook\&. Structural subsets of the requests in \fBman\fR(7), \fBmdoc\fR(7), \fBms\fR(7), \fBme\fR(7), \fBmm\fR(7), and \fBtroff\fR(1) are supported\&.
34
35 .PP
36 The translation brings over all the structure of the original document at section, subsection, and paragraph level\&. Command and C function synopses are translated into DocBook markup, not just a verbatim display\&. Tables (TBL markup) are translated into DocBook table markup\&. PIC diagrams are translated into SVG\&. Troff\-level information that might have structural implications is preserved in XML comments\&.
37
38 .PP
39 Where possible, font\-change macros are translated into structural markup\&. \fBdoclifter\fR recognizes stereotyped patterns of markup and content (such as the use of italics in a FILES section to mark filenames) and lifts them\&. A means to edit, add, and save semantic hints about highlighting is supported\&.
40
41 .PP
42 Some cliches are recognized and lifted to structural markup even without highlighting\&. Patterns recognized include such things as URLs, email addresses, man page references, and C program listings\&.
43
44 .PP
45 The \&.in, \&.ta, and \&.ti requests are ignored\&. Thus, presentation\-level simulation of tables and columnar\-spacing effects using these will not be translated correctly\&.
46
47 .PP
48 Under some circumstances, \fBdoclifter\fR can even lift formatted manual pages and the text output produced by \fBlynx\fR(1) from HTML\&. If it finds no macros in the input, but does find a NAME section header, it tries to interpret the plain text as a manual page (skipping boilerplate headers and footers generated by \fBlynx\fR(1))\&. Translations produced in this way will be prone to miss structural features, but this fallback is good enough for simple man pages\&.
49
50 .PP
51 \fBdoclifter\fR does not do a perfect job, only about 95% of one; the last 5% has to be applied by a human recognizing patterns too subtle for a computer\&. But \fBdoclifter\fR will almost always produce translations that are good enough to be usable before hand\-hacking\&.
52
53 .PP
54 See the Troubleshooting section for discussion of how to solve document conversion problems\&.
55
15 .PP
16 \fBdoclifter\fR
17 translates documents written in troff macros to DocBook. Structural subsets of the requests in
18 \fBman\fR(7),
19 \fBmdoc\fR(7),
20 \fBms\fR(7),
21 \fBme\fR(7),
22 \fBmm\fR(7), and
23 \fBtroff\fR(1)
24 are supported.
25 .PP
26 The translation brings over all the structure of the original document at section, subsection, and paragraph level. Command and C function synopses are translated into DocBook markup, not just a verbatim display. Tables (TBL markup) are translated into DocBook table markup. PIC diagrams are translated into SVG. Troff\-level information that might have structural implications is preserved in XML comments.
27 .PP
28 Where possible, font\-change macros are translated into structural markup.
29 \fBdoclifter\fR
30 recognizes stereotyped patterns of markup and content (such as the use of italics in a FILES section to mark filenames) and lifts them. A means to edit, add, and save semantic hints about highlighting is supported.
31 .PP
32 Some cliches are recognized and lifted to structural markup even without highlighting. Patterns recognized include such things as URLs, email addresses, man page references, and C program listings.
33 .PP
34 The
35 .in,
36 .ta, and
37 .ti
38 requests are ignored. Thus, presentation\-level simulation of tables and columnar\-spacing effects using these will not be translated correctly.
39 .PP
40 Under some circumstances,
41 \fBdoclifter\fR
42 can even lift formatted manual pages and the text output produced by
43 \fBlynx\fR(1)
44 from HTML. If it finds no macros in the input, but does find a NAME section header, it tries to interpret the plain text as a manual page (skipping boilerplate headers and footers generated by
45 \fBlynx\fR(1)). Translations produced in this way will be prone to miss structural features, but this fallback is good enough for simple man pages.
46 .PP
47 \fBdoclifter\fR
48 does not do a perfect job, merely an extremely good one. Final polish should be applied by a human being capable of recognizing patterns too subtle for a computer. But
49 \fBdoclifter\fR
50 will almost always produce translations that are good enough to be usable before hand\-hacking.
51 .PP
52 See the
53 Troubleshooting
54 section for discussion of how to solve document conversion problems.
5655 .SH "OPTIONS"
57
58 .PP
59 If called without arguments \fBdoclifter\fR acts as a filter, translating troff source input on standard input to DocBook markup on standard output\&. If called with arguments, each argument file is translated separately (but hints are retained, see below); the suffix \fI\&.xml\fR is given to the translated output\&.
60
56 .PP
57 If called without arguments
58 \fBdoclifter\fR
59 acts as a filter, translating troff source input on standard input to DocBook markup on standard output. If called with arguments, each argument file is translated separately (but hints are retained, see below); the suffix
60 \fI.xml\fR
61 is given to the translated output.
6162 .TP
6263 \-h
63 Name a file to which information on semantic hints gathered during analysis should be written\&.
64
64 Name a file to which information on semantic hints gathered during analysis should be written.
6565 .TP
6666 \-I
67 The \fB\-I\fR option adds its argument to the include path used when docfilter searches for inclusions\&. The include path is initially just the current directory\&.
68
67 The
68 \fB\-I\fR
69 option adds its argument to the include path used when docfilter searches for inclusions. The include path is initially just the current directory.
6970 .TP
7071 \-D
71 The \fB\-D\fR allows you to post a hint\&. This may be useful, for example, if \fBdoclifter\fR is mis\-parsing a synopsis because it doesn't recognize a token as a command\&. This hint is merged after hints in the input source have been read\&.
72
72 The
73 \fB\-D\fR
74 allows you to post a hint. This may be useful, for example, if
75 \fBdoclifter\fR
76 is mis\-parsing a synopsis because it doesn't recognize a token as a command. This hint is merged after hints in the input source have been read.
7377 .TP
7478 \-e
75 The \fB\-e\fR allows you to set the encoding field to be emitted in the output XML\&. It defaults to ISO\-8859\-1 (Latin\-1)\&.
76
79 The
80 \fB\-e\fR
81 allows you to set the encoding field to be emitted in the output XML. It defaults to ISO\-8859\-1 (Latin\-1).
7782 .TP
7883 \-q
79 Normally, requests that \fBdoclifter\fR could not interpret (usually because they're presentation\-level) are passed through to XML comments in the output\&. The \-q option suppresses this\&. It also suppresses listing of macros\&. Messages about requests that are unrecognized or cannot be translated go to standard error whatever the state of this option\&. This option is intended to reduce clutter when you believe you have a clean lift of a document and want to lose the troff legacy\&.
80
84 Normally, requests that
85 \fBdoclifter\fR
86 could not interpret (usually because they're presentation\-level) are passed through to XML comments in the output. The \-q option suppresses this. It also suppresses listing of macros. Messages about requests that are unrecognized or cannot be translated go to standard error whatever the state of this option. This option is intended to reduce clutter when you believe you have a clean lift of a document and want to lose the troff legacy.
8187 .TP
8288 \-v
83 The \-v option makes \fBdoclifter\fR noisier about what it's doing\&. This is mainly useful for debugging\&.
84
89 The \-v option makes
90 \fBdoclifter\fR
91 noisier about what it's doing. This is mainly useful for debugging.
8592 .SH "TRANSLATION RULES"
86
87 .PP
88 Overall, you can expect that font changes will be turned into Emphasis macros with a Remap attribute taken from the troff font name\&. The basic font names are R, I, B, U, CW, and SM\&.
89
90 .PP
91 Troff and macro\-package special character escapes are mapped into ISO character entities\&.
92
93 .PP
94 When \fBdoclifter\fR encounters a \&.so directive, it searches for the file\&. If it can get read access to the file, and open it, and the file consists entirely of command lines and comments, then it is included\&. If any of these conditions fails, an entity reference for it is generated\&.
95
96 .PP
97 \fBdoclifter\fR performs special parsing when it recognizes a display such as is generated by \&.DS/\&.DE\&. It repeatedly tries to parse first a function synopsis, and then plain text off what remains in the display\&. Thus, most inline C function prototypes will be lifted to structured markup\&.
98
93 .PP
94 Overall, you can expect that font changes will be turned into
95 Emphasis
96 macros with a
97 Remap
98 attribute taken from the troff font name. The basic font names are R, I, B, U, CW, and SM.
99 .PP
100 Troff and macro\-package special character escapes are mapped into ISO character entities.
101 .PP
102 When
103 \fBdoclifter\fR
104 encounters a
105 .so
106 directive, it searches for the file. If it can get read access to the file, and open it, and the file consists entirely of command lines and comments, then it is included. If any of these conditions fails, an entity reference for it is generated.
107 .PP
108 \fBdoclifter\fR
109 performs special parsing when it recognizes a display such as is generated by
110 .DS/.DE. It repeatedly tries to parse first a function synopsis, and then plain text off what remains in the display. Thus, most inline C function prototypes will be lifted to structured markup.
99111 .PP
100112 Some notes on specific translations:
101
102113 .SS "Man Translation"
103
104 .PP
105 \fBdoclifter\fR does a good job on most man pages, It knows about the extended UR/UE/UN requests supported under Linux\&. If any \&.UR request is present, it will translate these but not wrap URLs outide them with Ulink tags\&. It also knows about the extended \&.L (literal) font markup from Bell Labs Version 8, and its friends\&.
106
107 .PP
108 The \&.TH macro is used to generate a RefMeta section\&. If present, the date/source/manual arguments (see \fBman\fR(7)) are wrapped in RefMiscInfo tag pairs with those class attributes\&. Note that \fBdoclifter\fR does not change the date\&.
109
110 .PP
111 \fBdoclifter\fR performs special parsing when it recognizes a synopsis section\&. It repeatedly tries to parse first a function synopsis, then a command synopsis , and then plain text off what remains in the section\&.
112
113 .PP
114 The following man macros are translated into emphasis tags with a remap attribute: \&.B, \&.I, \&.L, \&.BI, \&.BR, \&.BL, \&.IB, \&.IR, \&.IL, \&.RB, \&.RI, \&.RL, \&.LB, \&.LI, \&.LR, \&.SB, \&.SM\&. Some stereotyped patterns involving these macros are recognized and turned into semantic markup\&.
115
116 .PP
117 The following macros are translated into paragraph breaks: \&.LP, \&.PP, \&.P, \&.HP, and the single\-argument form of \&.IP\&.
118
119 .PP
120 The two\-argument form of \&.IP is translated either as a VariableList (usually) or ItemizedList (if the tag is the troff bullet or square character)\&.
121
122 .PP
123 The following macros are translated semantically: \&.SH,\&.SS, \&.TP, \&.UR, \&.UE, \&.UN, \&.IX\&. A \&.UN call just before \&.SH or \&.SS sets the ID for the new section\&.
124
125 .PP
126 The \\*R, \\*(Tm, \\*(lq, and \\*(rq symbols are translated\&.
127
128 .PP
129 The following (purely presentation\-level) macros are ignored: \&.PD,\&.DT\&.
130
131 .PP
132 The \&.RS/\&.RE macros are translated when they occur within list structure (\&.TP or \&.IP); the result is nested lists\&. A few other \&.RS/\&.RE cliches are also lifted; when the program cannot find a matching cliche, it will issue a warning\&. Use the \fB\-v\fR option to get line numbers on these\&.
133
134 .PP
135 \&.DS/\&.DE is not part of the documented man macro set, but is recognized because it shows up with some frequency on legacy man pages from older Unixes\&.
136
137 .PP
138 Certain extension macros originally defined under Ultrix are translated structurally, including those that occasionally show up on the manual pages of Linux and other open\-source Unixes\&. \&.EX/\&.EE, \&.Ds/\&.De, \&.NT/\&.NE, \&.PN, and \&.MS are translated structurally\&. parsed as a display\&.
139
140 .PP
141 The following extension macros used by the X distribution are also recognized and translated structurally: FD, FN, IN, ZN, hN, and \&.C{/\&.C}
142
143 .PP
144 When the man macros are active, any \&.Pp macro definition containing the request \&.PP will be ignored\&. and all instances of \&.Pp replaced with \&.PP\&. Similarly, \&.Tp will be replaced with \&.TP\&. This is the least painful way to deal with some frequently\-encountered stereotyped wrapper definitions that would otherwise cause serious interpretation problems
145
146 .PP
147 On some man pages paragraphed text is found in a Synopsis section as an annotation or description of the syntax\&. The DocBook DTD has no way to support this, so \fBdoclifter\fR ends the Synopsis section at that point and inserts a first\-level "Synopsis Notes" section\&.
148
114 .PP
115 \fBdoclifter\fR
116 does a good job on most man pages, It knows about the extended
117 UR/UE/UN
118 requests supported under Linux. If any
119 .UR
120 request is present, it will translate these but not wrap URLs outide them with
121 Ulink
122 tags. It also knows about the extended
123 .L
124 (literal) font markup from Bell Labs Version 8, and its friends.
125 .PP
126 The
127 .TH
128 macro is used to generate a
129 RefMeta
130 section. If present, the date/source/manual arguments (see
131 \fBman\fR(7)) are wrapped in
132 RefMiscInfo
133 tag pairs with those class attributes. Note that
134 \fBdoclifter\fR
135 does not change the date.
136 .PP
137 \fBdoclifter\fR
138 performs special parsing when it recognizes a synopsis section. It repeatedly tries to parse first a function synopsis, then a command synopsis , and then plain text off what remains in the section.
139 .PP
140 The following man macros are translated into emphasis tags with a remap attribute:
141 .B,
142 .I,
143 .L,
144 .BI,
145 .BR,
146 .BL,
147 .IB,
148 .IR,
149 .IL,
150 .RB,
151 .RI,
152 .RL,
153 .LB,
154 .LI,
155 .LR,
156 .SB,
157 .SM. Some stereotyped patterns involving these macros are recognized and turned into semantic markup.
158 .PP
159 The following macros are translated into paragraph breaks:
160 .LP,
161 .PP,
162 .P,
163 .HP, and the single\-argument form of
164 .IP.
165 .PP
166 The two\-argument form of
167 .IP
168 is translated either as a
169 VariableList
170 (usually) or
171 ItemizedList
172 (if the tag is the troff bullet or square character).
173 .PP
174 The following macros are translated semantically:
175 .SH,.SS,
176 .TP,
177 .UR,
178 .UE,
179 .UN,
180 .IX. A
181 .UN
182 call just before
183 .SH
184 or
185 .SS
186 sets the ID for the new section.
187 .PP
188 The
189 \\*R,
190 \\*(Tm,
191 \\*(lq, and
192 \\*(rq
193 symbols are translated.
194 .PP
195 The following (purely presentation\-level) macros are ignored:
196 .PD,.DT.
197 .PP
198 The
199 .RS/.RE
200 macros are translated differently depending on whether or not they precede list markup. When
201 .RS
202 occurs just before
203 .TP
204 or
205 .IP
206 the result is nested lists. Otherwise, the
207 .RS/.RE
208 pair is translated into a Blockquote tag\-pair.
209 .PP
210 .DS/.DE
211 is not part of the documented man macro set, but is recognized because it shows up with some frequency on legacy man pages from older Unixes.
212 .PP
213 Certain extension macros originally defined under Ultrix are translated structurally, including those that occasionally show up on the manual pages of Linux and other open\-source Unixes.
214 .EX/.EE
215 (and the symptoms
216 .Ex/.Ee),
217 .Ds/.De,.NT/.NE,
218 .PN, and
219 .MS
220 are translated structurally.
221 .PP
222 The following extension macros used by the X distribution are also recognized and translated structurally:
223 .FD,
224 .FN,
225 .IN,
226 .ZN,
227 .hN, and
228 .C{/.C}The
229 .TA
230 and
231 IN
232 requests are ignored.
233 .PP
234 When the man macros are active, any
235 .Pp
236 macro definition containing the request
237 .PP
238 will be ignored. and all instances of
239 .Pp
240 replaced with
241 .PP. Similarly,
242 .Tp
243 will be replaced with
244 .TP. This is the least painful way to deal with some frequently\-encountered stereotyped wrapper definitions that would otherwise cause serious interpretation problems
149245 .PP
150246 Known problem areas with man translation:
151
152247 .TP 3
153248 \(bu
154 Weird uses of \&.TP\&. These will sometime generate invalid XML and sometimes result in a FIX\-ME comment in the generated XML
249 Weird uses of
250 .TP. These will sometime generate invalid XML and sometimes result in a FIX\-ME comment in the generated XML
155251 .TP
156252 \(bu
157 It is debatable how the man macros \&.HP and \&.IP without tag should be translated\&. We treat them as an ordinary paragraph break\&. We could visually simulate a hanging paragraph with list markup, but this would not be a structural translation\&.
158 .LP
159
253 It is debatable how the man macros
254 .HP
255 and
256 .IP
257 without tag should be translated. We treat them as an ordinary paragraph break. We could visually simulate a hanging paragraph with list markup, but this would not be a structural translation.
160258 .SS "Pod2man Translation"
161
162 .PP
163 \fBdoclifter\fR recognizes the extension macros produced by \fBpod2man\fR (\&.Sh, \&.Sp, \&.Ip, \&.Vb, \&.Ve) and translates them structurally\&.
164
165 .PP
166 The results of lifting pages produced by \fBpod2man\fR should be checked carefully by eyeball, especially the rendering of command and function synopses\&. \fBPod2man\fR generates rather perverse markup; \fBdoclifter\fR's struggle to untangle it is sometimes in vain\&.
167
168 .PP
169 If possible, generate your DocBook from the POD sources\&. There is a pod2docbook module on CPAN that does this\&.
170
259 .PP
260 \fBdoclifter\fR
261 recognizes the extension macros produced by
262 \fBpod2man\fR
263 (.Sh,
264 .Sp,
265 .Ip,
266 .Vb,
267 .Ve) and translates them structurally.
268 .PP
269 The results of lifting pages produced by
270 \fBpod2man\fR
271 should be checked carefully by eyeball, especially the rendering of command and function synopses.
272 \fBPod2man\fR
273 generates rather perverse markup;
274 \fBdoclifter\fR's struggle to untangle it is sometimes in vain.
275 .PP
276 If possible, generate your DocBook from the POD sources. There is a
277 pod2docbook
278 module on CPAN that does this.
171279 .SS "Tkman Translation"
172
173 .PP
174 \fBdoclifter\fR recognizes the extension macros used by the Tcl/Tk documentation system: \&.AP, \&.AS, \&.BS, \&.BE, \&.CS, \&.CE, \&.DS, \&.DE, \&.SO, \&.SE, \&.UL, \&.VS, \&.VE\&. The \&.AP, \&.CS, \&.CE, \&.SO, \&.SE, and \&.UL macros are translated structurally\&.
175
280 .PP
281 \fBdoclifter\fR
282 recognizes the extension macros used by the Tcl/Tk documentation system:
283 .AP,
284 .AS,
285 .BS,
286 .BE,
287 .CS,
288 .CE,
289 .DS,
290 .DE,
291 .SO,
292 .SE,
293 .UL,
294 .VS,
295 .VE. The
296 .AP,
297 .CS,
298 .CE,
299 .SO,
300 .SE, and
301 .UL
302 macros are translated structurally.
176303 .SS "Mandoc Translation"
177
178 .PP
179 \fBdoclifter\fR should be able to do an excellent job on most \fBmdoc\fR(7) pages, because this macro package expresses a lot of semantic structure\&.
180
181 .PP
182 Known problems with mandoc translation: All \&.Bd/\&.Ed display blocks are translated as LiteralLayout tag pairs\&.
183
304 .PP
305 \fBdoclifter\fR
306 should be able to do an excellent job on most
307 \fBmdoc\fR(7)
308 pages, because this macro package expresses a lot of semantic structure.
309 .PP
310 Known problems with mandoc translation: All
311 .Bd/.Ed
312 display blocks are translated as
313 LiteralLayout
314 tag pairs.
184315 .SS "Ms Translation"
185
186 .PP
187 \fBdoclifter\fR does a good job on most ms pages\&. One weak spot to watch out for is the generation of Author and Affiliation tags\&. The heuristics used to mine this information out of the \&.AU section work for authors who format their names in the way usual for English (e\&.g\&. "M\&. E\&. Lesk", "Eric S\&. Raymond") but are quite brittle\&.
188
189 .PP
190 For a document to be recognized as containing ms markup, it must have the extension \fI\&.ms\fR\&. This avoids problems with false positives\&.
191
192 .PP
193 The \&.TL, \&.AU, \&.AI, and \&.AE macros turn into article metainformation in the expected way\&. The \&.PP, \&.LP, \&.SH, and \&.NH macros turn into paragraph and section structure\&. The tagged form of \&.IP is translated either as a VariableList (usually) or ItemizedList (if the tag is the troff bullet or square character); the untagged version is treated as an ordinary paragraph break\&.
194
195 .PP
196 The \&.DS/\&.DE pair is translated to a LiteralLayout tag pair\&. The \&.FS/\&.FE pair is translated to a Footnote tag pair\&. The \&.QP/\&.QS/\&.QE requests define BlockQuotes\&.
197
198 .PP
199 The \&.UL font change is mapped to U\&. \&.SM and \&.LG become numeric plus or minus size steps suffixed to the Remap attribute\&.
200
201 .PP
202 The \&.B1 and \&.B2 box macros are translated to a Sidebar tag pair\&.
203
204 .PP
205 All macros relating to page footers, multicolumn mode, and keeps are ignored (\&.ND, \&.DA, \&.1C, \&.2C, \&.MC, \&.BX, \&.KS, \&.KE, \&.KF)\&. The \&.R, \&.RS, and \&.RE macros are ignored as well\&.
206
316 .PP
317 \fBdoclifter\fR
318 does a good job on most ms pages. One weak spot to watch out for is the generation of Author and Affiliation tags. The heuristics used to mine this information out of the
319 .AU
320 section work for authors who format their names in the way usual for English (e.g. "M. E. Lesk", "Eric S. Raymond") but are quite brittle.
321 .PP
322 For a document to be recognized as containing ms markup, it must have the extension
323 \fI.ms\fR. This avoids problems with false positives.
324 .PP
325 The
326 .TL,
327 .AU,
328 .AI, and
329 .AE
330 macros turn into article metainformation in the expected way. The
331 .PP,
332 .LP,
333 .SH, and
334 .NH
335 macros turn into paragraph and section structure. The tagged form of
336 .IP
337 is translated either as a
338 VariableList
339 (usually) or
340 ItemizedList
341 (if the tag is the troff bullet or square character); the untagged version is treated as an ordinary paragraph break.
342 .PP
343 The
344 .DS/.DE
345 pair is translated to a
346 LiteralLayout
347 tag pair. The
348 .FS/.FE
349 pair is translated to a
350 Footnote
351 tag pair. The
352 .QP/.QS/.QE
353 requests define
354 BlockQuotes.
355 .PP
356 The
357 .UL
358 font change is mapped to U.
359 .SM
360 and
361 .LG
362 become numeric plus or minus size steps suffixed to the
363 Remap
364 attribute.
365 .PP
366 The
367 .B1
368 and
369 .B2
370 box macros are translated to a
371 Sidebar
372 tag pair.
373 .PP
374 All macros relating to page footers, multicolumn mode, and keeps are ignored (.ND,
375 .DA,
376 .1C,
377 .2C,
378 .MC,
379 .BX,
380 .KS,
381 .KE,
382 .KF). The
383 .R,
384 .RS, and
385 .RE
386 macros are ignored as well.
207387 .SS "Me Translation"
208
209 .PP
210 Translation of me documents tends to produce crude results that need a lot of hand\-hacking\&. The format has little usable structure, and documents written in it tend to use a lot of low\-level troff macros; both these properties tend to confuse \fBdoclifter\fR\&.
211
212 .PP
213 For a document to be recognized as containing me markup, it must have the extension \fI\&.me\fR\&. This avoids problems with false positives\&.
214
215 .PP
216 The following macros are translated into paragraph breaks: \&.lp, \&.pp\&. The \&.ip macro is translated into a VariableList\&. The \&.bp macro is translated into an ItemizedList\&. The \&.np macro is translated into an OrderedList\&.
217
218 .PP
219 The b, i, and r fonts are mapped to emphasis tags with B, I, and R Remap attributes\&. The \&.rb ("real bold") font is treated the same as \&.b\&.
220
221 .PP
222 \&.q(/\&.q) is translated structurally\&.
223
224 .PP
225 Most other requests are ignored\&.
226
388 .PP
389 Translation of me documents tends to produce crude results that need a lot of hand\-hacking. The format has little usable structure, and documents written in it tend to use a lot of low\-level troff macros; both these properties tend to confuse
390 \fBdoclifter\fR.
391 .PP
392 For a document to be recognized as containing me markup, it must have the extension
393 \fI.me\fR. This avoids problems with false positives.
394 .PP
395 The following macros are translated into paragraph breaks:
396 .lp,
397 .pp. The
398 .ip
399 macro is translated into a
400 VariableList. The
401 .bp
402 macro is translated into an
403 ItemizedList. The
404 .np
405 macro is translated into an
406 OrderedList.
407 .PP
408 The b, i, and r fonts are mapped to emphasis tags with B, I, and R
409 Remap
410 attributes. The
411 .rb
412 ("real bold") font is treated the same as
413 .b.
414 .PP
415 .q(/.q)
416 is translated structurally.
417 .PP
418 Most other requests are ignored.
227419 .SS "Mm Translation"
228
229 .PP
230 Memorandum Macros documents translate well, as these macros carry a lot of structural information\&. The translation rules are tuned for Memorandum or Released Paper styles; information associated with external\-letter style will be preserved in comments\&.
231
232 .PP
233 For a document to be recognized as containing mm markup, it must have the extension \fI\&.mm\fR\&. This avoids problems with false positives\&.
234
235 .PP
236 The following highlight macros are translated int Emphasis tags: \&.B, \&.I, \&.R, \&.BI, \&.BR, \&.IB, \&.IR, \&.RB, \&.RI\&.
237
238 .PP
239 The following macros are structurally translated: \&.AE, \&.AF, \&.AL, \&.RL, \&.APP, \&.APPSK, \&.AS, \&.AT, \&.AU, \&.B1, \&.B2, \&.BE, \&.BL, \&.ML, \&.BS, \&.BVL, \&.VL, \&.DE, \&.DL \&.DS, \&.FE, \&.FS, \&.H, \&.HU, \&.IA, \&.IE, \&.IND, \&.LB, \&.LC, \&.LE, \&.LI, \&.P, \&.RF, \&.SM, \&.TL, \&.VERBOFF, \&.VERBON, \&.WA, \&.WE\&.
240
420 .PP
421 Memorandum Macros documents translate well, as these macros carry a lot of structural information. The translation rules are tuned for Memorandum or Released Paper styles; information associated with external\-letter style will be preserved in comments.
422 .PP
423 For a document to be recognized as containing mm markup, it must have the extension
424 \fI.mm\fR. This avoids problems with false positives.
425 .PP
426 The following highlight macros are translated int Emphasis tags:
427 .B,
428 .I,
429 .R,
430 .BI,
431 .BR,
432 .IB,
433 .IR,
434 .RB,
435 .RI.
436 .PP
437 The following macros are structurally translated:
438 .AE,
439 .AF,
440 .AL,
441 .RL,
442 .APP,
443 .APPSK,
444 .AS,
445 .AT,
446 .AU,
447 .B1,
448 .B2,
449 .BE,
450 .BL,
451 .ML,
452 .BS,
453 .BVL,
454 .VL,
455 .DE,
456 .DL.DS,
457 .FE,
458 .FS,
459 .H,
460 .HU,
461 .IA,
462 .IE,
463 .IND,
464 .LB,
465 .LC,
466 .LE,
467 .LI,
468 .P,
469 .RF,
470 .SM,
471 .TL,
472 .VERBOFF,
473 .VERBON,
474 .WA,
475 .WE.
241476 .PP
242477 The following macros are ignored:
243
244 .PP
245 \~\&.)E, \&.1C, \&.2C, \&.AST, \&.AV, \&.AVL, \&.COVER, \&.COVEND, \&.EF, \&.EH, \&.EDP, \&.EPIC, \&.FC, \&.FD, \&.HC, \&.HM, \&.GETR, \&.GETST, \&.HM, \&.INITI, \&.INITR, \&.INDP, \&.ISODATE, \&.MT, \&.NS, \&.ND, \&.OF, \&.OH, \&.OP, \&.PGFORM, \&.PGNH, \&.PE, \&.PF, \&.PH, \&.RP, \&.S, \&.SA, \&.SP, \&.SG, \&.SK, \&.TAB, \&.TB, \&.TC, \&.VM, \&.WC\&.
246
247 .PP
248 The following macros generate warnings: \&.EC, \&.EX, \&.FG, \&.GETHN, \&.GETPN, \&.GETR, \&.GETST, \&.LT, \&.LD, \&.LO, \&.MOVE, \&.MULB, \&.MULN, \&.MULE, \&.NCOL, \&.nP, \&.PIC, \&.RD, \&.RS, \&.RE, \&.SETR
249
250 .PP
251 \~\&.BS/\&.BE and \&.IA/\&.IE pairs are passed through\&. The text inside them may need to be deleted or moved\&.
252
253 .PP
254 The mark argument of \&.ML is ignored; the following list id formatted as a normal ItemizedList\&.
255
256 .PP
257 The contents of \&.DS/\&.DE or \&.DF/\&.DE gets turned into a Screen display\&. Arguments controlling presentation\-level formatting are ignored\&.
258
478 .PP
479 \ .)E,
480 .1C,
481 .2C,
482 .AST,
483 .AV,
484 .AVL,
485 .COVER,
486 .COVEND,
487 .EF,
488 .EH,
489 .EDP,
490 .EPIC,
491 .FC,
492 .FD,
493 .HC,
494 .HM,
495 .GETR,
496 .GETST,
497 .HM,
498 .INITI,
499 .INITR,
500 .INDP,
501 .ISODATE,
502 .MT,
503 .NS,
504 .ND,
505 .OF,
506 .OH,
507 .OP,
508 .PGFORM,
509 .PGNH,
510 .PE,
511 .PF,
512 .PH,
513 .RP,
514 .S,
515 .SA,
516 .SP,
517 .SG,
518 .SK,
519 .TAB,
520 .TB,
521 .TC,
522 .VM,
523 .WC.
524 .PP
525 The following macros generate warnings:
526 .EC,
527 .EX,
528 .FG,
529 .GETHN,
530 .GETPN,
531 .GETR,
532 .GETST,
533 .LT,
534 .LD,
535 .LO,
536 .MOVE,
537 .MULB,
538 .MULN,
539 .MULE,
540 .NCOL,
541 .nP,
542 .PIC,
543 .RD,
544 .RS,
545 .RE,
546 .SETR
547 .PP
548 \ .BS/.BE
549 and
550 .IA/.IE
551 pairs are passed through. The text inside them may need to be deleted or moved.
552 .PP
553 The mark argument of
554 .ML
555 is ignored; the following list id formatted as a normal
556 ItemizedList.
557 .PP
558 The contents of
559 .DS/.DE
560 or
561 .DF/.DE
562 gets turned into a
563 Screen
564 display. Arguments controlling presentation\-level formatting are ignored.
259565 .SS "Mwww Translation"
260
261 .PP
262 The mwww macros are an extension to the man macros supported by \fBgroff\fR(1) for producing web pages\&.
263
264 .PP
265 The URL, FTP, MAILTO, FTP, IMAGE, TAG tags are translated structurally\&. The HTMLINDEX, BODYCOLOR, BACKGROUND, HTML, an LINE tags are ignored\&.
266
566 .PP
567 The mwww macros are an extension to the man macros supported by
568 \fBgroff\fR(1)
569 for producing web pages.
570 .PP
571 The
572 URL,
573 FTP,
574 MAILTO,
575 FTP,
576 IMAGE,
577 TAG
578 tags are translated structurally. The
579 HTMLINDEX,
580 BODYCOLOR,
581 BACKGROUND,
582 HTML, an
583 LINE
584 tags are ignored.
267585 .SS "TBL Translation"
268
269 .PP
270 All structural features of TBL tables are translated, including both horizontal and vertical spanning with ‘s’ and ‘^’\&. The ‘l’, ‘r’, and ‘c’ formats are supported; the ‘n’ column format is rendered as ‘r’\&. Line continuations with T{ and T} are handled correctly\&. So is \&.TH\&.
271
272 .PP
273 The expand, box, doublebox, allbox, center, left, and right options are supported\&. The GNU synonyms frame and doubleframe are also recognized\&. But the distinction between single and double rules and boxes is lost\&.
274
275 .PP
276 Table continuations (\&.T&) are not supported\&.
277
278 .PP
279 If the first nonempty line of text immediately before a table is boldfaced, it is interpreted as a ctitle for the table and the table is generated using a table and title\&. Otherwise the table is translated with infornaltable\&.
280
281 .PP
282 Most other presentation\-level TBL commands are ignored\&. The ‘b’ format qualifier is processed, but point size and width qualifiers are not\&.
283
586 .PP
587 All structural features of TBL tables are translated, including both horizontal and vertical spanning with \(oqs\(cq and \(oq^\(cq. The \(oql\(cq, \(oqr\(cq, and \(oqc\(cq formats are supported; the \(oqn\(cq column format is rendered as \(oqr\(cq. Line continuations with
588 T{
589 and
590 T}
591 are handled correctly. So is
592 .TH.
593 .PP
594 The
595 expand,
596 box,
597 doublebox,
598 allbox,
599 center,
600 left, and
601 right
602 options are supported. The GNU synonyms
603 frame
604 and
605 doubleframe
606 are also recognized. But the distinction between single and double rules and boxes is lost.
607 .PP
608 Table continuations (.T&) are not supported.
609 .PP
610 If the first nonempty line of text immediately before a table is boldfaced, it is interpreted as a title for the table and the table is generated using a
611 table
612 and
613 title. Otherwise the table is translated with
614 infornaltable.
615 .PP
616 Most other presentation\-level TBL commands are ignored. The \(oqb\(cq format qualifier is processed, but point size and width qualifiers are not.
284617 .SS "Pic Translation"
285
286 .PP
287 PIC sections are translated to SVG\&. doclifter calls out to \fBpic2plot\fR(1) to accomplish this; you must have that utility installed for PIC translation to work\&.
288
618 .PP
619 PIC sections are translated to SVG.
620 doclifter
621 calls out to
622 \fBpic2plot\fR(1)
623 to accomplish this; you must have that utility installed for PIC translation to work.
289624 .SS "Eqn Translation"
290
291 .PP
292 EQN sections are passed through enclosed in LiteralLayout tags\&. After a delim statement has been seen, inline eqn delimiters are translated into an XML processing instruction\&. Exception: inline eqn equations consisting of a single character are translated to an Emphasis with a Role attribute of eqn\&.
293
625 .PP
626 EQN sections are passed through enclosed in
627 LiteralLayout
628 tags. After a delim statement has been seen, inline eqn delimiters are translated into an XML processing instruction. Exception: inline eqn equations consisting of a single character are translated to an
629 Emphasis
630 with a Role attribute of eqn.
294631 .SS "Troff Translation"
295
296 .PP
297 The troff translation is meant only to support interpretation of the macro sets\&. It is not useful standalone\&.
298
299 .PP
300 The \&.nf and \&.fi macros are interpreted as literal\-layout boundaries\&. Calls to the \&.so macro either cause inclusion or are translated into XML entity inclusions (see above)\&. Calls to the \&.ul and \&.cu macros cause following lines to be wrapped in an Emphasis tag with a Remap attribute of "U"\&. Calls to \&.ft generate corresponding start or end emphasis tags\&. Calls to \&.tr cause character translation on output\&. Calls to \&.bp generate a BeginPage tag\&. Calls to \&.sp generate a paragraph break (in paragraphed text only)\&. These are the only troff requests we translate to DocBook\&. The rest of the troff emulation exists because macro packages use it internally to expand macros into elements that might be structural\&.
301
302 .PP
303 Requests relating to macro definitions and strings (\&.ds, \&.as, \&.de, \&.am, \&.rm, \&.rn, \&.em) are processed and expanded\&. The \&.ig macro is also processed\&.
304
305 .PP
306 Conditional macros (\&.if, \&.ie, \&.el) are handled\&. The built\-in conditions o, n, t, e, and c are evaluated as if for nroff on page one of a document\&. String comparisons are evaluated by straight textual comparison\&. All numeric expressions evaluate to true\&.
307
308 .PP
309 The extended groff requests ab, als, do, nop, and return and shift are interpreted\&. Its \&.PSPIC extension is translated into a MediaObject\&.
310
311 .PP
312 The \&.tm macro writes its arguments to standard error (with \fB\-t\fR)\&. The \&.pm macro reports on defined macros and strings\&. These facilities may aid in debugging your translation\&.
313
314 .PP
315 All other troff requests are ignored but passed through into XML comments\&. A few (such as \&.ce) also trigger a warning message\&.
316
632 .PP
633 The troff translation is meant only to support interpretation of the macro sets. It is not useful standalone.
634 .PP
635 The
636 .nf
637 and
638 .fi
639 macros are interpreted as literal\-layout boundaries. Calls to the
640 .so
641 macro either cause inclusion or are translated into XML entity inclusions (see above). Calls to the
642 .ul
643 and
644 .cu
645 macros cause following lines to be wrapped in an
646 Emphasis
647 tag with a
648 Remap
649 attribute of "U". Calls to
650 .ft
651 generate corresponding start or end emphasis tags. Calls to
652 .tr
653 cause character translation on output. Calls to
654 .bp
655 generate a
656 BeginPage
657 tag. Calls to
658 .sp
659 generate a paragraph break (in paragraphed text only). These are the only troff requests we translate to DocBook. The rest of the troff emulation exists because macro packages use it internally to expand macros into elements that might be structural.
660 .PP
661 Requests relating to macro definitions and strings (.ds,
662 .as,
663 .de,
664 .am,
665 .rm,
666 .rn,
667 .em) are processed and expanded. The
668 .ig
669 macro is also processed.
670 .PP
671 Conditional macros (.if,
672 .ie,
673 .el) are handled. The built\-in conditions o, n, t, e, and c are evaluated as if for
674 nroff
675 on page one of a document. String comparisons are evaluated by straight textual comparison. All numeric expressions evaluate to true.
676 .PP
677 The extended
678 groff
679 requests
680 cc,
681 c2,
682 ab,
683 als,
684 do,
685 nop, and
686 return
687 and
688 shift
689 are interpreted. Its
690 .PSPIC
691 extension is translated into a
692 MediaObject.
693 .PP
694 The
695 .tm
696 macro writes its arguments to standard error (with
697 \fB\-t\fR). The
698 .pm
699 macro reports on defined macros and strings. These facilities may aid in debugging your translation.
700 .PP
701 All other troff requests are ignored but passed through into XML comments. A few (such as
702 .ce) also trigger a warning message.
317703 .SH "SEMANTIC ANALYSIS"
318
319 .PP
320 \fBdoclifter\fR keeps two lists of semantic hints that it picks up from analyzing source documents (especially from parsing command and function synopses)\&. The local list includes:
321
704 .PP
705 \fBdoclifter\fR
706 keeps two lists of semantic hints that it picks up from analyzing source documents (especially from parsing command and function synopses). The local list includes:
322707 .TP 3
323708 \(bu
324709 Names of function formal arguments
325710 .TP
326711 \(bu
327712 Names of command options
328 .LP
329
330 .PP
331 Local hints are used to mark up the individual page from which they are gathered\&. The global list includes:
332
713 .PP
714 Local hints are used to mark up the individual page from which they are gathered. The global list includes:
333715 .TP 3
334716 \(bu
335717 Names of functions
339721 .TP
340722 \(bu
341723 Names of function return types
342 .LP
343
344 .PP
345 If \fBdoclifter\fR is applied to multiple files, the global list is retained in memory\&. You can dump a report of global hints at the end of the with the \fB\-h\fR\&. The format of the hints is as follows:
346
724 .PP
725 If
726 \fBdoclifter\fR
727 is applied to multiple files, the global list is retained in memory. You can dump a report of global hints at the end of the run with the
728 \fB\-h\fR
729 option. The format of the hints is as follows:
730 .sp
347731 .nf
348
349 \~\&.\\" | mark <phrase> as <markup>
350
732 \ .\" | mark <phrase> as <markup>
351733 .fi
352
353 .PP
354 where \fB<phrase>\fR is an item of text and \fB<markup>\fR is the DocBook markup text it should be wrapped with whenever it appeared either highlighted or as a word surrounded by whitespace in the source text\&.
355
356 .PP
357 Hints derived from earlier files are also applied to later ones\&. This behavior may be useful when lifting collections of documents that apply to a function or command library\&. What should be more useful is the fact that a hints file dumped with \fB\-h\fR can be one of the file arguments to \fBdoclifter\fR; the code detects this special case and does not write XML output for such a file\&. Thus, a good procedure for lifting a large library is to generate a hints file with a first run, inspect it to delete false positives, and use it as the first input to a second run\&.
358
359 .PP
360 It is also possible to include a hints file directly in a troff sourcefile\&. This may be useful if you want to enrich the file by stages before converting to XML\&.
361
734 .PP
735 where
736 \fB<phrase>\fR
737 is an item of text and
738 \fB<markup>\fR
739 is the DocBook markup text it should be wrapped with whenever it appeared either highlighted or as a word surrounded by whitespace in the source text.
740 .PP
741 Hints derived from earlier files are also applied to later ones. This behavior may be useful when lifting collections of documents that apply to a function or command library. What should be more useful is the fact that a hints file dumped with
742 \fB\-h\fR
743 can be one of the file arguments to
744 \fBdoclifter\fR; the code detects this special case and does not write XML output for such a file. Thus, a good procedure for lifting a large library is to generate a hints file with a first run, inspect it to delete false positives, and use it as the first input to a second run.
745 .PP
746 It is also possible to include a hints file directly in a troff sourcefile. This may be useful if you want to enrich the file by stages before converting to XML.
362747 .SH "TROUBLESHOOTING"
363
364 .PP
365 After converting your source, look through the generated DocBook for comments containing the string FIX\-ME\&. These will tag problems that doclifter can diagnose but not fix by itself\&.
366
367 .PP
368 Occasionally (less than 2% of the time) \fBdoclifter\fR will produce invalid DocBook markup even from correct troff markup\&. Usually this results from strange constructions in the source page, or macro calls that are beyond the ability of \fBdoclifter\fR's macro processor to get right\&. Here are some things to watch for, and how to fix them:
369
370 .PP
371 \fIMalformed command synopses\&.\fR If you get a message that says command synopsis parse failed, look at the XML output\&. It will contain a comment telling you what the command synopsis looked like after preprocessing, and indicate on which token the parse failed (both with a token number and a caret sign inserted in the dump of the synopsis tokens)\&. Try rewriting the synopsis in your manual page source\&. The most common cause of failure is unbalanced [] groupings, a bug that can be very difficult to notice by eyeball\&. To assist with this, the error token dump tries to insert ‘$’ at the point of the last nesting\-depth increase, but the code that does this is failure\-prone\&.
372
373 .PP
374 \fIRelative\-indent (\&.RS/\&.RE) macros\&.\fR Odd combinations of these macros with list markup will not translate properly\&. If you get a message warning you that these macros have been seen, go in and simplify\&.
375
376 .PP
377 \fIConfusing macro calls\&.\fR Some manual page authors replace standard requests (like \&.PP, \&.SH and \&.TP) with versions that do different things in \fBnroff\fR and \fBtroff\fR environments\&. While \fBdoclifter\fR tries to cope and usually does a good job, the quirks of [nt]roff are legion and confusing macro calls sometimes lead to bad XML being generated (a common symptom is unclosed Emphasis tags)\&.
378
379 .PP
380 The message possible section nesting error means that the program has seen two adjacent subsection headers\&. In man pages, subsections don't have a depth argument, so \fBdoclifter\fR cannot be certain how subsections should be nested\&. Any subsection heading between the indicated line and the beginning of the next top\-level section might be wrong and require correcting by hand\&.
381
382 .PP
383 If you're translating a page that uses user\-defined macros and you get bad output, the first thing to do is simplify or eliminate the user\-defined macros\&. Replace them with stock requests where possible\&.
384
748 .PP
749 After converting your source, look through the generated DocBook for comments containing the string FIX\-ME. These will tag problems that doclifter can diagnose but not fix by itself.
750 .PP
751 Occasionally (less than 2% of the time)
752 \fBdoclifter\fR
753 will produce invalid DocBook markup even from correct troff markup. Usually this results from strange constructions in the source page, or macro calls that are beyond the ability of
754 \fBdoclifter\fR's macro processor to get right. Here are some things to watch for, and how to fix them:
755 .PP
756 \fIMalformed command synopses.\fR
757 If you get a message that says
758 "command synopsis parse failed", look at the XML output. It will contain a comment telling you what the command synopsis looked like after preprocessing, and indicate on which token the parse failed (both with a token number and a caret sign inserted in the dump of the synopsis tokens). Try rewriting the synopsis in your manual page source. The most common cause of failure is unbalanced [] groupings, a bug that can be very difficult to notice by eyeball. To assist with this, the error token dump tries to insert \(oq$\(cq at the point of the last nesting\-depth increase, but the code that does this is failure\-prone.
759 .PP
760 \fIConfusing macro calls.\fR
761 Some manual page authors replace standard requests (like
762 .PP,
763 .SH
764 and
765 .TP) with versions that do different things in
766 \fBnroff\fR
767 and
768 \fBtroff\fR
769 environments. While
770 \fBdoclifter\fR
771 tries to cope and usually does a good job, the quirks of [nt]roff are legion and confusing macro calls sometimes lead to bad XML being generated. A common symptom of such problems is unclosed
772 Emphasis
773 tags.
774 .PP
775 The message
776 "possible section nesting error"
777 means that the program has seen two adjacent subsection headers. In man pages, subsections don't have a depth argument, so
778 \fBdoclifter\fR
779 cannot be certain how subsections should be nested. Any subsection heading between the indicated line and the beginning of the next top\-level section might be wrong and require correcting by hand.
780 .PP
781 If you're translating a page that uses user\-defined macros and you get bad output, the first thing to do is simplify or eliminate the user\-defined macros. Replace them with stock requests where possible.
385782 .SH "RETURN VALUES"
386
387 .PP
388 On successful completion, the program returns status 0\&. It returns 1 if some file or standard input could not be translated\&. It returns 2 if one of the input sources was a \&.so inclusion\&. It returns 3 if there is an error in reading or writing files\&. It returns 4 to indicate an internal error\&. It returns 5 when aborted by a keyboard interrupt\&.
389
390 .PP
391 Note that a zero return does not guarantee that the output is valid DocBook\&. It will be syntactically valid XML, but in some (rare) cases fixups by hand may be necessary to meet the semantics of the DocBook DTD\&. Validation problems are most likely to occur with complicated list markup\&.
392
783 .PP
784 On successful completion, the program returns status 0. It returns 1 if some file or standard input could not be translated. It returns 2 if one of the input sources was a
785 .so
786 inclusion. It returns 3 if there is an error in reading or writing files. It returns 4 to indicate an internal error. It returns 5 when aborted by a keyboard interrupt.
787 .PP
788 Note that a zero return does not guarantee that the output is valid DocBook. It will almost always (as in, more than 96% of cases) be syntactically valid XML, but in some rare cases fixups by hand may be necessary to meet the semantics of the DocBook DTD. Validation problems are most likely to occur with complicated list markup.
393789 .SH "BUGS AND WARNINGS"
394
395 .PP
396 EQN sections are not translated to MathML as they should be\&.
397
398 .PP
399 The function\-synopsis parser is crude (it's not a compiler) and prone to errors\&. Function\-synopsis markup should be checked carefully by a human\&.
400
401 .PP
402 If a man page has both paragraphed text in a Synopsis section and also a body section before the Synopis section, bad things will happen\&.
403
404 .PP
405 Running text (e\&.g\&., explanatory notes) at the end of a Synopsis section cannot reliably be distinguished from synopsis\-syntax markup\&.
406
407 .PP
408 Some firewalls put in to cope with common malformations in troff code mean that the tail end of a span between two \\f{B,I,U,(CW} or \&.ft highlight changes may not be completely covered by corresponding Emphasis macros if (for example) the span crosses a boundary between filled and unfilled (\&.nf/\&.fi) text\&.
409
410 .PP
411 The crude treatment of conditionals relies on the assumption that conditional macros never generate structural or font\-highlight markup that differs between the if and else branches\&. This appears to be true of all the standard macro packages, but if you roll any of your own macros you're on your own\&.
412
790 .PP
791 About 4% of man pages will either make this program throw error status 1 or generate invalid XML. In almost all such cases the misbehavior is triggered by markup bugs in the source that are too severe to be coped with.
792 .PP
793 EQN sections are not translated to MathML as they should be.
794 .PP
795 The function\-synopsis parser is crude (it's not a compiler) and prone to errors. Function\-synopsis markup should be checked carefully by a human.
796 .PP
797 If a man page has both paragraphed text in a Synopsis section and also a body section before the Synopis section, bad things will happen.
798 .PP
799 Running text (e.g., explanatory notes) at the end of a Synopsis section cannot reliably be distinguished from synopsis\-syntax markup. (This problem is AI\-complete.)
800 .PP
801 Some firewalls put in to cope with common malformations in troff code mean that the tail end of a span between two
802 \\f{B,I,U,(CW}
803 or
804 .ft
805 highlight changes may not be completely covered by corresponding
806 Emphasis
807 macros if (for example) the span crosses a boundary between filled and unfilled (.nf/.fi) text.
808 .PP
809 The treatment of conditionals relies on the assumption that conditional macros never generate structural or font\-highlight markup that differs between the if and else branches. This appears to be true of all the standard macro packages, but if you roll any of your own macros you're on your own.
810 .PP
811 Attempt to typeset tables in troff with
812 .ta
813 requests and tabs do not translate properly.
814 .PP
815 Macro definitions in a manual page NAME section are not interpreted.
816 .PP
817 In Berkeley mdoc interpretation, handling of
818 .Xo/.Xc
819 enclosures is failure\-prone.
413820 .SH "OLD MACRO SETS"
414
415 .PP
416 There is a conflict between Berkeley ms's documented \&.P1 print\-header\-on\-page request and an undocumented Bell Labs use for displayed program and equation listings\&. The \fIms\fR translator chooses the Bell Labs interpretation because (a) it's structural, and (b) otherwise we'd have to throw out the paired \&.P2 request\&.
417
418 .PP
419 The composition characters for large math brackets from old troff are not supported, as there are neither ISO entity nor Unicode equivalents\&.
420
821 .PP
822 There is a conflict between Berkeley ms's documented
823 .P1
824 print\-header\-on\-page request and an undocumented Bell Labs use for displayed program and equation listings. The
825 \fIms\fR
826 translator chooses the Bell Labs interpretation because (a) it's structural, and (b) otherwise we'd have to throw out the paired
827 .P2
828 request.
829 .PP
830 The composition characters for large math brackets from old troff are not supported, as there are neither ISO entity nor Unicode equivalents.
421831 .SH "REQUIREMENTS"
422
423 .PP
424 \fBdoclifter\fR was written in Python 2\&.2a1\&. It will not work under Python 1\&.5\&.2\&.
425
426 .PP
427 The \fBpic2plot\fR(1) utility must be installed in order to translate PIC diagrams to SVG\&.
428
429 .SH "BUGS"
430
431 .PP
432 Attempt to typeset tables in troff with \&.ta requests and tabs do not translate properly\&.
433
434 .PP
435 Macro definitions in a manual page NAME section are not interpreted\&.
436
437 .PP
438 In Berkeley mdoc interpretation, handlig of ,Xo/\&.Xc enclosures is failure\-prone\&.
439
832 .PP
833 The
834 \fBpic2plot\fR(1)
835 utility must be installed in order to translate PIC diagrams to SVG.
440836 .SH "SEE ALSO"
441
442 .PP
443 \fBman\fR(7), \fBmdoc\fR(7), \fBms\fR(7), \fBme\fR(7), \fBmm\fR(7), \fBmwww\fR(7), \fBtroff\fR(1)\&.
444
837 .PP
838 \fBman\fR(7),
839 \fBmdoc\fR(7),
840 \fBms\fR(7),
841 \fBme\fR(7),
842 \fBmm\fR(7),
843 \fBmwww\fR(7),
844 \fBtroff\fR(1).
445845 .SH "AUTHOR"
446
447 .PP
448 Eric S\&. Raymond <esr@thyrsus\&.com>
449
450 .PP
451 There is a project web page at http://www\&.catb\&.org/~esr/doclifter/: \fIhttp://www.catb.org/~esr/doclifter/\fR\&.
452
846 .PP
847 Eric S. Raymond
848 <esr@thyrsus.com>
849 .PP
850 There is a project web page at
851 [1]\&\fIhttp://www.catb.org/~esr/doclifter/\fR.
852 .SH "REFERENCES"
853 .TP 3
854 1.\ http://www.catb.org/~esr/doclifter/
855 \%http://www.catb.org/~esr/doclifter/
00 Name: doclifter
1 Version: 2.1
1 Version: 2.3
22 Release: 1
33 URL: http://www.catb.org/~esr/doclifter/
44 Source0: %{name}-%{version}.tar.gz
55 License: GPL
66 Group: Applications/System
77 Requires: python2
8 Summary: converts man/mdoc/ms/me/mm documents to DocBook
8 Summary: Converts man/mdoc/ms/me/mm documents to DocBook
99 BuildRoot: %{_tmppath}/%{name}-root
1010 BuildArch: noarch
1111 #Keywords: DocBook, man, ms, mm, me, mdoc, lifting, XML, SGML
1212
1313 %description
14 The doclifter program translates documents written in troff macros to DocBook.
15 Lifting documents from presentation level to semantic level is hard, and
16 a really good job requires human polishing. This tool aims to do everything
17 that can be mechanized, and to preserve in XML comments any troff-level
18 information that might have structural implications. Also includes manlifter,
19 a driver script that can be used to convert entire manual-page hierarchies.
14 The doclifter program translates documents written in troff macros to
15 DocBook. Lifting documents from presentation level to semantic level
16 is difficult, and a really good job requires human polishing, but this
17 tool does about 95% of the work. It aims to do everything that can be
18 mechanized, and to preserve in XML comments any troff-level
19 information that might have structural implications. Also includes
20 manlifter, a driver script that can be used to convert entire
21 manual-page hierarchies.
2022
2123 %prep
2224 %setup -q
4345 %{_bindir}/manlifter
4446
4547 %changelog
48 * Mon Dec 25 2006 Eric S. Raymond <esr@snark.thyrsus.com> - 2.3-1
49 - Work around a bug in db2man.xsl. Implement Markus Hoenicka's
50 requested behavior for multiple-file conversions. Implement
51 translation of groff extended .cc and .c2 requests. Ignore
52 the .TA macro that occurs duplicatively with .ta in X.org
53 manual pages. Cope with unresolved .Sx refererences in mdoc.
54 Handle .Ex and .Ee. Cope with X consortium macro preamble better.
55 .RS/.RE is now fully handled, no more spurious warnings.
56
57 * Sat Jan 15 2005 Eric S. Raymond <esr@snark.thyrsus.com> - 2.2-1
58 - Have manlifter create subdirectories and the xslfragment
59 only in batch mode. Use current list indent on block start/end.
60
4661 * Fri Jan 14 2005 Eric S. Raymond <esr@snark.thyrsus.com> - 2.1-1
4762 - Interrupt handlers are refactored so manlifter can be aborted with
4863 a single ^C; as a result, exit values 4 and 5 have swapped places.
252267
253268 # The following sets edit modes for GNU EMACS
254269 # Local Variables:
255 # mode:rpm-spec-mode
270 # mode:rpm-spec
256271 # End:
7272 features, but this fallback is good enough for simple man
7373 pages.</para>
7474
75 <para><command>doclifter</command> does not do a perfect job, only
76 about 95% of one; the last 5% has to be applied by a human
77 recognizing patterns too subtle for a computer. But
75 <para><command>doclifter</command> does not do a perfect job, merely
76 an extremely good one. Final polish should be applied by a human
77 being capable of recognizing patterns too subtle for a computer. But
7878 <command>doclifter</command> will almost always produce translations
7979 that are good enough to be usable before hand-hacking.</para>
8080
231231 <markup>.PD</markup>,<markup>.DT</markup>.</para>
232232
233233 <para>The <markup>.RS</markup>/<markup>.RE</markup> macros are
234 translated when they occur within list structure (<markup>.TP</markup>
235 or <markup>.IP</markup>); the result is nested lists. A few other
236 <markup>.RS</markup>/<markup>.RE</markup> cliches are also lifted;
237 when the program cannot find a matching cliche, it
238 will issue a warning. Use the <option>-v</option> option to get line
239 numbers on these.</para>
234 translated differently depending on whether or not they precede
235 list markup. When <markup>.RS</markup> occurs just before <markup>.TP</markup>
236 or <markup>.IP</markup> the result is nested lists. Otherwise, the
237 <markup>.RS</markup>/<markup>.RE</markup> pair is translated into a
238 Blockquote tag-pair.</para>
240239
241240 <para><markup>.DS</markup>/<markup>.DE</markup> is not part of the
242241 documented man macro set, but is recognized because it shows up with
246245 <para>Certain extension macros originally defined under Ultrix are
247246 translated structurally, including those that occasionally show up on
248247 the manual pages of Linux and other open-source Unixes.
249 <markup>.EX</markup>/<markup>.EE</markup>,
248 <markup>.EX</markup>/<markup>.EE</markup> (and the symptoms
249 <markup>.Ex</markup>/<markup>.Ee</markup>),
250250 <markup>.Ds</markup>/<markup>.De</markup>, <!-- cause display
251251 parsing. --> <markup>.NT</markup>/<markup>.NE</markup>,
252252 <markup>.PN</markup>, and <markup>.MS</markup> are translated
253 structurally. parsed as a display.</para>
253 structurally.</para>
254254
255255 <para>The following extension macros used by the X distribution are
256 also recognized and translated structurally: <markup>FD</markup>,
257 <markup>FN</markup>, <markup>IN</markup>, <markup>ZN</markup>,
258 <markup>hN</markup>, and <markup>.C{</markup>/<markup>.C}</markup>
259 <!-- triggers display parsing.--></para>
256 also recognized and translated structurally: <markup>.FD</markup>,
257 <markup>.FN</markup>, <markup>.IN</markup>, <markup>.ZN</markup>,
258 <markup>.hN</markup>, and <markup>.C{</markup>/<markup>.C}</markup>
259 <!-- triggers display parsing.--> The <markup>.TA</markup> and
260 <markup>IN</markup> requests are ignored.</para>
260261
261262 <para>When the man macros are active, any <markup>.Pp</markup> macro
262263 definition containing the request <markup>.PP</markup> will be
265266 replaced with <markup>.TP</markup>. This is the least painful way to
266267 deal with some frequently-encountered stereotyped wrapper definitions
267268 that would otherwise cause serious interpretation problems</para>
268
269 <para>On some man pages paragraphed text is found in a Synopsis
270 section as an annotation or description of the syntax. The DocBook
271 DTD has no way to support this, so <command>doclifter</command> ends
272 the Synopsis section at that point and inserts a first-level
273 "Synopsis Notes" section.</para>
274269
275270 <para>Known problem areas with man translation:</para>
276271 <itemizedlist>
526521 are not supported.</para>
527522
528523 <para>If the first nonempty line of text immediately before a table is
529 boldfaced, it is interpreted as a ctitle for the table and the table
524 boldfaced, it is interpreted as a title for the table and the table
530525 is generated using a <sgmltag class='element'>table</sgmltag> and
531526 <sgmltag class='element'>title</sgmltag>. Otherwise the table is
532527 translated with <sgmltag
587582 textual comparison. All numeric expressions evaluate to true. </para>
588583
589584 <para>The extended <application>groff</application> requests
585 <markup>cc</markup>, <markup>c2</markup>,
590586 <markup>ab</markup>, <markup>als</markup>, <markup>do</markup>,
591587 <markup>nop</markup>, and <markup>return</markup> and
592588 <markup>shift</markup> are interpreted. Its <markup>.PSPIC</markup>
625621
626622 <para>If <command>doclifter</command> is applied to multiple files,
627623 the global list is retained in memory. You can dump a report of
628 global hints at the end of the with the <option>-h</option>. The
629 format of the hints is as follows:</para>
624 global hints at the end of the run with the <option>-h</option>
625 option. The format of the hints is as follows:</para>
630626
631627 <programlisting>
632628 &nbsp;.\&quot; | mark &lt;phrase&gt; as &lt;markup&gt;
666662 right. Here are some things to watch for, and how to fix them:</para>
667663
668664 <para><emphasis>Malformed command synopses.</emphasis> If you get a
669 message that says <computeroutput>command synopsis parse
670 failed</computeroutput>, look at the XML output. It will contain a
665 message that says <computeroutput>"command synopsis parse
666 failed"</computeroutput>, look at the XML output. It will contain a
671667 comment telling you what the command synopsis looked like after
672668 preprocessing, and indicate on which token the parse failed (both with
673669 a token number and a caret sign inserted in the dump of the synopsis
678674 last nesting-depth increase, but the code that does this is
679675 failure-prone.</para>
680676
681 <para><emphasis>Relative-indent (<markup>.RS/.RE</markup>)
682 macros.</emphasis> Odd combinations of these macros with list markup
683 will not translate properly. If you get a message warning you that
684 these macros have been seen, go in and simplify.</para>
685
686677 <para><emphasis>Confusing macro calls.</emphasis> Some manual page
687678 authors replace standard requests (like <markup>.PP</markup>,
688679 <markup>.SH</markup> and <markup>.TP</markup>) with versions that do
690681 <command>troff</command> environments. While
691682 <command>doclifter</command> tries to cope and usually does a good
692683 job, the quirks of [nt]roff are legion and confusing macro calls
693 sometimes lead to bad XML being generated (a common symptom is
694 unclosed <sgmltag class='element'>Emphasis</sgmltag> tags).</para>
695
696 <para>The message <computeroutput>possible section nesting
697 error</computeroutput> means that the program has seen two adjacent
684 sometimes lead to bad XML being generated. A common symptom of such
685 problems is unclosed <sgmltag class='element'>Emphasis</sgmltag>
686 tags.</para>
687
688 <para>The message <computeroutput>"possible section nesting
689 error"</computeroutput> means that the program has seen two adjacent
698690 subsection headers. In man pages, subsections don't have a depth
699691 argument, so <command>doclifter</command> cannot be certain how
700692 subsections should be nested. Any subsection heading between the
725717 It returns 5 when aborted by a keyboard interrupt. </para>
726718
727719 <para>Note that a zero return does not guarantee that the output is
728 valid DocBook. It will be syntactically valid XML, but in some
729 (rare) cases fixups by hand may be necessary to meet the semantics of
730 the DocBook DTD. Validation problems are most likely to occur with
731 complicated list markup.</para>
720 valid DocBook. It will almost always (as in, more than 96% of cases)
721 be syntactically valid XML, but in some rare cases fixups by hand may be
722 necessary to meet the semantics of the DocBook DTD. Validation
723 problems are most likely to occur with complicated list markup.</para>
732724 </refsect1>
733725
734726 <refsect1><title>Bugs And Warnings</title>
727
728 <para>About 4% of man pages will either make this program throw error status
729 1 or generate invalid XML. In almost all such cases the misbehavior is
730 triggered by markup bugs in the source that are too severe to be
731 coped with.</para>
735732
736733 <para>EQN sections are not translated to MathML as they should be.</para>
737734
745742
746743 <para>Running text (e.g., explanatory notes) at the end of a Synopsis
747744 section cannot reliably be distinguished from synopsis-syntax
748 markup.</para>
745 markup. (This problem is AI-complete.)</para>
749746
750747 <para>Some firewalls put in to cope with common malformations in troff
751748 code mean that the tail end of a span between two
755752 crosses a boundary between filled and unfilled
756753 (<markup>.nf</markup>/<markup>.fi</markup>) text.</para>
757754
758 <para>The crude treatment of conditionals relies on the assumption that
755 <para>The treatment of conditionals relies on the assumption that
759756 conditional macros never generate structural or font-highlight markup
760757 that differs between the if and else branches. This appears to be
761758 true of all the standard macro packages, but if you roll any of your
762759 own macros you're on your own.</para>
763 </refsect1>
764
765 <refsect1><title>Old macro sets</title> <para>There is a conflict
766 between Berkeley ms's documented <markup>.P1</markup>
767 print-header-on-page request and an undocumented Bell Labs use for
768 displayed program and equation listings. The <emphasis
769 remap='B'>ms</emphasis> translator chooses the Bell Labs
760
761 <para>Attempt to typeset tables in troff with <markup>.ta</markup>
762 requests and tabs do not translate properly.</para>
763
764 <para>Macro definitions in a manual page NAME section are not
765 interpreted.</para>
766
767 <para>In Berkeley mdoc interpretation, handling of
768 <markup>.Xo</markup>/<markup>.Xc</markup> enclosures is failure-prone.</para>
769 </refsect1>
770
771 <refsect1><title>Old macro sets</title>
772 <para>There is a conflict between Berkeley ms's documented
773 <markup>.P1</markup> print-header-on-page request and an undocumented
774 Bell Labs use for displayed program and equation listings. The
775 <emphasis remap='B'>ms</emphasis> translator chooses the Bell Labs
770776 interpretation because (a) it's structural, and (b) otherwise we'd
771777 have to throw out the paired <markup>.P2</markup> request.</para>
772778
776782 </refsect1>
777783
778784 <refsect1><title>Requirements</title>
779 <para><command>doclifter</command> was written in Python 2.2a1. It
780 will not work under Python 1.5.2. </para>
781
782785 <para>The
783786 <citerefentry><refentrytitle>pic2plot</refentrytitle><manvolnum>1</manvolnum></citerefentry>
784787 utility must be installed in order to translate PIC diagrams to SVG.</para>
785 </refsect1>
786
787 <refsect1><title>Bugs</title>
788 <para>Attempt to typeset tables in troff with <markup>.ta</markup>
789 requests and tabs do not translate properly.</para>
790
791 <para>Macro definitions in a manual page NAME section are not
792 interpreted.</para>
793
794 <para>In Berkeley mdoc interpretation, handlig of
795 <markup>,Xo</markup>/<markup>.Xc</markup> enclosures is failure-prone.</para>
796788 </refsect1>
797789
798790 <refsect1><title>See Also</title>
22 # Run doclifter against an entire manual tree.
33 # Sees all files in section 1 through 9 by default.
44
5 import sys, os, getopt, signal, time, re, commands, cStringIO, stat
5 import sys, os, getopt, signal, time, re, commands, cStringIO, stat, sets
66
77 mandir = "/usr/share/man"
88 patchdir = os.path.abspath("prepatch")
1010 patched = 0
1111 makehtml = False
1212 xslfragment = None
13 processed = sets.Set([])
1314
1415 def manfile(section, basename=""):
1516 "Return a manual file or directory based on section name."
122123 return (6, output)
123124 return (0, output)
124125
125 def format(translation, fmt):
126 def format(translation, fmt, xslfragment):
126127 "Format an XML file to a specified format."
127128 output = ""
128129 here = os.getcwd()
129130 os.chdir(os.path.dirname(translation))
130 command = "xmlto -m %s %s %s" % (xslfragment, fmt, os.path.basename(translation))
131 if xslfragment:
132 command = "xmlto %s %s" % (fmt, os.path.basename(translation))
133 else:
134 command = "xmlto -m %s %s %s" % (xslfragment, fmt, os.path.basename(translation))
131135 (bstat, format_out) = commands.getstatusoutput(command)
132136 os.chdir(here)
133137 if format_out:
179183 if os.path.exists(patch):
180184 patched += 1
181185 try:
186 global processed
182187 tmpstem = os.path.join(outdir, tmpstem)
183188 source = tmpstem + ".man"
184189 # Save work by doing conversions only as needed
186191 if batchmode and os.path.exists(xmlloc):
187192 if os.stat(file).st_mtime < os.lstat(xmlloc).st_mtime:
188193 output += "XML conversion is up to date\n"
194 processed.discard(withsect)
189195 rebuild_xml = False
190196 htmlloc = os.path.join(subdir, stem + ".html")
191197 if rebuild_xml:
194200 (status, output) = fetch_page(file, localcopy, patch)
195201 if (status):
196202 return (status, output)
203 # Note the the patch was used
204 processed.discard(withsect)
197205 # Add any annotations
198206 output += analyze_manpage(localcopy)
199207 # Move the source file into the output directory
212220 # of putting this in its permanent location.
213221 try:
214222 # This will foo up if we ever have to symlink between dirs
215 if not os.path.exists(subdir):
223 if batchmode and not os.path.exists(subdir):
216224 os.mkdir(subdir)
217225 except OSError, e:
218226 return(3, output + "Creation of %s failed, errno = %d\n"%(subdir,e.errno))
249257 if batchmode and stat.S_ISLNK(os.lstat(xmlloc).st_mode):
250258 makelink(os.readlink(xmlloc)[:-4]+".html", htmlloc)
251259 else:
252 (status, more) = format(translation, "xhtml-nochunks")
260 (status, more) = format(translation, "xhtml-nochunks", xslfragment)
253261 output += more
254262 if status:
255263 if batchmode:
290298 def report(sig, frame, out=sys.stderr):
291299 ftotal = float(total)
292300 elapsed = int(time.time()) - starttime
293 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" % \
301 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" % \
294302 (total, eligible,
295303 elapsed/3600, (elapsed % 3600)/60, elapsed % 60,
296304 (total - doclifter_error_count - xmllint_error_count),
315323 (status, output) = test(file=file, options=options)
316324 if status == -1:
317325 break
318 elif status in (1, 5): # Doclifter parse or internal error
319 if output.find("is empty") == -1 and output.find("has no text") == -1:
320 doclifter_error_count = doclifter_error_count + 1
326 elif status in (1, 4): # Doclifter parse or internal error
327 if output.find("is empty") == -1 and output.find("has no text") == -1 and output.find("has no content") == -1:
328 doclifter_error_count += 1
321329 elif status == 2: # .so inclusion
322330 pass
323 elif status in (3, 4): # File I/O error or keyboard interrupt
331 elif status in (3, 5): # File I/O error or keyboard interrupt
324332 pass
325333 elif status == 6:
326 xmllint_error_count = xmllint_error_count + 1
334 xmllint_error_count += 1
327335 total = total + 1
328336 except KeyboardInterrupt:
329337 pass
439447
440448 def errorclean(error_only, pattern):
441449 if pattern:
442 pattern = re.compile(filter)
450 pattern = re.compile(pattern)
443451 pagename = re.compile(r"! (.*)=([0-9]+)")
444452 while 1:
445453 header = sys.stdin.readline()
494502
495503 def doclifter_driver(options, arguments):
496504 "Lift old markup to new."
497 global makehtml, outdir, xslfragment
505 global makehtml, outdir, xslfragment, patchdir
498506 filelist = []
499507 sections = []
500508 callopts = ""
531539 else:
532540 outdir = '.'
533541 # Clean/create the output directory
534 if not os.path.exists(outdir):
535 os.mkdir(outdir)
542 if not arguments:
543 if not os.path.exists(outdir):
544 os.mkdir(outdir)
545 # Create XSL fragment for making refentries into links
546 xslfragment = os.path.abspath(os.path.join(outdir, "citerefentry.xsl"))
547 fp = open(xslfragment, "w")
548 fp.write(citereftemplate % outdir)
549 fp.close()
536550 try:
537 # Create XSL fragment for making refentries into links
538 xslfragment = os.path.abspath(os.path.join(outdir, "citerefentry.xsl"))
539 fp = open(xslfragment, "w")
540 fp.write(citereftemplate % outdir)
541 fp.close()
542551 # Process args, if present
543552 if arguments:
544553 for file in arguments:
557566 fp.close()
558567 massrun(filelist, callopts)
559568 else:
569 global processed
570 processed = sets.Set(map(lambda x: x.replace(".patch", "").replace(".correction", ""), os.listdir(patchdir)))
560571 massrun(sectionfiles(sections), callopts)
572 if processed:
573 print "# Patches not used:"
574 for file in processed:
575 print file
561576 finally:
562577 pass
563578 #os.remove(xslfragment)
574589 if os.path.exists(where):
575590 break
576591 else:
577 sys.stderr.write("manlifter: can't find doclifter!")
592 sys.stderr.write("manlifter: can't find doclifter!\n")
578593 sys.exit(1)
579594 # Import it, so we can modify it while the test is running without
580595 # screwing up the results
0 .\"Generated by db2man.xsl. Don't modify this, modify the source.
1 .de Sh \" Subsection
2 .br
3 .if t .Sp
4 .ne 5
5 .PP
6 \fB\\$1\fR
7 .PP
8 ..
9 .de Sp \" Vertical space (when we can't use .PP)
10 .if t .sp .5v
11 .if n .sp
12 ..
13 .de Ip \" List item
14 .br
15 .ie \\n(.$>=3 .ne \\$3
16 .el .ne 3
17 .IP "\\$1" \\$2
18 ..
19 .TH "MANLIFTER" 1 "" "" ""
20 .SH NAME
21 manlifter \- mass-conversion script and test harness for doclifter
0 .\" ** You probably do not want to edit this file directly **
1 .\" It was generated using the DocBook XSL Stylesheets (version 1.69.1).
2 .\" Instead of manually editing it, you probably should edit the DocBook XML
3 .\" source for it and then use the DocBook XSL Stylesheets to regenerate it.
4 .TH "MANLIFTER" "1" "12/25/2006" "" ""
5 .\" disable hyphenation
6 .nh
7 .\" disable justification (adjust text to left margin only)
8 .ad l
9 .SH "NAME"
10 manlifter \- mass\-conversion script and test harness for doclifter
2211 .SH "SYNOPSIS"
23 .ad l
24 .hy 0
2512 .HP 10
2613 \fBmanlifter\fR [\-d\ \fIoption\fR] [\-e] [\-f\ \fIlistfile\fR] [\-h] [\-I\ \fImandir\fR] [\-o\ \fIoutdir\fR] [\-p\ \fIpatch\-directory\fR] [\-q] [\-v] [\-s\ \fIsection\fR] \fIname\fR...
27 .ad
28 .hy
29 .ad l
30 .hy 0
3114 .HP 10
3215 \fBmanlifter\fR [\-S]
33 .ad
34 .hy
35
3616 .SH "DESCRIPTION"
37
3817 .PP
39 \fBmanlifter\fR is a script that sequences \fBdoclifter\fR(1) to convert an entire manual\-page tree to XML\-Docbook, optionally also generating HTML from the XML\&. Another use is as a torture\-test tool for doclifter; it logs errors to standard output and collects timings\&.
40
18 \fBmanlifter\fR
19 is a script that sequences
20 \fBdoclifter\fR(1)
21 to convert an entire manual\-page tree to XML\-Docbook, optionally also generating HTML from the XML. Another use is as a torture\-test tool for doclifter; it logs errors to standard output and collects timings.
4122 .PP
42 Called without any file arguments, manlifter tries to convert all man pages installed on the system, placing the resulting xml files under \fIxmlman\fR in the current directory\&. Each successfully translated page foo\&.N is copied to manN/foo\&.xml beneath the output directory, regardless of what source directory it came from\&.
43
23 Called without any file arguments, manlifter tries to convert all man pages installed on the system, placing the resulting xml files under
24 \fIxmlman\fR
25 in the current directory. Each successfully translated page foo.N is copied to manN/foo.xml beneath the output directory, regardless of what source directory it came from.
4426 .PP
45 For each source file examined, if the destination file exists and is newer than the source, the conversion is skipped; thus, incremental runs of \fBmanlifter\fR do the least work needed to keep the target XML tree up to date\&. Likewise, in \-h mode derived HTML files are only made when necessary\&.
46
27 For each source file examined, if the destination file exists and is newer than the source, the conversion is skipped; thus, incremental runs of
28 \fBmanlifter\fR
29 do the least work needed to keep the target XML tree up to date. Likewise, in \-h mode derived HTML files are only made when necessary.
4730 .PP
48 Stub pages that are just \&.so redirections are translated to corresponding symlinks of XML files (and, with \-h, HTML files)\&.
49
31 Stub pages that are just
32 .so
33 redirections are translated to corresponding symlinks of XML files (and, with \-h, HTML files).
5034 .PP
51 \fBmanlifter\fR may also be called with a single file argument, which is interpreted as the stem name of a potential manual page\&. \fBmanlifter\fR then searches all selected manual sections for a matching page and attempts to convert it\&. In this case, a copy of the man page and the converted version are dropped immediately beheath the output directory, with the names foobar\&.man and foobar\&.man\&.xml, respectively\&. This mode is normally only of interest only to \fBdoclifter\fR developers for debugging that program\&.
52
35 \fBmanlifter\fR
36 may also be called with a single file argument, which is interpreted as the stem name of a potential manual page.
37 \fBmanlifter\fR
38 then searches all selected manual sections for a matching page and attempts to convert it. In this case, a copy of the man page and the converted version are dropped immediately beheath the output directory, with the names foobar.man and foobar.man.xml, respectively. This mode is normally only of interest only to
39 \fBdoclifter\fR
40 developers for debugging that program.
5341 .PP
54 In either of the above cases, \fBmanlifter\fR will uncompress the file if it has a \fI\&.gz\fR, \fI\&.bz2\fR or \fI\&.Z\fRsuffix on the name\&.
55
42 In either of the above cases,
43 \fBmanlifter\fR
44 will uncompress the file if it has a
45 \fI.gz\fR,
46 \fI.bz2\fR
47 or
48 \fI.Z\fR
49 suffix on the name.
5650 .PP
5751 Options are as follows:
58
5952 .TP
6053 \-d
61 Pass the string argument to each doclifter call as options\&. Each space\-separated token in the string becomes a separate argument in the call\&.
62
54 Pass the string argument to each doclifter call as options. Each space\-separated token in the string becomes a separate argument in the call.
6355 .TP
6456 \-e
65 Run in log\-filter mode (mainly of interest to \fBdoclifter\fR developers)\&. In this mode, \fBmanlifter\fR reads a test log from standard input and filters it in a a way dependent on the \-f and \-q options\&. If neither of these is given, messages from successful runs are stripped out and only errors passed through to standard output\&.
66
57 Run in log\-filter mode (mainly of interest to
58 \fBdoclifter\fR
59 developers). In this mode,
60 \fBmanlifter\fR
61 reads a test log from standard input and filters it in a a way dependent on the \-f and \-q options. If neither of these is given, messages from successful runs are stripped out and only errors passed through to standard output.
6762 .TP
6863 \-f
69 Normally, run doclifter on the files named by each line in the argument file\&. In error\-filter mode the argument is instead interpreted as a filtering regular expression\&.
70
64 Normally, run doclifter on the files named by each line in the argument file. In error\-filter mode the argument is instead interpreted as a filtering regular expression.
7165 .TP
7266 \-h
73 Also generate HTML translations into the output directory\&. DocBook citerefentry markup is transformed to hyperlinks in the directory, and a contents listing is generated to \fIindex\&.html\fR\&.
74
67 Also generate HTML translations into the output directory. DocBook citerefentry markup is transformed to hyperlinks in the directory, and a contents listing is generated to
68 \fIindex.html\fR.
7569 .TP
7670 \-I
77 Specify the root of the manual\-page tree\&. By default this is \fI/usr/share/man\fR\&.
78
71 Specify the root of the manual\-page tree. By default this is
72 \fI/usr/share/man\fR.
7973 .TP
8074 \-o
81 Set the output directory into which XML\-DocBooktranslations will be dropped\&. By default this is \fIxmlman\fR under the current directory in batch mode, or the current directory otherwise\&.
82
75 Set the output directory into which XML\-DocBook translations will be dropped. By default this is
76 \fIxmlman\fR
77 under the current directory in batch mode, or the current directory otherwise.
8378 .TP
8479 \-p
85 Interpret the argument as the name of a patch directory (the default name is \fIprepatch\fR under the current directory)\&. Each file named \fIfoo\&.N\&.patch\fR is interpreted as a patch to be applied to the manual page foo(N) before doclifter translates it\&.
86
80 Interpret the argument as the name of a patch directory (the default name is
81 \fIprepatch\fR
82 under the current directory). Each file named
83 \fIfoo.N.patch\fR
84 is interpreted as a patch to be applied to the manual page foo(N) before doclifter translates it.
8785 .TP
8886 \-q
89 Normally, pass the \-q (quiet) option to each doclifter call\&. In error\-filter mode, return a list of files on which translation failed\&.
90
87 Normally, pass the \-q (quiet) option to each doclifter call. In error\-filter mode, return a list of files on which translation failed.
9188 .TP
9289 \-v
93 Pass the \-v (verbose) option to each doclifter call\&. This option can be repeated to increase the verbosity level\&.
94
90 Pass the \-v (verbose) option to each doclifter call. This option can be repeated to increase the verbosity level.
9591 .TP
9692 \-s
97 Specify a section to scan\&. Use this with an argument; it should not be necessary when doing a conversion of the entire tree\&.
98
93 Specify a section to scan. Use this with an argument; it should not be necessary when doing a conversion of the entire tree.
9994 .TP
10095 \-S
101 Compile error statistics from a \fBmanlifter\fR logfile presented on standard input\&. This option will be of interest mainly to \fBdoclifter\fR developers\&.
102
96 Compile error statistics from a
97 \fBmanlifter\fR
98 logfile presented on standard input. This option will be of interest mainly to
99 \fBdoclifter\fR
100 developers.
103101 .PP
104 \fBmanlifter\fR emits a logfile to standard 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 \fBdoclifter\fR was run\&.
105
102 \fBmanlifter\fR
103 emits a logfile to standard 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, one for each file on which
104 \fBdoclifter\fR
105 was run.
106106 .PP
107 The first line of each stanza beguns with "! ", followed by the pathname of the source manual pager, followed by "=" and the return status of doclifter run on that file\&. Following that is a space and \fBdoclifter\fR's runtime in seconds\&.
108
107 The first line of each stanza beguns with "! ", followed by the pathname of the source manual pager, followed by "=" and the return status of doclifter run on that file. Following that is a space and
108 \fBdoclifter\fR's runtime in seconds.
109109 .PP
110 This initial line may be followed by information messages and the error output of the doclifter run\&.
111
110 This initial line may be followed by information messages and the error output of the doclifter run.
112111 .PP
113 \fBmanlifter\fR must find a copy of \fBdoclifter\fR in either the current directory or one of the command directories in your \fBPATH\fR in order to run\&.
114
112 \fBmanlifter\fR
113 must find a copy of
114 \fBdoclifter\fR
115 in either the current directory or one of the command directories in your
116 \fBPATH\fR
117 in order to run.
115118 .SH "BUGS"
116
117119 .PP
118 HTML generation is painfully slow\&. Unfortunately, there is little we can do to remedy this, because XSLT engines are painfully slow\&.
119
120 HTML generation is painfully slow. Unfortunately, there is little we can do to remedy this, because XSLT engines are painfully slow.
120121 .SH "SEE ALSO"
121
122122 .PP
123 \fBdoclifter\fR(1), \fBxmlto\fR(1)
124
123 \fBdoclifter\fR(1),
124 \fBxmlto\fR(1)
125125 .SH "AUTHOR"
126
127126 .PP
128 Eric S\&. Raymond <esr@thyrsus\&.com>
129
127 Eric S. Raymond
128 <esr@thyrsus.com>
130129 .PP
131 There is a project web page at http://www\&.catb\&.org/~esr/doclifter/: \fIhttp://www.catb.org/~esr/doclifter/\fR\&.
132
130 There is a project web page at
131 [1]\&\fIhttp://www.catb.org/~esr/doclifter/\fR.
132 .SH "REFERENCES"
133 .TP 3
134 1.\ http://www.catb.org/~esr/doclifter/
135 \%http://www.catb.org/~esr/doclifter/
6969
7070 <para>In either of the above cases, <command>manlifter</command> will
7171 uncompress the file if it has a <filename>.gz</filename>,
72 <filename>.bz2</filename> or <filename>.Z</filename>suffix on the
72 <filename>.bz2</filename> or <filename>.Z</filename> suffix on the
7373 name.</para>
7474
7575 <para>Options are as follows:</para>
111111 <varlistentry>
112112 <term>-o</term>
113113 <listitem><para>Set the output directory into which
114 XML-DocBooktranslations will be dropped. By default this is
114 XML-DocBook translations will be dropped. By default this is
115115 <filename>xmlman</filename> under the current directory in batch mode,
116116 or the current directory otherwise.</para></listitem>
117117 </varlistentry>
153153 output. The file begins with a timestamp line and a blank line,
154154 and ends with a line giving run time and various interesting
155155 statistics. Between these are stanzas, separated by blank lines,
156 wone for each file on which <command>doclifter</command> was
156 one for each file on which <command>doclifter</command> was
157157 run.</para>
158158
159159 <para>The first line of each stanza beguns with "! ", followed by the