blob: 3e8725452ed3236357ed3528315eedadb3e16878 [file] [log] [blame]
#!/usr/bin/awk
#
# $Id: mdoc2man.awk,v 1.9 2009/10/24 00:52:42 dtucker Exp $
#
# Version history:
# v4+ Adapted for OpenSSH Portable (see cvs Id and history)
# v3, I put the program under a proper license
# Dan Nelson <dnelson@allantgroup.com> added .An, .Aq and fixed a typo
# v2, fixed to work on GNU awk --posix and MacOS X
# v1, first attempt, didn't work on MacOS X
#
# Copyright (c) 2003 Peter Stuge <stuge-mdoc2man@cdy.org>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
BEGIN {
optlist=0
oldoptlist=0
nospace=0
synopsis=0
reference=0
block=0
ext=0
extopt=0
literal=0
prenl=0
breakw=0
line=""
}
function wtail() {
retval=""
while(w<nwords) {
if(length(retval))
retval=retval OFS
retval=retval words[++w]
}
return retval
}
function add(str) {
for(;prenl;prenl--)
line=line "\n"
line=line str
}
! /^\./ {
for(;prenl;prenl--)
print ""
print
if(literal)
print ".br"
next
}
/^\.\\"/ { next }
{
option=0
parens=0
angles=0
sub("^\\.","")
nwords=split($0,words)
for(w=1;w<=nwords;w++) {
skip=0
if(match(words[w],"^Li|Pf$")) {
skip=1
} else if(match(words[w],"^Xo$")) {
skip=1
ext=1
if(length(line)&&!(match(line," $")||prenl))
add(OFS)
} else if(match(words[w],"^Xc$")) {
skip=1
ext=0
if(!extopt)
prenl++
w=nwords
} else if(match(words[w],"^Bd$")) {
skip=1
if(match(words[w+1],"-literal")) {
literal=1
prenl++
w=nwords
}
} else if(match(words[w],"^Ed$")) {
skip=1
literal=0
} else if(match(words[w],"^Ns$")) {
skip=1
if(!nospace)
nospace=1
sub(" $","",line)
} else if(match(words[w],"^No$")) {
skip=1
sub(" $","",line)
add(words[++w])
} else if(match(words[w],"^Dq$")) {
skip=1
add("``")
add(words[++w])
while(w<nwords&&!match(words[w+1],"^[\\.,]"))
add(OFS words[++w])
add("''")
if(!nospace&&match(words[w+1],"^[\\.,]"))
nospace=1
} else if(match(words[w],"^Sq|Ql$")) {
skip=1
add("`" words[++w] "'")
if(!nospace&&match(words[w+1],"^[\\.,]"))
nospace=1
} else if(match(words[w],"^Oo$")) {
skip=1
extopt=1
if(!nospace)
nospace=1
add("[")
} else if(match(words[w],"^Oc$")) {
skip=1
extopt=0
add("]")
}
if(!skip) {
if(!nospace&&length(line)&&!(match(line," $")||prenl))
add(OFS)
if(nospace==1)
nospace=0
}
if(match(words[w],"^Dd$")) {
if(match(words[w+1],"^\\$Mdocdate:")) {
w++;
if(match(words[w+4],"^\\$$")) {
words[w+4] = ""
}
}
date=wtail()
next
} else if(match(words[w],"^Dt$")) {
id=wtail()
next
} else if(match(words[w],"^Ux$")) {
add("UNIX")
skip=1
} else if(match(words[w],"^Ox$")) {
add("OpenBSD")
skip=1
} else if(match(words[w],"^Os$")) {
add(".TH " id " \"" date "\" \"" wtail() "\"")
} else if(match(words[w],"^Sh$")) {
add(".SH")
synopsis=match(words[w+1],"SYNOPSIS")
} else if(match(words[w],"^Xr$")) {
add("\\fB" words[++w] "\\fP(" words[++w] ")" words[++w])
} else if(match(words[w],"^Rs$")) {
split("",refauthors)
nrefauthors=0
reftitle=""
refissue=""
refdate=""
refopt=""
refreport=""
reference=1
next
} else if(match(words[w],"^Re$")) {
prenl++
for(i=nrefauthors-1;i>0;i--) {
add(refauthors[i])
if(i>1)
add(", ")
}
if(nrefauthors>1)
add(" and ")
if(nrefauthors>0)
add(refauthors[0] ", ")
add("\\fI" reftitle "\\fP")
if(length(refissue))
add(", " refissue)
if(length(refreport)) {
add(", " refreport)
}
if(length(refdate))
add(", " refdate)
if(length(refopt))
add(", " refopt)
add(".")
reference=0
} else if(reference) {
if(match(words[w],"^%A$")) { refauthors[nrefauthors++]=wtail() }
if(match(words[w],"^%T$")) {
reftitle=wtail()
sub("^\"","",reftitle)
sub("\"$","",reftitle)
}
if(match(words[w],"^%N$")) { refissue=wtail() }
if(match(words[w],"^%D$")) { refdate=wtail() }
if(match(words[w],"^%O$")) { refopt=wtail() }
if(match(words[w],"^%R$")) { refreport=wtail() }
} else if(match(words[w],"^Nm$")) {
if(synopsis) {
add(".br")
prenl++
}
n=words[++w]
if(!length(name))
name=n
if(!length(n))
n=name
add("\\fB" n "\\fP")
if(!nospace&&match(words[w+1],"^[\\.,]"))
nospace=1
} else if(match(words[w],"^Nd$")) {
add("\\- " wtail())
} else if(match(words[w],"^Fl$")) {
add("\\fB\\-" words[++w] "\\fP")
if(!nospace&&match(words[w+1],"^[\\.,]"))
nospace=1
} else if(match(words[w],"^Ar$")) {
add("\\fI")
if(w==nwords)
add("file ...\\fP")
else {
add(words[++w] "\\fP")
while(match(words[w+1],"^\\|$"))
add(OFS words[++w] " \\fI" words[++w] "\\fP")
}
if(!nospace&&match(words[w+1],"^[\\.,]"))
nospace=1
} else if(match(words[w],"^Cm$")) {
add("\\fB" words[++w] "\\fP")
while(w<nwords&&match(words[w+1],"^[\\.,:;)]"))
add(words[++w])
} else if(match(words[w],"^Op$")) {
option=1
if(!nospace)
nospace=1
add("[")
} else if(match(words[w],"^Pp$")) {
prenl++
} else if(match(words[w],"^An$")) {
prenl++
} else if(match(words[w],"^Ss$")) {
add(".SS")
} else if(match(words[w],"^Pa$")&&!option) {
add("\\fI")
w++
if(match(words[w],"^\\."))
add("\\&")
add(words[w] "\\fP")
while(w<nwords&&match(words[w+1],"^[\\.,:;)]"))
add(words[++w])
} else if(match(words[w],"^Dv$")) {
add(".BR")
} else if(match(words[w],"^Em|Ev$")) {
add(".IR")
} else if(match(words[w],"^Pq$")) {
add("(")
nospace=1
parens=1
} else if(match(words[w],"^Aq$")) {
add("<")
nospace=1
angles=1
} else if(match(words[w],"^S[xy]$")) {
add(".B " wtail())
} else if(match(words[w],"^Ic$")) {
plain=1
add("\\fB")
while(w<nwords) {
w++
if(match(words[w],"^Op$")) {
w++
add("[")
words[nwords]=words[nwords] "]"
}
if(match(words[w],"^Ar$")) {
add("\\fI" words[++w] "\\fP")
} else if(match(words[w],"^[\\.,]")) {
sub(" $","",line)
if(plain) {
add("\\fP")
plain=0
}
add(words[w])
} else {
if(!plain) {
add("\\fB")
plain=1
}
add(words[w])
}
if(!nospace)
add(OFS)
}
sub(" $","",line)
if(plain)
add("\\fP")
} else if(match(words[w],"^Bl$")) {
oldoptlist=optlist
if(match(words[w+1],"-bullet"))
optlist=1
else if(match(words[w+1],"-enum")) {
optlist=2
enum=0
} else if(match(words[w+1],"-tag"))
optlist=3
else if(match(words[w+1],"-item"))
optlist=4
else if(match(words[w+1],"-bullet"))
optlist=1
w=nwords
} else if(match(words[w],"^El$")) {
optlist=oldoptlist
if(!optlist)
add(".PP")
} else if(match(words[w],"^Bk$")) {
if(match(words[w+1],"-words")) {
w++
breakw=1
}
} else if(match(words[w],"^Ek$")) {
breakw=0
} else if(match(words[w],"^It$")&&optlist) {
if(optlist==1)
add(".IP \\(bu")
else if(optlist==2)
add(".IP " ++enum ".")
else if(optlist==3) {
add(".TP")
prenl++
if(match(words[w+1],"^Pa$|^Ev$")) {
add(".B")
w++
}
} else if(optlist==4)
add(".IP")
} else if(match(words[w],"^Sm$")) {
if(match(words[w+1],"off"))
nospace=2
else if(match(words[w+1],"on"))
nospace=0
w++
} else if(!skip) {
add(words[w])
}
}
if(match(line,"^\\.[^a-zA-Z]"))
sub("^\\.","",line)
if(parens)
add(")")
if(angles)
add(">")
if(option)
add("]")
if(ext&&!extopt&&!match(line," $"))
add(OFS)
if(!ext&&!extopt&&length(line)) {
print line
prenl=0
line=""
}
}