1928fc495Schristos#!/usr/bin/awk 2928fc495Schristos# 3*9fb66d81Schristos# Id: mdoc2man.awk,v 1.9 2009/10/24 00:52:42 dtucker Exp 4928fc495Schristos# 5928fc495Schristos# Version history: 6928fc495Schristos# v4+ Adapted for OpenSSH Portable (see cvs Id and history) 7928fc495Schristos# v3, I put the program under a proper license 8928fc495Schristos# Dan Nelson <dnelson@allantgroup.com> added .An, .Aq and fixed a typo 9928fc495Schristos# v2, fixed to work on GNU awk --posix and MacOS X 10928fc495Schristos# v1, first attempt, didn't work on MacOS X 11928fc495Schristos# 12928fc495Schristos# Copyright (c) 2003 Peter Stuge <stuge-mdoc2man@cdy.org> 13928fc495Schristos# 14928fc495Schristos# Permission to use, copy, modify, and distribute this software for any 15928fc495Schristos# purpose with or without fee is hereby granted, provided that the above 16928fc495Schristos# copyright notice and this permission notice appear in all copies. 17928fc495Schristos# 18928fc495Schristos# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 19928fc495Schristos# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 20928fc495Schristos# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 21928fc495Schristos# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 22928fc495Schristos# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 23928fc495Schristos# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 24928fc495Schristos# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 25928fc495Schristos 26928fc495Schristos 27928fc495SchristosBEGIN { 28928fc495Schristos optlist=0 29928fc495Schristos oldoptlist=0 30928fc495Schristos nospace=0 31928fc495Schristos synopsis=0 32928fc495Schristos reference=0 33928fc495Schristos block=0 34928fc495Schristos ext=0 35928fc495Schristos extopt=0 36928fc495Schristos literal=0 37928fc495Schristos prenl=0 38928fc495Schristos breakw=0 39928fc495Schristos line="" 40928fc495Schristos} 41928fc495Schristos 42928fc495Schristosfunction wtail() { 43928fc495Schristos retval="" 44928fc495Schristos while(w<nwords) { 45928fc495Schristos if(length(retval)) 46928fc495Schristos retval=retval OFS 47928fc495Schristos retval=retval words[++w] 48928fc495Schristos } 49928fc495Schristos return retval 50928fc495Schristos} 51928fc495Schristos 52928fc495Schristosfunction add(str) { 53928fc495Schristos for(;prenl;prenl--) 54928fc495Schristos line=line "\n" 55928fc495Schristos line=line str 56928fc495Schristos} 57928fc495Schristos 58928fc495Schristos! /^\./ { 59928fc495Schristos for(;prenl;prenl--) 60928fc495Schristos print "" 61928fc495Schristos print 62928fc495Schristos if(literal) 63928fc495Schristos print ".br" 64928fc495Schristos next 65928fc495Schristos} 66928fc495Schristos 67928fc495Schristos/^\.\\"/ { next } 68928fc495Schristos 69928fc495Schristos{ 70928fc495Schristos option=0 71928fc495Schristos parens=0 72928fc495Schristos angles=0 73928fc495Schristos sub("^\\.","") 74928fc495Schristos nwords=split($0,words) 75928fc495Schristos for(w=1;w<=nwords;w++) { 76928fc495Schristos skip=0 77928fc495Schristos if(match(words[w],"^Li|Pf$")) { 78928fc495Schristos skip=1 79928fc495Schristos } else if(match(words[w],"^Xo$")) { 80928fc495Schristos skip=1 81928fc495Schristos ext=1 82928fc495Schristos if(length(line)&&!(match(line," $")||prenl)) 83928fc495Schristos add(OFS) 84928fc495Schristos } else if(match(words[w],"^Xc$")) { 85928fc495Schristos skip=1 86928fc495Schristos ext=0 87928fc495Schristos if(!extopt) 88928fc495Schristos prenl++ 89928fc495Schristos w=nwords 90928fc495Schristos } else if(match(words[w],"^Bd$")) { 91928fc495Schristos skip=1 92928fc495Schristos if(match(words[w+1],"-literal")) { 93928fc495Schristos literal=1 94928fc495Schristos prenl++ 95928fc495Schristos w=nwords 96928fc495Schristos } 97928fc495Schristos } else if(match(words[w],"^Ed$")) { 98928fc495Schristos skip=1 99928fc495Schristos literal=0 100928fc495Schristos } else if(match(words[w],"^Ns$")) { 101928fc495Schristos skip=1 102928fc495Schristos if(!nospace) 103928fc495Schristos nospace=1 104928fc495Schristos sub(" $","",line) 105928fc495Schristos } else if(match(words[w],"^No$")) { 106928fc495Schristos skip=1 107928fc495Schristos sub(" $","",line) 108928fc495Schristos add(words[++w]) 109928fc495Schristos } else if(match(words[w],"^Dq$")) { 110928fc495Schristos skip=1 111928fc495Schristos add("``") 112928fc495Schristos add(words[++w]) 113928fc495Schristos while(w<nwords&&!match(words[w+1],"^[\\.,]")) 114928fc495Schristos add(OFS words[++w]) 115928fc495Schristos add("''") 116928fc495Schristos if(!nospace&&match(words[w+1],"^[\\.,]")) 117928fc495Schristos nospace=1 118928fc495Schristos } else if(match(words[w],"^Sq|Ql$")) { 119928fc495Schristos skip=1 120928fc495Schristos add("`" words[++w] "'") 121928fc495Schristos if(!nospace&&match(words[w+1],"^[\\.,]")) 122928fc495Schristos nospace=1 123928fc495Schristos } else if(match(words[w],"^Oo$")) { 124928fc495Schristos skip=1 125928fc495Schristos extopt=1 126928fc495Schristos if(!nospace) 127928fc495Schristos nospace=1 128928fc495Schristos add("[") 129928fc495Schristos } else if(match(words[w],"^Oc$")) { 130928fc495Schristos skip=1 131928fc495Schristos extopt=0 132928fc495Schristos add("]") 133928fc495Schristos } 134928fc495Schristos if(!skip) { 135928fc495Schristos if(!nospace&&length(line)&&!(match(line," $")||prenl)) 136928fc495Schristos add(OFS) 137928fc495Schristos if(nospace==1) 138928fc495Schristos nospace=0 139928fc495Schristos } 140928fc495Schristos if(match(words[w],"^Dd$")) { 141928fc495Schristos if(match(words[w+1],"^\\$Mdocdate:")) { 142928fc495Schristos w++; 143928fc495Schristos if(match(words[w+4],"^\\$$")) { 144928fc495Schristos words[w+4] = "" 145928fc495Schristos } 146928fc495Schristos } 147928fc495Schristos date=wtail() 148928fc495Schristos next 149928fc495Schristos } else if(match(words[w],"^Dt$")) { 150928fc495Schristos id=wtail() 151928fc495Schristos next 152928fc495Schristos } else if(match(words[w],"^Ux$")) { 153928fc495Schristos add("UNIX") 154928fc495Schristos skip=1 155928fc495Schristos } else if(match(words[w],"^Ox$")) { 156928fc495Schristos add("OpenBSD") 157928fc495Schristos skip=1 158928fc495Schristos } else if(match(words[w],"^Os$")) { 159928fc495Schristos add(".TH " id " \"" date "\" \"" wtail() "\"") 160928fc495Schristos } else if(match(words[w],"^Sh$")) { 161928fc495Schristos add(".SH") 162928fc495Schristos synopsis=match(words[w+1],"SYNOPSIS") 163928fc495Schristos } else if(match(words[w],"^Xr$")) { 164928fc495Schristos add("\\fB" words[++w] "\\fP(" words[++w] ")" words[++w]) 165928fc495Schristos } else if(match(words[w],"^Rs$")) { 166928fc495Schristos split("",refauthors) 167928fc495Schristos nrefauthors=0 168928fc495Schristos reftitle="" 169928fc495Schristos refissue="" 170928fc495Schristos refdate="" 171928fc495Schristos refopt="" 172928fc495Schristos refreport="" 173928fc495Schristos reference=1 174928fc495Schristos next 175928fc495Schristos } else if(match(words[w],"^Re$")) { 176928fc495Schristos prenl++ 177928fc495Schristos for(i=nrefauthors-1;i>0;i--) { 178928fc495Schristos add(refauthors[i]) 179928fc495Schristos if(i>1) 180928fc495Schristos add(", ") 181928fc495Schristos } 182928fc495Schristos if(nrefauthors>1) 183928fc495Schristos add(" and ") 184928fc495Schristos if(nrefauthors>0) 185928fc495Schristos add(refauthors[0] ", ") 186928fc495Schristos add("\\fI" reftitle "\\fP") 187928fc495Schristos if(length(refissue)) 188928fc495Schristos add(", " refissue) 189928fc495Schristos if(length(refreport)) { 190928fc495Schristos add(", " refreport) 191928fc495Schristos } 192928fc495Schristos if(length(refdate)) 193928fc495Schristos add(", " refdate) 194928fc495Schristos if(length(refopt)) 195928fc495Schristos add(", " refopt) 196928fc495Schristos add(".") 197928fc495Schristos reference=0 198928fc495Schristos } else if(reference) { 199928fc495Schristos if(match(words[w],"^%A$")) { refauthors[nrefauthors++]=wtail() } 200928fc495Schristos if(match(words[w],"^%T$")) { 201928fc495Schristos reftitle=wtail() 202928fc495Schristos sub("^\"","",reftitle) 203928fc495Schristos sub("\"$","",reftitle) 204928fc495Schristos } 205928fc495Schristos if(match(words[w],"^%N$")) { refissue=wtail() } 206928fc495Schristos if(match(words[w],"^%D$")) { refdate=wtail() } 207928fc495Schristos if(match(words[w],"^%O$")) { refopt=wtail() } 208928fc495Schristos if(match(words[w],"^%R$")) { refreport=wtail() } 209928fc495Schristos } else if(match(words[w],"^Nm$")) { 210928fc495Schristos if(synopsis) { 211928fc495Schristos add(".br") 212928fc495Schristos prenl++ 213928fc495Schristos } 214928fc495Schristos n=words[++w] 215928fc495Schristos if(!length(name)) 216928fc495Schristos name=n 217928fc495Schristos if(!length(n)) 218928fc495Schristos n=name 219928fc495Schristos add("\\fB" n "\\fP") 220928fc495Schristos if(!nospace&&match(words[w+1],"^[\\.,]")) 221928fc495Schristos nospace=1 222928fc495Schristos } else if(match(words[w],"^Nd$")) { 223928fc495Schristos add("\\- " wtail()) 224928fc495Schristos } else if(match(words[w],"^Fl$")) { 225928fc495Schristos add("\\fB\\-" words[++w] "\\fP") 226928fc495Schristos if(!nospace&&match(words[w+1],"^[\\.,]")) 227928fc495Schristos nospace=1 228928fc495Schristos } else if(match(words[w],"^Ar$")) { 229928fc495Schristos add("\\fI") 230928fc495Schristos if(w==nwords) 231928fc495Schristos add("file ...\\fP") 232928fc495Schristos else { 233928fc495Schristos add(words[++w] "\\fP") 234928fc495Schristos while(match(words[w+1],"^\\|$")) 235928fc495Schristos add(OFS words[++w] " \\fI" words[++w] "\\fP") 236928fc495Schristos } 237928fc495Schristos if(!nospace&&match(words[w+1],"^[\\.,]")) 238928fc495Schristos nospace=1 239928fc495Schristos } else if(match(words[w],"^Cm$")) { 240928fc495Schristos add("\\fB" words[++w] "\\fP") 241928fc495Schristos while(w<nwords&&match(words[w+1],"^[\\.,:;)]")) 242928fc495Schristos add(words[++w]) 243928fc495Schristos } else if(match(words[w],"^Op$")) { 244928fc495Schristos option=1 245928fc495Schristos if(!nospace) 246928fc495Schristos nospace=1 247928fc495Schristos add("[") 248928fc495Schristos } else if(match(words[w],"^Pp$")) { 249928fc495Schristos prenl++ 250928fc495Schristos } else if(match(words[w],"^An$")) { 251928fc495Schristos prenl++ 252928fc495Schristos } else if(match(words[w],"^Ss$")) { 253928fc495Schristos add(".SS") 254928fc495Schristos } else if(match(words[w],"^Pa$")&&!option) { 255928fc495Schristos add("\\fI") 256928fc495Schristos w++ 257928fc495Schristos if(match(words[w],"^\\.")) 258928fc495Schristos add("\\&") 259928fc495Schristos add(words[w] "\\fP") 260928fc495Schristos while(w<nwords&&match(words[w+1],"^[\\.,:;)]")) 261928fc495Schristos add(words[++w]) 262928fc495Schristos } else if(match(words[w],"^Dv$")) { 263928fc495Schristos add(".BR") 264928fc495Schristos } else if(match(words[w],"^Em|Ev$")) { 265928fc495Schristos add(".IR") 266928fc495Schristos } else if(match(words[w],"^Pq$")) { 267928fc495Schristos add("(") 268928fc495Schristos nospace=1 269928fc495Schristos parens=1 270928fc495Schristos } else if(match(words[w],"^Aq$")) { 271928fc495Schristos add("<") 272928fc495Schristos nospace=1 273928fc495Schristos angles=1 274928fc495Schristos } else if(match(words[w],"^S[xy]$")) { 275928fc495Schristos add(".B " wtail()) 276928fc495Schristos } else if(match(words[w],"^Ic$")) { 277928fc495Schristos plain=1 278928fc495Schristos add("\\fB") 279928fc495Schristos while(w<nwords) { 280928fc495Schristos w++ 281928fc495Schristos if(match(words[w],"^Op$")) { 282928fc495Schristos w++ 283928fc495Schristos add("[") 284928fc495Schristos words[nwords]=words[nwords] "]" 285928fc495Schristos } 286928fc495Schristos if(match(words[w],"^Ar$")) { 287928fc495Schristos add("\\fI" words[++w] "\\fP") 288928fc495Schristos } else if(match(words[w],"^[\\.,]")) { 289928fc495Schristos sub(" $","",line) 290928fc495Schristos if(plain) { 291928fc495Schristos add("\\fP") 292928fc495Schristos plain=0 293928fc495Schristos } 294928fc495Schristos add(words[w]) 295928fc495Schristos } else { 296928fc495Schristos if(!plain) { 297928fc495Schristos add("\\fB") 298928fc495Schristos plain=1 299928fc495Schristos } 300928fc495Schristos add(words[w]) 301928fc495Schristos } 302928fc495Schristos if(!nospace) 303928fc495Schristos add(OFS) 304928fc495Schristos } 305928fc495Schristos sub(" $","",line) 306928fc495Schristos if(plain) 307928fc495Schristos add("\\fP") 308928fc495Schristos } else if(match(words[w],"^Bl$")) { 309928fc495Schristos oldoptlist=optlist 310928fc495Schristos if(match(words[w+1],"-bullet")) 311928fc495Schristos optlist=1 312928fc495Schristos else if(match(words[w+1],"-enum")) { 313928fc495Schristos optlist=2 314928fc495Schristos enum=0 315928fc495Schristos } else if(match(words[w+1],"-tag")) 316928fc495Schristos optlist=3 317928fc495Schristos else if(match(words[w+1],"-item")) 318928fc495Schristos optlist=4 319928fc495Schristos else if(match(words[w+1],"-bullet")) 320928fc495Schristos optlist=1 321928fc495Schristos w=nwords 322928fc495Schristos } else if(match(words[w],"^El$")) { 323928fc495Schristos optlist=oldoptlist 324928fc495Schristos } else if(match(words[w],"^Bk$")) { 325928fc495Schristos if(match(words[w+1],"-words")) { 326928fc495Schristos w++ 327928fc495Schristos breakw=1 328928fc495Schristos } 329928fc495Schristos } else if(match(words[w],"^Ek$")) { 330928fc495Schristos breakw=0 331928fc495Schristos } else if(match(words[w],"^It$")&&optlist) { 332928fc495Schristos if(optlist==1) 333928fc495Schristos add(".IP \\(bu") 334928fc495Schristos else if(optlist==2) 335928fc495Schristos add(".IP " ++enum ".") 336928fc495Schristos else if(optlist==3) { 337928fc495Schristos add(".TP") 338928fc495Schristos prenl++ 339928fc495Schristos if(match(words[w+1],"^Pa$|^Ev$")) { 340928fc495Schristos add(".B") 341928fc495Schristos w++ 342928fc495Schristos } 343928fc495Schristos } else if(optlist==4) 344928fc495Schristos add(".IP") 345928fc495Schristos } else if(match(words[w],"^Sm$")) { 346928fc495Schristos if(match(words[w+1],"off")) 347928fc495Schristos nospace=2 348928fc495Schristos else if(match(words[w+1],"on")) 349928fc495Schristos nospace=0 350928fc495Schristos w++ 351928fc495Schristos } else if(!skip) { 352928fc495Schristos add(words[w]) 353928fc495Schristos } 354928fc495Schristos } 355928fc495Schristos if(match(line,"^\\.[^a-zA-Z]")) 356928fc495Schristos sub("^\\.","",line) 357928fc495Schristos if(parens) 358928fc495Schristos add(")") 359928fc495Schristos if(angles) 360928fc495Schristos add(">") 361928fc495Schristos if(option) 362928fc495Schristos add("]") 363928fc495Schristos if(ext&&!extopt&&!match(line," $")) 364928fc495Schristos add(OFS) 365928fc495Schristos if(!ext&&!extopt&&length(line)) { 366928fc495Schristos print line 367928fc495Schristos prenl=0 368928fc495Schristos line="" 369928fc495Schristos } 370928fc495Schristos} 371