mdoc2man.awk revision 272461
1163953Srrs#!/usr/bin/awk
2185694Srrs#
3218269Srrs# $Id: mdoc2man.awk,v 1.9 2009/10/24 00:52:42 dtucker Exp $
4218269Srrs#
5163953Srrs# Version history:
6163953Srrs#  v4+ Adapted for OpenSSH Portable (see cvs Id and history)
7163953Srrs#  v3, I put the program under a proper license
8163953Srrs#      Dan Nelson <dnelson@allantgroup.com> added .An, .Aq and fixed a typo
9163953Srrs#  v2, fixed to work on GNU awk --posix and MacOS X
10228653Stuexen#  v1, first attempt, didn't work on MacOS X
11163953Srrs#
12163953Srrs# Copyright (c) 2003 Peter Stuge <stuge-mdoc2man@cdy.org>
13163953Srrs#
14228653Stuexen# Permission to use, copy, modify, and distribute this software for any
15163953Srrs# purpose with or without fee is hereby granted, provided that the above
16163953Srrs# copyright notice and this permission notice appear in all copies.
17163953Srrs#
18163953Srrs# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
19163953Srrs# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
20163953Srrs# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
21163953Srrs# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22163953Srrs# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
23163953Srrs# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
24163953Srrs# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25163953Srrs
26163953Srrs
27163953SrrsBEGIN {
28163953Srrs  optlist=0
29163953Srrs  oldoptlist=0
30163953Srrs  nospace=0
31163953Srrs  synopsis=0
32163953Srrs  reference=0
33163953Srrs  block=0
34163953Srrs  ext=0
35163953Srrs  extopt=0
36163953Srrs  literal=0
37163953Srrs  prenl=0
38163953Srrs  breakw=0
39163953Srrs  line=""
40167598Srrs}
41163953Srrs
42163953Srrsfunction wtail() {
43163953Srrs  retval=""
44163953Srrs  while(w<nwords) {
45163953Srrs    if(length(retval))
46163953Srrs      retval=retval OFS
47163953Srrs    retval=retval words[++w]
48163953Srrs  }
49170091Srrs  return retval
50172091Srrs}
51188067Srrs
52179157Srrsfunction add(str) {
53218211Srrs  for(;prenl;prenl--)
54163953Srrs    line=line "\n"
55163953Srrs  line=line str
56163953Srrs}
57163953Srrs
58163953Srrs! /^\./ {
59163953Srrs  for(;prenl;prenl--)
60163953Srrs    print ""
61163953Srrs  print
62165220Srrs  if(literal)
63165220Srrs    print ".br"
64165220Srrs  next
65165220Srrs}
66165220Srrs
67163953Srrs/^\.\\"/ { next }
68163953Srrs
69165220Srrs{
70163953Srrs  option=0
71163953Srrs  parens=0
72163953Srrs  angles=0
73165220Srrs  sub("^\\.","")
74165220Srrs  nwords=split($0,words)
75165220Srrs  for(w=1;w<=nwords;w++) {
76165220Srrs    skip=0
77165220Srrs    if(match(words[w],"^Li|Pf$")) {
78165220Srrs      skip=1
79163953Srrs    } else if(match(words[w],"^Xo$")) {
80163953Srrs      skip=1
81163953Srrs      ext=1
82163953Srrs      if(length(line)&&!(match(line," $")||prenl))
83163953Srrs	add(OFS)
84163953Srrs    } else if(match(words[w],"^Xc$")) {
85163953Srrs      skip=1
86163953Srrs      ext=0
87228653Stuexen      if(!extopt)
88163953Srrs	prenl++
89163953Srrs      w=nwords
90163953Srrs    } else if(match(words[w],"^Bd$")) {
91163953Srrs      skip=1
92169420Srrs      if(match(words[w+1],"-literal")) {
93169420Srrs	literal=1
94172396Srrs	prenl++
95172396Srrs	w=nwords
96172396Srrs      }
97229774Stuexen    } else if(match(words[w],"^Ed$")) {
98163953Srrs      skip=1
99163953Srrs      literal=0
100169352Srrs    } else if(match(words[w],"^Ns$")) {
101179157Srrs      skip=1
102168299Srrs      if(!nospace)
103168299Srrs	nospace=1
104172396Srrs      sub(" $","",line)
105163953Srrs    } else if(match(words[w],"^No$")) {
106163953Srrs      skip=1
107229774Stuexen      sub(" $","",line)
108163953Srrs      add(words[++w])
109163953Srrs    } else if(match(words[w],"^Dq$")) {
110163953Srrs      skip=1
111169352Srrs      add("``")
112179157Srrs      add(words[++w])
113168299Srrs      while(w<nwords&&!match(words[w+1],"^[\\.,]"))
114168299Srrs	add(OFS words[++w])
115172396Srrs      add("''")
116163953Srrs      if(!nospace&&match(words[w+1],"^[\\.,]"))
117163953Srrs	nospace=1
118163953Srrs    } else if(match(words[w],"^Sq|Ql$")) {
119163953Srrs      skip=1
120169352Srrs      add("`" words[++w] "'")
121179157Srrs      if(!nospace&&match(words[w+1],"^[\\.,]"))
122171440Srrs	nospace=1
123171440Srrs    } else if(match(words[w],"^Oo$")) {
124172396Srrs      skip=1
125163953Srrs      extopt=1
126163953Srrs      if(!nospace)
127163953Srrs	nospace=1
128163953Srrs      add("[")
129169352Srrs    } else if(match(words[w],"^Oc$")) {
130179157Srrs      skip=1
131168299Srrs      extopt=0
132168299Srrs      add("]")
133172396Srrs    }
134163953Srrs    if(!skip) {
135163953Srrs      if(!nospace&&length(line)&&!(match(line," $")||prenl))
136163953Srrs	add(OFS)
137163953Srrs      if(nospace==1)
138169352Srrs	nospace=0
139179157Srrs    }
140168299Srrs    if(match(words[w],"^Dd$")) {
141168299Srrs      if(match(words[w+1],"^\\$Mdocdate:")) {
142172396Srrs        w++;
143163953Srrs        if(match(words[w+4],"^\\$$")) {
144163953Srrs          words[w+4] = ""
145229774Stuexen        }
146163953Srrs      }
147179157Srrs      date=wtail()
148168299Srrs      next
149168299Srrs    } else if(match(words[w],"^Dt$")) {
150172396Srrs      id=wtail()
151163953Srrs      next
152229774Stuexen    } else if(match(words[w],"^Ux$")) {
153229774Stuexen      add("UNIX")
154229774Stuexen      skip=1
155229774Stuexen    } else if(match(words[w],"^Ox$")) {
156229774Stuexen      add("OpenBSD")
157229774Stuexen      skip=1
158229774Stuexen    } else if(match(words[w],"^Os$")) {
159229774Stuexen      add(".TH " id " \"" date "\" \"" wtail() "\"")
160229774Stuexen    } else if(match(words[w],"^Sh$")) {
161229774Stuexen      add(".SH")
162229774Stuexen      synopsis=match(words[w+1],"SYNOPSIS")
163229774Stuexen    } else if(match(words[w],"^Xr$")) {
164229774Stuexen      add("\\fB" words[++w] "\\fP(" words[++w] ")" words[++w])
165229774Stuexen    } else if(match(words[w],"^Rs$")) {
166229774Stuexen      split("",refauthors)
167229774Stuexen      nrefauthors=0
168229774Stuexen      reftitle=""
169229774Stuexen      refissue=""
170229774Stuexen      refdate=""
171229774Stuexen      refopt=""
172229774Stuexen      refreport=""
173229805Stuexen      reference=1
174229805Stuexen      next
175229805Stuexen    } else if(match(words[w],"^Re$")) {
176229774Stuexen      prenl++
177229774Stuexen      for(i=nrefauthors-1;i>0;i--) {
178229774Stuexen	add(refauthors[i])
179229774Stuexen	if(i>1)
180229774Stuexen	  add(", ")
181229774Stuexen      }
182229774Stuexen      if(nrefauthors>1)
183229774Stuexen	add(" and ")
184229774Stuexen      if(nrefauthors>0)
185229774Stuexen        add(refauthors[0] ", ")
186229774Stuexen      add("\\fI" reftitle "\\fP")
187229774Stuexen      if(length(refissue))
188172396Srrs	add(", " refissue)
189172396Srrs      if(length(refreport)) {
190172396Srrs	add(", " refreport)
191172396Srrs      }
192163953Srrs      if(length(refdate))
193163953Srrs	add(", " refdate)
194163953Srrs      if(length(refopt))
195163953Srrs	add(", " refopt)
196163953Srrs      add(".")
197171158Srrs      reference=0
198171158Srrs    } else if(reference) {
199221627Stuexen      if(match(words[w],"^%A$")) { refauthors[nrefauthors++]=wtail() }
200221627Stuexen      if(match(words[w],"^%T$")) {
201221627Stuexen	reftitle=wtail()
202221627Stuexen	sub("^\"","",reftitle)
203221627Stuexen	sub("\"$","",reftitle)
204171158Srrs      }
205171158Srrs      if(match(words[w],"^%N$")) { refissue=wtail() }
206217760Stuexen      if(match(words[w],"^%D$")) { refdate=wtail() }
207217760Stuexen      if(match(words[w],"^%O$")) { refopt=wtail() }
208171158Srrs      if(match(words[w],"^%R$")) { refreport=wtail() }
209171158Srrs    } else if(match(words[w],"^Nm$")) {
210171158Srrs      if(synopsis) {
211171158Srrs	add(".br")
212171158Srrs	prenl++
213171158Srrs      }
214171158Srrs      n=words[++w]
215171158Srrs      if(!length(name))
216171158Srrs	name=n
217171158Srrs      if(!length(n))
218217760Stuexen	n=name
219217760Stuexen      add("\\fB" n "\\fP")
220217760Stuexen      if(!nospace&&match(words[w+1],"^[\\.,]"))
221217760Stuexen	nospace=1
222217760Stuexen    } else if(match(words[w],"^Nd$")) {
223217760Stuexen      add("\\- " wtail())
224217760Stuexen    } else if(match(words[w],"^Fl$")) {
225217760Stuexen      add("\\fB\\-" words[++w] "\\fP")
226171158Srrs      if(!nospace&&match(words[w+1],"^[\\.,]"))
227171158Srrs	nospace=1
228171158Srrs    } else if(match(words[w],"^Ar$")) {
229171158Srrs      add("\\fI")
230171158Srrs      if(w==nwords)
231171158Srrs	add("file ...\\fP")
232171158Srrs      else {
233171158Srrs	add(words[++w] "\\fP")
234171158Srrs	while(match(words[w+1],"^\\|$"))
235171158Srrs	  add(OFS words[++w] " \\fI" words[++w] "\\fP")
236171158Srrs      }
237171158Srrs      if(!nospace&&match(words[w+1],"^[\\.,]"))
238171158Srrs	nospace=1
239171158Srrs    } else if(match(words[w],"^Cm$")) {
240171158Srrs      add("\\fB" words[++w] "\\fP")
241171158Srrs      while(w<nwords&&match(words[w+1],"^[\\.,:;)]"))
242217760Stuexen	add(words[++w])
243217760Stuexen    } else if(match(words[w],"^Op$")) {
244212712Stuexen      option=1
245212712Stuexen      if(!nospace)
246212712Stuexen	nospace=1
247212712Stuexen      add("[")
248171158Srrs    } else if(match(words[w],"^Pp$")) {
249171158Srrs      prenl++
250171158Srrs    } else if(match(words[w],"^An$")) {
251171158Srrs      prenl++
252221627Stuexen    } else if(match(words[w],"^Ss$")) {
253171158Srrs      add(".SS")
254171158Srrs    } else if(match(words[w],"^Pa$")&&!option) {
255216822Stuexen      add("\\fI")
256171158Srrs      w++
257171158Srrs      if(match(words[w],"^\\."))
258171158Srrs	add("\\&")
259171158Srrs      add(words[w] "\\fP")
260171158Srrs      while(w<nwords&&match(words[w+1],"^[\\.,:;)]"))
261171158Srrs	add(words[++w])
262171158Srrs    } else if(match(words[w],"^Dv$")) {
263163953Srrs      add(".BR")
264228653Stuexen    } else if(match(words[w],"^Em|Ev$")) {
265163953Srrs      add(".IR")
266163953Srrs    } else if(match(words[w],"^Pq$")) {
267163953Srrs      add("(")
268163953Srrs      nospace=1
269163953Srrs      parens=1
270163953Srrs    } else if(match(words[w],"^Aq$")) {
271163953Srrs      add("<")
272163953Srrs      nospace=1
273163953Srrs      angles=1
274163953Srrs    } else if(match(words[w],"^S[xy]$")) {
275163953Srrs      add(".B " wtail())
276218129Srrs    } else if(match(words[w],"^Ic$")) {
277218129Srrs      plain=1
278218129Srrs      add("\\fB")
279212712Stuexen      while(w<nwords) {
280163953Srrs	w++
281163953Srrs	if(match(words[w],"^Op$")) {
282163953Srrs	  w++
283179783Srrs	  add("[")
284170744Srrs	  words[nwords]=words[nwords] "]"
285170744Srrs	}
286163953Srrs	if(match(words[w],"^Ar$")) {
287163953Srrs	  add("\\fI" words[++w] "\\fP")
288164181Srrs	} else if(match(words[w],"^[\\.,]")) {
289163953Srrs	  sub(" $","",line)
290163953Srrs	  if(plain) {
291163953Srrs	    add("\\fP")
292216822Stuexen	    plain=0
293216822Stuexen	  }
294163953Srrs	  add(words[w])
295196260Stuexen	} else {
296163953Srrs	  if(!plain) {
297216822Stuexen	    add("\\fB")
298216822Stuexen	    plain=1
299216822Stuexen	  }
300216822Stuexen	  add(words[w])
301216822Stuexen	}
302216822Stuexen	if(!nospace)
303235416Stuexen	  add(OFS)
304235416Stuexen      }
305216822Stuexen      sub(" $","",line)
306216822Stuexen      if(plain)
307216822Stuexen	add("\\fP")
308196260Stuexen    } else if(match(words[w],"^Bl$")) {
309196260Stuexen      oldoptlist=optlist
310221627Stuexen      if(match(words[w+1],"-bullet"))
311216822Stuexen	optlist=1
312196260Stuexen      else if(match(words[w+1],"-enum")) {
313196260Stuexen	optlist=2
314163953Srrs	enum=0
315163953Srrs      } else if(match(words[w+1],"-tag"))
316163953Srrs	optlist=3
317216822Stuexen      else if(match(words[w+1],"-item"))
318196260Stuexen	optlist=4
319163953Srrs      else if(match(words[w+1],"-bullet"))
320163953Srrs	optlist=1
321235416Stuexen      w=nwords
322163953Srrs    } else if(match(words[w],"^El$")) {
323163953Srrs      optlist=oldoptlist
324163953Srrs    } else if(match(words[w],"^Bk$")) {
325163953Srrs      if(match(words[w+1],"-words")) {
326212712Stuexen	w++
327212712Stuexen	breakw=1
328212712Stuexen      }
329212712Stuexen    } else if(match(words[w],"^Ek$")) {
330163953Srrs      breakw=0
331221627Stuexen    } else if(match(words[w],"^It$")&&optlist) {
332169655Srrs      if(optlist==1)
333163953Srrs	add(".IP \\(bu")
334163953Srrs      else if(optlist==2)
335163953Srrs	add(".IP " ++enum ".")
336196260Stuexen      else if(optlist==3) {
337163953Srrs	add(".TP")
338163953Srrs	prenl++
339164181Srrs	if(match(words[w+1],"^Pa$|^Ev$")) {
340188854Srrs	  add(".B")
341218129Srrs	  w++
342185694Srrs	}
343185694Srrs      } else if(optlist==4)
344179783Srrs	add(".IP")
345170744Srrs    } else if(match(words[w],"^Sm$")) {
346170744Srrs      if(match(words[w+1],"off"))
347163953Srrs	nospace=2
348163953Srrs      else if(match(words[w+1],"on"))
349163953Srrs	nospace=0
350163953Srrs      w++
351180955Srrs    } else if(!skip) {
352218129Srrs      add(words[w])
353163953Srrs    }
354163953Srrs  }
355170091Srrs  if(match(line,"^\\.[^a-zA-Z]"))
356163953Srrs    sub("^\\.","",line)
357163953Srrs  if(parens)
358216822Stuexen    add(")")
359164181Srrs  if(angles)
360164181Srrs    add(">")
361216822Stuexen  if(option)
362164181Srrs    add("]")
363164181Srrs  if(ext&&!extopt&&!match(line," $"))
364171158Srrs    add(OFS)
365164181Srrs  if(!ext&&!extopt&&length(line)) {
366164181Srrs    print line
367164181Srrs    prenl=0
368164181Srrs    line=""
369164181Srrs  }
370170091Srrs}
371163953Srrs