Home | History | Annotate | Download | only in doc
      1 #!/usr/bin/awk
      2 #
      3 # Version history:
      4 #  v3, I put the program under a proper license
      5 #      Dan Nelson <dnelson (at] allantgroup.com> added .An, .Aq and fixed a typo
      6 #  v2, fixed to work on GNU awk --posix and MacOS X
      7 #  v1, first attempt, didn't work on MacOS X
      8 #
      9 # Copyright (c) 2003 Peter Stuge <stuge-mdoc2man (at] cdy.org>
     10 #
     11 # Permission to use, copy, modify, and distribute this software for any
     12 # purpose with or without fee is hereby granted, provided that the above
     13 # copyright notice and this permission notice appear in all copies.
     14 #
     15 # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     16 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     17 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     18 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     19 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     20 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     21 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     22 
     23 
     24 BEGIN {
     25   optlist=0
     26   oldoptlist=0
     27   nospace=0
     28   synopsis=0
     29   reference=0
     30   block=0
     31   ext=0
     32   extopt=0
     33   literal=0
     34   prenl=0
     35   breakw=0
     36   line=""
     37   proto=0
     38   bl_level=0
     39 }
     40 
     41 function wtail() {
     42   retval=""
     43   while(w<nwords) {
     44     if(length(retval))
     45       retval=retval OFS
     46     retval=retval words[++w]
     47   }
     48   return retval
     49 }
     50 
     51 function add(str) {
     52   for(;prenl;prenl--)
     53     line=line "\n"
     54   line=line str
     55 }
     56 
     57 ! /^\./ {
     58   for(;prenl;prenl--)
     59     print ""
     60   print
     61   if(literal)
     62     print ".br"
     63   next
     64 }
     65 
     66 /^\.\\"/ { next }
     67 
     68 {
     69   option=0
     70   parens=0
     71   angles=0
     72   sub("^\\.","")
     73   nwords=split($0,words)
     74   for(w=1;w<=nwords;w++) {
     75     skip=0
     76     if(match(words[w],"^Li|Pf$")) {
     77       skip=1
     78     } else if(match(words[w],"^Xo$")) {
     79       skip=1
     80       ext=1
     81       if(length(line)&&!(match(line," $")||prenl))
     82 	add(OFS)
     83     } else if(match(words[w],"^Xc$")) {
     84       skip=1
     85       ext=0
     86       if(!extopt)
     87 	prenl++
     88       w=nwords
     89     } else if(match(words[w],"^Bd$")) {
     90       skip=1
     91       if(match(words[w+1],"-literal")) {
     92 	literal=1
     93 	prenl++
     94 	w=nwords
     95       }
     96     } else if(match(words[w],"^Po$")) {
     97       skip=1
     98       add("(")
     99       if(!nospace)
    100 	nospace=1
    101     } else if(match(words[w],"^Pc$")) {
    102       skip=1
    103       add(")")
    104       if(!nospace)
    105 	nospace=1
    106     } else if(match(words[w],"^Ed$")) {
    107       skip=1
    108       literal=0
    109     } else if(match(words[w],"^Ns$")) {
    110       skip=1
    111       if(!nospace)
    112 	nospace=1
    113       sub(" $","",line)
    114     } else if(match(words[w],"^No$")) {
    115       skip=1
    116       sub(" $","",line)
    117       add(words[++w])
    118     } else if(match(words[w],"^Dq$")) {
    119       skip=1
    120       add("``")
    121       add(words[++w])
    122       while(w<nwords&&!match(words[w+1],"^[\\.,]"))
    123 	add(OFS words[++w])
    124       add("''")
    125       if(!nospace&&match(words[w+1],"^[\\.,]"))
    126 	nospace=1
    127     } else if(match(words[w],"^Va$")) {
    128       skip=1
    129       add("\\fI" words[++w])
    130       while(w<nwords&&!match(words[w+1],"^[\\.,]"))
    131 	add(OFS words[++w])
    132       add("\\fP")
    133       if(!nospace&&match(words[w+1],"^[\\.,]"))
    134 	nospace=1
    135     } else if(match(words[w],"^Sq|Ql$")) {
    136       skip=1
    137       add("`" words[++w] "'")
    138       if(!nospace&&match(words[w+1],"^[\\.,]"))
    139 	nospace=1
    140     } else if(match(words[w],"^Oo$")) {
    141       skip=1
    142       extopt=1
    143       if(!nospace)
    144 	nospace=1
    145       add("[")
    146     } else if(match(words[w],"^Oc$")) {
    147       skip=1
    148       extopt=0
    149       add("]")
    150     }
    151     if(!skip) {
    152       if(!nospace&&length(line)&&!(match(line," $")||prenl))
    153 	add(OFS)
    154       if(nospace==1)
    155 	nospace=0
    156     }
    157     if(match(words[w],"^Dd$")) {
    158       date=wtail()
    159       next
    160     } else if(match(words[w],"^Dt$")) {
    161       id=wtail()
    162       next
    163     } else if(match(words[w],"^Os$")) {
    164       add(".TH " id " \"" date "\" \"" wtail() "\"")
    165     } else if(match(words[w],"^Sh$")) {
    166       add(".SH")
    167       synopsis=match(words[w+1],"SYNOPSIS")
    168     } else if(match(words[w],"^Xr$")) {
    169       #add("\\fB" words[++w] "\\fP(" words[++w] ")" words[++w])
    170       add("\\fB" words[++w] "\\fP(" words[++w] ")")
    171       sub("^Ns$", "", words[w+1])
    172       add(words[++w])
    173     } else if(match(words[w],"^Rs$")) {
    174       split("",refauthors)
    175       nrefauthors=0
    176       reftitle=""
    177       refissue=""
    178       refdate=""
    179       refopt=""
    180       reference=1
    181       next
    182     } else if(match(words[w],"^Re$")) {
    183       prenl++
    184       for(i=nrefauthors-1;i>0;i--) {
    185 	add(refauthors[i])
    186 	if(i>1)
    187 	  add(", ")
    188       }
    189       if(nrefauthors>1)
    190 	add(" and ")
    191       add(refauthors[0] ", \\fI" reftitle "\\fP")
    192       if(length(refissue))
    193 	add(", " refissue)
    194       if(length(refdate))
    195 	add(", " refdate)
    196       if(length(refopt))
    197 	add(", " refopt)
    198       add(".")
    199       reference=0
    200     } else if(reference) {
    201       if(match(words[w],"^%A$")) { refauthors[nrefauthors++]=wtail() }
    202       if(match(words[w],"^%T$")) {
    203 	reftitle=wtail()
    204 	sub("^\"","",reftitle)
    205 	sub("\"$","",reftitle)
    206       }
    207       if(match(words[w],"^%N$")) { refissue=wtail() }
    208       if(match(words[w],"^%D$")) { refdate=wtail() }
    209       if(match(words[w],"^%O$")) { refopt=wtail() }
    210     } else if(match(words[w],"^Nm$")) {
    211       if(synopsis) {
    212 	add(".br")
    213 	prenl++
    214       }
    215       n=words[++w]
    216       if(!length(name))
    217 	name=n
    218       if(!length(n))
    219 	n=name
    220       add("\\fB" n "\\fP")
    221       if(!nospace&&match(words[w+1],"^[\\.,]"))
    222 	nospace=1
    223     } else if(match(words[w],"^Nd$")) {
    224       add("\\- " wtail())
    225     } else if(match(words[w],"^Fl$")) {
    226       add("\\fB\\-" words[++w] "\\fP")
    227       if(!nospace&&match(words[w+1],"^[\\.,]"))
    228 	nospace=1
    229     } else if(match(words[w],"^Ar$")) {
    230       add("\\fI")
    231       if(w==nwords)
    232 	add("file ...\\fP")
    233       else {
    234 	add(words[++w] "\\fP")
    235 	while(match(words[w+1],"^\\|$"))
    236 	  add(OFS words[++w] " \\fI" words[++w] "\\fP")
    237       }
    238       if(!nospace&&match(words[w+1],"^[\\.,]"))
    239 	nospace=1
    240     } else if(match(words[w],"^Cm$")) {
    241       add("\\fB" words[++w] "\\fP")
    242       while(w<nwords&&match(words[w+1],"^[\\.,:;)]"))
    243 	add(words[++w])
    244     } else if(match(words[w],"^Op$")) {
    245       option=1
    246       if(!nospace)
    247 	nospace=1
    248       add("[")
    249     } else if(match(words[w],"^Pp$")) {
    250       prenl++
    251     } else if(match(words[w],"^An$")) {
    252       prenl++
    253     } else if(match(words[w],"^Ss$")) {
    254       add(".SS")
    255     } else if(match(words[w],"^Pa$")&&!option) {
    256       add("\\fI")
    257       w++
    258       if(match(words[w],"^\\."))
    259 	add("\\&")
    260       add(words[w] "\\fP")
    261       while(w<nwords&&match(words[w+1],"^[\\.,:;)]"))
    262 	add(words[++w])
    263     } else if(match(words[w],"^Dv$")) {
    264       #add(".BR")
    265     } else if(match(words[w],"^Em|Ev$")) {
    266       add(".IR")
    267     } else if(match(words[w],"^Pq$")) {
    268       add("(")
    269       nospace=1
    270       parens=1
    271     } else if(match(words[w],"^Aq$")) {
    272       add("<")
    273       nospace=1
    274       angles=1
    275     } else if(match(words[w],"^S[xy]$")) {
    276       add(".B " wtail())
    277     } else if(match(words[w],"^Ic$")) {
    278       plain=1
    279       add("\\fB")
    280       while(w<nwords) {
    281 	w++
    282 	if(match(words[w],"^Op$")) {
    283 	  w++
    284 	  add("[")
    285 	  words[nwords]=words[nwords] "]"
    286 	}
    287 	if(match(words[w],"^Ar$")) {
    288 	  add("\\fI" words[++w] "\\fP")
    289 	} else if(match(words[w],"^[\\.,]")) {
    290 	  sub(" $","",line)
    291 	  if(plain) {
    292 	    add("\\fP")
    293 	    plain=0
    294 	  }
    295 	  add(words[w])
    296 	} else if(match(words[w],"^Xo$")) {
    297 	} else {
    298 	  if(!plain) {
    299 	    add("\\fB")
    300 	    plain=1
    301 	  }
    302 	  add(words[w])
    303 	}
    304 	if(!nospace)
    305 	  add(OFS)
    306       }
    307       sub(" $","",line)
    308       if(plain)
    309 	add("\\fP")
    310     } else if(match(words[w],"^Dl$")) {
    311        ## remove is ok for editrc.5
    312     } else if(match(words[w],"^Bl$")) {
    313       ++bl_level
    314       if (bl_level > 1)
    315          add(".RS")
    316       oldoptlist=optlist
    317       if(match(words[w+1],"-bullet"))
    318 	optlist=1
    319       else if(match(words[w+1],"-enum")) {
    320 	optlist=2
    321 	enum=0
    322       } else if(match(words[w+1],"-tag"))
    323 	optlist=3
    324       else if(match(words[w+1],"-item"))
    325 	optlist=4
    326       else if(match(words[w+1],"-bullet"))
    327 	optlist=1
    328       w=nwords
    329     } else if(match(words[w],"^El$")) {
    330       if (bl_level > 1)
    331          add(".RE")
    332       --bl_level
    333       optlist=oldoptlist
    334     } else if(match(words[w],"^Bk$")) {
    335       if(match(words[w+1],"-words")) {
    336 	w++
    337 	breakw=1
    338       }
    339     } else if(match(words[w],"^Ek$")) {
    340       breakw=0
    341     } else if(match(words[w],"^It$")&&optlist) {
    342       if(optlist==1)
    343 	add(".IP \\(bu")
    344       else if(optlist==2)
    345 	add(".IP " ++enum ".")
    346       else if(optlist==3) {
    347 	add(".TP")
    348 	prenl++
    349 	if(match(words[w+1],"^Pa$|^Ev$")) {
    350 	  add(".B")
    351 	  w++
    352 	}
    353       } else if(optlist==4)
    354 	add(".IP")
    355     } else if(match(words[w],"^Sm$")) {
    356       if(match(words[w+1],"off"))
    357 	nospace=2
    358       else if(match(words[w+1],"on"))
    359 	nospace=0
    360       w++
    361     } else if(match(words[w],"^Lb$")) {
    362       wtail()
    363       add("Command Line Editor Library (libedit, -ledit)")
    364     } else if(match(words[w],"^In$")) {
    365       add(".PP\n")
    366       add("\\fB#include <" wtail() ">\\fP")
    367     } else if(match(words[w],"^Ft$")) {
    368       add(".PP\n")
    369       add("\\fI" wtail() "\\fP\n")
    370       add(".br")
    371       proto=1
    372     } else if(match(words[w],"^Fn$")) {
    373       add("\\fB" words[++w] "\\fP(")
    374       punct=0
    375       while(++w<=nwords) {
    376          if(match(words[w], "^\".*\"$")) {
    377             sub("^\"", "", words[w])
    378             sub("\"$", "", words[w])
    379 	    add("\\fI" words[w] "\\fP")
    380             if (w!=nwords) {
    381 	       add(", ")
    382             }
    383          } else if(match(words[w], "^\"")) {
    384             sub("^\"", "", words[w])
    385 	    add("\\fI" words[w] " ")
    386          } else if (match(words[w], "\"$")) {
    387             sub("\"$", "", words[w])
    388 	    add(words[w] "\\fP")
    389             if (w!=nwords) {
    390 	       add(", ")
    391             }
    392          } else {
    393             if (w==nwords&&(match(words[w], "^[.,]$"))) {
    394                punct=1
    395             } else {
    396 	       add(words[w] " ")
    397             }
    398                
    399          }
    400       }
    401       add(")")
    402       if (punct==1) {
    403          add(words[w-1])
    404       } else {
    405          if (proto==1) {
    406             add(";")
    407             proto=0
    408          }
    409       }
    410     } else if(match(words[w],"^Fa$")) {
    411       punct=0
    412       add("\\fI")
    413       while(++w<=nwords) {
    414          if(match(words[w], "^\".*\"$")) {
    415             sub("^\"", "", words[w])
    416             sub("\"$", "", words[w])
    417 	    add(words[w])
    418          } else if(match(words[w], "^\"")) {
    419             sub("^\"", "", words[w])
    420 	    add(words[w] " ")
    421          } else if (match(words[w], "\"$")) {
    422             sub("\"$", "", words[w])
    423 	    add(words[w])
    424          } else {
    425             if (w==nwords&&(match(words[w], "^[.,]$"))) {
    426                punct=1
    427             } else {
    428                if (w+1==nwords&&(match(words[w+1], "^[.,]$"))) {
    429 	          add(words[w])
    430                } else {
    431 	          add(words[w] " ")
    432                }
    433             }
    434          }
    435       }
    436       add("\\fP")
    437       if (punct==1) {
    438          add(words[w-1])
    439       }
    440     } else if(!skip) {
    441       add(words[w])
    442     }
    443   }
    444   if(match(line,"^\\.[^a-zA-Z]"))
    445     sub("^\\.","",line)
    446   if(parens)
    447     add(")")
    448   if(angles)
    449     add(">")
    450   if(option)
    451     add("]")
    452   if(ext&&!extopt&&!match(line," $"))
    453     add(OFS)
    454   if(!ext&&!extopt&&length(line)) {
    455     print line
    456     prenl=0
    457     line=""
    458   }
    459 }
    460