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
4 | 4 | # Send 3 was on 11 Jul 2004 |
5 | 5 | # Send 4 was on 20 Nov 2004 |
6 | 6 | # Send 5 was on 14 Jan 2005 |
7 | # | |
8 | # * means there is no patch corresponding to this bug | |
7 | 9 | # |
8 | 10 | A Dot or single-quote at start of line turns it into a garbage command. |
9 | 11 | This is a serious error; some lines of your page get silently lost |
19 | 21 | D Section or macro out of place; this confuses translators. |
20 | 22 | E My translator trips over a useless command in list markup. |
21 | 23 | F List structure can be better expressed with .IP |
22 | G m4 macro syntax in manual page | |
23 | 24 | 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. | |
25 | 26 | J Ambiguous or invalid backslash. This doesn't cause groff a problem. |
26 | 27 | but it confuses doclifter and may confuse older troff implementations. |
27 | 28 | 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. | |
30 | 30 | L List syntax error. This means .IP, .TP or .RS/.RE markup is garbled. |
31 | 31 | This confuses doclifter, and may also mess up stricter troff |
32 | 32 | interpreters like groffer and TkMan. |
33 | 33 | M Macro definition is in a location (such as the Synopsis section) |
34 | 34 | 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. | |
45 | 38 | R English usage errors, apparently the writer is not a native speaker. |
46 | 39 | S DEPRECATED: in function syntax connot be translated. Also, the |
47 | 40 | code and examples need to be marked up better. |
48 | 41 | T There are multiple description lines. This makes it impossible to |
49 | 42 | translate the page to DocBook. It may also confuse some |
50 | 43 | 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. | |
54 | 47 | W Missing or garbled name section. The most common form of garbling |
55 | 48 | is a missing - or extra -. Or your manual page may have been generated |
56 | 49 | by a tool that doesn't emit a NAME section as it should. These |
62 | 55 | incorrectly. |
63 | 56 | Y Missing or garbled section header. |
64 | 57 | 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. | |
67 | 58 | 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. | |
70 | 62 | d This old-style C prototype is too hard to parse, best to fix it. |
71 | 63 | e Garbage generated by docbook2man |
72 | 64 | 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. | |
77 | 68 | j Parenthesized comments in command synopsis. This is impossible |
78 | 69 | to translate to DocBook. |
79 | 70 | k Translated to man+tbl because the content is, in fact, a table. |
80 | 71 | 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. | |
83 | 74 | n Unbalanced .RS or .RE macro |
84 | 75 | o TBL markup not used where it should be. |
85 | 76 | p It is unnecessary to explain basic shell redirects on a man page. |
87 | 78 | unparseable SYNOPSIS section. |
88 | 79 | q Formatting file lists as tables in a Synopsis is impossible to |
89 | 80 | 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. | |
92 | 81 | s Example URLs which should *not* be turned into hyperlinks need |
93 | 82 | an invisible stopper so tools which try to lift URLs from the page |
94 | 83 | source will pass over them. |
95 | 84 | 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. | |
98 | 85 | 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 | |
102 | 87 | y Page is empty. This probably means there is some sort of glitch in |
103 | 88 | your build machinery. |
104 | 89 | 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. | |
117 | 105 | %% |
118 | bn|ac.1 |t | | |
119 | 106 | bn|acl_from_text.3,acl_to_text.3 |X | |
120 | 107 | 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 | |
123 | 111 | 5r|afmtodit.1 |M |bug-groff@gnu.org |
124 | 112 | 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 | |
127 | 115 | 2n|AnyDBM_File.3pm |T |perl-documentation@perl.org |
128 | 116 | 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 | |
130 | 119 | 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 | |
131 | 124 | 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 | |
133 | 126 | y|bash.1 | |bug-bash@gnu.org |
134 | 127 | 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 | |
137 | 131 | 2n|bzfs.6 |UX |bzflag-dev@lists.sourceforge.net |
138 | 2p|bzflag.6 |Xr |bzflag-dev@lists.sourceforge.net | |
139 | 132 | 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 | | | |
142 | 136 | 5n|cannastat.1 |C |Canna@nec.co.jp |
143 | 137 | 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 | | |
145 | 141 | 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 | |
147 | 144 | 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 | |
150 | 146 | 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 | |
152 | 149 | bn|chkconfig.8 |X |ewt@redhat.com |
153 | 150 | 5n|chmoddic.1 |C |Canna@nec.co.jp |
154 | 151 | 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 | |
156 | 154 | 5n|cshost.1 |C |Canna@nec.co.jp |
157 | 155 | 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 | |
160 | 158 | y|dbz.3 | |inn-bugs@isc.org |
161 | 159 | y|ddd.1 | |ddd@gnu.org |
162 | 160 | 5n|default.session.5 |W |miguel@gnu.org |
163 | 161 | 1n|dhcp6r.8 |f |bug@dhcpv6.org |
164 | 162 | 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 | |
166 | 165 | 2n|dictfmt.1 |A |faith@cs.unc.edu |
167 | bn|diffstat.1 |D | | |
166 | y|diffstat.1 | | | |
168 | 167 | y|dislocate.1 | |Don Libes <libes@nist.gov> |
169 | 168 | 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> | |
171 | 170 | bn|dpromdic.1 |X | |
172 | 171 | 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 | |
174 | 174 | 5n|epic.1 |X |Jeremy Nelson <jnelson@acronet.net> |
175 | 175 | y|epoll_ctl.2 | |aeb@cwi.nl, davidel@xmailserver.org |
176 | 176 | y|epoll.4 | |aeb@cwi.nl, davidel@xmailserver.org |
177 | 177 | 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 | |
179 | 180 | y|expect.1 | |Don Libes <libes@nist.gov> |
180 | 5n|fam.3x |XC |fam@oss.sgi.com | |
181 | 181 | 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 | |
182 | 183 | 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 | |
187 | 188 | 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> | |
192 | 192 | 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 | |
194 | 194 | y|GetUid.3 | |tcl-core@lists.sourceforge.net |
195 | 195 | 3n|getcontext.2 |C |mtk-manpages@gmx.net |
196 | 196 | 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 | |
201 | 203 | 5n|gnome-session.1 |Y |Miguel de Icaza <miguel@gnu.org> |
202 | 5n|gnome-vfs-mime.5 |W |Miguel de Icaza <miguel@gnu.org> | |
203 | 204 | 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> | |
206 | 206 | 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 | |
208 | 209 | 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 | | |
210 | 211 | 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> | |
213 | 214 | 2n|htfuzzy.1 |A |htdig-dev@htdig.org |
214 | 215 | 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 | |
216 | 217 | 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 |
217 | 218 | 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 | |
222 | 222 | 2n|ipsec_mailkey.8 |H |hugh@mimosa.com |
223 | 223 | 2n|ipsec_newhostkey.8,ipsec_rsasigkey.8 |C |hugh@mimosa.com |
224 | 224 | 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 |
225 | 225 | 5n|iptraf.8 |X |riker@seul.org |
226 | 3n|iptables.8 |tx |Herve Eychenne <rv@wallfire.org> | |
227 | 226 | 5n|irb.1 |W |ruby-doc@ruby-lang.org |
228 | 227 | 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 | |
230 | 229 | 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 | | |
233 | 233 | 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 | | | |
236 | 237 | 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 | |
237 | 240 | 3n|libpng.3 |S |png-implement@ccrc.wustl.edu |
238 | 241 | 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 | |
240 | 244 | 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 | | | |
244 | 248 | 5n|lv.1 |C |nrt@ff.iij4u.or.jp |
245 | 249 | 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 | |
250 | 254 | y|man.1,manpath.1 | |mtk-manpages@gmx.net |
255 | bn|mcs.8 |X | | |
251 | 256 | bn|mdadm.conf.5 |X | |
252 | 257 | bn|mdadm.8 |X | |
253 | 258 | 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 | |
255 | 260 | y|mkoctfile.1 | |jwe@bevo.che.wisc.edu>, edd@debian.org |
261 | n|mkxauth.1x |C | | |
256 | 262 | y|mkzftree.1 | |hpa@zytor.com |
257 | 263 | 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 | |
260 | 266 | y|mpage.1 | |Marcel Mol <marcel@mesa.nl> |
267 | n|mpcd.8 | |Heikki Vatiainen <hessu@cs.tut.fi>, Sampo Saaristo <s156953@cs.tut.fi> | |
261 | 268 | 5n|MPI_Group_free.3 |C |lam-devel@lam.mpi.org |
262 | 269 | 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 | |
265 | 273 | 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 | |
267 | 275 | y|nbp_name.3 | |netatalk-devel@lists.sourceforge.net |
268 | 3n|netsnmp_deprecated.3 |D |net-snmp-coders@lists.sourceforge.net | |
269 | 276 | 2n|netsnmp_iterator_info_s.3|s |net-snmp-coders@lists.sourceforge.net |
270 | 277 | 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 | |
272 | 279 | 5n|netdump.8 |L |anderson@redhat.com |
273 | 280 | 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 | |
277 | 290 | 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 | |
279 | 291 | 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> | |
280 | 293 | 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 | |
286 | 304 | 2n|PDL::GSL::INTEG.3pm |D |pdl-porters@jach.hawaii.edu |
287 | 305 | 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 | |
291 | 310 | 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 | |
293 | 312 | 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 | | |
295 | 315 | 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 | |
301 | 319 | 4p|privoxy.1 |j |developers@privoxy.org |
302 | 320 | 5n|ps2epsi.1 |j |giles@artifex.com |
303 | 321 | 5n|ps2pdf.1,ps2pdf12.1,ps2pdf13.1| |giles@artifex.com |
304 | 5n|psbanner.1 |T |Patrick Powell <papowell@lprng.com> | |
305 | 322 | 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 | |
307 | 324 | 4p|pvm_addmhf.3 |T |gst@ornl.gov |
308 | 325 | 2n|pvm_newcontext.3 |T |gst@ornl.gov |
309 | 326 | 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 | | |
313 | 332 | y|rdump.8,dump.8,restore.8,rrestore.8 | |Stelian Pop <stelian@popies.net> |
314 | 333 | 2n|rlm_expr.5 |X |Chris Parker <cparker@segv.org> |
315 | 334 | 2n|rlm_attr_filter.5 |XF |Chris Parker <cparker@segv.org> |
316 | 335 | 4p|roff.7 |A |wl@gnu.org |
317 | 336 | 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 | |
323 | 338 | 3n|sftp.1 |C |Damien Miller <djm@mindrot.org> |
324 | 339 | 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 | |
326 | 341 | 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 | |
329 | 343 | 5n|sgml2lyx.1 |Z |Taketoshi Sano <sano@debian.org> |
330 | 344 | 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 | |
333 | 347 | 2n|slapd.8 |C |OpenLDAP-devel@OpenLDAP.org |
334 | 348 | y|smartd.8,smartctl.8,smartd.conf.5| |smartmontools-support@lists.sourceforge.net |
335 | 349 | y|snmpvacm.1 | |net-snmp-coders@lists.sourceforge.net |
336 | 350 | 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 | | |
340 | 354 | y|squid_ldap_auth.8,squid_ldap_group.8 | |squid-bugs@squid-cache.org |
341 | 355 | y|ssh-keyscan.1 | |brad@openbsd.org |
342 | 356 | 2n|sshd_config.5,ssh_config.5 |q |brad@openbsd.org |
344 | 358 | 3n|tvtime.xml.5 |X |vektor@dumbterm.net |
345 | 359 | 5n|sysklogd.8 |X |greg@wind.enjellic.com |
346 | 360 | 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 | |
350 | 363 | 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 | |
352 | 366 | y|timidity.cfg.5 | |breeze.nagano@nifty.ne.jp, mo@goice.co.jp |
353 | 367 | 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 | |
356 | 369 | y|tree.1 | |Steve Baker <ice@mama.indstate.edu> |
357 | 370 | 5n|tsclient.1 |W |Miguel de Icaza <miguel@gnu.org> |
358 | 371 | bn|ttcp.1 |XD | |
359 | 372 | 5n|tune2fs.8 |C |tytso@thunk.org |
360 | 373 | 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 | |
363 | 375 | 3n|vacuumdb.1 |C |pgsql-docs@postgresql.org |
364 | 376 | 5n|vgsplit.8 |C |lvm-devel@lists.sistina.com |
365 | 377 | 5n|vorbiscomment.1 |C |Christopher L Cheney <ccheney@debian.org> |
366 | 378 | y|vsftpd.conf.5 | |chris@scary.beasts.org |
367 | 379 | 4r|wget.1 |s |mtortonesi@ing.unife.it |
368 | 5n|wmix.1x |X |timecop@japan.co.jp | |
369 | 380 | 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 | |
370 | 386 | 3n|XML::DOM::Element.3pm|z |perl-documentation@perl.org |
371 | 387 | 5n|XML::Encoding.3pm |n |perl-documentation@perl.org,coopercc@netheaven.com |
372 | 388 | 3n|XML::Parser::Style::Objects.3pm|W |perl-documentation@perl.org,coopercc@netheaven.com |
373 | 389 | 3n|XML::Parser::Style::Tree.3pm|W |perl-documentation@perl.org,coopercc@netheaven.com |
374 | 390 | 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 | |
377 | 393 | 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 | |
381 | 404 | bn|zshcompctl.1 |L | |
382 | 405 | bn|zshmodules.1 |nt | |
12 | 12 | |
13 | 13 | Test loads are included in the distribution. The code has been tested |
14 | 14 | 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. | |
16 | 16 | It lifts over 95% of these pages without requiring any hand-hacking. |
17 | 17 | |
18 | 18 | There is a detailed change log in the RPM spec file. |
19 | 19 | |
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 | ||
23 | 20 | Eric S. Raymond |
24 | 21 | November 2003 |
0 | 0 | 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. | |
1 | 11 | |
2 | 12 | * .Xo/.Xc Berkeley macro needs work. See elf.5. |
3 | 13 | |
6 | 16 | |
7 | 17 | * CA.pl.1ssl -- CA.pl is not properly tagged as a command. |
8 | 18 | |
9 | * Why aren't the command synopses in ab.1 and ac.1 parsed correctly? | |
10 | ||
11 | 19 | Edge cases in which we could do better -- |
12 | 20 | |
13 | 21 | * sox(1), soxmix(1) |
14 | 22 | These are totally hosed. |
15 | ||
16 | * qurlinfo(3qt) and others: | |
17 | operator declaration is seen as text, not structured. | |
18 | 23 | |
19 | 24 | Other things to do: |
20 | 25 | |
24 | 29 | |
25 | 30 | Big projects: |
26 | 31 | |
27 | * Translate EQN. | |
32 | * Translate EQN to MathXML. | |
28 | 33 | |
29 | 34 | See the BUGS file for other, more minor problems mainly due to bad markup. |
30 | 35 |
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 | ||
0 | 8 | doclifter (2.1-1) unstable; urgency=low |
1 | 9 | |
2 | 10 | * New upstream release |
1 | 1 | Section: devel |
2 | 2 | Priority: optional |
3 | 3 | 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 | |
6 | 6 | |
7 | 7 | Package: doclifter |
8 | 8 | Architecture: all |
17 | 17 | GNU General Public License for more details. |
18 | 18 | |
19 | 19 | 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. | |
22 | 23 | |
23 | 24 | On Debian GNU/Linux systems, the complete text of the GNU General |
24 | 25 | Public License can be found in `/usr/share/common-licenses/GPL'. |
30 | 30 | dh_testroot |
31 | 31 | dh_installdocs |
32 | 32 | dh_installexamples |
33 | dh_installman doclifter.1 | |
33 | dh_installman doclifter.1 manlifter.1 | |
34 | 34 | dh_installchangelogs |
35 | 35 | dh_link |
36 | 36 | dh_compress |
1 | 1 | """ |
2 | 2 | doclifter: translate man/mdoc/ms/me/mm sources to DocBook. |
3 | 3 | |
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. | |
5 | 6 | |
6 | 7 | This comment is addressed to you if you want to add support for another |
7 | 8 | macro package to doclifter. Or if you have encountered a bug in doclifter |
86 | 87 | interpret |
87 | 88 | The request interpreter. Called on every input line that begins |
88 | 89 | with a command character, that is . or ' not followed by another ' on the |
89 | samw line. | |
90 | same line. | |
90 | 91 | This method needs to be careful about troff continuation (\c) |
91 | 92 | characters. If you add trailing markup to a line, or entirely replace the |
92 | 93 | line, be sure to check for trailing \c first, remove it if present, and |
121 | 122 | Warning: much of this code is grubby. Alas, the grubbiness is |
122 | 123 | intrinsic, because the troff request language is grubby. |
123 | 124 | |
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 $ | |
125 | 126 | """ |
126 | 127 | # Requires Python 2.2a |
127 | 128 | import sys, os, glob, re, sre, string, exceptions, copy, tempfile, time, pprint |
221 | 222 | def is_command(line): |
222 | 223 | # This works around a common bug -- string-enclosing ' at the left margin |
223 | 224 | 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)) | |
225 | 226 | |
226 | 227 | def is_comment(line): |
227 | 228 | # The malformed crap people write as troff comments is amazing... |
228 | 229 | 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"'.\"") | |
230 | 231 | |
231 | 232 | def match_command(line, tag): |
232 | 233 | # 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): | |
234 | 235 | return False |
235 | 236 | tokens = line[1:].strip().split() |
236 | 237 | return tokens and tokens[0] == tag |
257 | 258 | str = re_compile(r"\f[^P]\fR$").sub(r"\fR", str) |
258 | 259 | return str |
259 | 260 | |
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." | |
262 | 263 | if len(str) == 0: |
263 | 264 | return "" |
264 | elif str[0] != "\\": | |
265 | elif str[0] != "&": | |
265 | 266 | return str[0] |
266 | take = 1 | |
267 | if str[1] == '*': | |
268 | take += 1 | |
269 | if str[take] == '(': | |
270 | take += 3 | |
271 | 267 | else: |
272 | take += 1 | |
273 | return str[:take] | |
268 | take = 1 | |
269 | while str[take] != ';': | |
270 | take += 1 | |
271 | return str[:take+1] | |
274 | 272 | |
275 | 273 | def make_comment(str): |
276 | 274 | str = str.replace(r'.\"', "").replace(r'.\\"', "").replace(r'\(co', "(C)") |
397 | 395 | out += '.\\" | mark %s as %s\n' % (token, tag) |
398 | 396 | out += '.\\" End doclifter hints.\n' |
399 | 397 | 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__` + ">" | |
400 | 407 | |
401 | 408 | class DocLifter: |
402 | 409 | "DocBook translation of generic troff macros." |
497 | 504 | )) |
498 | 505 | post_translation_patterns = ( |
499 | 506 | # man(7)-style man-page references |
500 | (re.compile(r"<emphasis remap='[BI]'>([^ ]+)</emphasis>(?:&zerosp;| )?\(([0-9]+)\)"), | |
507 | (re.compile(r"<emphasis remap='[BI]'>([^ ]+)</emphasis>(?:&zerosp;| )?\(([0-9]+[A-Za-z]?)\)"), | |
501 | 508 | r"<citerefentry><refentrytitle>\1</refentrytitle><manvolnum>\2</manvolnum></citerefentry>"), |
502 | 509 | # Here's where we fold all those continuation lines. |
503 | 510 | (re.compile("\\\c\n"), ""), |
732 | 739 | "Pop to new section level." |
733 | 740 | if section_verbosity in self.verbose: |
734 | 741 | self.notify("pop_section(%d)" % depth) |
742 | self.poplist('section-end') # Terminate all list structure | |
735 | 743 | toplevel = (depth == 1) and (self.sectiondepth == 1) |
736 | 744 | self.troff.nf = False |
737 | 745 | self.end_paragraph(label="pop_section") |
783 | 791 | self.nonblanks = 0 |
784 | 792 | def paragraph_break(self, line): |
785 | 793 | "Are we looking at a paragraph break command?" |
786 | if line.startswith(".end"): | |
794 | if line.startswith(TroffInterpreter.ctrl + "end"): | |
787 | 795 | return True |
788 | 796 | elif not is_command(line): |
789 | 797 | return False |
798 | 806 | return False |
799 | 807 | def section_break(self, line): |
800 | 808 | "Are we looking at a section break command?" |
801 | if line.startswith(".end"): | |
809 | if line.startswith(TroffInterpreter.ctrl + "end"): | |
802 | 810 | return True |
803 | 811 | elif not is_command(line): |
804 | 812 | return False |
810 | 818 | return True |
811 | 819 | return False |
812 | 820 | |
821 | def indent(self): | |
822 | return len(self.stash_indents) * " " | |
823 | ||
813 | 824 | def begin_block(self, markup, remap=""): |
814 | 825 | "Begin a block-context markup section." |
815 | self.in_block = True | |
816 | 826 | self.end_paragraph(label="begin_block") |
817 | 827 | if remap and not self.quiet: |
818 | 828 | remap = " remap='" + remap + "'" |
822 | 832 | self.warning("Begin display collection") |
823 | 833 | self.displaystack.append((markup, remap, DisplayParser(self,True,{}))) |
824 | 834 | else: |
825 | self.emit("<" + markup + remap + ">") | |
835 | self.emit(self.indent() + "<" + markup + remap + ">") | |
826 | 836 | self.need_paragraph() |
827 | 837 | |
828 | def end_block(self, markup, remap=""): | |
838 | def end_block(self, markup, remap="", ends=None): | |
829 | 839 | "End a block-context markup section." |
840 | # FIXME: use ends to ignore stray things that look like terminators | |
830 | 841 | if remap and not self.quiet: |
831 | 842 | remap = " <!-- remap='" + remap + "' -->" |
832 | if not self.in_block: | |
833 | return | |
843 | self.troff.nf = False | |
834 | 844 | # Turn off all font highlights -- technically incorrect, |
835 | 845 | # but almost always the right thing to do. We also |
836 | 846 | # probably need an end-paragraph here, but that will be |
837 | 847 | # taken care of by close_tags() later on. |
838 | if self.troff.nf: | |
839 | self.troff.nf = False | |
848 | if self.displaystack: | |
840 | 849 | (beginmarkup, beginremap, display) = self.displaystack.pop() |
841 | 850 | (parsed, userwarning) = display.transform() |
842 | 851 | self.emit("<" + beginmarkup + beginremap + ">") |
843 | 852 | self.emit(parsed + (r"\fR</%s>" % markup + remap)) |
844 | 853 | else: |
845 | self.emit(r"\fR</%s>" % markup + remap) | |
854 | self.emit(self.indent() + r"\fR</%s>" % markup + remap) | |
846 | 855 | self.need_paragraph() |
847 | self.in_block = False | |
848 | 856 | |
849 | 857 | def pushlist(self, cmd, type=None): |
850 | 858 | if io_verbosity in self.verbose: |
851 | 859 | self.notify("pushlist(%s, %s)" % (cmd, type)) |
852 | self.stash_indents.append([cmd, type, 0]) | |
860 | self.stash_indents.append(Frame(cmd, type)) | |
853 | 861 | |
854 | 862 | def poplist(self, cmd, backto=None): |
855 | 863 | "Pop levels off the list stack until we've removed specified command." |
856 | 864 | if io_verbosity in self.verbose: |
857 | 865 | self.notify("poplist(%s, %s) %s" % (cmd, backto, self.stash_indents)) |
858 | 866 | 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": | |
861 | 869 | self.emit_variablelist("end") |
862 | elif listtype == "itemizedlist": | |
870 | elif frame.type == "itemizedlist": | |
863 | 871 | self.emit_itemizedlist("end") |
864 | else: | |
872 | elif frame.type == "blockquote": | |
873 | self.end_block("blockquote", remap='RE') | |
865 | 874 | self.stash_indents.pop() |
866 | if top == backto: | |
875 | else: | |
876 | self.stash_indents.pop() | |
877 | if frame.command == backto: | |
867 | 878 | break |
868 | 879 | if io_verbosity in self.verbose: |
869 | 880 | self.notify("after popping %s" % (self.stash_indents,)) |
870 | 881 | |
871 | 882 | def last_tag(self, lookfor): |
872 | 883 | "What was the last actual tag emitted?" |
884 | if not self.diversion: | |
885 | return False | |
873 | 886 | back = -1 |
874 | 887 | while True: |
875 | 888 | backline = self.diversion[back].strip() |
887 | 900 | self.notify("emit_variablelist(%s) %s"%(cmd, self.stash_indents)) |
888 | 901 | if cmd == "end": |
889 | 902 | if self.stash_indents: |
890 | indent = (len(self.stash_indents) * " ") | |
903 | indent = self.indent() | |
891 | 904 | self.stash_indents.pop() |
892 | 905 | if self.last_tag("<listitem"): |
893 | 906 | self.emit("<para> <!-- FIXME: blank list item -->") |
897 | 910 | self.emit("%s</variablelist>" % indent[2:]) |
898 | 911 | return |
899 | 912 | # 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: | |
901 | 914 | if self.quiet: |
902 | 915 | remap = "" |
903 | 916 | else: |
904 | 917 | 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() | |
908 | 921 | back = self.last_tag("<listitem") |
909 | 922 | if back: |
910 | 923 | self.diversion[back] = "<!-- DELETE ME! -->" |
911 | 924 | else: |
912 | if self.stash_indents[-1][2] > 0: | |
925 | if self.stash_indents[-1].count > 0: | |
913 | 926 | self.emit("%s</listitem>" % indent) |
914 | 927 | self.emit("%s</varlistentry>" % indent) |
915 | 928 | self.emit("%s<varlistentry>" % indent) |
916 | 929 | self.emit("%s<term>%s</term>" % (indent, fontclose(term))) |
917 | 930 | self.emit("%s<listitem>" % indent) |
918 | self.stash_indents[-1][2] += 1 | |
931 | self.stash_indents[-1].count += 1 | |
919 | 932 | self.need_paragraph() |
920 | 933 | |
921 | 934 | def emit_itemizedlist(self, cmd, bullet=None): |
924 | 937 | self.notify("emit_itemizedlist(%s) %s"%(cmd, self.stash_indents)) |
925 | 938 | if cmd == "end": |
926 | 939 | if self.stash_indents: |
927 | indent = len(self.stash_indents) * " " | |
940 | indent = self.indent() | |
928 | 941 | self.stash_indents.pop() |
929 | 942 | if self.last_tag("<listitem"): |
930 | 943 | self.emit("<para> <!-- FIXME: blank list item -->") |
933 | 946 | self.emit("%s</itemizedlist>" % indent[2:]) |
934 | 947 | return |
935 | 948 | # 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: | |
937 | 950 | if self.quiet: |
938 | 951 | remap = "" |
939 | 952 | else: |
940 | 953 | 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() | |
944 | 957 | back = self.last_tag("<listitem") |
945 | 958 | if back: |
946 | 959 | self.diversion[back] = "<!-- DELETE ME! -->" |
947 | 960 | else: |
948 | if self.stash_indents[-1][2] > 0: | |
961 | if self.stash_indents[-1].count > 0: | |
949 | 962 | self.emit("%s</listitem>" % indent) |
950 | 963 | self.emit("%s<listitem override='%s'>" % (indent, bullet)) |
951 | self.stash_indents[-1][2] += 1 | |
964 | self.stash_indents[-1].count += 1 | |
952 | 965 | self.need_paragraph() |
953 | 966 | |
954 | 967 | # Highlight handling |
1084 | 1097 | if squashed[0] in "_0123456789": |
1085 | 1098 | squashed = "x" + squashed |
1086 | 1099 | # 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] | |
1089 | 1101 | else: |
1090 | 1102 | # 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 | |
1092 | 1108 | def make_id_from_title(self, str): |
1093 | 1109 | id = self.id_from_title(str) |
1094 | 1110 | # We allow duplicate sections, but warn about them |
1120 | 1136 | def id_exists(self, id): |
1121 | 1137 | "Test whether an id already exists" |
1122 | 1138 | return self.idlist.has_key(id) |
1123 | def TBL(self, enddelim=".TE"): | |
1139 | def TBL(self, enddelim=None): | |
1124 | 1140 | "Translate and emit a tbl section." |
1141 | if enddelim == None: | |
1142 | enddelim = TroffInterpreter.ctrl + "TE" | |
1125 | 1143 | # Detect and avoid QT breakage |
1126 | 1144 | if self.find("Trolltech"): |
1127 | 1145 | self.warning("garbage table elided") |
1200 | 1218 | tline = self.lines.pop(0) |
1201 | 1219 | if tline.strip() == enddelim: |
1202 | 1220 | break |
1203 | elif tline == ".TH": | |
1221 | elif tline == TroffInterpreter.ctrl + "TH": | |
1204 | 1222 | lastheaderline = len(data) |
1205 | 1223 | elif tline[-2:] == "T{": |
1206 | 1224 | while self.lines: |
1385 | 1403 | eqnlines.append(line) |
1386 | 1404 | if nondelimlines: |
1387 | 1405 | if self.preamble: |
1388 | self.emit(make_comment(".EQ")) | |
1406 | self.emit(make_comment(TroffInterpreter.ctrl + "EQ")) | |
1389 | 1407 | for line in eqnlines: |
1390 | 1408 | self.emit(make_comment(line)) |
1391 | self.emit(make_comment(".EN")) | |
1409 | self.emit(make_comment(TroffInterpreter.ctrl + "EN")) | |
1392 | 1410 | else: |
1393 | 1411 | self.emit("<literallayout remap='EQN'>") |
1394 | self.emit(".EQ") | |
1412 | self.emit(TroffInterpreter.ctrl + "EQ") | |
1395 | 1413 | for line in eqnlines: |
1396 | 1414 | self.emit(line) |
1397 | self.emit(".EN") | |
1415 | self.emit(TroffInterpreter.ctrl + "EN") | |
1398 | 1416 | self.emit("</literallayout>") |
1399 | 1417 | |
1400 | 1418 | def PIC(self): |
1404 | 1422 | if not self.pic_seen: |
1405 | 1423 | self.pic_seen = True |
1406 | 1424 | 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") | |
1408 | 1426 | |
1409 | 1427 | def ignore(self, cmd): |
1410 | 1428 | "Declare that we want to ignore a command." |
1420 | 1438 | if not command: |
1421 | 1439 | return False |
1422 | 1440 | command = command.split()[0] # only look at first token |
1423 | if command[0] in ".'": | |
1441 | if command[0] in (TroffInterpreter.ctrl,TroffInterpreter.ctrl_nobreak): | |
1424 | 1442 | command = command[1:] |
1425 | 1443 | return command in self.ignore_set or (nocomplaints and command in self.complain_set) |
1426 | 1444 | |
1445 | 1463 | if self.stash_indents and listbreaker: |
1446 | 1464 | if io_verbosity in self.verbose: |
1447 | 1465 | self.notify("list closer %s: %s"%(command,self.stash_indents)) |
1448 | enclosing = self.stash_indents[-1][0] | |
1466 | enclosing = self.stash_indents[-1].command | |
1449 | 1467 | if enclosing in self.listbreak_set and enclosing != command: |
1450 | 1468 | 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) | |
1452 | 1475 | # Here is where string expansion gets done: |
1453 | 1476 | stripped = [] |
1454 | 1477 | for arg in stripquotes(tokens): |
1496 | 1519 | # pass it through for the interpreters to munch on. |
1497 | 1520 | if line == '': |
1498 | 1521 | if self.body_section() and not self.troff.nf: |
1499 | self.pushline(".blank") | |
1522 | self.pushline(TroffInterpreter.ctrl + "blank") | |
1500 | 1523 | # Treat blank lines in synopses as break commands; |
1501 | 1524 | # see cpio.1 for an example of why this is necessary. |
1502 | 1525 | elif self.in_synopsis(): |
1503 | self.pushline(".br") | |
1526 | self.pushline(TroffInterpreter.ctrl + "br") | |
1504 | 1527 | else: |
1505 | 1528 | self.emit('') |
1506 | 1529 | continue |
1523 | 1546 | # who forget that the closing bracket of a conditional is |
1524 | 1547 | # a command. It's probably going to bite us someday. |
1525 | 1548 | if line == r"\}": |
1526 | self.pushline(".\}") | |
1549 | self.pushline(TroffInterpreter.ctrl + "\}") | |
1527 | 1550 | if macro_verbosity in self.verbose: |
1528 | 1551 | self.warning(r"adventitious \} should probably be .\}") |
1529 | 1552 | continue |
1664 | 1687 | "arg":1, "group":1, "cmdsynopsis":1, "command":1, |
1665 | 1688 | "funcsynopsis":1, "funcsynopsisinfo":1, "funcprototype":1, "funcdef":1, |
1666 | 1689 | "paramdef":1, "parameter":1, "function":1, "void":1, "vaargs":1, |
1667 | "synopsis":1, | |
1690 | "synopsis":1, "symbol":1, | |
1668 | 1691 | } |
1669 | 1692 | while True: |
1670 | 1693 | if state == 0: # Looking for <tag> |
1681 | 1704 | elif state == 1: # Found <tag>, looking for next tag |
1682 | 1705 | nexttag = before.find("<") |
1683 | 1706 | if nexttag == -1: |
1684 | self.error("missing tag after <tag>!") | |
1707 | self.error("tag closer is confused by `%s`!" % before) | |
1708 | break | |
1685 | 1709 | after += before[:nexttag] |
1686 | 1710 | before = before[nexttag:] |
1687 | 1711 | # </tag> just closes the scope |
1755 | 1779 | if lines[0].find("Updated: ") > -1: |
1756 | 1780 | date = lines[0][lines[0].find("Updated: ")+10:].strip() |
1757 | 1781 | lines.pop(0) |
1782 | if not lines: | |
1783 | raise LiftException("plain text where manual page expected", 1) | |
1758 | 1784 | inoptions = False |
1759 | 1785 | for i in range(len(lines)): |
1760 | 1786 | if len(lines[i]) == 0: |
1761 | 1787 | continue |
1762 | 1788 | elif lines[i][0] in "ABCDEFGHIJKLMNOPQRSTUVWXYZ": |
1763 | 1789 | inoptions = lines[i].startswith("OPTIONS") |
1764 | lines[i] = ".SH " + lines[i].strip() | |
1790 | lines[i] = TroffInterpreter.ctrl + "SH " + lines[i].strip() | |
1765 | 1791 | else: |
1766 | 1792 | lines[i] = lines[i].strip() |
1767 | 1793 | if lines[i].startswith("____________"): |
1768 | 1794 | lines = lines[:i] |
1769 | 1795 | break |
1770 | 1796 | 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: | |
1773 | 1799 | lines[i] = "\\&" + lines[i] |
1774 | 1800 | 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(".") | |
1777 | 1803 | name = os.path.basename(name) |
1778 | 1804 | th = '.TH "%s" "%s" "%s" "" ""\n' % (name, section, date) |
1779 | 1805 | return th + "\n".join(lines) + "\n" |
1780 | 1806 | |
1781 | def __call__(self, name, file, text): | |
1807 | def __call__(self, name, file, text, multiarg): | |
1782 | 1808 | "Translate a string containing troff source to DocBook markup." |
1809 | self.name = name | |
1783 | 1810 | self.file = file |
1811 | self.multiarg = multiarg | |
1784 | 1812 | self.eqnsub = None |
1785 | 1813 | self.preamble = True |
1786 | 1814 | self.body_start = 0 |
1800 | 1828 | self.troff = TroffInterpreter(self, self.verbose) |
1801 | 1829 | self.interpreters = [self.troff] |
1802 | 1830 | 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) | |
1803 | 1835 | # Parse semantic hints from the text, if present. |
1804 | 1836 | # Yes, they should go to the global registry. |
1805 | 1837 | global globalhints |
1880 | 1912 | # Split it into lines |
1881 | 1913 | toplevel = text.split("\n") |
1882 | 1914 | # Check for pure inclusions |
1915 | def is_inclusion(x): | |
1916 | return x[:4] == TroffInterpreter.ctrl + "so " | |
1883 | 1917 | 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]): | |
1885 | 1919 | 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) | |
1886 | 1922 | # If it's not a pure inclusion, warn if we don't have a macro set. |
1887 | 1923 | if len(self.interpreters) == 1: |
1888 | stderr.write("doclifter: no macro set recognized\n") | |
1924 | raise LiftException("no macro set recognized", 1) | |
1889 | 1925 | # Strip off trailing blank lines, they interact badly with the |
1890 | 1926 | # paragraphing logic. |
1891 | 1927 | while toplevel and toplevel[-1] == "": |
1893 | 1929 | # This actually happens with some generated Perl pages |
1894 | 1930 | # that stop after .TH |
1895 | 1931 | if len(toplevel) <= 1: |
1896 | raise LiftException("warning: %s is empty" % self.file) | |
1932 | raise LiftException("%s has no content" % self.file) | |
1897 | 1933 | # Is there any text at all in this file? |
1898 | 1934 | textcount = 0 |
1899 | 1935 | for line in toplevel: |
1905 | 1941 | i = -1 |
1906 | 1942 | if not toplevel[i] and is_comment(toplevel[i]): |
1907 | 1943 | i -= 1 |
1908 | toplevel.insert(len(toplevel)-i, ".end") | |
1944 | toplevel.insert(len(toplevel)-i, TroffInterpreter.ctrl + "end") | |
1909 | 1945 | # Emit the top-level tag, with an id that will direct the |
1910 | 1946 | # DocBook toolchain to do the right thing. |
1911 | 1947 | if self.toptag: |
1948 | 1984 | # again afterwards. Because body_start is a line index, |
1949 | 1985 | # we have to not insert or delete lines here. |
1950 | 1986 | 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) | |
1953 | 1989 | self.output = after.split("\n") |
1954 | 1990 | if timing_verbosity in self.verbose: |
1955 | 1991 | now = time.time() |
1956 | 1992 | stderr.write("timing: tag closing = %2.2f\n" % (now-self.basetime,)) |
1957 | 1993 | 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). | |
1959 | 1995 | # 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): | |
1961 | 1997 | return None |
1962 | 1998 | if timing_verbosity in self.verbose: |
1963 | 1999 | now = time.time() |
2028 | 2064 | if self.complaints and general_verbosity in self.verbose: |
2029 | 2065 | stderr.write("warning: " + ", ".join(self.complaints.keys()) + " seen\n") |
2030 | 2066 | # 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. | |
2032 | 2068 | text = text.replace("\\\\", "\\") |
2033 | 2069 | if timing_verbosity in self.verbose: |
2034 | 2070 | now = time.time() |
2063 | 2099 | # This can substantially reduce the amount of manual hackery |
2064 | 2100 | # needed to hand-translate the eqn. |
2065 | 2101 | 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) | |
2067 | 2103 | # Also nuke hair-thin space, at this late stage it shouldn't make |
2068 | 2104 | # any difference. This avoids an apparent bug in the DocBook |
2069 | 2105 | # stylesheets;   is documented but not actually defined. |
2112 | 2148 | # Complain about stuff that produces gross motions. |
2113 | 2149 | "ne":1,"mk":1,"rt":1,"ce":1, #"in":1, |
2114 | 2150 | # 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, | |
2116 | 2152 | # We can't handle environments, insertions, or next file. |
2117 | 2153 | "ev":1,"rd":1,"nx":1,"pi":1, |
2118 | 2154 | } |
2524 | 2560 | ("option", "option"), |
2525 | 2561 | )) |
2526 | 2562 | |
2563 | # These are interpreter state which can be modified by the .cc command | |
2564 | ctrl = "." | |
2565 | ctrl_nobreak = "'" | |
2566 | ||
2527 | 2567 | def __init__(self, source, verbose): |
2528 | 2568 | self.source = source |
2529 | 2569 | self.verbose = verbose |
2530 | 2570 | self.strings = {} # String table for ds, as, rm, rn |
2531 | 2571 | 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 | |
2533 | 2573 | self.macroargs = [] # Macro argument stack |
2534 | 2574 | self.macronames = [] # Macro name stack (only used in error msgs) |
2535 | 2575 | self.nf = False # Initially we're filling and adjusting |
2815 | 2855 | while self.source.ignorable(self.source.peekline(), nocomplaints=1): |
2816 | 2856 | self.source.emit(make_comment(self.source.popline())) |
2817 | 2857 | next = self.source.peekline() |
2818 | if next and next[0:3] == ".ft": | |
2858 | if next and next[0:3] == TroffInterpreter.ctrl + "ft": | |
2819 | 2859 | cmd = lineparse(self.source.popline()) |
2820 | 2860 | if len(cmd) == 1: |
2821 | 2861 | self.source.emit(r"\fR") |
2837 | 2877 | self.source.need_paragraph() |
2838 | 2878 | elif command in ("nf", "NF"): # .NF is an oddly common typo |
2839 | 2879 | self.source.end_paragraph(label="nf") |
2840 | if self.source.peekline() == ".ft CW": | |
2880 | if self.source.peekline() == TroffInterpreter.ctrl + "ft CW": | |
2841 | 2881 | self.source.popline() |
2842 | 2882 | self.source.end_paragraph() |
2843 | 2883 | self.source.emit("<screen> <!-- .nf -->") |
2860 | 2900 | self.source.lines[i] = r"\fU" + self.source.lines[i] + r"\fP" |
2861 | 2901 | elif command == "tr": |
2862 | 2902 | while True: |
2863 | frompart = get_troff_char(args[0]) | |
2903 | frompart = get_xml_char(args[0]) | |
2864 | 2904 | args[0] = args[0][len(frompart):] |
2865 | topart = get_troff_char(args[0]) | |
2905 | topart = get_xml_char(args[0]) | |
2866 | 2906 | args[0] = args[0][len(topart):] |
2867 | 2907 | if not frompart: |
2868 | 2908 | break |
2935 | 2975 | value = " ".join(tokens[2:]) |
2936 | 2976 | else: |
2937 | 2977 | value = " ".join(tokens[2:]) |
2978 | value = value.replace("'", "'"); | |
2938 | 2979 | if self.source.preamble and self.entities_from_strings: |
2939 | 2980 | self.source.localentities.append((stringname, value)) |
2940 | 2981 | self.strings[stringname] = "&" + stringname + ";" |
2983 | 3024 | endon = newname |
2984 | 3025 | else: |
2985 | 3026 | 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: | |
2987 | 3028 | 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) | |
2989 | 3030 | suppressed = False |
2990 | 3031 | for interpreter in self.source.interpreters: |
2991 | 3032 | if name in interpreter.immutable_set.keys(): |
3064 | 3105 | if len(tokens) == 1: |
3065 | 3106 | # Cope with a transposition typo...see vmstat(8) for example. |
3066 | 3107 | if command == "if" and self.nf: |
3067 | self.source.pushline(".fi") | |
3108 | self.source.pushline(TroffInterpreter.ctrl + "fi") | |
3068 | 3109 | else: |
3069 | 3110 | self.source.error("malformed conditional %s" % command) |
3070 | 3111 | return True |
3088 | 3129 | # Evidently this is somebody's way of getting "and" into |
3089 | 3130 | # conditionals. Ugh... |
3090 | 3131 | 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": | |
3092 | 3133 | if macro_verbosity in self.verbose: |
3093 | 3134 | self.source.notify("if or ie does one-line pushback") |
3094 | self.source.pushline(r".\}") | |
3135 | self.source.pushline(TroffInterpreter.ctrl + r"\}") | |
3095 | 3136 | if tokens[2].startswith(r"\{"): |
3096 | 3137 | tokens[2] = tokens[2][2:] |
3097 | 3138 | if macro_verbosity in self.verbose: |
3130 | 3171 | # If it's a one-liner and condition false, push back remaining text |
3131 | 3172 | oneliner = len(tokens) > 1 and tokens[1][:2] != r"\{" |
3132 | 3173 | if not condition and oneliner: |
3133 | self.source.pushline(r".\}") | |
3174 | self.source.pushline(TroffInterpreter.ctrl + r"\}") | |
3134 | 3175 | self.source.pushline(" ".join(tokens[1:])) |
3135 | 3176 | # If condition is true we need to do a skip now |
3136 | 3177 | if condition and not oneliner: |
3155 | 3196 | self.source.emit("<!-- " + " ".join(tokens)) |
3156 | 3197 | while self.source.lines: |
3157 | 3198 | line = self.source.popline() |
3158 | if line.startswith("." + args[0]): | |
3199 | if line.startswith(TroffInterpreter.ctrl + args[0]): | |
3159 | 3200 | self.source.emit(".%s -->" % args[0], trans=0) |
3160 | 3201 | break |
3161 | 3202 | line = line.replace("--", "––") |
3174 | 3215 | self.macronames.append(command) |
3175 | 3216 | self.source.lines = self.macros[command] + [self.source.lineno] + self.source.lines |
3176 | 3217 | # Extended groff macros |
3218 | elif command == "cc": | |
3219 | TroffInterpreter.ctrl = args[0] | |
3220 | elif command == "c2": | |
3221 | TroffInterpreter.ctrl_break = args[0] | |
3177 | 3222 | elif command == "ab": |
3178 | 3223 | if not args: |
3179 | 3224 | args = ["User Abort"] |
3196 | 3241 | elif command == "PSPIC": |
3197 | 3242 | file = args[0] |
3198 | 3243 | 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 -->") | |
3199 | 3246 | # We're done |
3200 | 3247 | else: |
3201 | 3248 | return False |
3203 | 3250 | if len(tokens) > 1 and tokens[-1] == r"\}": |
3204 | 3251 | if macro_verbosity in self.verbose: |
3205 | 3252 | self.source.notify("pushing back a trailing bracket") |
3206 | self.source.pushline(r".\}") | |
3253 | self.source.pushline(TroffInterpreter.ctrl + r"\}") | |
3207 | 3254 | return True |
3208 | 3255 | def conditionally_replace(self, wrapper, standard): |
3209 | 3256 | "Replace a wrapper with a standard macro if the wrapper contains it." |
3211 | 3258 | if not self.source.quiet: |
3212 | 3259 | self.source.emit(make_comment("%s reduced to %s" % (wrapper, standard))) |
3213 | 3260 | 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) | |
3215 | 3262 | def preprocess(self, text): |
3216 | 3263 | 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") | |
3217 | 3268 | for line in text.split("\n"): |
3218 | 3269 | # Fix a common error -- beginning a line with a string quote |
3219 | 3270 | # that isn't supposed to be a non-breaking request (example at |
3230 | 3281 | # XMLify everything |
3231 | 3282 | for (pattern, substitute) in TroffInterpreter.xmlify_patterns: |
3232 | 3283 | line = pattern.sub(substitute, line) |
3284 | # Handle a grotty special case from spax.1 | |
3285 | line = line.replace(r"\l'\n(.lu'", ".DOCLIFTER-HR") | |
3233 | 3286 | expanded.append(line) |
3234 | 3287 | return "\n".join(expanded) |
3235 | 3288 | def postprocess(self, text): |
3290 | 3343 | if general_verbosity in self.verbose: |
3291 | 3344 | self.source.notify("Starting from down, I see upward %s" % upward) |
3292 | 3345 | elif downward: |
3293 | self.source.error("two downward motions in a row %s") | |
3346 | self.source.error("two downward motions in a row") | |
3294 | 3347 | raise SystemExit |
3295 | 3348 | else: |
3296 | 3349 | self.source.error("error in vertical-motion match (down)") |
3328 | 3381 | "Skip blank lines and ignorable commands." |
3329 | 3382 | while source.lines: |
3330 | 3383 | line = source.popline() |
3331 | if line == ".end": | |
3332 | source.pushline(".end") | |
3384 | if line == TroffInterpreter.ctrl + "end": | |
3385 | source.pushline(TroffInterpreter.ctrl + "end") | |
3333 | 3386 | break; |
3334 | 3387 | elif line == None: |
3335 | 3388 | break |
3336 | elif line in ("", ".", "'"): # Skip blank or null lines | |
3389 | elif line in ("", TroffInterpreter.ctrl, TroffInterpreter.ctrl_nobreak): # Skip blank or null lines | |
3337 | 3390 | continue |
3338 | 3391 | elif source.paragraph_break(line): # Skip ordinary paragraphs |
3339 | 3392 | continue |
3378 | 3431 | while source.lines: |
3379 | 3432 | line = source.popline() |
3380 | 3433 | # 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") | |
3383 | 3436 | while True: |
3384 | 3437 | line = source.popline() |
3385 | 3438 | savesect.append(line) |
3386 | if line == "..": | |
3439 | if line == TroffInterpreter.ctrl + ".": | |
3387 | 3440 | break |
3388 | 3441 | continue |
3389 | 3442 | elif line is None: |
3390 | 3443 | break |
3391 | elif line.startswith(".blank"): | |
3444 | elif line.startswith(TroffInterpreter.ctrl + "blank"): | |
3392 | 3445 | # The point is not to end the list on these. |
3393 | savesect.append(".blank") | |
3446 | savesect.append(TroffInterpreter.ctrl + "blank") | |
3394 | 3447 | elif source.section_break(line): |
3395 | 3448 | # Push back any blank lines before the section break. |
3396 | 3449 | # This avoids generating some spurious paragraph() |
3451 | 3504 | nameline = nameline.replace(r" — ", r' \- ') |
3452 | 3505 | if nameline.find(r" \- ") == -1: |
3453 | 3506 | nameline = nameline.replace("--", r' \- ') |
3454 | # Apparent pod2man breakage,,, | |
3507 | # Apparent pod2man breakage... | |
3455 | 3508 | nameline = nameline.replace(r"&zerosp;-", "\-") |
3456 | 3509 | # SDL pages make this kluge necessary |
3457 | 3510 | if nameline.find(r" \- ") == -1: |
3500 | 3553 | elif self.type == "\n": |
3501 | 3554 | return "" |
3502 | 3555 | else: |
3556 | res = "" | |
3503 | 3557 | for child in self.children: |
3504 | 3558 | res += `child` |
3505 | return res | |
3559 | return ("<%s>" % self.type) + res + ("</%s>" % self.type) | |
3506 | 3560 | |
3507 | 3561 | def is_file_or_command_name(tok): |
3508 | 3562 | # Yes, some legitimate commands begin with digits; |
4280 | 4334 | # If the first token is bolded, that probably means it's a command |
4281 | 4335 | # name that doesn't happen to match anything in the name section. |
4282 | 4336 | # 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 "): | |
4284 | 4338 | return 9 |
4285 | 4339 | # Nope, doesn't look like a command synopsis line |
4286 | 4340 | if classify_verbosity in self.source.verbose: |
4311 | 4365 | if arg == None: |
4312 | 4366 | break |
4313 | 4367 | 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 | |
4314 | 4373 | return "<cmdsynopsis>\n"+output+"</cmdsynopsis>\n" |
4315 | 4374 | except LiftException, e: |
4316 | 4375 | self.error = "command synopsis parse failed on `%s' (%d): %s" % \ |
4342 | 4401 | next = self.io.token_peek() |
4343 | 4402 | if next and next[0] in ('-', '+') or next.startswith("±"): |
4344 | 4403 | self.confirmed = True |
4404 | return True | |
4405 | elif next and self.lastnest and next in ('&', '\'): # See tex.1 | |
4345 | 4406 | return True |
4346 | 4407 | else: |
4347 | 4408 | return False |
4518 | 4579 | class DisplayParser: |
4519 | 4580 | "Parse a block into function synopsis, command synopsis or display text." |
4520 | 4581 | old_style_option_glue = re_compile(r"([^A-Za-z]-[A-Za-z]*)(?:\f.)([A-Za-z])") |
4521 | unparseable = re_compile(r"\$|=>|print|//") # Perl and other nightmares | |
4582 | unparseable = re_compile(r"\$|=>|[^:]//") # Perl and other nightmares | |
4522 | 4583 | def __init__(self, source, try_synopsis, refnames={}): |
4523 | 4584 | "Arrange the interpreter to accumulate synopsis lines in this object." |
4524 | 4585 | self.source = source |
4597 | 4658 | else: |
4598 | 4659 | processed.append(line+"\n") |
4599 | 4660 | # Translate troff characters and XMLlify everything. |
4661 | if classify_verbosity in self.source.verbose: | |
4662 | self.source.notify("Before tokenization: %s\n" % processed) | |
4600 | 4663 | self.io = LineTokenizer(processed, |
4601 | 4664 | tokenizer_verbosity in self.source.verbose) |
4602 | 4665 | 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)) | |
4604 | 4667 | |
4605 | 4668 | # This code is failure-prone. It is coping as best it can with a mess. |
4606 | 4669 | # |
4764 | 4827 | "FM":1, |
4765 | 4828 | # Undocumented, used in the attr(3) man pages |
4766 | 4829 | "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, | |
4767 | 4833 | # .Id is used to embed RCS/SCCS IDs. |
4768 | 4834 | "Id":1,} |
4769 | 4835 | complain_set = {} |
4794 | 4860 | self.seen_DS = False |
4795 | 4861 | self.qt_grotty_hack = False |
4796 | 4862 | self.have_name = False |
4797 | self.rsre_count = 0 | |
4798 | 4863 | self.stash_linkender = None |
4799 | 4864 | #self.systype = None |
4800 | 4865 | def fold_highlights(self, cmd, args): |
4854 | 4919 | while True: |
4855 | 4920 | line = self.source.popline() |
4856 | 4921 | # 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"): | |
4858 | 4923 | self.source.pushline(line) |
4859 | 4924 | break |
4860 | 4925 | #self.source.pushline(line) |
4875 | 4940 | self.source.ignore("fi") |
4876 | 4941 | while True: |
4877 | 4942 | 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) | |
4878 | 4949 | if line is None or self.source.section_break(line): |
4879 | 4950 | self.source.pushline(line) |
4880 | 4951 | 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"):] | |
4883 | 4954 | if is_comment(line): |
4884 | 4955 | continue |
4885 | 4956 | elif not (is_command(line) and self.source.ignorable(line)): |
4897 | 4968 | self.source.unignore("fi") |
4898 | 4969 | # Skip lines that are blank or consist of a leading dot only |
4899 | 4970 | # (as in groff_mdoc(7)). |
4900 | while not namelines[0] or namelines[0] == ".": | |
4971 | while not namelines[0] or namelines[0] == TroffInterpreter.ctrl: | |
4901 | 4972 | namelines.pop(0) |
4902 | 4973 | try: |
4903 | 4974 | namesect = parse_name_section(" ".join(namelines)) |
5030 | 5101 | if self.source.body_section(): |
5031 | 5102 | while blankline.match(self.source.peekline()): |
5032 | 5103 | self.source.popline() |
5033 | self.source.trap_emit(".TP ") | |
5104 | self.source.trap_emit(TroffInterpreter.ctrl + "TP ") | |
5034 | 5105 | # Relative indent changes |
5035 | 5106 | elif cmd == "RS": |
5036 | 5107 | # Check for no-ops generated by pod2man. |
5037 | if self.source.peekline().startswith(".RE"): | |
5108 | if self.source.peekline().startswith(TroffInterpreter.ctrl + "RE"): | |
5038 | 5109 | self.source.popline() |
5039 | 5110 | 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. | |
5044 | 5112 | # Notably, if we're looking at .RS+.nf, this is |
5045 | 5113 | # 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") | |
5047 | 5118 | return True |
5048 | # We can ignore .nf+.RS, too | |
5119 | # No markup for .nf+.RS, too, but | |
5049 | 5120 | elif self.source.last_tag("<literallayout"): |
5121 | self.source.pushlist("RS") | |
5050 | 5122 | return True |
5051 | 5123 | # If we're in list content, nest the list a level deeper |
5052 | 5124 | 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") | |
5054 | 5128 | self.source.need_paragraph() |
5055 | 5129 | return True |
5056 | 5130 | # Next check for single-line .RS/.RE blocks. |
5057 | 5131 | # This will fail if the line has a highlight. |
5058 | 5132 | elif not is_command(self.source.peekline()): |
5059 | 5133 | text = self.source.popline() |
5060 | if self.source.peekline() == ".RE": | |
5134 | if self.source.peekline() == TroffInterpreter.ctrl + "RE": | |
5061 | 5135 | self.source.popline() |
5062 | 5136 | self.source.begin_block("literallayout", remap='RS') |
5063 | 5137 | self.source.emit(text) |
5066 | 5140 | else: |
5067 | 5141 | self.source.pushline(text) |
5068 | 5142 | # 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') | |
5074 | 5146 | 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() | |
5096 | 5149 | # Hyperlinks |
5097 | elif cmd == "UE": | |
5150 | elif cmd == "UE": # End of link text | |
5098 | 5151 | if self.source.body_section(): |
5099 | 5152 | self.source.pushline(self.stash_linkender) |
5100 | elif cmd == "UN": | |
5153 | elif cmd == "UN": # Anchor for a hyperlink target | |
5101 | 5154 | if not args: |
5102 | 5155 | self.source.error("UN macro requires an argument") |
5103 | 5156 | 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"): | |
5105 | 5158 | self.source.stash_id = args[0] |
5106 | 5159 | else: |
5107 | 5160 | 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 | |
5109 | 5162 | if not args: |
5110 | 5163 | self.source.error("UR macro requires an argument") |
5111 | 5164 | elif self.source.body_section(): |
5132 | 5185 | elif cmd == "Ds": |
5133 | 5186 | self.source.begin_block("literallayout", remap="Ds") |
5134 | 5187 | elif cmd == "De": |
5135 | self.source.end_block("literallayout", remap="De") | |
5188 | self.source.end_block("literallayout", remap="De", ends="Ds") | |
5136 | 5189 | elif cmd == "EX": |
5137 | 5190 | self.source.begin_block("literallayout", remap="EX") |
5138 | 5191 | 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") | |
5140 | 5197 | elif cmd == "NT": |
5141 | 5198 | self.source.begin_block("note", remap="NT") |
5142 | 5199 | elif cmd == "NE": |
5143 | self.source.end_block("note", remap="NE") | |
5200 | self.source.end_block("note", remap="NE", ends="NT") | |
5144 | 5201 | elif cmd == "RN": |
5145 | 5202 | self.source.pushline("<keycap>RETURN</keycap>") |
5146 | 5203 | elif cmd == "PN": |
5179 | 5236 | # self.systype = "4.4 Berkeley Distribution" |
5180 | 5237 | # mtools man pages use these...ugh |
5181 | 5238 | elif cmd == "(l": |
5182 | self.source.pushline(".nf") | |
5239 | self.source.pushline(TroffInterpreter.ctrl + "nf") | |
5183 | 5240 | elif cmd == ")l": |
5184 | self.source.pushline(".fi") | |
5241 | self.source.pushline(TroffInterpreter.ctrl + "fi") | |
5185 | 5242 | # DS/DE isn't part of the man macros. Interpret it anyway, |
5186 | 5243 | # as there is an obvious meaning that people try to use. |
5187 | 5244 | elif cmd == "DS": |
5188 | 5245 | # Catch an odd, pointless use of .DS that pops up on a number |
5189 | 5246 | # of SANE manual pages (probably generated from something). |
5190 | if self.source.peekline() == ".sp\n": | |
5247 | if self.source.peekline() == TroffInterpreter.ctrl + "sp\n": | |
5191 | 5248 | self.source.popline() |
5192 | 5249 | self.source.popline() |
5193 | 5250 | elif self.source.find("DE"): |
5201 | 5258 | # Use our reductions as fallbacks |
5202 | 5259 | elif cmd in ManInterpreter.reductions: |
5203 | 5260 | replace_with = ManInterpreter.reductions[cmd] |
5204 | self.source.pushline("." + replace_with + " " + quoteargs(args)) | |
5261 | self.source.pushline(TroffInterpreter.ctrl + replace_with + " " + quoteargs(args)) | |
5205 | 5262 | # Recover from some common typos |
5206 | 5263 | 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:] | |
5208 | 5265 | self.source.warning("rewriting %s as %s" % (tokens, newtokens)) |
5209 | 5266 | self.source.pushline(newtokens[0]+" "+quoteargs(newtokens[1:])) |
5210 | 5267 | else: |
5228 | 5285 | # This step makes .TP lists easier to process without a boatload |
5229 | 5286 | # of special-case code. See the handling of .DOCLIFTER-BOOJUM above |
5230 | 5287 | 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. | |
5233 | 5290 | text = text.replace("\n.I ", "\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) | |
5234 | 5301 | return text |
5235 | 5302 | 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") | |
5238 | 5303 | # 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. | |
5240 | 5305 | if not self.source.section_count: |
5241 | 5306 | raise LiftException("no section structure in %s, can't be lifted." % self.source.file) |
5242 | 5307 | elif not self.have_name: |
5256 | 5321 | if foundit > -1: |
5257 | 5322 | before = text[:foundit] |
5258 | 5323 | 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) | |
5260 | 5325 | text = before + after |
5261 | 5326 | foundit = text.rfind("FILES") |
5262 | 5327 | if foundit > -1: |
5304 | 5369 | elif self.source.in_synopsis(): |
5305 | 5370 | self.source.emit("<sbr/>") |
5306 | 5371 | elif cmd == "Sh": |
5307 | self.source.pushline(quoteargs([".SS"] + args)) | |
5372 | self.source.pushline(quoteargs([TroffInterpreter.ctrl + "SS"] + args)) | |
5308 | 5373 | elif cmd == "Vb": |
5309 | 5374 | if self.source.body_section(): |
5310 | 5375 | self.source.begin_block("literallayout", remap="Vb") |
5349 | 5414 | # Some of the X local macros (Ds, De, NT, NE, PN) are Ultrix extensions |
5350 | 5415 | # already handled by ManInterpreter. |
5351 | 5416 | immutable_set = {"FD":1,"FN":1,"IN":1,"ZN":1,"hN":1} |
5352 | ignore_set = {} | |
5417 | ignore_set = {"IN":1} | |
5353 | 5418 | complain_set = {} |
5354 | 5419 | parabreak_set = {} |
5355 | 5420 | sectionbreak_set = {} |
5356 | 5421 | listbreak_set = {} |
5357 | 5422 | translations = () |
5358 | reductions = {"IN":"IX"} # Reduce IN to vanilla-man IX. | |
5423 | reductions = {} | |
5359 | 5424 | def __init__(self, source, verbose=0): |
5360 | 5425 | self.source = source |
5361 | 5426 | self.verbose = verbose |
5368 | 5433 | # This wants to be a keep, but DocBook can't express that. |
5369 | 5434 | self.source.begin_block("literallayout", remap="FD") |
5370 | 5435 | elif cmd == "FN": |
5371 | self.source.end_block("literallayout", remap="FN") | |
5436 | self.source.end_block("literallayout", remap="FN", ends="FD") | |
5372 | 5437 | 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:]))) | |
5374 | 5439 | 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:]))) | |
5376 | 5441 | elif cmd == "hN": |
5377 | self.source.emit("<symbol><%s></symbol>%s" % (args[0], "".join(args[1:]))) | |
5442 | self.source.pushline("<symbol><%s></symbol>%s" % (args[0], "".join(args[1:]))) | |
5378 | 5443 | elif cmd == "C{": |
5379 | 5444 | self.source.begin_block("programlisting", remap="C{") |
5380 | 5445 | elif cmd == "C}": |
5381 | self.source.end_block("programlisting", remap="C}") | |
5446 | self.source.end_block("programlisting", remap="C}", ends="C{") | |
5382 | 5447 | elif cmd == "NT": |
5383 | 5448 | self.source.begin_block("note", remap="NT") |
5384 | 5449 | elif cmd == "NE": |
5385 | self.source.end_block("note", remap="NE") | |
5450 | self.source.end_block("note", remap="NE", ends="NT") | |
5386 | 5451 | else: |
5387 | 5452 | return False |
5388 | 5453 | return True |
5389 | 5454 | def preprocess(self, text): |
5390 | 5455 | # 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 | |
5397 | 5466 | lines.pop(0) |
5398 | 5467 | 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 | |
5403 | 5471 | def postprocess(self, text): |
5404 | 5472 | return text |
5405 | 5473 | |
5480 | 5548 | # argument is present, then a line break is forced before starting |
5481 | 5549 | # the sidebar. |
5482 | 5550 | 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>. | |
5484 | 5552 | # Problem is the usage pattern really is presentation-level; |
5485 | 5553 | # .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. | |
5487 | 5555 | self.source.passthrough(tokens) |
5488 | 5556 | # .VE |
5489 | 5557 | # End of vertical sidebar. |
5499 | 5567 | elif cmd == "SO": |
5500 | 5568 | self.source.push_section(1, 'STANDARD OPTIONS') |
5501 | 5569 | self.source.pushline("l l l l.") |
5502 | self.source.TBL(".SE") | |
5570 | self.source.TBL(TroffInterpreter.ctrl + "SE") | |
5503 | 5571 | elif cmd == "OP": |
5504 | 5572 | # .OP cmdName dbName dbClass |
5505 | 5573 | # Start of description of a specific option. cmdName gives the |
5798 | 5866 | if name_synonyms.match(args[0]): |
5799 | 5867 | self.source.sectname = "Name" |
5800 | 5868 | # 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): | |
5802 | 5870 | self.source.popline() |
5803 | 5871 | # Kluge -- it turns out that some web pages (like ash.1) |
5804 | 5872 | # don't use the mandoc macros. Instead they use a Linux- |
5829 | 5897 | self.source.declare_body_start() |
5830 | 5898 | # in case someone forgets to close a list (see mktemp.1). |
5831 | 5899 | for lst in self.liststack: |
5832 | self.source.pushline(".El") | |
5900 | self.source.pushline(TroffInterpreter.ctrl + "El") | |
5833 | 5901 | return True |
5834 | 5902 | if self.source.preamble: |
5835 | 5903 | self.source.preamble = False |
5837 | 5905 | elif command == "Ss": |
5838 | 5906 | # in case someone forgets to close a list |
5839 | 5907 | for lst in self.liststack: |
5840 | self.source.pushline(".El") | |
5908 | self.source.pushline(TroffInterpreter.ctrl + "El") | |
5841 | 5909 | return True |
5842 | 5910 | self.source.push_section(2, " ".join(args)) |
5843 | 5911 | elif command == "Pp": |
5846 | 5914 | else: |
5847 | 5915 | self.source.emit("<sbr/>") |
5848 | 5916 | 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": | |
5850 | 5918 | self.source.begin_block("literallayout", remap="Bd") |
5851 | 5919 | elif command == "Ed": |
5852 | 5920 | if self.source.troff.nf: |
6167 | 6235 | return self.process_punct(args, self.sthook, 1) |
6168 | 6236 | elif cmd == "Sx": |
6169 | 6237 | 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) | |
6171 | 6239 | elif cmd == "Sy": |
6172 | 6240 | return self.styleargs(args, "emphasis", 'remap="Sy"') |
6173 | 6241 | elif cmd == "Ta": |
6183 | 6251 | elif cmd == "Xc": |
6184 | 6252 | return self.replacemacro(args, "") |
6185 | 6253 | elif cmd == "Xo": |
6254 | self.source.warning("translation of .Xo/.Xc blocks is unreliable.") | |
6186 | 6255 | return self.replacemacro(args, "") |
6187 | 6256 | elif cmd == "Xr": |
6188 | 6257 | return self.process_punct(args, self.xrhook, 0) |
6324 | 6393 | def preprocess(self, text): |
6325 | 6394 | return text |
6326 | 6395 | 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 | |
6327 | 6414 | if not self.source.section_count: |
6328 | 6415 | raise LiftException("no mdoc section structure, can't be lifted.") |
6329 | 6416 | return text |
6528 | 6615 | # Some tags can turn into an itemized list. |
6529 | 6616 | if tokens[1] in ip_tag_mapping: |
6530 | 6617 | self.source.pushline(quoteargs(tokens)) |
6531 | gather_itemizedlist(".IP", self.source, | |
6618 | gather_itemizedlist(TroffInterpreter.ctrl + "IP", self.source, | |
6532 | 6619 | ip_tag_mapping[tokens[1]]) |
6533 | 6620 | # Otherwise, emit a variable list |
6534 | 6621 | else: |
6635 | 6722 | self.source.emit_variablelist("ip", args[1]) |
6636 | 6723 | elif cmd == "bp": |
6637 | 6724 | self.source.pushline(quoteargs(tokens)) |
6638 | gather_itemizedlist(".bp", self.source, "bullet") | |
6725 | gather_itemizedlist(TroffInterpreter.ctrl + "bp", self.source, "bullet") | |
6639 | 6726 | elif cmd == "np": |
6640 | 6727 | self.source.pushline(quoteargs(tokens)) |
6641 | gather_orderedlist(".np", self.source) | |
6728 | gather_orderedlist(TroffInterpreter.ctrl + "np", self.source) | |
6642 | 6729 | elif cmd == "(q": |
6643 | 6730 | self.source.begin_block("blockquote", remap='(q') |
6644 | 6731 | elif cmd == ")q": |
7020 | 7107 | "the F register is turned on": Pod2ManInterpreter, |
7021 | 7108 | "ZN": XManInterpreter, |
7022 | 7109 | "Pn": XManInterpreter, |
7110 | "ny0": XManInterpreter, | |
7023 | 7111 | # These are all of the supported Mwww tags |
7024 | 7112 | "URL": MwwwInterpreter, |
7025 | 7113 | "FTP": MwwwInterpreter, |
7052 | 7140 | def transfile(name, arguments, translate_data, trans_filename=None): |
7053 | 7141 | "Read input sources entire and transform them in memory." |
7054 | 7142 | if not arguments: |
7055 | outdoc = translate_data(name, "stdin", sys.stdin.read()) | |
7143 | outdoc = translate_data(name, "stdin", sys.stdin.read(), False) | |
7056 | 7144 | if outdoc: |
7057 | 7145 | stdout.write(outdoc) |
7058 | 7146 | else: |
7067 | 7155 | stderr.write("%s: can't open tempfile" % name) |
7068 | 7156 | return True |
7069 | 7157 | try: |
7070 | outdoc = translate_data(name, file, indoc) | |
7158 | outdoc = translate_data(name, file, indoc, len(arguments)>1) | |
7071 | 7159 | except: |
7072 | 7160 | os.remove(tempfile) |
7073 | 7161 | # 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" | |
21 | 10 | doclifter \- translate troff requests into DocBook |
22 | 11 | .SH "SYNOPSIS" |
23 | .ad l | |
24 | .hy 0 | |
25 | 12 | .HP 10 |
26 | 13 | \fBdoclifter\fR [\-h\ \fIhintfile\fR] [\-e\ \fIencoding\fR] [\-q] [\-v] [\-I\ \fIpath\fR] [\-D\ \fItoken=type\fR] \fIfile\fR... |
27 | .ad | |
28 | .hy | |
29 | ||
30 | 14 | .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. | |
56 | 55 | .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. | |
61 | 62 | .TP |
62 | 63 | \-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. | |
65 | 65 | .TP |
66 | 66 | \-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. | |
69 | 70 | .TP |
70 | 71 | \-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. | |
73 | 77 | .TP |
74 | 78 | \-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). | |
77 | 82 | .TP |
78 | 83 | \-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. | |
81 | 87 | .TP |
82 | 88 | \-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. | |
85 | 92 | .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. | |
99 | 111 | .PP |
100 | 112 | Some notes on specific translations: |
101 | ||
102 | 113 | .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 | |
149 | 245 | .PP |
150 | 246 | Known problem areas with man translation: |
151 | ||
152 | 247 | .TP 3 |
153 | 248 | \(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 | |
155 | 251 | .TP |
156 | 252 | \(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. | |
160 | 258 | .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. | |
171 | 279 | .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. | |
176 | 303 | .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. | |
184 | 315 | .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. | |
207 | 387 | .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. | |
227 | 419 | .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. | |
241 | 476 | .PP |
242 | 477 | 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. | |
259 | 565 | .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. | |
267 | 585 | .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. | |
284 | 617 | .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. | |
289 | 624 | .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. | |
294 | 631 | .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. | |
317 | 703 | .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: | |
322 | 707 | .TP 3 |
323 | 708 | \(bu |
324 | 709 | Names of function formal arguments |
325 | 710 | .TP |
326 | 711 | \(bu |
327 | 712 | 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: | |
333 | 715 | .TP 3 |
334 | 716 | \(bu |
335 | 717 | Names of functions |
339 | 721 | .TP |
340 | 722 | \(bu |
341 | 723 | 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 | |
347 | 731 | .nf |
348 | ||
349 | \~\&.\\" | mark <phrase> as <markup> | |
350 | ||
732 | \ .\" | mark <phrase> as <markup> | |
351 | 733 | .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. | |
362 | 747 | .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. | |
385 | 782 | .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. | |
393 | 789 | .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. | |
413 | 820 | .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. | |
421 | 831 | .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. | |
440 | 836 | .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). | |
445 | 845 | .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/ |
0 | 0 | Name: doclifter |
1 | Version: 2.1 | |
1 | Version: 2.3 | |
2 | 2 | Release: 1 |
3 | 3 | URL: http://www.catb.org/~esr/doclifter/ |
4 | 4 | Source0: %{name}-%{version}.tar.gz |
5 | 5 | License: GPL |
6 | 6 | Group: Applications/System |
7 | 7 | Requires: python2 |
8 | Summary: converts man/mdoc/ms/me/mm documents to DocBook | |
8 | Summary: Converts man/mdoc/ms/me/mm documents to DocBook | |
9 | 9 | BuildRoot: %{_tmppath}/%{name}-root |
10 | 10 | BuildArch: noarch |
11 | 11 | #Keywords: DocBook, man, ms, mm, me, mdoc, lifting, XML, SGML |
12 | 12 | |
13 | 13 | %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. | |
20 | 22 | |
21 | 23 | %prep |
22 | 24 | %setup -q |
43 | 45 | %{_bindir}/manlifter |
44 | 46 | |
45 | 47 | %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 | ||
46 | 61 | * Fri Jan 14 2005 Eric S. Raymond <esr@snark.thyrsus.com> - 2.1-1 |
47 | 62 | - Interrupt handlers are refactored so manlifter can be aborted with |
48 | 63 | a single ^C; as a result, exit values 4 and 5 have swapped places. |
252 | 267 | |
253 | 268 | # The following sets edit modes for GNU EMACS |
254 | 269 | # Local Variables: |
255 | # mode:rpm-spec-mode | |
270 | # mode:rpm-spec | |
256 | 271 | # End: |
72 | 72 | features, but this fallback is good enough for simple man |
73 | 73 | pages.</para> |
74 | 74 | |
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 | |
78 | 78 | <command>doclifter</command> will almost always produce translations |
79 | 79 | that are good enough to be usable before hand-hacking.</para> |
80 | 80 | |
231 | 231 | <markup>.PD</markup>,<markup>.DT</markup>.</para> |
232 | 232 | |
233 | 233 | <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> | |
240 | 239 | |
241 | 240 | <para><markup>.DS</markup>/<markup>.DE</markup> is not part of the |
242 | 241 | documented man macro set, but is recognized because it shows up with |
246 | 245 | <para>Certain extension macros originally defined under Ultrix are |
247 | 246 | translated structurally, including those that occasionally show up on |
248 | 247 | 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>), | |
250 | 250 | <markup>.Ds</markup>/<markup>.De</markup>, <!-- cause display |
251 | 251 | parsing. --> <markup>.NT</markup>/<markup>.NE</markup>, |
252 | 252 | <markup>.PN</markup>, and <markup>.MS</markup> are translated |
253 | structurally. parsed as a display.</para> | |
253 | structurally.</para> | |
254 | 254 | |
255 | 255 | <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> | |
260 | 261 | |
261 | 262 | <para>When the man macros are active, any <markup>.Pp</markup> macro |
262 | 263 | definition containing the request <markup>.PP</markup> will be |
265 | 266 | replaced with <markup>.TP</markup>. This is the least painful way to |
266 | 267 | deal with some frequently-encountered stereotyped wrapper definitions |
267 | 268 | 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> | |
274 | 269 | |
275 | 270 | <para>Known problem areas with man translation:</para> |
276 | 271 | <itemizedlist> |
526 | 521 | are not supported.</para> |
527 | 522 | |
528 | 523 | <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 | |
530 | 525 | is generated using a <sgmltag class='element'>table</sgmltag> and |
531 | 526 | <sgmltag class='element'>title</sgmltag>. Otherwise the table is |
532 | 527 | translated with <sgmltag |
587 | 582 | textual comparison. All numeric expressions evaluate to true. </para> |
588 | 583 | |
589 | 584 | <para>The extended <application>groff</application> requests |
585 | <markup>cc</markup>, <markup>c2</markup>, | |
590 | 586 | <markup>ab</markup>, <markup>als</markup>, <markup>do</markup>, |
591 | 587 | <markup>nop</markup>, and <markup>return</markup> and |
592 | 588 | <markup>shift</markup> are interpreted. Its <markup>.PSPIC</markup> |
625 | 621 | |
626 | 622 | <para>If <command>doclifter</command> is applied to multiple files, |
627 | 623 | 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> | |
630 | 626 | |
631 | 627 | <programlisting> |
632 | 628 | .\" | mark <phrase> as <markup> |
666 | 662 | right. Here are some things to watch for, and how to fix them:</para> |
667 | 663 | |
668 | 664 | <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 | |
671 | 667 | comment telling you what the command synopsis looked like after |
672 | 668 | preprocessing, and indicate on which token the parse failed (both with |
673 | 669 | a token number and a caret sign inserted in the dump of the synopsis |
678 | 674 | last nesting-depth increase, but the code that does this is |
679 | 675 | failure-prone.</para> |
680 | 676 | |
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 | ||
686 | 677 | <para><emphasis>Confusing macro calls.</emphasis> Some manual page |
687 | 678 | authors replace standard requests (like <markup>.PP</markup>, |
688 | 679 | <markup>.SH</markup> and <markup>.TP</markup>) with versions that do |
690 | 681 | <command>troff</command> environments. While |
691 | 682 | <command>doclifter</command> tries to cope and usually does a good |
692 | 683 | 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 | |
698 | 690 | subsection headers. In man pages, subsections don't have a depth |
699 | 691 | argument, so <command>doclifter</command> cannot be certain how |
700 | 692 | subsections should be nested. Any subsection heading between the |
725 | 717 | It returns 5 when aborted by a keyboard interrupt. </para> |
726 | 718 | |
727 | 719 | <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> | |
732 | 724 | </refsect1> |
733 | 725 | |
734 | 726 | <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> | |
735 | 732 | |
736 | 733 | <para>EQN sections are not translated to MathML as they should be.</para> |
737 | 734 | |
745 | 742 | |
746 | 743 | <para>Running text (e.g., explanatory notes) at the end of a Synopsis |
747 | 744 | section cannot reliably be distinguished from synopsis-syntax |
748 | markup.</para> | |
745 | markup. (This problem is AI-complete.)</para> | |
749 | 746 | |
750 | 747 | <para>Some firewalls put in to cope with common malformations in troff |
751 | 748 | code mean that the tail end of a span between two |
755 | 752 | crosses a boundary between filled and unfilled |
756 | 753 | (<markup>.nf</markup>/<markup>.fi</markup>) text.</para> |
757 | 754 | |
758 | <para>The crude treatment of conditionals relies on the assumption that | |
755 | <para>The treatment of conditionals relies on the assumption that | |
759 | 756 | conditional macros never generate structural or font-highlight markup |
760 | 757 | that differs between the if and else branches. This appears to be |
761 | 758 | true of all the standard macro packages, but if you roll any of your |
762 | 759 | 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 | |
770 | 776 | interpretation because (a) it's structural, and (b) otherwise we'd |
771 | 777 | have to throw out the paired <markup>.P2</markup> request.</para> |
772 | 778 | |
776 | 782 | </refsect1> |
777 | 783 | |
778 | 784 | <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 | ||
782 | 785 | <para>The |
783 | 786 | <citerefentry><refentrytitle>pic2plot</refentrytitle><manvolnum>1</manvolnum></citerefentry> |
784 | 787 | 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> | |
796 | 788 | </refsect1> |
797 | 789 | |
798 | 790 | <refsect1><title>See Also</title> |
2 | 2 | # Run doclifter against an entire manual tree. |
3 | 3 | # Sees all files in section 1 through 9 by default. |
4 | 4 | |
5 | import sys, os, getopt, signal, time, re, commands, cStringIO, stat | |
5 | import sys, os, getopt, signal, time, re, commands, cStringIO, stat, sets | |
6 | 6 | |
7 | 7 | mandir = "/usr/share/man" |
8 | 8 | patchdir = os.path.abspath("prepatch") |
10 | 10 | patched = 0 |
11 | 11 | makehtml = False |
12 | 12 | xslfragment = None |
13 | processed = sets.Set([]) | |
13 | 14 | |
14 | 15 | def manfile(section, basename=""): |
15 | 16 | "Return a manual file or directory based on section name." |
122 | 123 | return (6, output) |
123 | 124 | return (0, output) |
124 | 125 | |
125 | def format(translation, fmt): | |
126 | def format(translation, fmt, xslfragment): | |
126 | 127 | "Format an XML file to a specified format." |
127 | 128 | output = "" |
128 | 129 | here = os.getcwd() |
129 | 130 | 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)) | |
131 | 135 | (bstat, format_out) = commands.getstatusoutput(command) |
132 | 136 | os.chdir(here) |
133 | 137 | if format_out: |
179 | 183 | if os.path.exists(patch): |
180 | 184 | patched += 1 |
181 | 185 | try: |
186 | global processed | |
182 | 187 | tmpstem = os.path.join(outdir, tmpstem) |
183 | 188 | source = tmpstem + ".man" |
184 | 189 | # Save work by doing conversions only as needed |
186 | 191 | if batchmode and os.path.exists(xmlloc): |
187 | 192 | if os.stat(file).st_mtime < os.lstat(xmlloc).st_mtime: |
188 | 193 | output += "XML conversion is up to date\n" |
194 | processed.discard(withsect) | |
189 | 195 | rebuild_xml = False |
190 | 196 | htmlloc = os.path.join(subdir, stem + ".html") |
191 | 197 | if rebuild_xml: |
194 | 200 | (status, output) = fetch_page(file, localcopy, patch) |
195 | 201 | if (status): |
196 | 202 | return (status, output) |
203 | # Note the the patch was used | |
204 | processed.discard(withsect) | |
197 | 205 | # Add any annotations |
198 | 206 | output += analyze_manpage(localcopy) |
199 | 207 | # Move the source file into the output directory |
212 | 220 | # of putting this in its permanent location. |
213 | 221 | try: |
214 | 222 | # 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): | |
216 | 224 | os.mkdir(subdir) |
217 | 225 | except OSError, e: |
218 | 226 | return(3, output + "Creation of %s failed, errno = %d\n"%(subdir,e.errno)) |
249 | 257 | if batchmode and stat.S_ISLNK(os.lstat(xmlloc).st_mode): |
250 | 258 | makelink(os.readlink(xmlloc)[:-4]+".html", htmlloc) |
251 | 259 | else: |
252 | (status, more) = format(translation, "xhtml-nochunks") | |
260 | (status, more) = format(translation, "xhtml-nochunks", xslfragment) | |
253 | 261 | output += more |
254 | 262 | if status: |
255 | 263 | if batchmode: |
290 | 298 | def report(sig, frame, out=sys.stderr): |
291 | 299 | ftotal = float(total) |
292 | 300 | 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" % \ | |
294 | 302 | (total, eligible, |
295 | 303 | elapsed/3600, (elapsed % 3600)/60, elapsed % 60, |
296 | 304 | (total - doclifter_error_count - xmllint_error_count), |
315 | 323 | (status, output) = test(file=file, options=options) |
316 | 324 | if status == -1: |
317 | 325 | 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 | |
321 | 329 | elif status == 2: # .so inclusion |
322 | 330 | 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 | |
324 | 332 | pass |
325 | 333 | elif status == 6: |
326 | xmllint_error_count = xmllint_error_count + 1 | |
334 | xmllint_error_count += 1 | |
327 | 335 | total = total + 1 |
328 | 336 | except KeyboardInterrupt: |
329 | 337 | pass |
439 | 447 | |
440 | 448 | def errorclean(error_only, pattern): |
441 | 449 | if pattern: |
442 | pattern = re.compile(filter) | |
450 | pattern = re.compile(pattern) | |
443 | 451 | pagename = re.compile(r"! (.*)=([0-9]+)") |
444 | 452 | while 1: |
445 | 453 | header = sys.stdin.readline() |
494 | 502 | |
495 | 503 | def doclifter_driver(options, arguments): |
496 | 504 | "Lift old markup to new." |
497 | global makehtml, outdir, xslfragment | |
505 | global makehtml, outdir, xslfragment, patchdir | |
498 | 506 | filelist = [] |
499 | 507 | sections = [] |
500 | 508 | callopts = "" |
531 | 539 | else: |
532 | 540 | outdir = '.' |
533 | 541 | # 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() | |
536 | 550 | 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() | |
542 | 551 | # Process args, if present |
543 | 552 | if arguments: |
544 | 553 | for file in arguments: |
557 | 566 | fp.close() |
558 | 567 | massrun(filelist, callopts) |
559 | 568 | else: |
569 | global processed | |
570 | processed = sets.Set(map(lambda x: x.replace(".patch", "").replace(".correction", ""), os.listdir(patchdir))) | |
560 | 571 | massrun(sectionfiles(sections), callopts) |
572 | if processed: | |
573 | print "# Patches not used:" | |
574 | for file in processed: | |
575 | print file | |
561 | 576 | finally: |
562 | 577 | pass |
563 | 578 | #os.remove(xslfragment) |
574 | 589 | if os.path.exists(where): |
575 | 590 | break |
576 | 591 | else: |
577 | sys.stderr.write("manlifter: can't find doclifter!") | |
592 | sys.stderr.write("manlifter: can't find doclifter!\n") | |
578 | 593 | sys.exit(1) |
579 | 594 | # Import it, so we can modify it while the test is running without |
580 | 595 | # 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 | |
22 | 11 | .SH "SYNOPSIS" |
23 | .ad l | |
24 | .hy 0 | |
25 | 12 | .HP 10 |
26 | 13 | \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 | |
31 | 14 | .HP 10 |
32 | 15 | \fBmanlifter\fR [\-S] |
33 | .ad | |
34 | .hy | |
35 | ||
36 | 16 | .SH "DESCRIPTION" |
37 | ||
38 | 17 | .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. | |
41 | 22 | .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. | |
44 | 26 | .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. | |
47 | 30 | .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). | |
50 | 34 | .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. | |
53 | 41 | .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. | |
56 | 50 | .PP |
57 | 51 | Options are as follows: |
58 | ||
59 | 52 | .TP |
60 | 53 | \-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. | |
63 | 55 | .TP |
64 | 56 | \-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. | |
67 | 62 | .TP |
68 | 63 | \-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. | |
71 | 65 | .TP |
72 | 66 | \-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. | |
75 | 69 | .TP |
76 | 70 | \-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. | |
79 | 73 | .TP |
80 | 74 | \-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. | |
83 | 78 | .TP |
84 | 79 | \-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. | |
87 | 85 | .TP |
88 | 86 | \-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. | |
91 | 88 | .TP |
92 | 89 | \-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. | |
95 | 91 | .TP |
96 | 92 | \-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. | |
99 | 94 | .TP |
100 | 95 | \-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. | |
103 | 101 | .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. | |
106 | 106 | .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. | |
109 | 109 | .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. | |
112 | 111 | .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. | |
115 | 118 | .SH "BUGS" |
116 | ||
117 | 119 | .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. | |
120 | 121 | .SH "SEE ALSO" |
121 | ||
122 | 122 | .PP |
123 | \fBdoclifter\fR(1), \fBxmlto\fR(1) | |
124 | ||
123 | \fBdoclifter\fR(1), | |
124 | \fBxmlto\fR(1) | |
125 | 125 | .SH "AUTHOR" |
126 | ||
127 | 126 | .PP |
128 | Eric S\&. Raymond <esr@thyrsus\&.com> | |
129 | ||
127 | Eric S. Raymond | |
128 | <esr@thyrsus.com> | |
130 | 129 | .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/ |
69 | 69 | |
70 | 70 | <para>In either of the above cases, <command>manlifter</command> will |
71 | 71 | 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 | |
73 | 73 | name.</para> |
74 | 74 | |
75 | 75 | <para>Options are as follows:</para> |
111 | 111 | <varlistentry> |
112 | 112 | <term>-o</term> |
113 | 113 | <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 | |
115 | 115 | <filename>xmlman</filename> under the current directory in batch mode, |
116 | 116 | or the current directory otherwise.</para></listitem> |
117 | 117 | </varlistentry> |
153 | 153 | output. The file begins with a timestamp line and a blank line, |
154 | 154 | and ends with a line giving run time and various interesting |
155 | 155 | 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 | |
157 | 157 | run.</para> |
158 | 158 | |
159 | 159 | <para>The first line of each stanza beguns with "! ", followed by the |