|  | #!/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 | 
|  | } 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="" | 
|  | } | 
|  | } |