mdoc2man.awk revision 149749
1235267Sgabor#!/usr/bin/awk 2235267Sgabor# 3251245Sgabor# Version history: 4235267Sgabor# v3, I put the program under a proper license 5235267Sgabor# Dan Nelson <dnelson@allantgroup.com> added .An, .Aq and fixed a typo 6235267Sgabor# v2, fixed to work on GNU awk --posix and MacOS X 7235267Sgabor# v1, first attempt, didn't work on MacOS X 8235267Sgabor# 9235267Sgabor# Copyright (c) 2003 Peter Stuge <stuge-mdoc2man@cdy.org> 10235267Sgabor# 11235267Sgabor# Permission to use, copy, modify, and distribute this software for any 12235267Sgabor# purpose with or without fee is hereby granted, provided that the above 13235267Sgabor# copyright notice and this permission notice appear in all copies. 14235267Sgabor# 15235267Sgabor# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 16235267Sgabor# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17235267Sgabor# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18235267Sgabor# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19235267Sgabor# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20235267Sgabor# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 21235267Sgabor# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22235267Sgabor 23235267Sgabor 24235267SgaborBEGIN { 25235267Sgabor optlist=0 26235267Sgabor oldoptlist=0 27235267Sgabor nospace=0 28235267Sgabor synopsis=0 29235267Sgabor reference=0 30235267Sgabor block=0 31235267Sgabor ext=0 32235267Sgabor extopt=0 33235267Sgabor literal=0 34235267Sgabor prenl=0 35235267Sgabor breakw=0 36235267Sgabor line="" 37235267Sgabor} 38235267Sgabor 39235267Sgaborfunction wtail() { 40235267Sgabor retval="" 41235267Sgabor while(w<nwords) { 42235267Sgabor if(length(retval)) 43235267Sgabor retval=retval OFS 44235435Sgabor retval=retval words[++w] 45235267Sgabor } 46235435Sgabor return retval 47235435Sgabor} 48235267Sgabor 49235267Sgaborfunction add(str) { 50235267Sgabor for(;prenl;prenl--) 51235267Sgabor line=line "\n" 52235267Sgabor line=line str 53235267Sgabor} 54235267Sgabor 55235267Sgabor! /^\./ { 56235267Sgabor for(;prenl;prenl--) 57235267Sgabor print "" 58235267Sgabor print 59235267Sgabor if(literal) 60235267Sgabor print ".br" 61235267Sgabor next 62235267Sgabor} 63235267Sgabor 64235267Sgabor/^\.\\"/ { next } 65235267Sgabor 66235267Sgabor{ 67235267Sgabor option=0 68235267Sgabor parens=0 69235267Sgabor angles=0 70235267Sgabor sub("^\\.","") 71235267Sgabor nwords=split($0,words) 72242430Sgabor for(w=1;w<=nwords;w++) { 73235267Sgabor skip=0 74235267Sgabor if(match(words[w],"^Li|Pf$")) { 75235267Sgabor skip=1 76235267Sgabor } else if(match(words[w],"^Xo$")) { 77235267Sgabor skip=1 78235267Sgabor ext=1 79235267Sgabor if(length(line)&&!(match(line," $")||prenl)) 80235267Sgabor add(OFS) 81235267Sgabor } else if(match(words[w],"^Xc$")) { 82235267Sgabor skip=1 83235267Sgabor ext=0 84235267Sgabor if(!extopt) 85235267Sgabor prenl++ 86235267Sgabor w=nwords 87235267Sgabor } else if(match(words[w],"^Bd$")) { 88235267Sgabor skip=1 89235267Sgabor if(match(words[w+1],"-literal")) { 90235267Sgabor literal=1 91235267Sgabor prenl++ 92235267Sgabor w=nwords 93235267Sgabor } 94235267Sgabor } else if(match(words[w],"^Ed$")) { 95235267Sgabor skip=1 96235267Sgabor literal=0 97235267Sgabor } else if(match(words[w],"^Ns$")) { 98242430Sgabor skip=1 99235267Sgabor if(!nospace) 100235267Sgabor nospace=1 101235267Sgabor sub(" $","",line) 102235267Sgabor } else if(match(words[w],"^No$")) { 103235267Sgabor skip=1 104242430Sgabor sub(" $","",line) 105235267Sgabor add(words[++w]) 106235267Sgabor } else if(match(words[w],"^Dq$")) { 107235267Sgabor skip=1 108235267Sgabor add("``") 109235267Sgabor add(words[++w]) 110235267Sgabor while(w<nwords&&!match(words[w+1],"^[\\.,]")) 111235267Sgabor add(OFS words[++w]) 112235267Sgabor add("''") 113235267Sgabor if(!nospace&&match(words[w+1],"^[\\.,]")) 114235267Sgabor nospace=1 115235267Sgabor } else if(match(words[w],"^Sq|Ql$")) { 116235267Sgabor skip=1 117235267Sgabor add("`" words[++w] "'") 118235267Sgabor if(!nospace&&match(words[w+1],"^[\\.,]")) 119235267Sgabor nospace=1 120235267Sgabor } else if(match(words[w],"^Oo$")) { 121235267Sgabor skip=1 122235267Sgabor extopt=1 123235267Sgabor if(!nospace) 124235267Sgabor nospace=1 125235267Sgabor add("[") 126235267Sgabor } else if(match(words[w],"^Oc$")) { 127235267Sgabor skip=1 128235267Sgabor extopt=0 129235267Sgabor add("]") 130235267Sgabor } 131235267Sgabor if(!skip) { 132235267Sgabor if(!nospace&&length(line)&&!(match(line," $")||prenl)) 133235267Sgabor add(OFS) 134235267Sgabor if(nospace==1) 135235267Sgabor nospace=0 136235267Sgabor } 137235267Sgabor if(match(words[w],"^Dd$")) { 138235267Sgabor date=wtail() 139235267Sgabor next 140235267Sgabor } else if(match(words[w],"^Dt$")) { 141235267Sgabor id=wtail() 142235267Sgabor next 143235267Sgabor } else if(match(words[w],"^Ox$")) { 144235267Sgabor add("OpenBSD") 145235267Sgabor skip=1 146235267Sgabor } else if(match(words[w],"^Os$")) { 147235267Sgabor add(".TH " id " \"" date "\" \"" wtail() "\"") 148235267Sgabor } else if(match(words[w],"^Sh$")) { 149235267Sgabor add(".SH") 150235267Sgabor synopsis=match(words[w+1],"SYNOPSIS") 151235267Sgabor } else if(match(words[w],"^Xr$")) { 152235267Sgabor add("\\fB" words[++w] "\\fP(" words[++w] ")" words[++w]) 153235267Sgabor } else if(match(words[w],"^Rs$")) { 154235267Sgabor split("",refauthors) 155235267Sgabor nrefauthors=0 156235267Sgabor reftitle="" 157235267Sgabor refissue="" 158235267Sgabor refdate="" 159235267Sgabor refopt="" 160235267Sgabor reference=1 161235267Sgabor next 162235267Sgabor } else if(match(words[w],"^Re$")) { 163235267Sgabor prenl++ 164235267Sgabor for(i=nrefauthors-1;i>0;i--) { 165235267Sgabor add(refauthors[i]) 166235267Sgabor if(i>1) 167235267Sgabor add(", ") 168235267Sgabor } 169235267Sgabor if(nrefauthors>1) 170235267Sgabor add(" and ") 171235267Sgabor add(refauthors[0] ", \\fI" reftitle "\\fP") 172235267Sgabor if(length(refissue)) 173235267Sgabor add(", " refissue) 174235267Sgabor if(length(refdate)) 175235267Sgabor add(", " refdate) 176235267Sgabor if(length(refopt)) 177235267Sgabor add(", " refopt) 178235267Sgabor add(".") 179235267Sgabor reference=0 180235267Sgabor } else if(reference) { 181235267Sgabor if(match(words[w],"^%A$")) { refauthors[nrefauthors++]=wtail() } 182235267Sgabor if(match(words[w],"^%T$")) { 183235267Sgabor reftitle=wtail() 184235267Sgabor sub("^\"","",reftitle) 185235267Sgabor sub("\"$","",reftitle) 186235267Sgabor } 187235267Sgabor if(match(words[w],"^%N$")) { refissue=wtail() } 188235267Sgabor if(match(words[w],"^%D$")) { refdate=wtail() } 189235267Sgabor if(match(words[w],"^%O$")) { refopt=wtail() } 190235267Sgabor } else if(match(words[w],"^Nm$")) { 191235267Sgabor if(synopsis) { 192235267Sgabor add(".br") 193235267Sgabor prenl++ 194235267Sgabor } 195235267Sgabor n=words[++w] 196235267Sgabor if(!length(name)) 197235267Sgabor name=n 198235267Sgabor if(!length(n)) 199235267Sgabor n=name 200235267Sgabor add("\\fB" n "\\fP") 201235267Sgabor if(!nospace&&match(words[w+1],"^[\\.,]")) 202235267Sgabor nospace=1 203235267Sgabor } else if(match(words[w],"^Nd$")) { 204235267Sgabor add("\\- " wtail()) 205235267Sgabor } else if(match(words[w],"^Fl$")) { 206235267Sgabor add("\\fB\\-" words[++w] "\\fP") 207235267Sgabor if(!nospace&&match(words[w+1],"^[\\.,]")) 208235267Sgabor nospace=1 209235267Sgabor } else if(match(words[w],"^Ar$")) { 210235267Sgabor add("\\fI") 211235267Sgabor if(w==nwords) 212235267Sgabor add("file ...\\fP") 213235267Sgabor else { 214235267Sgabor add(words[++w] "\\fP") 215235267Sgabor while(match(words[w+1],"^\\|$")) 216235267Sgabor add(OFS words[++w] " \\fI" words[++w] "\\fP") 217235267Sgabor } 218235267Sgabor if(!nospace&&match(words[w+1],"^[\\.,]")) 219235267Sgabor nospace=1 220235267Sgabor } else if(match(words[w],"^Cm$")) { 221235267Sgabor add("\\fB" words[++w] "\\fP") 222235267Sgabor while(w<nwords&&match(words[w+1],"^[\\.,:;)]")) 223235267Sgabor add(words[++w]) 224235267Sgabor } else if(match(words[w],"^Op$")) { 225235267Sgabor option=1 226235267Sgabor if(!nospace) 227235267Sgabor nospace=1 228235267Sgabor add("[") 229235267Sgabor } else if(match(words[w],"^Pp$")) { 230235267Sgabor prenl++ 231235267Sgabor } else if(match(words[w],"^An$")) { 232235267Sgabor prenl++ 233235267Sgabor } else if(match(words[w],"^Ss$")) { 234235267Sgabor add(".SS") 235235267Sgabor } else if(match(words[w],"^Pa$")&&!option) { 236235267Sgabor add("\\fI") 237235267Sgabor w++ 238235267Sgabor if(match(words[w],"^\\.")) 239235267Sgabor add("\\&") 240235267Sgabor add(words[w] "\\fP") 241235267Sgabor while(w<nwords&&match(words[w+1],"^[\\.,:;)]")) 242235267Sgabor add(words[++w]) 243235267Sgabor } else if(match(words[w],"^Dv$")) { 244235267Sgabor add(".BR") 245235267Sgabor } else if(match(words[w],"^Em|Ev$")) { 246235267Sgabor add(".IR") 247235267Sgabor } else if(match(words[w],"^Pq$")) { 248235267Sgabor add("(") 249235267Sgabor nospace=1 250235267Sgabor parens=1 251235267Sgabor } else if(match(words[w],"^Aq$")) { 252235267Sgabor add("<") 253235267Sgabor nospace=1 254235267Sgabor angles=1 255235267Sgabor } else if(match(words[w],"^S[xy]$")) { 256235267Sgabor add(".B " wtail()) 257235267Sgabor } else if(match(words[w],"^Ic$")) { 258235267Sgabor plain=1 259235267Sgabor add("\\fB") 260235267Sgabor while(w<nwords) { 261235267Sgabor w++ 262235267Sgabor if(match(words[w],"^Op$")) { 263235267Sgabor w++ 264235267Sgabor add("[") 265235267Sgabor words[nwords]=words[nwords] "]" 266235267Sgabor } 267235267Sgabor if(match(words[w],"^Ar$")) { 268235267Sgabor add("\\fI" words[++w] "\\fP") 269235267Sgabor } else if(match(words[w],"^[\\.,]")) { 270235267Sgabor sub(" $","",line) 271235267Sgabor if(plain) { 272235267Sgabor add("\\fP") 273235267Sgabor plain=0 274235267Sgabor } 275235267Sgabor add(words[w]) 276235267Sgabor } else { 277235267Sgabor if(!plain) { 278235267Sgabor add("\\fB") 279235267Sgabor plain=1 280235267Sgabor } 281235267Sgabor add(words[w]) 282235267Sgabor } 283235267Sgabor if(!nospace) 284235267Sgabor add(OFS) 285235267Sgabor } 286235267Sgabor sub(" $","",line) 287235267Sgabor if(plain) 288235267Sgabor add("\\fP") 289235267Sgabor } else if(match(words[w],"^Bl$")) { 290235267Sgabor oldoptlist=optlist 291235267Sgabor if(match(words[w+1],"-bullet")) 292235267Sgabor optlist=1 293235267Sgabor else if(match(words[w+1],"-enum")) { 294235267Sgabor optlist=2 295235267Sgabor enum=0 296235267Sgabor } else if(match(words[w+1],"-tag")) 297235267Sgabor optlist=3 298235267Sgabor else if(match(words[w+1],"-item")) 299235267Sgabor optlist=4 300235267Sgabor else if(match(words[w+1],"-bullet")) 301235267Sgabor optlist=1 302235267Sgabor w=nwords 303235267Sgabor } else if(match(words[w],"^El$")) { 304235267Sgabor optlist=oldoptlist 305235267Sgabor } else if(match(words[w],"^Bk$")) { 306235267Sgabor if(match(words[w+1],"-words")) { 307235267Sgabor w++ 308235267Sgabor breakw=1 309235267Sgabor } 310235267Sgabor } else if(match(words[w],"^Ek$")) { 311235267Sgabor breakw=0 312235267Sgabor } else if(match(words[w],"^It$")&&optlist) { 313235267Sgabor if(optlist==1) 314235267Sgabor add(".IP \\(bu") 315235267Sgabor else if(optlist==2) 316235267Sgabor add(".IP " ++enum ".") 317235267Sgabor else if(optlist==3) { 318235267Sgabor add(".TP") 319235267Sgabor prenl++ 320235267Sgabor if(match(words[w+1],"^Pa$|^Ev$")) { 321235267Sgabor add(".B") 322235267Sgabor w++ 323235267Sgabor } 324235267Sgabor } else if(optlist==4) 325235267Sgabor add(".IP") 326235267Sgabor } else if(match(words[w],"^Sm$")) { 327235267Sgabor if(match(words[w+1],"off")) 328235267Sgabor nospace=2 329235267Sgabor else if(match(words[w+1],"on")) 330235267Sgabor nospace=0 331235267Sgabor w++ 332235267Sgabor } else if(!skip) { 333235267Sgabor add(words[w]) 334235267Sgabor } 335235267Sgabor } 336235267Sgabor if(match(line,"^\\.[^a-zA-Z]")) 337235267Sgabor sub("^\\.","",line) 338235267Sgabor if(parens) 339235267Sgabor add(")") 340235267Sgabor if(angles) 341235267Sgabor add(">") 342235267Sgabor if(option) 343235267Sgabor add("]") 344235267Sgabor if(ext&&!extopt&&!match(line," $")) 345235267Sgabor add(OFS) 346235267Sgabor if(!ext&&!extopt&&length(line)) { 347235267Sgabor print line 348235267Sgabor prenl=0 349235267Sgabor line="" 350235267Sgabor } 351235267Sgabor} 352235267Sgabor