I maintain a man-page-to-DocBook converter, doclifter. A side effect of this program is that it serves as a validator for the correctness and portability of the markup used on Unix manual pages. I test it by running it against all the manual pages in a full Fedora Core 6 with some extras; there are 13467 of these on my development machine. It converts 13017 (96.66%) into valid XML-DocBook.

Most of the remaining 3.34% of errors happen because groff(1) and its kin have weak-to-nonexistent validity checking. Often, doclifter fails because of outright errors in macro usage that groff does not catch. Sometime it fails on constructions that are legal but perverse. Very occasionally it throws an error because a man page is correct but has a structure that cannot be translated to DocBook. I keep a database of patches for such problems, and periodically try to push fix patches out to the manual-page maintainers.

Even if you do not care about DocBook, this cleanup work benefits all third-party manual page viewers, including the GNOME and KDE documentation browsers; groff constructions that confuse doclifter are very likely to produce visible problems on these.

The table below is a listing of the 394 (2.93%) pages on which doclifter fails, but the failure can be prevented with a fix patch to the manual page source. 56 pages (0.42%) remain intractable, generally due to markup problems more severe than a point patch can address. I am working with the individual projects responsible to get those cleaned up.

It is likely that you are reading this because you have received email telling you that patches are associated with your name or list address. Please consider incorporating them, or equivalents, in your next release. Also, please write back and tell me what you plan to do so I can keep my database up-to-date.

If you are not already considering it, please think about moving the documentation masters of your project to DocBook (or some format from which you can generate DocBook). If everybody moved to using DocBook as a common exchange format, it would become much easier to support unified browsing of all system documentation with Web-like hypertext capabilities, automatic indexing, and rich search facilities.

Tools to generate man pages, HTML, and PostScript from DocBook files are open-source and generally available. My program, doclifter, should make moving your manual-page masters to DocBook a fairly painless process.

Many major open source projects (including the Linux kernel, the Linux Documentation Project, X.org, GNOME, KDE, and FreeBSD) have already moved to DocBook or are in the process of doing so.

Summary: 349 patches pending, 223 accepted, 8 rejected.

Status codes are as follows:


n No response yet.
p Maintainer has informed me that this is fixed in the masters, but I have not seen the fix yet.
y Accepted
r Rejected
[0-9]+ number of mailings sent
b Address is blocked

Problem codes are explained after the table.


Patch:Problem code:Status:
acl_from_text.3
acl_to_text.3
Xbn
adjtimex.8
Xbn
read-expenses.1
O6n
aconnect.1
u1n
addresses.1
p6n
aecho.1
n
afmtodit.1
M6r
afm2tfm.1
81n
amidi.1
amixer.1
aplay.1
arecord.1
y
amrecover.8
9bn
awk.1
u1n
pgawk.1
gawk.1
u1n
animate.1
compare.1
conjure.1
composite.1
convert.1
display.1
identify.1
import.1
mogrify.1
montage.1
y
amanda.8
amanda.conf.5
amrestore.8
A 01n
apple_cp.1
apple_mv.1
apple_rm.1
y
arp.8
A6n
ApplicationShell.3
E1n
appres.1x
U1p
aspell.1
X1n
atmsigd.conf.4
Abn
authconfig.8
C4n
bash.1
y
bgpd.8
y
bitmap.1x
X1p
bounce.5
aliases.postfix.5
relocated.5
81n
builtins.1
W1n
bzadmin.6
y
bzw.5
81n
bzfquery.6
l3n*
bzfs.6
y
cadaver.1
5y
calcomp.4
1p
cancel-cups.1
cancel.1
lp.1
lp-cups.1
y
cannastat.1
C6n
cman.5
81n
CrtImgType.3
Tk_InitImageArgs.3
y
lpr.1
lpr-cups.1
U6n
lpstat.1
lpstat-cups.1
y
cdda2wav.1
A 81n
cdparanoia.1
c4n
cdrdao.1
E6n
chat.8
X J 7bn
chcat.8
C1n
chkconfig.8
Xbn
chmoddic.1
C6n
ci.1
n o6n
citron.4
3 n1n
cpufreq-info.1
cpufreq-set.1
81n
crash.8
y
cshost.1
C6n
cscope.1
B3p
cxpm.1x
Wbn
dasher.1
g3b
DBM_Filter::compress.3pm
DBM_Filter::encode.3pm
DBM_Filter::int32.3pm
DBM_Filter::null.3pm
DBM_Filter::utf8.3pm
W1n
dbz.3
y
ddd.1
y
default.session.5
W6n
dhcp6r.8
f2n
dicar.1
X 81n
dictionary.5
Ln
dictfmt.1
A3n
dictl.1
W1n
diffstat.1
y
dislocate.1
y
dlpsh.1
W6n
dmraid.8
y
dpromdic.1
Xbn
dvdrecord.1
v6n
dvipdfm.1
y
editres.1x
8 o1n
epic.1
X6n
elinkskeys.5
G O J1n
emacs.1
o1n
epoll_ctl.2
y
epoll.4
y
eqn.1
geqn.1
n6n
error.3
71n
openais_overview.8
evs_overview.8
cpg_overview.8
Wn
expect.1
y
fbset.8
L6p
fence.8
gfs.8
gnbd.8
W1n
fig2dev.1x
X5r
File::Basename.3pm
y
findchip.8
irdadump.8
irdaping.8
irpsion5.8
irattach.8
e3n
flock.1
y
foomatic-ppdfile.1
X6n
fsinfo.8
y
gaim.1
y
gda-config.5
3n
getcon.3
getexeccon.3
y
GetUid.3
y
getcontext.2
C4n
getrpcport.3
dbn
gfdl.1
Wn
gfs_jadd.8
X1n
gftodvi.1
8bn
ghostscript.1
y
g3topbm.1
Cb
giftopnm.1
pnmcolormap.1
libppm.3
pam.5
Pb
netpbm.1
Pb
gij.1
y
gkrellmd.1
y
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
X1n
gnome-session.1
Y6n
gnome-wm.1
W6n
gob2.1
y
gpic.1
pic.1
L5r
gpm-types.7
W5p
groff.1
1p
groff_diff.7
A5p
gsbj.1
gsdj.1
gsdj500.1
gslj.1
gslp.1
C6n
gulm_tool.8
81n
hformat.1
hfs.1
hfssh.1
hfsutils.1
hmount.1
xhfs.1
X6n
hinotes.1
W1n
hidd.1
y
hostname.1
A6n
htfuzzy.1
A3n
hwclock.8
C1n
ibod.1
X1n
icc2ps.1
icclink.1
jpegicc.1
tifficc.1
X R L1n
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
y
punycode_encode.3
y
ImageMagick.1
D1n
inews.1
y
install.1
y
ipsec_mailkey.8
H3n
ipsec_newhostkey.8
ipsec_rsasigkey.8
C3n
iptraf.8
X6n
irb.1
W6n
isadump.8
isaset.8
y
isdnrep.1
8 m1p
kdesvn-build.1
s1n
kermit.1
W1n
klogd.8
X6n
ksh.1
i1p
kwordtrans.1
wordtrans.1
K6n*
lamboot.1
lamexec.1
X 41p
lammsg.1
8 o C 41p
lamrun.1
41p
lamtask.1
4 o1p
lamshrink.1
C 41p
lamd.1
81p
lame.1
Xbn
lastcomm.1
u1n
LAM.7
MPI.7
81p
latex.1
y
latex2html.1
Q1n
LDP.7
y
less.1
C6n
lesstif.1
W O 81n
libbind-getipnodebyname.3
T1n
libbind-resolver.3
r1n
libpng.3
S4n
libpngpf.3
y
libexpect.3
O1n
libmng.3
71n
linuxdoc.1
j6n
ln.1
j1n
lock_gulmd.5
lock_gulmd.8
81n
logrotate.8
y
lv.1
C6n
lvreduce.8
y
mag.1
y
magma_tool.8
81n
Mail::SpamAssassin::Client.3pm
Mail::SpamAssassin::Plugin::ReplaceTags.3pm
XML::LibXML::DocumentFragment.3pm
W1n
makestrs.1x
A1p
man.1
manpath.1
y
mcs.8
Xbn
mdadm.conf.5
Xbn
mdadm.8
Xbn
mdel.1
T6n
mdoc.7
N1n
mev.1
J1n
mf.1
inimf.1
virmf.1
y
mkoctfile.1
y
mkxauth.1x
C1n
mkzftree.1
y
ModPerl::Code.3pm
D2n
motd.news.5
y
mozplugger.7
y
mpage.1
81n
mpcd.8
1n
MPI_Group_free.3
C6bn
mpiexec.1
X3bn
mysqld.1
mysqld_multi.1
mysqldump.1
mysql_zap.1
mysqladmin.1
mysqlshow.1
y
mysqlmanager.1
I1n
mysqld_safe.1
T1n
named.conf.5
y
nasm.1
ndisasm.1
y
nbp_name.3
y
netsnmp_iterator_info_s.3
s3n
netsnmp_table.3
X3n
netdump.8
L6n
netdump-server.8
C3n
netstat.8
y
newgrp.1
y
nfsd.7
y
nisplus_table.5
C1n
NetworkManager.1
NetworkManagerDispatcher.1
nm-tool.1
W1n
nfs4_uid_to_name.3
W1n
nmap.1
A s1n
ntlm_auth.1
R X1n
ntpdate.1
C6r
ntpq.1
3r
octave-config.1
y
on_ac_power.1
pm-pmu.1
e1n
operator.7
o3r
pambayer.1
Ub
pamperspective.1
P Ub
pamstereogram.1
Pb
pamtilt.1
Ub
pammasksharpen.1
Ub
pbmtoppa.1
pbm2ppa.1
Pb
pamfunc.1
pamscale.1
pamslice.1
pbmclean.1
y
parted.8
y
pcreprecompile.3
X1p
pcrepattern.3
pcrecallout.3
pcretest.1
pcrepartial.3
J1p
PDL::BAD2_demo.3pm
PDL::BAD_demo.3pm
PDL::Config.3pm
PDL::Doc::Config
y4n*
PDL::GSL::INTEG.3pm
D3n
PDL::MatrixOps.3pm
W4n
pdl.1
y
perl-nocem.8
O2p
perlop.1
perlre.1
J1n
pflogsumm.1
W1n
pgmabel.1
pgmtopgm.1
pnmstitch.1
pgmmorphconv.1
pnmtoddif.1
ppmtopj.1
y
php.1
Wy
pilot-addresses.1
j6n
pilot-foto.1
U6n
pilot-xfer.1
j5n
pipethrough.3
3y
pkg-config.1
X1n
play.1
y
postconf.5
y
postmap.1
postsuper.1
I1n
powermust.8
W1p
ps.1
Dy
privoxy.1
j5p
proxymap.8
81n
ps2epsi.1
j6n
ps2pdf.1
ps2pdf12.1
ps2pdf13.1
6n
ptx.1
j6n
PVM.1
w1p
pvmd.1
pvm_shmd.1
pvmd3.1
y
pvm_addmhf.3
y
pvm_advise.3
W o1n
pvm_delete.3
pvm_insert.3
pvm_lookup.3
pvm_serror.3
pvm_setmwid.3
W1n
pvm_intro.1
81n
pxeos.8
pxeboot.8
8 41n
quantize.5
y
racoon.conf.5
y
rate.conf.5
81p
raw2tiff.1
tiffcmp.1
TIFFClose.3tiff
X1n
rcsfile.5
X1n
rcsintro.1
u1n
replace.1
isamchk.1
isamlog.1
y
rexec.3
X1n
rdist.1
8 o1n
rdump.8
dump.8
restore.8
rrestore.8
y
rlm_expr.5
X3n
rlm_attr_filter.5
X F3n
roff.7
A5p
rz.1
81n
samba_selinux.8
81n
selinux.8
81n
send-uucp.8
y
sftp.1
C4n
sg_senddiag.8
C1p
sgml2lyx.1
Z6n
sgmlpre.1
E5p
sk98lin.4
y
slapo-ppolicy.5
X1n
slapd.8
y
smartd.8
smartctl.8
smartd.conf.5
y
snmpvacm.1
y
snmpd.conf.5
y
snmp.conf.5
y
sntp.1
Cb
solterm.1
C1n
squid_ldap_auth.8
squid_ldap_group.8
y
ssh-keyscan.1
y
sshd_config.5
ssh_config.5
q3n
stationlist.xml.5
X R4n
system-config-httpd.1
81n
system-config-netboot.8
81n
system-config-services.8
8 41n
tvtime.xml.5
X4n
synclient.1
41n
sysklogd.8
X6n
sz.1
g 86n
tc-pbfifo.8
T3n
tcpd.8
81n
terminfo.5
x1n
texdoctk.1
y
tidy.1
W m1n
timidity.cfg.5
y
Tk_Uid.3
y
transfig.1x
X U5n
tree.1
y
tsclient.1
W6n
ttcp.1
X Dbn
tune2fs.8
C6n
udevd.8
udevsend.8
y
units.1
o1n
uuencode.1
y
vacuumdb.1
C4n
vgsplit.8
C6n
vorbiscomment.1
C6n
vsftpd.conf.5
y
wget.1
s5r
which.1
ubn
wvdial.1
Xbn
XAllocWMHints.3x
11n
XvSelectVideoNotify.3x
A1n
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
21n
XGrabDeviceKey.3x
XIfEvent.3x
n
XListInputDevices.3x
Vn
XML::DOM-ecmascript.3pm
W1n
XML::DOM::Element.3pm
z4n
XML::Parser::Style::Objects.3pm
W4n
XML::Parser::Style::Tree.3pm
W4n
XML::Parser::Style::Subs.3pm
W4n
xdpr.1x
X 51p
xfs_bmap.8
xfs_check.8
y
xinetd.conf.5
L6n
xfontsel.1x
xlsfonts.1x
81p
Xmark.1x
81n
xminicom.1
W1n
xml_pp.1
y
xml_spellcheck.1
y
xmlto.1
A1n
xrdb.1x
g1p
xtrap.1x
X 4 a1n
XQueryExtension.3x
X1n
xscreensaver-text.1
X1n
xset.1x
C1n
xsltproc.1
y
ypcat.1
R1n
zone2ldap.1
Wbn
zshcompctl.1
zshcontrib.1
L1n
zshmodules.1
n t1n

Error codes:

0
This problem reflects a serious bug in db2man.
1
Improper line wrap in .ds text.
2
Description as well as name is required in a name section.
3
Garbled escape sequence
4
SYNTAX section is actually a Unix SYNOPSIS and should be so marked.
5
Unescaped \d looks like a troff down-motion. This probably messes up the rendering of the page in some environments, and certainly confuses automated translation to XML.
7
Unbalanced highlights. This is not technically an error, but it makes display programs and translators to other formats much more likely to break.
8
Use of low-level troff hackery to set special indents or breaks can't be translated. The page will have rendering faults in HTML, and probably also under third-party man page browsers such as Xman, TkMan, Rosetta, and the KDE help browser. This patch eliminates .br, .ti and .in in favor of requests like .nf/.fi, and .RS/.RE that have structural translations.
9
Macro call is run on to the end of a line.
A
Dot or single-quote at start of line turns it into a garbage command. This is a serious error; some lines of your page get silently lost when it is formatted.
B
-[0-9] cannot be rendered in Docbook command-syntax markup. This is not technically an error, but it makes the page impossible to translate to DocBook.
C
Broken command synopsis syntax. This may mean you're using a construction in the command synopsis other than the standard [ ] | { }, or it may mean you have running text in the command synopsis section (the latter is not technically an error, but it's impossible to translate into DocBook markup).
D
Section or macro out of place; this confuses translators.
E
My translator trips over a useless command in list markup.
F
List structure can be better expressed with .IP.
G
Since this page was generated from db2man, I understand that some of its problems may be due to db2man bugs that need to be reported upstream. I am sending this heads-up nevertheless because at least some of the problems can be fixed or worked around in your sources.
H
Illegal metavariable in a Synopsis description.
I
.it or .ti macro use is impossible to translate structurally.
J
Ambiguous or invalid backslash. This doesn't cause groff a problem. but it confuses doclifter and may confuse older troff implementations.
K
You seem to be distributing a formatted manual page rather than source. This may be a packaging error.
L
List syntax error. This means .IP, .TP or .RS/.RE markup is garbled. This confuses doclifter, and may also mess up stricter troff interpreters like Xman, Rosetta, and TkMan.
M
Macro definition is in a location (such as the Synopsis section) that confuses translation tools.
N
Unbalanced or superfluous quotes may screw up argument parsing.
O
Running text in what should be a Unix command synopsis. The right fix for this is to change the section name.
P
Garbage in the man page probably reflects a bug in the netpbm makeman utility.
Q
You used .UN where .UR is needed.
R
English usage errors, apparently the writer is not a native speaker.
S
DEPRECATED: in function syntax connot be translated. Also, the code and examples need to be marked up better.
T
There are multiple description lines. This makes it impossible to translate the page to DocBook. It may also confuse some implementations of man -k.
U
Unbalanced group in command synopis. You probably forgot to open or close a [ ] or { } group properly.
V
.DS and .DE input macros are swapped.
W
Missing or garbled name section. The most common form of garbling is a missing - or extra -. Or your manual page may have been generated by a tool that doesn't emit a NAME section as it should. Or your page may add running text such as a version or authorship banner. These problems make it impossible to lift the page to DocBook. They can also confuse third-party manpage browsers and some implementations of man -k.
X
Unknown or invalid macro. That is, one that does not fit in the macro set that the man page seems to be using. This is a serious error; it often means part of your text is being lost or rendered incorrectly.
Y
Missing or garbled section header.
Z
Garbage character at beginning of file.
a
.EX/.EE macros are missing or misplaced.
c
SYNOPSIS must come before DESCRIPTION or other sections. Otherwise correctness-checking library pages that may have multiple Synopsis subheadings becomes too difficult.
d
This old-style C prototype is too hard to parse, best to fix it.
e
Garbage generated by docbook2man
f
Presentational use of .SH messes up section parsing.
g
Run-on .B or .I macro.
i
Macro invocation in conditional confuses the doclifter parser.
j
Parenthesized comments in command synopsis. This is impossible to translate to DocBook.
l
Page consists solely of NAME and SYNOPSIS.
m
Contains a request that is outside the portable subset that can be rendered by non-groff viewers such as the KDE help browser, Xman, TKman, or manserver.
n
Unbalanced .RS or .RE macro
o
TBL markup not used where it should be. Tables stitched together with .ta requests can't be lifted to DocBook and will often choke third-party viewers such as TKMan, XMan, Rosetta, etc.
p
It is unnecessary to explain basic shell redirects on a man page. It is also bad style, especially when doing so produces an unparseable SYNOPSIS section.
q
Formatting file lists as tables in a Synopsis is impossible to translate into DocBook.
r
.Ss within a Synopsis confuses my section parser.
s
Example URLs which should *not* be turned into hyperlinks need an invisible stopper so tools which try to lift URLs from the page source will pass over them.
t
Unclosed .RS, appears to be a broken attempt to express list structure.
u
Use local definitions of .EX/.EE or .DS/.DE to avoid low-level troff requests in the page body. There are plans to add these to groff man; in the interim, this patch adds a compatible definition to your page.
v
Doubled dot before macro command.
w
You wrote .br where you meant .sp -- as written, the markup will fail to produce a blank line where one was clearly intended.
x
Unclosed .nf needs a .fi
y
Page is empty. This probably means there is some sort of glitch in your build machinery.
z
pod2man generates an unbalanced .RS tag. This is a bug.