Imported Upstream version 3.1.2
[platform/upstream/libarchive.git] / doc / mdoc2man.awk
1 #!/usr/bin/awk
2 #
3 # Copyright (c) 2003 Peter Stuge <stuge-mdoc2man@cdy.org>
4 #
5 # Permission to use, copy, modify, and distribute this software for any
6 # purpose with or without fee is hereby granted, provided that the above
7 # copyright notice and this permission notice appear in all copies.
8 #
9 # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17 # Dramatically overhauled by Tim Kientzle.  This version almost
18 # handles library-style pages with Fn, Ft, etc commands.  Still
19 # a lot of problems...
20
21 BEGIN {
22   displaylines = 0
23   trailer = ""
24   out = ""
25   sep = ""
26   nextsep = " "
27 }
28
29 # Add a word with appropriate preceding whitespace
30 # Maintain a short queue of the expected upcoming word separators.
31 function add(str) {
32   out=out sep str
33   sep = nextsep
34   nextsep = " "
35 }
36
37 # Add a word with no following whitespace
38 # Use for opening punctuation such as '('
39 function addopen(str) {
40   add(str)
41   sep = ""
42 }
43
44 # Add a word with no preceding whitespace
45 # Use for closing punctuation such as ')' or '.'
46 function addclose(str) {
47   sep = ""
48   add(str)
49 }
50
51 # Add a word with no space before or after
52 # Use for separating punctuation such as '='
53 function addpunct(str) {
54   sep = ""
55   add(str)
56   sep = ""
57 }
58
59 # Emit the current line so far
60 function endline() {
61   addclose(trailer)
62   trailer = ""
63   if(length(out) > 0) {
64     print out
65     out=""
66   }
67   if(displaylines > 0) {
68     displaylines = displaylines - 1
69     if (displaylines == 0)
70       dispend()
71   }
72   # First word on next line has no preceding whitespace
73   sep = ""
74 }
75
76 function linecmd(cmd) {
77   endline()
78   add(cmd)
79   endline()
80 }
81
82 function breakline() {
83   linecmd(".br")
84 }
85
86 # Start an indented display
87 function dispstart() {
88   linecmd(".RS 4")
89 }
90
91 # End an indented display
92 function dispend() {
93   linecmd(".RE")
94 }
95
96 # Collect rest of input line
97 function wtail() {
98   retval=""
99   while(w<nwords) {
100     if(length(retval))
101       retval=retval " "
102     retval=retval words[++w]
103   }
104   return retval
105 }
106
107 function splitwords(l, dest, n, o, w) {
108   n = 1
109   delete dest
110   while (length(l) > 0) {
111     sub("^[ \t]*", "", l)
112     if (match(l, "^\"")) {
113       l = substr(l, 2)
114       o = index(l, "\"")
115       if (o > 0) {
116         w = substr(l, 1, o-1)
117         l = substr(l, o+1)
118         dest[n++] = w
119       } else {
120         dest[n++] = l
121         l = ""
122       }
123     } else {
124       o = match(l, "[ \t]")
125       if (o > 0) {
126         w = substr(l, 1, o-1)
127         l = substr(l, o+1)
128         dest[n++] = w
129       } else {
130         dest[n++] = l
131         l = ""
132       }
133     }
134   }
135   return n-1
136 }
137
138 ! /^\./ {
139   out = $0
140   endline()
141   next
142 }
143
144 /^\.\\"/ { next }
145
146 {
147   sub("^\\.","")
148   nwords=splitwords($0, words)
149   # TODO: Instead of iterating 'w' over the array, have a separate
150   # function that returns 'next word' and use that.  This will allow
151   # proper handling of double-quoted arguments as well.
152   for(w=1;w<=nwords;w++) {
153     if(match(words[w],"^Li$")) { # Literal; rest of line is unformatted
154       dispstart()
155       displaylines = 1
156     } else if(match(words[w],"^Dl$")) { # Display literal
157       dispstart()
158       displaylines = 1
159     } else if(match(words[w],"^Bd$")) { # Begin display
160       if(match(words[w+1],"-literal")) {
161         dispstart()
162         linecmd(".nf")
163         displaylines=10000
164         w=nwords
165       }
166     } else if(match(words[w],"^Ed$")) { # End display
167       displaylines = 0
168       dispend()
169     } else if(match(words[w],"^Ns$")) { # Suppress space after next word
170       nextsep = ""
171     } else if(match(words[w],"^No$")) { # Normal text
172       add(words[++w])
173     } else if(match(words[w],"^Dq$")) { # Quote
174       addopen("``")
175       add(words[++w])
176       while(w<nwords&&!match(words[w+1],"^[\\.,]"))
177         add(words[++w])
178       addclose("''")
179     } else if(match(words[w],"^Do$")) {
180       addopen("``")
181     } else if(match(words[w],"^Dc$")) {
182       addclose("''")
183     } else if(match(words[w],"^Oo$")) {
184       addopen("[")
185     } else if(match(words[w],"^Oc$")) {
186       addclose("]")
187     } else if(match(words[w],"^Ao$")) {
188       addopen("<")
189     } else if(match(words[w],"^Ac$")) {
190       addclose(">")
191     } else if(match(words[w],"^Dd$")) {
192       date=wtail()
193       next
194     } else if(match(words[w],"^Dt$")) {
195       id=wtail()
196       next
197     } else if(match(words[w],"^Ox$")) {
198       add("OpenBSD")
199     } else if(match(words[w],"^Fx$")) {
200       add("FreeBSD")
201     } else if(match(words[w],"^Nx$")) {
202       add("NetBSD")
203     } else if(match(words[w],"^St$")) {
204       if (match(words[w+1], "^-p1003.1$")) {
205          w++
206          add("IEEE Std 1003.1 (``POSIX.1'')")
207       } else if(match(words[w+1], "^-p1003.1-96$")) {
208          w++
209          add("ISO/IEC 9945-1:1996 (``POSIX.1'')")
210       } else if(match(words[w+1], "^-p1003.1-88$")) {
211          w++
212          add("IEEE Std 1003.1-1988 (``POSIX.1'')")
213       } else if(match(words[w+1], "^-p1003.1-2001$")) {
214          w++
215          add("IEEE Std 1003.1-2001 (``POSIX.1'')")
216       } else if(match(words[w+1], "^-susv2$")) {
217          w++
218          add("Version 2 of the Single UNIX Specification (``SUSv2'')")
219       }
220     } else if(match(words[w],"^Ex$")) {
221       if (match(words[w+1], "^-std$")) {
222          w++
223          add("The \\fB" name "\\fP utility exits 0 on success, and >0 if an error occurs.")
224       }
225     } else if(match(words[w],"^Os$")) {
226       add(".TH " id " \"" date "\" \"" wtail() "\"")
227     } else if(match(words[w],"^Sh$")) {
228       section=wtail()
229       add(".SH " section)
230       linecmd(".ad l")
231     } else if(match(words[w],"^Xr$")) {
232       add("\\fB" words[++w] "\\fP(" words[++w] ")" words[++w])
233     } else if(match(words[w],"^Nm$")) {
234       if(match(section,"SYNOPSIS"))
235         breakline()
236       if(w >= nwords)
237         n=name
238       else if (match(words[w+1], "^[A-Z][a-z]$"))
239         n=name
240       else if (match(words[w+1], "^[.,;:]$"))
241         n=name
242       else {
243         n=words[++w]
244         if(!length(name))
245           name=n
246       }
247       if(!length(n))
248         n=name
249       add("\\fB\\%" n "\\fP")
250     } else if(match(words[w],"^Nd$")) {
251       add("\\- " wtail())
252     } else if(match(words[w],"^Fl$")) {
253       add("\\fB\\-" words[++w] "\\fP")
254     } else if(match(words[w],"^Ar$")) {
255       addopen("\\fI")
256       if(w==nwords)
257         add("file ...\\fP")
258       else
259         add(words[++w] "\\fP")
260     } else if(match(words[w],"^Cm$")) {
261       add("\\fB" words[++w] "\\fP")
262     } else if(match(words[w],"^Op$")) {
263       addopen("[")
264       option=1
265       trailer="]" trailer
266     } else if(match(words[w],"^Pp$")) {
267       linecmd(".PP")
268     } else if(match(words[w],"^An$")) {
269       endline()
270     } else if(match(words[w],"^Ss$")) {
271       add(".SS")
272     } else if(match(words[w],"^Ft$")) {
273       if (match(section, "SYNOPSIS")) {
274         breakline()
275       }
276       add("\\fI" wtail() "\\fP")
277       if (match(section, "SYNOPSIS")) {
278         breakline()
279       }
280     } else if(match(words[w],"^Fn$")) {
281       ++w
282       F = "\\fB\\%" words[w] "\\fP("
283       Fsep = ""
284       while(w<nwords) {
285         ++w
286         if (match(words[w], "^[.,:]$")) {
287           --w
288           break
289         }
290         gsub(" ", "\\ ", words[w])
291         F = F Fsep "\\fI\\%"  words[w] "\\fP"
292         Fsep = ", "
293       }
294       add(F ")")
295       if (match(section, "SYNOPSIS")) {
296         addclose(";")
297       }
298     } else if(match(words[w],"^Fo$")) {
299       w++
300       F = "\\fB\\%" words[w] "\\fP("
301       Fsep = ""
302     } else if(match(words[w],"^Fa$")) {
303       w++
304       gsub(" ", "\\ ", words[w])
305       F = F Fsep "\\fI\\%"  words[w] "\\fP"
306       Fsep = ", "
307     } else if(match(words[w],"^Fc$")) {
308       add(F ")")
309       if (match(section, "SYNOPSIS")) {
310         addclose(";")
311       }
312     } else if(match(words[w],"^Va$")) {
313       w++
314       add("\\fI" words[w] "\\fP")
315     } else if(match(words[w],"^In$")) {
316       w++
317       add("\\fB#include <" words[w] ">\\fP")
318     } else if(match(words[w],"^Pa$")) {
319       addopen("\\fI")
320       w++
321       if(match(words[w],"^\\."))
322         add("\\&")
323       add(words[w] "\\fP")
324     } else if(match(words[w],"^Dv$")) {
325       add(".BR")
326     } else if(match(words[w],"^Em|Ev$")) {
327       add(".IR")
328     } else if(match(words[w],"^Pq$")) {
329       addopen("(")
330       trailer=")" trailer
331     } else if(match(words[w],"^Aq$")) {
332       addopen("\\%<")
333       trailer=">" trailer
334     } else if(match(words[w],"^Brq$")) {
335       addopen("{")
336       trailer="}" trailer
337     } else if(match(words[w],"^S[xy]$")) {
338       add(".B " wtail())
339     } else if(match(words[w],"^Ic$")) {
340       add("\\fB")
341       trailer="\\fP" trailer
342     } else if(match(words[w],"^Bl$")) {
343       oldoptlist=optlist
344       linecmd(".RS 5")
345       if(match(words[w+1],"-bullet"))
346         optlist=1
347       else if(match(words[w+1],"-enum")) {
348         optlist=2
349         enum=0
350       } else if(match(words[w+1],"-tag"))
351         optlist=3
352       else if(match(words[w+1],"-item"))
353         optlist=4
354       else if(match(words[w+1],"-bullet"))
355         optlist=1
356       w=nwords
357     } else if(match(words[w],"^El$")) {
358       linecmd(".RE")
359       optlist=oldoptlist
360     } else if(match(words[w],"^It$")&&optlist) {
361       if(optlist==1)
362         add(".IP \\(bu")
363       else if(optlist==2)
364         add(".IP " ++enum ".")
365       else if(optlist==3) {
366         add(".TP")
367         endline()
368         if(match(words[w+1],"^Pa$|^Ev$")) {
369           add(".B")
370           w++
371         }
372       } else if(optlist==4)
373         add(".IP")
374     } else if(match(words[w],"^Xo$")) {
375       # TODO: Figure out how to handle this
376     } else if(match(words[w],"^Xc$")) {
377       # TODO: Figure out how to handle this
378     } else if(match(words[w],"^[=]$")) {
379       addpunct(words[w])
380     } else if(match(words[w],"^[[{(]$")) {
381       addopen(words[w])
382     } else if(match(words[w],"^[\\])}.,;:]$")) {
383       addclose(words[w])
384     } else {
385       add(words[w])
386     }
387   }
388   if(match(out,"^\\.[^a-zA-Z]"))
389     sub("^\\.","",out)
390   endline()
391 }