#!/usr/bin/awk # # Version 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="" proto=0 bl_level=0 } 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],"^Po$")) { skip=1 add("(") if(!nospace) nospace=1 } else if(match(words[w],"^Pc$")) { skip=1 add(")") if(!nospace) nospace=1 } 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],"^Va$")) { skip=1 add("\\fI" words[++w]) while(w<nwords&&!match(words[w+1],"^[\\.,]")) add(OFS words[++w]) add("\\fP") 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$")) { date=wtail() next } else if(match(words[w],"^Dt$")) { id=wtail() next } 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]) add("\\fB" words[++w] "\\fP(" words[++w] ")") sub("^Ns$", "", words[w+1]) add(words[++w]) } else if(match(words[w],"^Rs$")) { split("",refauthors) nrefauthors=0 reftitle="" refissue="" refdate="" refopt="" 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 ") add(refauthors[0] ", \\fI" reftitle "\\fP") if(length(refissue)) add(", " refissue) 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() } } 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(match(words[w],"^Xo$")) { } 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],"^Dl$")) { ## remove is ok for editrc.5 } else if(match(words[w],"^Bl$")) { ++bl_level if (bl_level > 1) add(".RS") 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$")) { if (bl_level > 1) add(".RE") --bl_level 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(match(words[w],"^Lb$")) { wtail() add("Command Line Editor Library (libedit, -ledit)") } else if(match(words[w],"^In$")) { add(".PP\n") add("\\fB#include <" wtail() ">\\fP") } else if(match(words[w],"^Ft$")) { add(".PP\n") add("\\fI" wtail() "\\fP\n") add(".br") proto=1 } else if(match(words[w],"^Fn$")) { add("\\fB" words[++w] "\\fP(") punct=0 while(++w<=nwords) { if(match(words[w], "^\".*\"$")) { sub("^\"", "", words[w]) sub("\"$", "", words[w]) add("\\fI" words[w] "\\fP") if (w!=nwords) { add(", ") } } else if(match(words[w], "^\"")) { sub("^\"", "", words[w]) add("\\fI" words[w] " ") } else if (match(words[w], "\"$")) { sub("\"$", "", words[w]) add(words[w] "\\fP") if (w!=nwords) { add(", ") } } else { if (w==nwords&&(match(words[w], "^[.,]$"))) { punct=1 } else { add(words[w] " ") } } } add(")") if (punct==1) { add(words[w-1]) } else { if (proto==1) { add(";") proto=0 } } } else if(match(words[w],"^Fa$")) { punct=0 add("\\fI") while(++w<=nwords) { if(match(words[w], "^\".*\"$")) { sub("^\"", "", words[w]) sub("\"$", "", words[w]) add(words[w]) } else if(match(words[w], "^\"")) { sub("^\"", "", words[w]) add(words[w] " ") } else if (match(words[w], "\"$")) { sub("\"$", "", words[w]) add(words[w]) } else { if (w==nwords&&(match(words[w], "^[.,]$"))) { punct=1 } else { if (w+1==nwords&&(match(words[w+1], "^[.,]$"))) { add(words[w]) } else { add(words[w] " ") } } } } add("\\fP") if (punct==1) { add(words[w-1]) } } 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="" } }