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